phpvms/public/assets/frontend/js/app.js
Nabeel S bbec276da8
#355 Calculate distance button (#366)
* #355 Calculate distance button in add/edit Flight page

* Styling

* Move add/edit flight logic out of controller and into service layer

* Styling

* Formatting

* Run styleci against modules dir

* Styleci config

* Style fixes in /modules
2019-08-26 12:32:46 -04:00

431 lines
1.6 MiB
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ({
/***/ "./node_modules/Leaflet.Geodesic/Leaflet.Geodesic.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\n// This file is part of Leaflet.Geodesic.\n// Copyright (C) 2017 Henry Thasler\n// based on code by Chris Veness Copyright (C) 2014 https://github.com/chrisveness/geodesy\n//\n// Leaflet.Geodesic is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Leaflet.Geodesic is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Leaflet.Geodesic. If not, see <http://www.gnu.org/licenses/>.\n\n\n/** Extend Number object with method to convert numeric degrees to radians */\nif (typeof Number.prototype.toRadians === \"undefined\") {\n Number.prototype.toRadians = function() {\n return this * Math.PI / 180;\n };\n}\n\n/** Extend Number object with method to convert radians to numeric (signed) degrees */\nif (typeof Number.prototype.toDegrees === \"undefined\") {\n Number.prototype.toDegrees = function() {\n return this * 180 / Math.PI;\n };\n}\n\nvar INTERSECT_LNG = 179.999; // Lng used for intersection and wrap around on map edges\n\nL.Geodesic = L.Polyline.extend({\n options: {\n color: \"blue\",\n steps: 10,\n dash: 1,\n wrap: true\n },\n\n initialize: function(latlngs, options) {\n this.options = this._merge_options(this.options, options);\n this.options.dash = Math.max(1e-3, Math.min(1, parseFloat(this.options.dash) || 1));\n this.datum = {};\n this.datum.ellipsoid = {\n a: 6378137,\n b: 6356752.3142,\n f: 1 / 298.257223563\n }; // WGS-84\n this._latlngs = this._generate_Geodesic(latlngs);\n L.Polyline.prototype.initialize.call(this, this._latlngs, this.options);\n },\n\n setLatLngs: function(latlngs) {\n this._latlngs = this._generate_Geodesic(latlngs);\n L.Polyline.prototype.setLatLngs.call(this, this._latlngs);\n },\n\n /**\n * Calculates some statistic values of current geodesic multipolyline\n * @returns (Object} Object with several properties (e.g. overall distance)\n */\n getStats: function() {\n let obj = {\n distance: 0,\n points: 0,\n polygons: this._latlngs.length\n }, poly, points;\n\n for (poly = 0; poly < this._latlngs.length; poly++) {\n obj.points += this._latlngs[poly].length;\n for (points = 0; points < (this._latlngs[poly].length - 1); points++) {\n obj.distance += this._vincenty_inverse(this._latlngs[poly][points],\n this._latlngs[poly][points + 1]).distance;\n }\n }\n return obj;\n },\n\n\n /**\n * Creates geodesic lines from geoJson. Replaces all current features of this instance.\n * Supports LineString, MultiLineString and Polygon\n * @param {Object} geojson - geosjon as object.\n */\n geoJson: function(geojson) {\n\n let normalized = L.GeoJSON.asFeature(geojson);\n let features = normalized.type === \"FeatureCollection\" ? normalized.features : [\n normalized\n ];\n this._latlngs = [];\n for (let feature of features) {\n let geometry = feature.type === \"Feature\" ? feature.geometry :\n feature,\n coords = geometry.coordinates;\n\n switch (geometry.type) {\n case \"LineString\":\n this._latlngs.push(this._generate_Geodesic([L.GeoJSON.coordsToLatLngs(\n coords, 0)]));\n break;\n case \"MultiLineString\":\n case \"Polygon\":\n this._latlngs.push(this._generate_Geodesic(L.GeoJSON.coordsToLatLngs(\n coords, 1)));\n break;\n case \"Point\":\n case \"MultiPoint\":\n console.log(\"Dude, points can't be drawn as geodesic lines...\");\n break;\n default:\n console.log(\"Drawing \" + geometry.type +\n \" as a geodesic is not supported. Skipping...\");\n }\n }\n L.Polyline.prototype.setLatLngs.call(this, this._latlngs);\n },\n\n /**\n * Creates a great circle. Replaces all current lines.\n * @param {Object} center - geographic position\n * @param {number} radius - radius of the circle in metres\n */\n createCircle: function(center, radius) {\n let polylineIndex = 0;\n let prev = {\n lat: 0,\n lng: 0,\n brg: 0\n };\n let step;\n\n this._latlngs = [];\n this._latlngs[polylineIndex] = [];\n\n let direct = this._vincenty_direct(L.latLng(center), 0, radius, this.options\n .wrap);\n prev = L.latLng(direct.lat, direct.lng);\n this._latlngs[polylineIndex].push(prev);\n for (step = 1; step <= this.options.steps;) {\n direct = this._vincenty_direct(L.latLng(center), 360 / this.options\n .steps * step, radius, this.options.wrap);\n let gp = L.latLng(direct.lat, direct.lng);\n if (Math.abs(gp.lng - prev.lng) > 180) {\n let inverse = this._vincenty_inverse(prev, gp);\n let sec = this._intersection(prev, inverse.initialBearing, {\n lat: -89,\n lng: ((gp.lng - prev.lng) > 0) ? -INTERSECT_LNG : INTERSECT_LNG\n }, 0);\n if (sec) {\n this._latlngs[polylineIndex].push(L.latLng(sec.lat, sec.lng));\n polylineIndex++;\n this._latlngs[polylineIndex] = [];\n prev = L.latLng(sec.lat, -sec.lng);\n this._latlngs[polylineIndex].push(prev);\n } else {\n polylineIndex++;\n this._latlngs[polylineIndex] = [];\n this._latlngs[polylineIndex].push(gp);\n prev = gp;\n step++;\n }\n } else {\n this._latlngs[polylineIndex].push(gp);\n prev = gp;\n step++;\n }\n }\n\n L.Polyline.prototype.setLatLngs.call(this, this._latlngs);\n },\n\n /**\n * Creates a geodesic Polyline from given coordinates\n * Note: dashed lines are under work\n * @param {Object} latlngs - One or more polylines as an array. See Leaflet doc about Polyline\n * @returns (Object} An array of arrays of geographical points.\n */\n _generate_Geodesic: function(latlngs) {\n let _geo = [], _geocnt = 0;\n\n for (let poly = 0; poly < latlngs.length; poly++) {\n _geo[_geocnt] = [];\n let prev = L.latLng(latlngs[poly][0]);\n for (let points = 0; points < (latlngs[poly].length - 1); points++) {\n // use prev, so that wrapping behaves correctly\n let pointA = prev;\n let pointB = L.latLng(latlngs[poly][points + 1]);\n if (pointA.equals(pointB)) {\n continue;\n }\n let inverse = this._vincenty_inverse(pointA, pointB);\n _geo[_geocnt].push(prev);\n for (let s = 1; s <= this.options.steps;) {\n let distance = inverse.distance / this.options.steps;\n // dashed lines don't go the full distance between the points\n let dist_mult = s - 1 + this.options.dash;\n let direct = this._vincenty_direct(pointA, inverse.initialBearing, distance*dist_mult, this.options.wrap);\n let gp = L.latLng(direct.lat, direct.lng);\n if (Math.abs(gp.lng - prev.lng) > 180) {\n let sec = this._intersection(pointA, inverse.initialBearing, {\n lat: -89,\n lng: ((gp.lng - prev.lng) > 0) ? -INTERSECT_LNG : INTERSECT_LNG\n }, 0);\n if (sec) {\n _geo[_geocnt].push(L.latLng(sec.lat, sec.lng));\n _geocnt++;\n _geo[_geocnt] = [];\n prev = L.latLng(sec.lat, -sec.lng);\n _geo[_geocnt].push(prev);\n } else {\n _geocnt++;\n _geo[_geocnt] = [];\n _geo[_geocnt].push(gp);\n prev = gp;\n s++;\n } \n } else {\n _geo[_geocnt].push(gp);\n // Dashed lines start a new line\n if (this.options.dash < 1){\n _geocnt++;\n // go full distance this time, to get starting point for next line\n let direct_full = this._vincenty_direct(pointA, inverse.initialBearing, distance*s, this.options.wrap);\n _geo[_geocnt] = [];\n prev = L.latLng(direct_full.lat, direct_full.lng);\n _geo[_geocnt].push(prev);\n }\n else prev = gp;\n s++;\n }\n }\n }\n _geocnt++;\n }\n return _geo;\n },\n\n /**\n * Vincenty direct calculation.\n * based on the work of Chris Veness (https://github.com/chrisveness/geodesy)\n *\n * @private\n * @param {number} initialBearing - Initial bearing in degrees from north.\n * @param {number} distance - Distance along bearing in metres.\n * @returns (Object} Object including point (destination point), finalBearing.\n */\n\n _vincenty_direct: function(p1, initialBearing, distance, wrap) {\n var φ1 = p1.lat.toRadians(),\n λ1 = p1.lng.toRadians();\n var α1 = initialBearing.toRadians();\n var s = distance;\n\n var a = this.datum.ellipsoid.a,\n b = this.datum.ellipsoid.b,\n f = this.datum.ellipsoid.f;\n\n var sinα1 = Math.sin(α1);\n var cosα1 = Math.cos(α1);\n\n var tanU1 = (1 - f) * Math.tan(φ1),\n cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)),\n sinU1 = tanU1 * cosU1;\n var σ1 = Math.atan2(tanU1, cosα1);\n var sinα = cosU1 * sinα1;\n var cosSqα = 1 - sinα * sinα;\n var uSq = cosSqα * (a * a - b * b) / (b * b);\n var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 *\n uSq)));\n var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));\n\n var σ = s / (b * A),\n σʹ, iterations = 0;\n var sinσ, cosσ;\n var cos2σM;\n do {\n cos2σM = Math.cos(2 * σ1 + σ);\n sinσ = Math.sin(σ);\n cosσ = Math.cos(σ);\n var Δσ = B * sinσ * (cos2σM + B / 4 * (cosσ * (-1 + 2 * cos2σM *\n cos2σM) -\n B / 6 * cos2σM * (-3 + 4 * sinσ * sinσ) * (-3 + 4 * cos2σM *\n cos2σM)));\n σʹ = σ;\n σ = s / (b * A) + Δσ;\n } while (Math.abs(σ - σʹ) > 1e-12 && ++iterations);\n\n var x = sinU1 * sinσ - cosU1 * cosσ * cosα1;\n var φ2 = Math.atan2(sinU1 * cosσ + cosU1 * sinσ * cosα1, (1 - f) *\n Math.sqrt(sinα * sinα + x * x));\n var λ = Math.atan2(sinσ * sinα1, cosU1 * cosσ - sinU1 * sinσ * cosα1);\n var C = f / 16 * cosSqα * (4 + f * (4 - 3 * cosSqα));\n var L = λ - (1 - C) * f * sinα *\n (σ + C * sinσ * (cos2σM + C * cosσ * (-1 + 2 * cos2σM * cos2σM)));\n\n var λ2;\n if (wrap) {\n λ2 = (λ1 + L + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalise to -180...+180\n } else {\n λ2 = (λ1 + L); // do not normalize\n }\n\n var revAz = Math.atan2(sinα, -x);\n\n return {\n lat: φ2.toDegrees(),\n lng: λ2.toDegrees(),\n finalBearing: revAz.toDegrees()\n };\n },\n\n /**\n * Vincenty inverse calculation.\n * based on the work of Chris Veness (https://github.com/chrisveness/geodesy)\n *\n * @private\n * @param {LatLng} p1 - Latitude/longitude of start point.\n * @param {LatLng} p2 - Latitude/longitude of destination point.\n * @returns {Object} Object including distance, initialBearing, finalBearing.\n * @throws {Error} If formula failed to converge.\n */\n _vincenty_inverse: function(p1, p2) {\n var φ1 = p1.lat.toRadians(),\n λ1 = p1.lng.toRadians();\n var φ2 = p2.lat.toRadians(),\n λ2 = p2.lng.toRadians();\n\n var a = this.datum.ellipsoid.a,\n b = this.datum.ellipsoid.b,\n f = this.datum.ellipsoid.f;\n\n var L = λ2 - λ1;\n var tanU1 = (1 - f) * Math.tan(φ1),\n cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)),\n sinU1 = tanU1 * cosU1;\n var tanU2 = (1 - f) * Math.tan(φ2),\n cosU2 = 1 / Math.sqrt((1 + tanU2 * tanU2)),\n sinU2 = tanU2 * cosU2;\n\n var λ = L,\n λʹ, iterations = 0;\n var cosSqα, sinσ, cos2σM, cosσ, σ, sinλ, cosλ;\n do {\n sinλ = Math.sin(λ);\n cosλ = Math.cos(λ);\n var sinSqσ = (cosU2 * sinλ) * (cosU2 * sinλ) + (cosU1 * sinU2 -\n sinU1 * cosU2 * cosλ) * (cosU1 * sinU2 - sinU1 * cosU2 * cosλ);\n sinσ = Math.sqrt(sinSqσ);\n if (sinσ == 0) return 0; // co-incident points\n cosσ = sinU1 * sinU2 + cosU1 * cosU2 * cosλ;\n σ = Math.atan2(sinσ, cosσ);\n var sinα = cosU1 * cosU2 * sinλ / sinσ;\n cosSqα = 1 - sinα * sinα;\n cos2σM = cosσ - 2 * sinU1 * sinU2 / cosSqα;\n if (isNaN(cos2σM)) cos2σM = 0; // equatorial line: cosSqα=0 (§6)\n var C = f / 16 * cosSqα * (4 + f * (4 - 3 * cosSqα));\n λʹ = λ;\n λ = L + (1 - C) * f * sinα * (σ + C * sinσ * (cos2σM + C * cosσ * (-\n 1 + 2 * cos2σM * cos2σM)));\n } while (Math.abs(λ - λʹ) > 1e-12 && ++iterations < 100);\n if (iterations >= 100) {\n console.log(\"Formula failed to converge. Altering target position.\");\n return this._vincenty_inverse(p1, {\n lat: p2.lat,\n lng: p2.lng - 0.01\n });\n // throw new Error('Formula failed to converge');\n }\n\n var uSq = cosSqα * (a * a - b * b) / (b * b);\n var A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 *\n uSq)));\n var B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));\n var Δσ = B * sinσ * (cos2σM + B / 4 * (cosσ * (-1 + 2 * cos2σM *\n cos2σM) -\n B / 6 * cos2σM * (-3 + 4 * sinσ * sinσ) * (-3 + 4 * cos2σM *\n cos2σM)));\n\n var s = b * A * (σ - Δσ);\n\n var fwdAz = Math.atan2(cosU2 * sinλ, cosU1 * sinU2 - sinU1 * cosU2 *\n cosλ);\n var revAz = Math.atan2(cosU1 * sinλ, -sinU1 * cosU2 + cosU1 * sinU2 *\n cosλ);\n\n s = Number(s.toFixed(3)); // round to 1mm precision\n return {\n distance: s,\n initialBearing: fwdAz.toDegrees(),\n finalBearing: revAz.toDegrees()\n };\n },\n\n\n /**\n * Returns the point of intersection of two paths defined by point and bearing.\n * based on the work of Chris Veness (https://github.com/chrisveness/geodesy)\n *\n * @param {LatLon} p1 - First point.\n * @param {number} brng1 - Initial bearing from first point.\n * @param {LatLon} p2 - Second point.\n * @param {number} brng2 - Initial bearing from second point.\n * @returns {Object} containing lat/lng information of intersection.\n *\n * @example\n * var p1 = LatLon(51.8853, 0.2545), brng1 = 108.55;\n * var p2 = LatLon(49.0034, 2.5735), brng2 = 32.44;\n * var pInt = LatLon.intersection(p1, brng1, p2, brng2); // pInt.toString(): 50.9078°N, 4.5084°E\n */\n _intersection: function(p1, brng1, p2, brng2) {\n // see http://williams.best.vwh.net/avform.htm#Intersection\n\n var φ1 = p1.lat.toRadians(),\n λ1 = p1.lng.toRadians();\n var φ2 = p2.lat.toRadians(),\n λ2 = p2.lng.toRadians();\n var θ13 = Number(brng1).toRadians(),\n θ23 = Number(brng2).toRadians();\n var Δφ = φ2 - φ1,\n Δλ = λ2 - λ1;\n\n var δ12 = 2 * Math.asin(Math.sqrt(Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +\n Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ /\n 2)));\n if (δ12 == 0) return null;\n\n // initial/final bearings between points\n var θ1 = Math.acos((Math.sin(φ2) - Math.sin(φ1) * Math.cos(δ12)) /\n (Math.sin(δ12) * Math.cos(φ1)));\n if (isNaN(θ1)) θ1 = 0; // protect against rounding\n var θ2 = Math.acos((Math.sin(φ1) - Math.sin(φ2) * Math.cos(δ12)) /\n (Math.sin(δ12) * Math.cos(φ2)));\n var θ12, θ21;\n if (Math.sin(λ2 - λ1) > 0) {\n θ12 = θ1;\n θ21 = 2 * Math.PI - θ2;\n } else {\n θ12 = 2 * Math.PI - θ1;\n θ21 = θ2;\n }\n\n var α1 = (θ13 - θ12 + Math.PI) % (2 * Math.PI) - Math.PI; // angle 2-1-3\n var α2 = (θ21 - θ23 + Math.PI) % (2 * Math.PI) - Math.PI; // angle 1-2-3\n\n if (Math.sin(α1) == 0 && Math.sin(α2) == 0) return null; // infinite intersections\n if (Math.sin(α1) * Math.sin(α2) < 0) return null; // ambiguous intersection\n\n //α1 = Math.abs(α1);\n //α2 = Math.abs(α2);\n // ... Ed Williams takes abs of α1/α2, but seems to break calculation?\n\n var α3 = Math.acos(-Math.cos(α1) * Math.cos(α2) +\n Math.sin(α1) * Math.sin(α2) * Math.cos(δ12));\n var δ13 = Math.atan2(Math.sin(δ12) * Math.sin(α1) * Math.sin(α2),\n Math.cos(α2) + Math.cos(α1) * Math.cos(α3));\n var φ3 = Math.asin(Math.sin(φ1) * Math.cos(δ13) +\n Math.cos(φ1) * Math.sin(δ13) * Math.cos(θ13));\n var Δλ13 = Math.atan2(Math.sin(θ13) * Math.sin(δ13) * Math.cos(φ1),\n Math.cos(δ13) - Math.sin(φ1) * Math.sin(φ3));\n var λ3 = λ1 + Δλ13;\n λ3 = (λ3 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // normalise to -180..+180º\n\n return {\n lat: φ3.toDegrees(),\n lng: λ3.toDegrees()\n };\n },\n\n /**\n * Overwrites obj1's values with obj2's and adds obj2's if non existent in obj1\n * @param obj1\n * @param obj2\n * @returns obj3 a new object based on obj1 and obj2\n */\n _merge_options: function(obj1, obj2) {\n let obj3 = {};\n for (let attrname in obj1) {\n obj3[attrname] = obj1[attrname];\n }\n for (let attrname in obj2) {\n obj3[attrname] = obj2[attrname];\n }\n return obj3;\n }\n});\n\nL.geodesic = function(latlngs, options) {\n return new L.Geodesic(latlngs, options);\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvTGVhZmxldC5HZW9kZXNpYy9MZWFmbGV0Lkdlb2Rlc2ljLmpzPzU3NGMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0QkFBNEI7O0FBRTVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxzQkFBc0I7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUCxrQkFBa0IsNkJBQTZCO0FBQy9DO0FBQ0Esc0JBQXNCLDJDQUEyQztBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLDRCQUE0QjtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLHNCQUFzQjtBQUN0QjtBQUNBO0FBQ0E7O0FBRUEsc0JBQXNCLHVCQUF1QjtBQUM3QztBQUNBO0FBQ0EsMEJBQTBCLHFDQUFxQztBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHlCQUF5QjtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEIsc0JBQXNCO0FBQ3RCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDREQUE0RDtBQUM1RCxLQUFLO0FBQ0wsb0JBQW9CO0FBQ3BCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCLGVBQWUsT0FBTztBQUN0QixjQUFjLE1BQU07QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRDtBQUMxRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSw2REFBNkQ7QUFDN0QsNkRBQTZEOztBQUU3RCw0REFBNEQ7QUFDNUQscURBQXFEOztBQUVyRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0RBQXNEOztBQUV0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9MZWFmbGV0Lkdlb2Rlc2ljL0xlYWZsZXQuR2VvZGVzaWMuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJcInVzZSBzdHJpY3RcIjtcblxuLy8gVGhpcyBmaWxlIGlzIHBhcnQgb2YgTGVhZmxldC5HZW9kZXNpYy5cbi8vIENvcHlyaWdodCAoQykgMjAxNyAgSGVucnkgVGhhc2xlclxuLy8gYmFzZWQgb24gY29kZSBieSBDaHJpcyBWZW5lc3MgQ29weXJpZ2h0IChDKSAyMDE0IGh0dHBzOi8vZ2l0aHViLmNvbS9jaHJpc3ZlbmVzcy9nZW9kZXN5XG4vL1xuLy8gTGVhZmxldC5HZW9kZXNpYyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4vLyBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuLy8gdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3Jcbi8vIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vL1xuLy8gTGVhZmxldC5HZW9kZXNpYyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbi8vIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vL1xuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2Vcbi8vIGFsb25nIHdpdGggTGVhZmxldC5HZW9kZXNpYy4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cblxuXG4vKiogRXh0ZW5kIE51bWJlciBvYmplY3Qgd2l0aCBtZXRob2QgdG8gY29udmVydCBudW1lcmljIGRlZ3JlZXMgdG8gcmFkaWFucyAqL1xuaWYgKHR5cGVvZiBOdW1iZXIucHJvdG90eXBlLnRvUmFkaWFucyA9PT0gXCJ1bmRlZmluZWRcIikge1xuICBOdW1iZXIucHJvdG90eXBlLnRvUmFkaWFucyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzICogTWF0aC5QSSAvIDE4MDtcbiAgfTtcbn1cblxuLyoqIEV4dGVuZCBOdW1iZXIgb2JqZWN0IHdpdGggbWV0aG9kIHRvIGNvbnZlcnQgcmFkaWFucyB0byBudW1lcmljIChzaWduZWQpIGRlZ3JlZXMgKi9cbmlmICh0eXBlb2YgTnVtYmVyLnByb3RvdHlwZS50b0RlZ3JlZXMgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgTnVtYmVyLnByb3RvdHlwZS50b0RlZ3JlZXMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcyAqIDE4MCAvIE1hdGguUEk7XG4gIH07XG59XG5cbnZhciBJTlRFUlNFQ1RfTE5HID0gMTc5Ljk5OTsgLy8gTG5nIHVzZWQgZm9yIGludGVyc2VjdGlvbiBhbmQgd3JhcCBhcm91bmQgb24gbWFwIGVkZ2VzXG5cbkwuR2VvZGVzaWMgPSBMLlBvbHlsaW5lLmV4dGVuZCh7XG4gIG9wdGlvbnM6IHtcbiAgICBjb2xvcjogXCJibHVlXCIsXG4gICAgc3RlcHM6IDEwLFxuICAgIGRhc2g6IDEsXG4gICAgd3JhcDogdHJ1ZVxuICB9LFxuXG4gIGluaXRpYWxpemU6IGZ1bmN0aW9uKGxhdGxuZ3MsIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSB0aGlzLl9tZXJnZV9vcHRpb25zKHRoaXMub3B0aW9ucywgb3B0aW9ucyk7XG4gICAgdGhpcy5vcHRpb25zLmRhc2ggPSBNYXRoLm1heCgxZS0zLCBNYXRoLm1pbigxLCBwYXJzZUZsb2F0KHRoaXMub3B0aW9ucy5kYXNoKSB8fCAxKSk7XG4gICAgdGhpcy5kYXR1bSA9IHt9O1xuICAgIHRoaXMuZGF0dW0uZWxsaXBzb2lkID0ge1xuICAgICAgICBhOiA2Mzc4MTM3LFxuICAgICAgICBiOiA2MzU2NzUyLjMxNDIsXG4gICAgICAgIGY6IDEgLyAyOTguMjU3MjIzNTYzXG4gICAgICB9OyAvLyBXR1MtODRcbiAgICB0aGlzLl9sYXRsbmdzID0gdGhpcy5fZ2VuZXJhdGVfR2VvZGVzaWMobGF0bG5ncyk7XG4gICAgTC5Qb2x5bGluZS5wcm90b3R5cGUuaW5pdGlhbGl6ZS5jYWxsKHRoaXMsIHRoaXMuX2xhdGxuZ3MsIHRoaXMub3B0aW9ucyk7XG4gIH0sXG5cbiAgc2V0TGF0TG5nczogZnVuY3Rpb24obGF0bG5ncykge1xuICAgIHRoaXMuX2xhdGxuZ3MgPSB0aGlzLl9nZW5lcmF0ZV9HZW9kZXNpYyhsYXRsbmdzKTtcbiAgICBMLlBvbHlsaW5lLnByb3RvdHlwZS5zZXRMYXRMbmdzLmNhbGwodGhpcywgdGhpcy5fbGF0bG5ncyk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgc29tZSBzdGF0aXN0aWMgdmFsdWVzIG9mIGN1cnJlbnQgZ2VvZGVzaWMgbXVsdGlwb2x5bGluZVxuICAgKiBAcmV0dXJucyAoT2JqZWN0fSBPYmplY3Qgd2l0aCBzZXZlcmFsIHByb3BlcnRpZXMgKGUuZy4gb3ZlcmFsbCBkaXN0YW5jZSlcbiAgICovXG4gIGdldFN0YXRzOiBmdW5jdGlvbigpIHtcbiAgICBsZXQgb2JqID0ge1xuICAgICAgICBkaXN0YW5jZTogMCxcbiAgICAgICAgcG9pbnRzOiAwLFxuICAgICAgICBwb2x5Z29uczogdGhpcy5fbGF0bG5ncy5sZW5ndGhcbiAgICAgIH0sIHBvbHksIHBvaW50cztcblxuICAgIGZvciAocG9seSA9IDA7IHBvbHkgPCB0aGlzLl9sYXRsbmdzLmxlbmd0aDsgcG9seSsrKSB7XG4gICAgICBvYmoucG9pbnRzICs9IHRoaXMuX2xhdGxuZ3NbcG9seV0ubGVuZ3RoO1xuICAgICAgZm9yIChwb2ludHMgPSAwOyBwb2ludHMgPCAodGhpcy5fbGF0bG5nc1twb2x5XS5sZW5ndGggLSAxKTsgcG9pbnRzKyspIHtcbiAgICAgICAgb2JqLmRpc3RhbmNlICs9IHRoaXMuX3ZpbmNlbnR5X2ludmVyc2UodGhpcy5fbGF0bG5nc1twb2x5XVtwb2ludHNdLFxuICAgICAgICAgIHRoaXMuX2xhdGxuZ3NbcG9seV1bcG9pbnRzICsgMV0pLmRpc3RhbmNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gb2JqO1xuICB9LFxuXG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgZ2VvZGVzaWMgbGluZXMgZnJvbSBnZW9Kc29uLiBSZXBsYWNlcyBhbGwgY3VycmVudCBmZWF0dXJlcyBvZiB0aGlzIGluc3RhbmNlLlxuICAgKiBTdXBwb3J0cyBMaW5lU3RyaW5nLCBNdWx0aUxpbmVTdHJpbmcgYW5kIFBvbHlnb25cbiAgICogQHBhcmFtIHtPYmplY3R9IGdlb2pzb24gLSBnZW9zam9uIGFzIG9iamVjdC5cbiAgICovXG4gIGdlb0pzb246IGZ1bmN0aW9uKGdlb2pzb24pIHtcblxuICAgIGxldCBub3JtYWxpemVkID0gTC5HZW9KU09OLmFzRmVhdHVyZShnZW9qc29uKTtcbiAgICBsZXQgZmVhdHVyZXMgPSBub3JtYWxpemVkLnR5cGUgPT09IFwiRmVhdHVyZUNvbGxlY3Rpb25cIiA/IG5vcm1hbGl6ZWQuZmVhdHVyZXMgOiBbXG4gICAgICBub3JtYWxpemVkXG4gICAgXTtcbiAgICB0aGlzLl9sYXRsbmdzID0gW107XG4gICAgZm9yIChsZXQgZmVhdHVyZSBvZiBmZWF0dXJlcykge1xuICAgICAgbGV0IGdlb21ldHJ5ID0gZmVhdHVyZS50eXBlID09PSBcIkZlYXR1cmVcIiA/IGZlYXR1cmUuZ2VvbWV0cnkgOlxuICAgICAgICBmZWF0dXJlLFxuICAgICAgICBjb29yZHMgPSBnZW9tZXRyeS5jb29yZGluYXRlcztcblxuICAgICAgc3dpdGNoIChnZW9tZXRyeS50eXBlKSB7XG4gICAgICAgIGNhc2UgXCJMaW5lU3RyaW5nXCI6XG4gICAgICAgICAgdGhpcy5fbGF0bG5ncy5wdXNoKHRoaXMuX2dlbmVyYXRlX0dlb2Rlc2ljKFtMLkdlb0pTT04uY29vcmRzVG9MYXRMbmdzKFxuICAgICAgICAgICAgY29vcmRzLCAwKV0pKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcIk11bHRpTGluZVN0cmluZ1wiOlxuICAgICAgICBjYXNlIFwiUG9seWdvblwiOlxuICAgICAgICAgIHRoaXMuX2xhdGxuZ3MucHVzaCh0aGlzLl9nZW5lcmF0ZV9HZW9kZXNpYyhMLkdlb0pTT04uY29vcmRzVG9MYXRMbmdzKFxuICAgICAgICAgICAgY29vcmRzLCAxKSkpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiUG9pbnRcIjpcbiAgICAgICAgY2FzZSBcIk11bHRpUG9pbnRcIjpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkR1ZGUsIHBvaW50cyBjYW4ndCBiZSBkcmF3biBhcyBnZW9kZXNpYyBsaW5lcy4uLlwiKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkRyYXdpbmcgXCIgKyBnZW9tZXRyeS50eXBlICtcbiAgICAgICAgICAgIFwiIGFzIGEgZ2VvZGVzaWMgaXMgbm90IHN1cHBvcnRlZC4gU2tpcHBpbmcuLi5cIik7XG4gICAgICB9XG4gICAgfVxuICAgIEwuUG9seWxpbmUucHJvdG90eXBlLnNldExhdExuZ3MuY2FsbCh0aGlzLCB0aGlzLl9sYXRsbmdzKTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGdyZWF0IGNpcmNsZS4gUmVwbGFjZXMgYWxsIGN1cnJlbnQgbGluZXMuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBjZW50ZXIgLSBnZW9ncmFwaGljIHBvc2l0aW9uXG4gICAqIEBwYXJhbSB7bnVtYmVyfSByYWRpdXMgLSByYWRpdXMgb2YgdGhlIGNpcmNsZSBpbiBtZXRyZXNcbiAgICovXG4gIGNyZWF0ZUNpcmNsZTogZnVuY3Rpb24oY2VudGVyLCByYWRpdXMpIHtcbiAgICBsZXQgcG9seWxpbmVJbmRleCA9IDA7XG4gICAgbGV0IHByZXYgPSB7XG4gICAgICBsYXQ6IDAsXG4gICAgICBsbmc6IDAsXG4gICAgICBicmc6IDBcbiAgICB9O1xuICAgIGxldCBzdGVwO1xuXG4gICAgdGhpcy5fbGF0bG5ncyA9IFtdO1xuICAgIHRoaXMuX2xhdGxuZ3NbcG9seWxpbmVJbmRleF0gPSBbXTtcblxuICAgIGxldCBkaXJlY3QgPSB0aGlzLl92aW5jZW50eV9kaXJlY3QoTC5sYXRMbmcoY2VudGVyKSwgMCwgcmFkaXVzLCB0aGlzLm9wdGlvbnNcbiAgICAgIC53cmFwKTtcbiAgICBwcmV2ID0gTC5sYXRMbmcoZGlyZWN0LmxhdCwgZGlyZWN0LmxuZyk7XG4gICAgdGhpcy5fbGF0bG5nc1twb2x5bGluZUluZGV4XS5wdXNoKHByZXYpO1xuICAgIGZvciAoc3RlcCA9IDE7IHN0ZXAgPD0gdGhpcy5vcHRpb25zLnN0ZXBzOykge1xuICAgICAgZGlyZWN0ID0gdGhpcy5fdmluY2VudHlfZGlyZWN0KEwubGF0TG5nKGNlbnRlciksIDM2MCAvIHRoaXMub3B0aW9uc1xuICAgICAgICAuc3RlcHMgKiBzdGVwLCByYWRpdXMsIHRoaXMub3B0aW9ucy53cmFwKTtcbiAgICAgIGxldCBncCA9IEwubGF0TG5nKGRpcmVjdC5sYXQsIGRpcmVjdC5sbmcpO1xuICAgICAgaWYgKE1hdGguYWJzKGdwLmxuZyAtIHByZXYubG5nKSA+IDE4MCkge1xuICAgICAgICBsZXQgaW52ZXJzZSA9IHRoaXMuX3ZpbmNlbnR5X2ludmVyc2UocHJldiwgZ3ApO1xuICAgICAgICBsZXQgc2VjID0gdGhpcy5faW50ZXJzZWN0aW9uKHByZXYsIGludmVyc2UuaW5pdGlhbEJlYXJpbmcsIHtcbiAgICAgICAgICBsYXQ6IC04OSxcbiAgICAgICAgICBsbmc6ICgoZ3AubG5nIC0gcHJldi5sbmcpID4gMCkgPyAtSU5URVJTRUNUX0xORyA6IElOVEVSU0VDVF9MTkdcbiAgICAgICAgfSwgMCk7XG4gICAgICAgIGlmIChzZWMpIHtcbiAgICAgICAgICB0aGlzLl9sYXRsbmdzW3BvbHlsaW5lSW5kZXhdLnB1c2goTC5sYXRMbmcoc2VjLmxhdCwgc2VjLmxuZykpO1xuICAgICAgICAgIHBvbHlsaW5lSW5kZXgrKztcbiAgICAgICAgICB0aGlzLl9sYXRsbmdzW3BvbHlsaW5lSW5kZXhdID0gW107XG4gICAgICAgICAgcHJldiA9IEwubGF0TG5nKHNlYy5sYXQsIC1zZWMubG5nKTtcbiAgICAgICAgICB0aGlzLl9sYXRsbmdzW3BvbHlsaW5lSW5kZXhdLnB1c2gocHJldik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcG9seWxpbmVJbmRleCsrO1xuICAgICAgICAgIHRoaXMuX2xhdGxuZ3NbcG9seWxpbmVJbmRleF0gPSBbXTtcbiAgICAgICAgICB0aGlzLl9sYXRsbmdzW3BvbHlsaW5lSW5kZXhdLnB1c2goZ3ApO1xuICAgICAgICAgIHByZXYgPSBncDtcbiAgICAgICAgICBzdGVwKys7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2xhdGxuZ3NbcG9seWxpbmVJbmRleF0ucHVzaChncCk7XG4gICAgICAgIHByZXYgPSBncDtcbiAgICAgICAgc3RlcCsrO1xuICAgICAgfVxuICAgIH1cblxuICAgIEwuUG9seWxpbmUucHJvdG90eXBlLnNldExhdExuZ3MuY2FsbCh0aGlzLCB0aGlzLl9sYXRsbmdzKTtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGdlb2Rlc2ljIFBvbHlsaW5lIGZyb20gZ2l2ZW4gY29vcmRpbmF0ZXNcbiAgICogTm90ZTogZGFzaGVkIGxpbmVzIGFyZSB1bmRlciB3b3JrXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsYXRsbmdzIC0gT25lIG9yIG1vcmUgcG9seWxpbmVzIGFzIGFuIGFycmF5LiBTZWUgTGVhZmxldCBkb2MgYWJvdXQgUG9seWxpbmVcbiAgICogQHJldHVybnMgKE9iamVjdH0gQW4gYXJyYXkgb2YgYXJyYXlzIG9mIGdlb2dyYXBoaWNhbCBwb2ludHMuXG4gICAqL1xuICBfZ2VuZXJhdGVfR2VvZGVzaWM6IGZ1bmN0aW9uKGxhdGxuZ3MpIHtcbiAgICBsZXQgX2dlbyA9IFtdLCBfZ2VvY250ID0gMDtcblxuICAgIGZvciAobGV0IHBvbHkgPSAwOyBwb2x5IDwgbGF0bG5ncy5sZW5ndGg7IHBvbHkrKykge1xuICAgICAgX2dlb1tfZ2VvY250XSA9IFtdO1xuICAgICAgbGV0IHByZXYgPSBMLmxhdExuZyhsYXRsbmdzW3BvbHldWzBdKTtcbiAgICAgIGZvciAobGV0IHBvaW50cyA9IDA7IHBvaW50cyA8IChsYXRsbmdzW3BvbHldLmxlbmd0aCAtIDEpOyBwb2ludHMrKykge1xuICAgICAgICAvLyB1c2UgcHJldiwgc28gdGhhdCB3cmFwcGluZyBiZWhhdmVzIGNvcnJlY3RseVxuICAgICAgICBsZXQgcG9pbnRBID0gcHJldjtcbiAgICAgICAgbGV0IHBvaW50QiA9IEwubGF0TG5nKGxhdGxuZ3NbcG9seV1bcG9pbnRzICsgMV0pO1xuICAgICAgICBpZiAocG9pbnRBLmVxdWFscyhwb2ludEIpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGludmVyc2UgPSB0aGlzLl92aW5jZW50eV9pbnZlcnNlKHBvaW50QSwgcG9pbnRCKTtcbiAgICAgICAgX2dlb1tfZ2VvY250XS5wdXNoKHByZXYpO1xuICAgICAgICBmb3IgKGxldCBzID0gMTsgcyA8PSB0aGlzLm9wdGlvbnMuc3RlcHM7KSB7XG4gICAgICAgICAgbGV0IGRpc3RhbmNlID0gaW52ZXJzZS5kaXN0YW5jZSAvIHRoaXMub3B0aW9ucy5zdGVwcztcbiAgICAgICAgICAvLyBkYXNoZWQgbGluZXMgZG9uJ3QgZ28gdGhlIGZ1bGwgZGlzdGFuY2UgYmV0d2VlbiB0aGUgcG9pbnRzXG4gICAgICAgICAgbGV0IGRpc3RfbXVsdCA9IHMgLSAxICsgdGhpcy5vcHRpb25zLmRhc2g7XG4gICAgICAgICAgbGV0IGRpcmVjdCA9IHRoaXMuX3ZpbmNlbnR5X2RpcmVjdChwb2ludEEsIGludmVyc2UuaW5pdGlhbEJlYXJpbmcsIGRpc3RhbmNlKmRpc3RfbXVsdCwgdGhpcy5vcHRpb25zLndyYXApO1xuICAgICAgICAgIGxldCBncCA9IEwubGF0TG5nKGRpcmVjdC5sYXQsIGRpcmVjdC5sbmcpO1xuICAgICAgICAgIGlmIChNYXRoLmFicyhncC5sbmcgLSBwcmV2LmxuZykgPiAxODApIHtcbiAgICAgICAgICAgIGxldCBzZWMgPSB0aGlzLl9pbnRlcnNlY3Rpb24ocG9pbnRBLCBpbnZlcnNlLmluaXRpYWxCZWFyaW5nLCB7XG4gICAgICAgICAgICAgIGxhdDogLTg5LFxuICAgICAgICAgICAgICBsbmc6ICgoZ3AubG5nIC0gcHJldi5sbmcpID4gMCkgPyAtSU5URVJTRUNUX0xORyA6IElOVEVSU0VDVF9MTkdcbiAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgaWYgKHNlYykge1xuICAgICAgICAgICAgICBfZ2VvW19nZW9jbnRdLnB1c2goTC5sYXRMbmcoc2VjLmxhdCwgc2VjLmxuZykpO1xuICAgICAgICAgICAgICBfZ2VvY250Kys7XG4gICAgICAgICAgICAgIF9nZW9bX2dlb2NudF0gPSBbXTtcbiAgICAgICAgICAgICAgcHJldiA9IEwubGF0TG5nKHNlYy5sYXQsIC1zZWMubG5nKTtcbiAgICAgICAgICAgICAgX2dlb1tfZ2VvY250XS5wdXNoKHByZXYpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgX2dlb2NudCsrO1xuICAgICAgICAgICAgICBfZ2VvW19nZW9jbnRdID0gW107XG4gICAgICAgICAgICAgIF9nZW9bX2dlb2NudF0ucHVzaChncCk7XG4gICAgICAgICAgICAgIHByZXYgPSBncDtcbiAgICAgICAgICAgICAgcysrO1xuICAgICAgICAgICAgfSAgXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIF9nZW9bX2dlb2NudF0ucHVzaChncCk7XG4gICAgICAgICAgICAvLyBEYXNoZWQgbGluZXMgc3RhcnQgYSBuZXcgbGluZVxuICAgICAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5kYXNoIDwgMSl7XG4gICAgICAgICAgICAgICAgX2dlb2NudCsrO1xuICAgICAgICAgICAgICAgIC8vIGdvIGZ1bGwgZGlzdGFuY2UgdGhpcyB0aW1lLCB0byBnZXQgc3RhcnRpbmcgcG9pbnQgZm9yIG5leHQgbGluZVxuICAgICAgICAgICAgICAgIGxldCBkaXJlY3RfZnVsbCA9IHRoaXMuX3ZpbmNlbnR5X2RpcmVjdChwb2ludEEsIGludmVyc2UuaW5pdGlhbEJlYXJpbmcsIGRpc3RhbmNlKnMsIHRoaXMub3B0aW9ucy53cmFwKTtcbiAgICAgICAgICAgICAgICBfZ2VvW19nZW9jbnRdID0gW107XG4gICAgICAgICAgICAgICAgcHJldiA9IEwubGF0TG5nKGRpcmVjdF9mdWxsLmxhdCwgZGlyZWN0X2Z1bGwubG5nKTtcbiAgICAgICAgICAgICAgICBfZ2VvW19nZW9jbnRdLnB1c2gocHJldik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHByZXYgPSBncDtcbiAgICAgICAgICAgIHMrKztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIF9nZW9jbnQrKztcbiAgICB9XG4gICAgcmV0dXJuIF9nZW87XG4gIH0sXG5cbiAgLyoqXG4gICAqIFZpbmNlbnR5IGRpcmVjdCBjYWxjdWxhdGlvbi5cbiAgICogYmFzZWQgb24gdGhlIHdvcmsgb2YgQ2hyaXMgVmVuZXNzIChodHRwczovL2dpdGh1Yi5jb20vY2hyaXN2ZW5lc3MvZ2VvZGVzeSlcbiAgICpcbiAgICogQHByaXZhdGVcbiAgICogQHBhcmFtIHtudW1iZXJ9IGluaXRpYWxCZWFyaW5nIC0gSW5pdGlhbCBiZWFyaW5nIGluIGRlZ3JlZXMgZnJvbSBub3J0aC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGRpc3RhbmNlIC0gRGlzdGFuY2UgYWxvbmcgYmVhcmluZyBpbiBtZXRyZXMuXG4gICAqIEByZXR1cm5zIChPYmplY3R9IE9iamVjdCBpbmNsdWRpbmcgcG9pbnQgKGRlc3RpbmF0aW9uIHBvaW50KSwgZmluYWxCZWFyaW5nLlxuICAgKi9cblxuICBfdmluY2VudHlfZGlyZWN0OiBmdW5jdGlvbihwMSwgaW5pdGlhbEJlYXJpbmcsIGRpc3RhbmNlLCB3cmFwKSB7XG4gICAgdmFyIM+GMSA9IHAxLmxhdC50b1JhZGlhbnMoKSxcbiAgICAgIM67MSA9IHAxLmxuZy50b1JhZGlhbnMoKTtcbiAgICB2YXIgzrExID0gaW5pdGlhbEJlYXJpbmcudG9SYWRpYW5zKCk7XG4gICAgdmFyIHMgPSBkaXN0YW5jZTtcblxuICAgIHZhciBhID0gdGhpcy5kYXR1bS5lbGxpcHNvaWQuYSxcbiAgICAgIGIgPSB0aGlzLmRhdHVtLmVsbGlwc29pZC5iLFxuICAgICAgZiA9IHRoaXMuZGF0dW0uZWxsaXBzb2lkLmY7XG5cbiAgICB2YXIgc2luzrExID0gTWF0aC5zaW4ozrExKTtcbiAgICB2YXIgY29zzrExID0gTWF0aC5jb3MozrExKTtcblxuICAgIHZhciB0YW5VMSA9ICgxIC0gZikgKiBNYXRoLnRhbijPhjEpLFxuICAgICAgY29zVTEgPSAxIC8gTWF0aC5zcXJ0KCgxICsgdGFuVTEgKiB0YW5VMSkpLFxuICAgICAgc2luVTEgPSB0YW5VMSAqIGNvc1UxO1xuICAgIHZhciDPgzEgPSBNYXRoLmF0YW4yKHRhblUxLCBjb3POsTEpO1xuICAgIHZhciBzaW7OsSA9IGNvc1UxICogc2luzrExO1xuICAgIHZhciBjb3NTcc6xID0gMSAtIHNpbs6xICogc2luzrE7XG4gICAgdmFyIHVTcSA9IGNvc1NxzrEgKiAoYSAqIGEgLSBiICogYikgLyAoYiAqIGIpO1xuICAgIHZhciBBID0gMSArIHVTcSAvIDE2Mzg0ICogKDQwOTYgKyB1U3EgKiAoLTc2OCArIHVTcSAqICgzMjAgLSAxNzUgKlxuICAgICAgdVNxKSkpO1xuICAgIHZhciBCID0gdVNxIC8gMTAyNCAqICgyNTYgKyB1U3EgKiAoLTEyOCArIHVTcSAqICg3NCAtIDQ3ICogdVNxKSkpO1xuXG4gICAgdmFyIM+DID0gcyAvIChiICogQSksXG4gICAgICDPg8q5LCBpdGVyYXRpb25zID0gMDtcbiAgICB2YXIgc2luz4MsIGNvc8+DO1xuICAgIHZhciBjb3Myz4NNO1xuICAgIGRvIHtcbiAgICAgIGNvczLPg00gPSBNYXRoLmNvcygyICogz4MxICsgz4MpO1xuICAgICAgc2luz4MgPSBNYXRoLnNpbijPgyk7XG4gICAgICBjb3PPgyA9IE1hdGguY29zKM+DKTtcbiAgICAgIHZhciDOlM+DID0gQiAqIHNpbs+DICogKGNvczLPg00gKyBCIC8gNCAqIChjb3PPgyAqICgtMSArIDIgKiBjb3Myz4NNICpcbiAgICAgICAgICBjb3Myz4NNKSAtXG4gICAgICAgIEIgLyA2ICogY29zMs+DTSAqICgtMyArIDQgKiBzaW7PgyAqIHNpbs+DKSAqICgtMyArIDQgKiBjb3Myz4NNICpcbiAgICAgICAgICBjb3Myz4NNKSkpO1xuICAgICAgz4PKuSA9IM+DO1xuICAgICAgz4MgPSBzIC8gKGIgKiBBKSArIM6Uz4M7XG4gICAgfSB3aGlsZSAoTWF0aC5hYnMoz4MgLSDPg8q5KSA+IDFlLTEyICYmICsraXRlcmF0aW9ucyk7XG5cbiAgICB2YXIgeCA9IHNpblUxICogc2luz4MgLSBjb3NVMSAqIGNvc8+DICogY29zzrExO1xuICAgIHZhciDPhjIgPSBNYXRoLmF0YW4yKHNpblUxICogY29zz4MgKyBjb3NVMSAqIHNpbs+DICogY29zzrExLCAoMSAtIGYpICpcbiAgICAgIE1hdGguc3FydChzaW7OsSAqIHNpbs6xICsgeCAqIHgpKTtcbiAgICB2YXIgzrsgPSBNYXRoLmF0YW4yKHNpbs+DICogc2luzrExLCBjb3NVMSAqIGNvc8+DIC0gc2luVTEgKiBzaW7PgyAqIGNvc86xMSk7XG4gICAgdmFyIEMgPSBmIC8gMTYgKiBjb3NTcc6xICogKDQgKyBmICogKDQgLSAzICogY29zU3HOsSkpO1xuICAgIHZhciBMID0gzrsgLSAoMSAtIEMpICogZiAqIHNpbs6xICpcbiAgICAgICjPgyArIEMgKiBzaW7PgyAqIChjb3Myz4NNICsgQyAqIGNvc8+DICogKC0xICsgMiAqIGNvczLPg00gKiBjb3Myz4NNKSkpO1xuXG4gICAgdmFyIM67MjtcbiAgICBpZiAod3JhcCkge1xuICAgICAgzrsyID0gKM67MSArIEwgKyAzICogTWF0aC5QSSkgJSAoMiAqIE1hdGguUEkpIC0gTWF0aC5QSTsgLy8gbm9ybWFsaXNlIHRvIC0xODAuLi4rMTgwXG4gICAgfSBlbHNlIHtcbiAgICAgIM67MiA9ICjOuzEgKyBMKTsgLy8gZG8gbm90IG5vcm1hbGl6ZVxuICAgIH1cblxuICAgIHZhciByZXZBeiA9IE1hdGguYXRhbjIoc2luzrEsIC14KTtcblxuICAgIHJldHVybiB7XG4gICAgICBsYXQ6IM+GMi50b0RlZ3JlZXMoKSxcbiAgICAgIGxuZzogzrsyLnRvRGVncmVlcygpLFxuICAgICAgZmluYWxCZWFyaW5nOiByZXZBei50b0RlZ3JlZXMoKVxuICAgIH07XG4gIH0sXG5cbiAgLyoqXG4gICAqIFZpbmNlbnR5IGludmVyc2UgY2FsY3VsYXRpb24uXG4gICAqIGJhc2VkIG9uIHRoZSB3b3JrIG9mIENocmlzIFZlbmVzcyAoaHR0cHM6Ly9naXRodWIuY29tL2NocmlzdmVuZXNzL2dlb2Rlc3kpXG4gICAqXG4gICAqIEBwcml2YXRlXG4gICAqIEBwYXJhbSB7TGF0TG5nfSBwMSAtIExhdGl0dWRlL2xvbmdpdHVkZSBvZiBzdGFydCBwb2ludC5cbiAgICogQHBhcmFtIHtMYXRMbmd9IHAyIC0gTGF0aXR1ZGUvbG9uZ2l0dWRlIG9mIGRlc3RpbmF0aW9uIHBvaW50LlxuICAgKiBAcmV0dXJucyB7T2JqZWN0fSBPYmplY3QgaW5jbHVkaW5nIGRpc3RhbmNlLCBpbml0aWFsQmVhcmluZywgZmluYWxCZWFyaW5nLlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgZm9ybXVsYSBmYWlsZWQgdG8gY29udmVyZ2UuXG4gICAqL1xuICBfdmluY2VudHlfaW52ZXJzZTogZnVuY3Rpb24ocDEsIHAyKSB7XG4gICAgdmFyIM+GMSA9IHAxLmxhdC50b1JhZGlhbnMoKSxcbiAgICAgIM67MSA9IHAxLmxuZy50b1JhZGlhbnMoKTtcbiAgICB2YXIgz4YyID0gcDIubGF0LnRvUmFkaWFucygpLFxuICAgICAgzrsyID0gcDIubG5nLnRvUmFkaWFucygpO1xuXG4gICAgdmFyIGEgPSB0aGlzLmRhdHVtLmVsbGlwc29pZC5hLFxuICAgICAgYiA9IHRoaXMuZGF0dW0uZWxsaXBzb2lkLmIsXG4gICAgICBmID0gdGhpcy5kYXR1bS5lbGxpcHNvaWQuZjtcblxuICAgIHZhciBMID0gzrsyIC0gzrsxO1xuICAgIHZhciB0YW5VMSA9ICgxIC0gZikgKiBNYXRoLnRhbijPhjEpLFxuICAgICAgY29zVTEgPSAxIC8gTWF0aC5zcXJ0KCgxICsgdGFuVTEgKiB0YW5VMSkpLFxuICAgICAgc2luVTEgPSB0YW5VMSAqIGNvc1UxO1xuICAgIHZhciB0YW5VMiA9ICgxIC0gZikgKiBNYXRoLnRhbijPhjIpLFxuICAgICAgY29zVTIgPSAxIC8gTWF0aC5zcXJ0KCgxICsgdGFuVTIgKiB0YW5VMikpLFxuICAgICAgc2luVTIgPSB0YW5VMiAqIGNvc1UyO1xuXG4gICAgdmFyIM67ID0gTCxcbiAgICAgIM67yrksIGl0ZXJhdGlvbnMgPSAwO1xuICAgIHZhciBjb3NTcc6xLCBzaW7PgywgY29zMs+DTSwgY29zz4MsIM+DLCBzaW7OuywgY29zzrs7XG4gICAgZG8ge1xuICAgICAgc2luzrsgPSBNYXRoLnNpbijOuyk7XG4gICAgICBjb3POuyA9IE1hdGguY29zKM67KTtcbiAgICAgIHZhciBzaW5Tcc+DID0gKGNvc1UyICogc2luzrspICogKGNvc1UyICogc2luzrspICsgKGNvc1UxICogc2luVTIgLVxuICAgICAgICBzaW5VMSAqIGNvc1UyICogY29zzrspICogKGNvc1UxICogc2luVTIgLSBzaW5VMSAqIGNvc1UyICogY29zzrspO1xuICAgICAgc2luz4MgPSBNYXRoLnNxcnQoc2luU3HPgyk7XG4gICAgICBpZiAoc2luz4MgPT0gMCkgcmV0dXJuIDA7IC8vIGNvLWluY2lkZW50IHBvaW50c1xuICAgICAgY29zz4MgPSBzaW5VMSAqIHNpblUyICsgY29zVTEgKiBjb3NVMiAqIGNvc867O1xuICAgICAgz4MgPSBNYXRoLmF0YW4yKHNpbs+DLCBjb3PPgyk7XG4gICAgICB2YXIgc2luzrEgPSBjb3NVMSAqIGNvc1UyICogc2luzrsgLyBzaW7PgztcbiAgICAgIGNvc1NxzrEgPSAxIC0gc2luzrEgKiBzaW7OsTtcbiAgICAgIGNvczLPg00gPSBjb3PPgyAtIDIgKiBzaW5VMSAqIHNpblUyIC8gY29zU3HOsTtcbiAgICAgIGlmIChpc05hTihjb3Myz4NNKSkgY29zMs+DTSA9IDA7IC8vIGVxdWF0b3JpYWwgbGluZTogY29zU3HOsT0wICjCpzYpXG4gICAgICB2YXIgQyA9IGYgLyAxNiAqIGNvc1NxzrEgKiAoNCArIGYgKiAoNCAtIDMgKiBjb3NTcc6xKSk7XG4gICAgICDOu8q5ID0gzrs7XG4gICAgICDOuyA9IEwgKyAoMSAtIEMpICogZiAqIHNpbs6xICogKM+DICsgQyAqIHNpbs+DICogKGNvczLPg00gKyBDICogY29zz4MgKiAoLVxuICAgICAgICAxICsgMiAqIGNvczLPg00gKiBjb3Myz4NNKSkpO1xuICAgIH0gd2hpbGUgKE1hdGguYWJzKM67IC0gzrvKuSkgPiAxZS0xMiAmJiArK2l0ZXJhdGlvbnMgPCAxMDApO1xuICAgIGlmIChpdGVyYXRpb25zID49IDEwMCkge1xuICAgICAgY29uc29sZS5sb2coXCJGb3JtdWxhIGZhaWxlZCB0byBjb252ZXJnZS4gQWx0ZXJpbmcgdGFyZ2V0IHBvc2l0aW9uLlwiKTtcbiAgICAgIHJldHVybiB0aGlzLl92aW5jZW50eV9pbnZlcnNlKHAxLCB7XG4gICAgICAgICAgbGF0OiBwMi5sYXQsXG4gICAgICAgICAgbG5nOiBwMi5sbmcgLSAwLjAxXG4gICAgICAgIH0pO1xuICAgICAgICAvLyAgdGhyb3cgbmV3IEVycm9yKCdGb3JtdWxhIGZhaWxlZCB0byBjb252ZXJnZScpO1xuICAgIH1cblxuICAgIHZhciB1U3EgPSBjb3NTcc6xICogKGEgKiBhIC0gYiAqIGIpIC8gKGIgKiBiKTtcbiAgICB2YXIgQSA9IDEgKyB1U3EgLyAxNjM4NCAqICg0MDk2ICsgdVNxICogKC03NjggKyB1U3EgKiAoMzIwIC0gMTc1ICpcbiAgICAgIHVTcSkpKTtcbiAgICB2YXIgQiA9IHVTcSAvIDEwMjQgKiAoMjU2ICsgdVNxICogKC0xMjggKyB1U3EgKiAoNzQgLSA0NyAqIHVTcSkpKTtcbiAgICB2YXIgzpTPgyA9IEIgKiBzaW7PgyAqIChjb3Myz4NNICsgQiAvIDQgKiAoY29zz4MgKiAoLTEgKyAyICogY29zMs+DTSAqXG4gICAgICAgIGNvczLPg00pIC1cbiAgICAgIEIgLyA2ICogY29zMs+DTSAqICgtMyArIDQgKiBzaW7PgyAqIHNpbs+DKSAqICgtMyArIDQgKiBjb3Myz4NNICpcbiAgICAgICAgY29zMs+DTSkpKTtcblxuICAgIHZhciBzID0gYiAqIEEgKiAoz4MgLSDOlM+DKTtcblxuICAgIHZhciBmd2RBeiA9IE1hdGguYXRhbjIoY29zVTIgKiBzaW7OuywgY29zVTEgKiBzaW5VMiAtIHNpblUxICogY29zVTIgKlxuICAgICAgY29zzrspO1xuICAgIHZhciByZXZBeiA9IE1hdGguYXRhbjIoY29zVTEgKiBzaW7OuywgLXNpblUxICogY29zVTIgKyBjb3NVMSAqIHNpblUyICpcbiAgICAgIGNvc867KTtcblxuICAgIHMgPSBOdW1iZXIocy50b0ZpeGVkKDMpKTsgLy8gcm91bmQgdG8gMW1tIHByZWNpc2lvblxuICAgIHJldHVybiB7XG4gICAgICBkaXN0YW5jZTogcyxcbiAgICAgIGluaXRpYWxCZWFyaW5nOiBmd2RBei50b0RlZ3JlZXMoKSxcbiAgICAgIGZpbmFsQmVhcmluZzogcmV2QXoudG9EZWdyZWVzKClcbiAgICB9O1xuICB9LFxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHBvaW50IG9mIGludGVyc2VjdGlvbiBvZiB0d28gcGF0aHMgZGVmaW5lZCBieSBwb2ludCBhbmQgYmVhcmluZy5cbiAgICogYmFzZWQgb24gdGhlIHdvcmsgb2YgQ2hyaXMgVmVuZXNzIChodHRwczovL2dpdGh1Yi5jb20vY2hyaXN2ZW5lc3MvZ2VvZGVzeSlcbiAgICpcbiAgICogQHBhcmFtIHtMYXRMb259IHAxIC0gRmlyc3QgcG9pbnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBicm5nMSAtIEluaXRpYWwgYmVhcmluZyBmcm9tIGZpcnN0IHBvaW50LlxuICAgKiBAcGFyYW0ge0xhdExvbn0gcDIgLSBTZWNvbmQgcG9pbnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBicm5nMiAtIEluaXRpYWwgYmVhcmluZyBmcm9tIHNlY29uZCBwb2ludC5cbiAgICogQHJldHVybnMge09iamVjdH0gY29udGFpbmluZyBsYXQvbG5nIGluZm9ybWF0aW9uIG9mIGludGVyc2VjdGlvbi5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogdmFyIHAxID0gTGF0TG9uKDUxLjg4NTMsIDAuMjU0NSksIGJybmcxID0gMTA4LjU1O1xuICAgKiB2YXIgcDIgPSBMYXRMb24oNDkuMDAzNCwgMi41NzM1KSwgYnJuZzIgPSAzMi40NDtcbiAgICogdmFyIHBJbnQgPSBMYXRMb24uaW50ZXJzZWN0aW9uKHAxLCBicm5nMSwgcDIsIGJybmcyKTsgLy8gcEludC50b1N0cmluZygpOiA1MC45MDc4wrBOLCA0LjUwODTCsEVcbiAgICovXG4gIF9pbnRlcnNlY3Rpb246IGZ1bmN0aW9uKHAxLCBicm5nMSwgcDIsIGJybmcyKSB7XG4gICAgLy8gc2VlIGh0dHA6Ly93aWxsaWFtcy5iZXN0LnZ3aC5uZXQvYXZmb3JtLmh0bSNJbnRlcnNlY3Rpb25cblxuICAgIHZhciDPhjEgPSBwMS5sYXQudG9SYWRpYW5zKCksXG4gICAgICDOuzEgPSBwMS5sbmcudG9SYWRpYW5zKCk7XG4gICAgdmFyIM+GMiA9IHAyLmxhdC50b1JhZGlhbnMoKSxcbiAgICAgIM67MiA9IHAyLmxuZy50b1JhZGlhbnMoKTtcbiAgICB2YXIgzrgxMyA9IE51bWJlcihicm5nMSkudG9SYWRpYW5zKCksXG4gICAgICDOuDIzID0gTnVtYmVyKGJybmcyKS50b1JhZGlhbnMoKTtcbiAgICB2YXIgzpTPhiA9IM+GMiAtIM+GMSxcbiAgICAgIM6UzrsgPSDOuzIgLSDOuzE7XG5cbiAgICB2YXIgzrQxMiA9IDIgKiBNYXRoLmFzaW4oTWF0aC5zcXJ0KE1hdGguc2luKM6Uz4YgLyAyKSAqIE1hdGguc2luKM6Uz4YgLyAyKSArXG4gICAgICBNYXRoLmNvcyjPhjEpICogTWF0aC5jb3Moz4YyKSAqIE1hdGguc2luKM6UzrsgLyAyKSAqIE1hdGguc2luKM6UzrsgL1xuICAgICAgICAyKSkpO1xuICAgIGlmICjOtDEyID09IDApIHJldHVybiBudWxsO1xuXG4gICAgLy8gaW5pdGlhbC9maW5hbCBiZWFyaW5ncyBiZXR3ZWVuIHBvaW50c1xuICAgIHZhciDOuDEgPSBNYXRoLmFjb3MoKE1hdGguc2luKM+GMikgLSBNYXRoLnNpbijPhjEpICogTWF0aC5jb3MozrQxMikpIC9cbiAgICAgIChNYXRoLnNpbijOtDEyKSAqIE1hdGguY29zKM+GMSkpKTtcbiAgICBpZiAoaXNOYU4ozrgxKSkgzrgxID0gMDsgLy8gcHJvdGVjdCBhZ2FpbnN0IHJvdW5kaW5nXG4gICAgdmFyIM64MiA9IE1hdGguYWNvcygoTWF0aC5zaW4oz4YxKSAtIE1hdGguc2luKM+GMikgKiBNYXRoLmNvcyjOtDEyKSkgL1xuICAgICAgKE1hdGguc2luKM60MTIpICogTWF0aC5jb3Moz4YyKSkpO1xuICAgIHZhciDOuDEyLCDOuDIxO1xuICAgIGlmIChNYXRoLnNpbijOuzIgLSDOuzEpID4gMCkge1xuICAgICAgzrgxMiA9IM64MTtcbiAgICAgIM64MjEgPSAyICogTWF0aC5QSSAtIM64MjtcbiAgICB9IGVsc2Uge1xuICAgICAgzrgxMiA9IDIgKiBNYXRoLlBJIC0gzrgxO1xuICAgICAgzrgyMSA9IM64MjtcbiAgICB9XG5cbiAgICB2YXIgzrExID0gKM64MTMgLSDOuDEyICsgTWF0aC5QSSkgJSAoMiAqIE1hdGguUEkpIC0gTWF0aC5QSTsgLy8gYW5nbGUgMi0xLTNcbiAgICB2YXIgzrEyID0gKM64MjEgLSDOuDIzICsgTWF0aC5QSSkgJSAoMiAqIE1hdGguUEkpIC0gTWF0aC5QSTsgLy8gYW5nbGUgMS0yLTNcblxuICAgIGlmIChNYXRoLnNpbijOsTEpID09IDAgJiYgTWF0aC5zaW4ozrEyKSA9PSAwKSByZXR1cm4gbnVsbDsgLy8gaW5maW5pdGUgaW50ZXJzZWN0aW9uc1xuICAgIGlmIChNYXRoLnNpbijOsTEpICogTWF0aC5zaW4ozrEyKSA8IDApIHJldHVybiBudWxsOyAvLyBhbWJpZ3VvdXMgaW50ZXJzZWN0aW9uXG5cbiAgICAvL86xMSA9IE1hdGguYWJzKM6xMSk7XG4gICAgLy/OsTIgPSBNYXRoLmFicyjOsTIpO1xuICAgIC8vIC4uLiBFZCBXaWxsaWFtcyB0YWtlcyBhYnMgb2YgzrExL86xMiwgYnV0IHNlZW1zIHRvIGJyZWFrIGNhbGN1bGF0aW9uP1xuXG4gICAgdmFyIM6xMyA9IE1hdGguYWNvcygtTWF0aC5jb3MozrExKSAqIE1hdGguY29zKM6xMikgK1xuICAgICAgTWF0aC5zaW4ozrExKSAqIE1hdGguc2luKM6xMikgKiBNYXRoLmNvcyjOtDEyKSk7XG4gICAgdmFyIM60MTMgPSBNYXRoLmF0YW4yKE1hdGguc2luKM60MTIpICogTWF0aC5zaW4ozrExKSAqIE1hdGguc2luKM6xMiksXG4gICAgICBNYXRoLmNvcyjOsTIpICsgTWF0aC5jb3MozrExKSAqIE1hdGguY29zKM6xMykpO1xuICAgIHZhciDPhjMgPSBNYXRoLmFzaW4oTWF0aC5zaW4oz4YxKSAqIE1hdGguY29zKM60MTMpICtcbiAgICAgIE1hdGguY29zKM+GMSkgKiBNYXRoLnNpbijOtDEzKSAqIE1hdGguY29zKM64MTMpKTtcbiAgICB2YXIgzpTOuzEzID0gTWF0aC5hdGFuMihNYXRoLnNpbijOuDEzKSAqIE1hdGguc2luKM60MTMpICogTWF0aC5jb3Moz4YxKSxcbiAgICAgIE1hdGguY29zKM60MTMpIC0gTWF0aC5zaW4oz4YxKSAqIE1hdGguc2luKM+GMykpO1xuICAgIHZhciDOuzMgPSDOuzEgKyDOlM67MTM7XG4gICAgzrszID0gKM67MyArIDMgKiBNYXRoLlBJKSAlICgyICogTWF0aC5QSSkgLSBNYXRoLlBJOyAvLyBub3JtYWxpc2UgdG8gLTE4MC4uKzE4MMK6XG5cbiAgICByZXR1cm4ge1xuICAgICAgbGF0OiDPhjMudG9EZWdyZWVzKCksXG4gICAgICBsbmc6IM67My50b0RlZ3JlZXMoKVxuICAgIH07XG4gIH0sXG5cbiAgLyoqXG4gICAqIE92ZXJ3cml0ZXMgb2JqMSdzIHZhbHVlcyB3aXRoIG9iajIncyBhbmQgYWRkcyBvYmoyJ3MgaWYgbm9uIGV4aXN0ZW50IGluIG9iajFcbiAgICogQHBhcmFtIG9iajFcbiAgICogQHBhcmFtIG9iajJcbiAgICogQHJldHVybnMgb2JqMyBhIG5ldyBvYmplY3QgYmFzZWQgb24gb2JqMSBhbmQgb2JqMlxuICAgKi9cbiAgX21lcmdlX29wdGlvbnM6IGZ1bmN0aW9uKG9iajEsIG9iajIpIHtcbiAgICBsZXQgb2JqMyA9IHt9O1xuICAgIGZvciAobGV0IGF0dHJuYW1lIGluIG9iajEpIHtcbiAgICAgIG9iajNbYXR0cm5hbWVdID0gb2JqMVthdHRybmFtZV07XG4gICAgfVxuICAgIGZvciAobGV0IGF0dHJuYW1lIGluIG9iajIpIHtcbiAgICAgIG9iajNbYXR0cm5hbWVdID0gb2JqMlthdHRybmFtZV07XG4gICAgfVxuICAgIHJldHVybiBvYmozO1xuICB9XG59KTtcblxuTC5nZW9kZXNpYyA9IGZ1bmN0aW9uKGxhdGxuZ3MsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIG5ldyBMLkdlb2Rlc2ljKGxhdGxuZ3MsIG9wdGlvbnMpO1xufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL0xlYWZsZXQuR2VvZGVzaWMvTGVhZmxldC5HZW9kZXNpYy5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvTGVhZmxldC5HZW9kZXNpYy9MZWFmbGV0Lkdlb2Rlc2ljLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/Leaflet.Geodesic/Leaflet.Geodesic.js\n");
/***/ }),
/***/ "./node_modules/axios/index.js":
/***/ (function(module, exports, __webpack_require__) {
eval("module.exports = __webpack_require__(\"./node_modules/axios/lib/axios.js\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvaW5kZXguanM/OWFkNSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxpQkFBaUIsbUJBQU8sQ0FBQyxtQ0FBYSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9pbmRleC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9saWIvYXhpb3MnKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9pbmRleC5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvaW5kZXguanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/axios/index.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/adapters/xhr.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\nvar settle = __webpack_require__(\"./node_modules/axios/lib/core/settle.js\");\nvar buildURL = __webpack_require__(\"./node_modules/axios/lib/helpers/buildURL.js\");\nvar parseHeaders = __webpack_require__(\"./node_modules/axios/lib/helpers/parseHeaders.js\");\nvar isURLSameOrigin = __webpack_require__(\"./node_modules/axios/lib/helpers/isURLSameOrigin.js\");\nvar createError = __webpack_require__(\"./node_modules/axios/lib/core/createError.js\");\n\nmodule.exports = function xhrAdapter(config) {\n return new Promise(function dispatchXhrRequest(resolve, reject) {\n var requestData = config.data;\n var requestHeaders = config.headers;\n\n if (utils.isFormData(requestData)) {\n delete requestHeaders['Content-Type']; // Let the browser set it\n }\n\n var request = new XMLHttpRequest();\n\n // HTTP basic authentication\n if (config.auth) {\n var username = config.auth.username || '';\n var password = config.auth.password || '';\n requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);\n }\n\n request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true);\n\n // Set the request timeout in MS\n request.timeout = config.timeout;\n\n // Listen for ready state\n request.onreadystatechange = function handleLoad() {\n if (!request || request.readyState !== 4) {\n return;\n }\n\n // The request errored out and we didn't get a response, this will be\n // handled by onerror instead\n // With one exception: request that using file: protocol, most browsers\n // will return status as 0 even though it's a successful request\n if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {\n return;\n }\n\n // Prepare the response\n var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;\n var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;\n var response = {\n data: responseData,\n status: request.status,\n statusText: request.statusText,\n headers: responseHeaders,\n config: config,\n request: request\n };\n\n settle(resolve, reject, response);\n\n // Clean up request\n request = null;\n };\n\n // Handle low level network errors\n request.onerror = function handleError() {\n // Real errors are hidden from us by the browser\n // onerror should only fire if it's a network error\n reject(createError('Network Error', config, null, request));\n\n // Clean up request\n request = null;\n };\n\n // Handle timeout\n request.ontimeout = function handleTimeout() {\n reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED',\n request));\n\n // Clean up request\n request = null;\n };\n\n // Add xsrf header\n // This is only done if running in a standard browser environment.\n // Specifically not if we're in a web worker, or react-native.\n if (utils.isStandardBrowserEnv()) {\n var cookies = __webpack_require__(\"./node_modules/axios/lib/helpers/cookies.js\");\n\n // Add xsrf header\n var xsrfValue = (config.withCredentials || isURLSameOrigin(config.url)) && config.xsrfCookieName ?\n cookies.read(config.xsrfCookieName) :\n undefined;\n\n if (xsrfValue) {\n requestHeaders[config.xsrfHeaderName] = xsrfValue;\n }\n }\n\n // Add headers to the request\n if ('setRequestHeader' in request) {\n utils.forEach(requestHeaders, function setRequestHeader(val, key) {\n if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {\n // Remove Content-Type if data is undefined\n delete requestHeaders[key];\n } else {\n // Otherwise add header to the request\n request.setRequestHeader(key, val);\n }\n });\n }\n\n // Add withCredentials to request if needed\n if (config.withCredentials) {\n request.withCredentials = true;\n }\n\n // Add responseType to request if needed\n if (config.responseType) {\n try {\n request.responseType = config.responseType;\n } catch (e) {\n // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2.\n // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function.\n if (config.responseType !== 'json') {\n throw e;\n }\n }\n }\n\n // Handle progress if needed\n if (typeof config.onDownloadProgress === 'function') {\n request.addEventListener('progress', config.onDownloadProgress);\n }\n\n // Not all browsers support upload events\n if (typeof config.onUploadProgress === 'function' && request.upload) {\n request.upload.addEventListener('progress', config.onUploadProgress);\n }\n\n if (config.cancelToken) {\n // Handle cancellation\n config.cancelToken.promise.then(function onCanceled(cancel) {\n if (!request) {\n return;\n }\n\n request.abort();\n reject(cancel);\n // Clean up request\n request = null;\n });\n }\n\n if (requestData === undefined) {\n requestData = null;\n }\n\n // Send the request\n request.send(requestData);\n });\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2FkYXB0ZXJzL3hoci5qcz9lYzZjIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFhOztBQUViLFlBQVksbUJBQU8sQ0FBQyxtQ0FBWTtBQUNoQyxhQUFhLG1CQUFPLENBQUMseUNBQWtCO0FBQ3ZDLGVBQWUsbUJBQU8sQ0FBQyw4Q0FBdUI7QUFDOUMsbUJBQW1CLG1CQUFPLENBQUMsa0RBQTJCO0FBQ3RELHNCQUFzQixtQkFBTyxDQUFDLHFEQUE4QjtBQUM1RCxrQkFBa0IsbUJBQU8sQ0FBQyw4Q0FBcUI7O0FBRS9DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNENBQTRDO0FBQzVDOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLG1CQUFPLENBQUMsNkNBQXNCOztBQUVsRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSCIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvYWRhcHRlcnMveGhyLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLy4uL3V0aWxzJyk7XG52YXIgc2V0dGxlID0gcmVxdWlyZSgnLi8uLi9jb3JlL3NldHRsZScpO1xudmFyIGJ1aWxkVVJMID0gcmVxdWlyZSgnLi8uLi9oZWxwZXJzL2J1aWxkVVJMJyk7XG52YXIgcGFyc2VIZWFkZXJzID0gcmVxdWlyZSgnLi8uLi9oZWxwZXJzL3BhcnNlSGVhZGVycycpO1xudmFyIGlzVVJMU2FtZU9yaWdpbiA9IHJlcXVpcmUoJy4vLi4vaGVscGVycy9pc1VSTFNhbWVPcmlnaW4nKTtcbnZhciBjcmVhdGVFcnJvciA9IHJlcXVpcmUoJy4uL2NvcmUvY3JlYXRlRXJyb3InKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB4aHJBZGFwdGVyKGNvbmZpZykge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gZGlzcGF0Y2hYaHJSZXF1ZXN0KHJlc29sdmUsIHJlamVjdCkge1xuICAgIHZhciByZXF1ZXN0RGF0YSA9IGNvbmZpZy5kYXRhO1xuICAgIHZhciByZXF1ZXN0SGVhZGVycyA9IGNvbmZpZy5oZWFkZXJzO1xuXG4gICAgaWYgKHV0aWxzLmlzRm9ybURhdGEocmVxdWVzdERhdGEpKSB7XG4gICAgICBkZWxldGUgcmVxdWVzdEhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddOyAvLyBMZXQgdGhlIGJyb3dzZXIgc2V0IGl0XG4gICAgfVxuXG4gICAgdmFyIHJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcblxuICAgIC8vIEhUVFAgYmFzaWMgYXV0aGVudGljYXRpb25cbiAgICBpZiAoY29uZmlnLmF1dGgpIHtcbiAgICAgIHZhciB1c2VybmFtZSA9IGNvbmZpZy5hdXRoLnVzZXJuYW1lIHx8ICcnO1xuICAgICAgdmFyIHBhc3N3b3JkID0gY29uZmlnLmF1dGgucGFzc3dvcmQgfHwgJyc7XG4gICAgICByZXF1ZXN0SGVhZGVycy5BdXRob3JpemF0aW9uID0gJ0Jhc2ljICcgKyBidG9hKHVzZXJuYW1lICsgJzonICsgcGFzc3dvcmQpO1xuICAgIH1cblxuICAgIHJlcXVlc3Qub3Blbihjb25maWcubWV0aG9kLnRvVXBwZXJDYXNlKCksIGJ1aWxkVVJMKGNvbmZpZy51cmwsIGNvbmZpZy5wYXJhbXMsIGNvbmZpZy5wYXJhbXNTZXJpYWxpemVyKSwgdHJ1ZSk7XG5cbiAgICAvLyBTZXQgdGhlIHJlcXVlc3QgdGltZW91dCBpbiBNU1xuICAgIHJlcXVlc3QudGltZW91dCA9IGNvbmZpZy50aW1lb3V0O1xuXG4gICAgLy8gTGlzdGVuIGZvciByZWFkeSBzdGF0ZVxuICAgIHJlcXVlc3Qub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24gaGFuZGxlTG9hZCgpIHtcbiAgICAgIGlmICghcmVxdWVzdCB8fCByZXF1ZXN0LnJlYWR5U3RhdGUgIT09IDQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBUaGUgcmVxdWVzdCBlcnJvcmVkIG91dCBhbmQgd2UgZGlkbid0IGdldCBhIHJlc3BvbnNlLCB0aGlzIHdpbGwgYmVcbiAgICAgIC8vIGhhbmRsZWQgYnkgb25lcnJvciBpbnN0ZWFkXG4gICAgICAvLyBXaXRoIG9uZSBleGNlcHRpb246IHJlcXVlc3QgdGhhdCB1c2luZyBmaWxlOiBwcm90b2NvbCwgbW9zdCBicm93c2Vyc1xuICAgICAgLy8gd2lsbCByZXR1cm4gc3RhdHVzIGFzIDAgZXZlbiB0aG91Z2ggaXQncyBhIHN1Y2Nlc3NmdWwgcmVxdWVzdFxuICAgICAgaWYgKHJlcXVlc3Quc3RhdHVzID09PSAwICYmICEocmVxdWVzdC5yZXNwb25zZVVSTCAmJiByZXF1ZXN0LnJlc3BvbnNlVVJMLmluZGV4T2YoJ2ZpbGU6JykgPT09IDApKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gUHJlcGFyZSB0aGUgcmVzcG9uc2VcbiAgICAgIHZhciByZXNwb25zZUhlYWRlcnMgPSAnZ2V0QWxsUmVzcG9uc2VIZWFkZXJzJyBpbiByZXF1ZXN0ID8gcGFyc2VIZWFkZXJzKHJlcXVlc3QuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkpIDogbnVsbDtcbiAgICAgIHZhciByZXNwb25zZURhdGEgPSAhY29uZmlnLnJlc3BvbnNlVHlwZSB8fCBjb25maWcucmVzcG9uc2VUeXBlID09PSAndGV4dCcgPyByZXF1ZXN0LnJlc3BvbnNlVGV4dCA6IHJlcXVlc3QucmVzcG9uc2U7XG4gICAgICB2YXIgcmVzcG9uc2UgPSB7XG4gICAgICAgIGRhdGE6IHJlc3BvbnNlRGF0YSxcbiAgICAgICAgc3RhdHVzOiByZXF1ZXN0LnN0YXR1cyxcbiAgICAgICAgc3RhdHVzVGV4dDogcmVxdWVzdC5zdGF0dXNUZXh0LFxuICAgICAgICBoZWFkZXJzOiByZXNwb25zZUhlYWRlcnMsXG4gICAgICAgIGNvbmZpZzogY29uZmlnLFxuICAgICAgICByZXF1ZXN0OiByZXF1ZXN0XG4gICAgICB9O1xuXG4gICAgICBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCByZXNwb25zZSk7XG5cbiAgICAgIC8vIENsZWFuIHVwIHJlcXVlc3RcbiAgICAgIHJlcXVlc3QgPSBudWxsO1xuICAgIH07XG5cbiAgICAvLyBIYW5kbGUgbG93IGxldmVsIG5ldHdvcmsgZXJyb3JzXG4gICAgcmVxdWVzdC5vbmVycm9yID0gZnVuY3Rpb24gaGFuZGxlRXJyb3IoKSB7XG4gICAgICAvLyBSZWFsIGVycm9ycyBhcmUgaGlkZGVuIGZyb20gdXMgYnkgdGhlIGJyb3dzZXJcbiAgICAgIC8vIG9uZXJyb3Igc2hvdWxkIG9ubHkgZmlyZSBpZiBpdCdzIGEgbmV0d29yayBlcnJvclxuICAgICAgcmVqZWN0KGNyZWF0ZUVycm9yKCdOZXR3b3JrIEVycm9yJywgY29uZmlnLCBudWxsLCByZXF1ZXN0KSk7XG5cbiAgICAgIC8vIENsZWFuIHVwIHJlcXVlc3RcbiAgICAgIHJlcXVlc3QgPSBudWxsO1xuICAgIH07XG5cbiAgICAvLyBIYW5kbGUgdGltZW91dFxuICAgIHJlcXVlc3Qub250aW1lb3V0ID0gZnVuY3Rpb24gaGFuZGxlVGltZW91dCgpIHtcbiAgICAgIHJlamVjdChjcmVhdGVFcnJvcigndGltZW91dCBvZiAnICsgY29uZmlnLnRpbWVvdXQgKyAnbXMgZXhjZWVkZWQnLCBjb25maWcsICdFQ09OTkFCT1JURUQnLFxuICAgICAgICByZXF1ZXN0KSk7XG5cbiAgICAgIC8vIENsZWFuIHVwIHJlcXVlc3RcbiAgICAgIHJlcXVlc3QgPSBudWxsO1xuICAgIH07XG5cbiAgICAvLyBBZGQgeHNyZiBoZWFkZXJcbiAgICAvLyBUaGlzIGlzIG9ubHkgZG9uZSBpZiBydW5uaW5nIGluIGEgc3RhbmRhcmQgYnJvd3NlciBlbnZpcm9ubWVudC5cbiAgICAvLyBTcGVjaWZpY2FsbHkgbm90IGlmIHdlJ3JlIGluIGEgd2ViIHdvcmtlciwgb3IgcmVhY3QtbmF0aXZlLlxuICAgIGlmICh1dGlscy5pc1N0YW5kYXJkQnJvd3NlckVudigpKSB7XG4gICAgICB2YXIgY29va2llcyA9IHJlcXVpcmUoJy4vLi4vaGVscGVycy9jb29raWVzJyk7XG5cbiAgICAgIC8vIEFkZCB4c3JmIGhlYWRlclxuICAgICAgdmFyIHhzcmZWYWx1ZSA9IChjb25maWcud2l0aENyZWRlbnRpYWxzIHx8IGlzVVJMU2FtZU9yaWdpbihjb25maWcudXJsKSkgJiYgY29uZmlnLnhzcmZDb29raWVOYW1lID9cbiAgICAgICAgICBjb29raWVzLnJlYWQoY29uZmlnLnhzcmZDb29raWVOYW1lKSA6XG4gICAgICAgICAgdW5kZWZpbmVkO1xuXG4gICAgICBpZiAoeHNyZlZhbHVlKSB7XG4gICAgICAgIHJlcXVlc3RIZWFkZXJzW2NvbmZpZy54c3JmSGVhZGVyTmFtZV0gPSB4c3JmVmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQWRkIGhlYWRlcnMgdG8gdGhlIHJlcXVlc3RcbiAgICBpZiAoJ3NldFJlcXVlc3RIZWFkZXInIGluIHJlcXVlc3QpIHtcbiAgICAgIHV0aWxzLmZvckVhY2gocmVxdWVzdEhlYWRlcnMsIGZ1bmN0aW9uIHNldFJlcXVlc3RIZWFkZXIodmFsLCBrZXkpIHtcbiAgICAgICAgaWYgKHR5cGVvZiByZXF1ZXN0RGF0YSA9PT0gJ3VuZGVmaW5lZCcgJiYga2V5LnRvTG93ZXJDYXNlKCkgPT09ICdjb250ZW50LXR5cGUnKSB7XG4gICAgICAgICAgLy8gUmVtb3ZlIENvbnRlbnQtVHlwZSBpZiBkYXRhIGlzIHVuZGVmaW5lZFxuICAgICAgICAgIGRlbGV0ZSByZXF1ZXN0SGVhZGVyc1trZXldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIE90aGVyd2lzZSBhZGQgaGVhZGVyIHRvIHRoZSByZXF1ZXN0XG4gICAgICAgICAgcmVxdWVzdC5zZXRSZXF1ZXN0SGVhZGVyKGtleSwgdmFsKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQWRkIHdpdGhDcmVkZW50aWFscyB0byByZXF1ZXN0IGlmIG5lZWRlZFxuICAgIGlmIChjb25maWcud2l0aENyZWRlbnRpYWxzKSB7XG4gICAgICByZXF1ZXN0LndpdGhDcmVkZW50aWFscyA9IHRydWU7XG4gICAgfVxuXG4gICAgLy8gQWRkIHJlc3BvbnNlVHlwZSB0byByZXF1ZXN0IGlmIG5lZWRlZFxuICAgIGlmIChjb25maWcucmVzcG9uc2VUeXBlKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXF1ZXN0LnJlc3BvbnNlVHlwZSA9IGNvbmZpZy5yZXNwb25zZVR5cGU7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIEV4cGVjdGVkIERPTUV4Y2VwdGlvbiB0aHJvd24gYnkgYnJvd3NlcnMgbm90IGNvbXBhdGlibGUgWE1MSHR0cFJlcXVlc3QgTGV2ZWwgMi5cbiAgICAgICAgLy8gQnV0LCB0aGlzIGNhbiBiZSBzdXBwcmVzc2VkIGZvciAnanNvbicgdHlwZSBhcyBpdCBjYW4gYmUgcGFyc2VkIGJ5IGRlZmF1bHQgJ3RyYW5zZm9ybVJlc3BvbnNlJyBmdW5jdGlvbi5cbiAgICAgICAgaWYgKGNvbmZpZy5yZXNwb25zZVR5cGUgIT09ICdqc29uJykge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgcHJvZ3Jlc3MgaWYgbmVlZGVkXG4gICAgaWYgKHR5cGVvZiBjb25maWcub25Eb3dubG9hZFByb2dyZXNzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICByZXF1ZXN0LmFkZEV2ZW50TGlzdGVuZXIoJ3Byb2dyZXNzJywgY29uZmlnLm9uRG93bmxvYWRQcm9ncmVzcyk7XG4gICAgfVxuXG4gICAgLy8gTm90IGFsbCBicm93c2VycyBzdXBwb3J0IHVwbG9hZCBldmVudHNcbiAgICBpZiAodHlwZW9mIGNvbmZpZy5vblVwbG9hZFByb2dyZXNzID09PSAnZnVuY3Rpb24nICYmIHJlcXVlc3QudXBsb2FkKSB7XG4gICAgICByZXF1ZXN0LnVwbG9hZC5hZGRFdmVudExpc3RlbmVyKCdwcm9ncmVzcycsIGNvbmZpZy5vblVwbG9hZFByb2dyZXNzKTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLmNhbmNlbFRva2VuKSB7XG4gICAgICAvLyBIYW5kbGUgY2FuY2VsbGF0aW9uXG4gICAgICBjb25maWcuY2FuY2VsVG9rZW4ucHJvbWlzZS50aGVuKGZ1bmN0aW9uIG9uQ2FuY2VsZWQoY2FuY2VsKSB7XG4gICAgICAgIGlmICghcmVxdWVzdCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlcXVlc3QuYWJvcnQoKTtcbiAgICAgICAgcmVqZWN0KGNhbmNlbCk7XG4gICAgICAgIC8vIENsZWFuIHVwIHJlcXVlc3RcbiAgICAgICAgcmVxdWVzdCA9IG51bGw7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAocmVxdWVzdERhdGEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmVxdWVzdERhdGEgPSBudWxsO1xuICAgIH1cblxuICAgIC8vIFNlbmQgdGhlIHJlcXVlc3RcbiAgICByZXF1ZXN0LnNlbmQocmVxdWVzdERhdGEpO1xuICB9KTtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvYWRhcHRlcnMveGhyLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvYWRhcHRlcnMveGhyLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/adapters/xhr.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/axios.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\nvar bind = __webpack_require__(\"./node_modules/axios/lib/helpers/bind.js\");\nvar Axios = __webpack_require__(\"./node_modules/axios/lib/core/Axios.js\");\nvar defaults = __webpack_require__(\"./node_modules/axios/lib/defaults.js\");\n\n/**\n * Create an instance of Axios\n *\n * @param {Object} defaultConfig The default config for the instance\n * @return {Axios} A new instance of Axios\n */\nfunction createInstance(defaultConfig) {\n var context = new Axios(defaultConfig);\n var instance = bind(Axios.prototype.request, context);\n\n // Copy axios.prototype to instance\n utils.extend(instance, Axios.prototype, context);\n\n // Copy context to instance\n utils.extend(instance, context);\n\n return instance;\n}\n\n// Create the default instance to be exported\nvar axios = createInstance(defaults);\n\n// Expose Axios class to allow class inheritance\naxios.Axios = Axios;\n\n// Factory for creating new instances\naxios.create = function create(instanceConfig) {\n return createInstance(utils.merge(defaults, instanceConfig));\n};\n\n// Expose Cancel & CancelToken\naxios.Cancel = __webpack_require__(\"./node_modules/axios/lib/cancel/Cancel.js\");\naxios.CancelToken = __webpack_require__(\"./node_modules/axios/lib/cancel/CancelToken.js\");\naxios.isCancel = __webpack_require__(\"./node_modules/axios/lib/cancel/isCancel.js\");\n\n// Expose all/spread\naxios.all = function all(promises) {\n return Promise.all(promises);\n};\naxios.spread = __webpack_require__(\"./node_modules/axios/lib/helpers/spread.js\");\n\nmodule.exports = axios;\n\n// Allow use of default import syntax in TypeScript\nmodule.exports.default = axios;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2F4aW9zLmpzP2I0ODEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWIsWUFBWSxtQkFBTyxDQUFDLG1DQUFTO0FBQzdCLFdBQVcsbUJBQU8sQ0FBQywwQ0FBZ0I7QUFDbkMsWUFBWSxtQkFBTyxDQUFDLHdDQUFjO0FBQ2xDLGVBQWUsbUJBQU8sQ0FBQyxzQ0FBWTs7QUFFbkM7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLFlBQVksTUFBTTtBQUNsQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxlQUFlLG1CQUFPLENBQUMsMkNBQWlCO0FBQ3hDLG9CQUFvQixtQkFBTyxDQUFDLGdEQUFzQjtBQUNsRCxpQkFBaUIsbUJBQU8sQ0FBQyw2Q0FBbUI7O0FBRTVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxtQkFBTyxDQUFDLDRDQUFrQjs7QUFFekM7O0FBRUE7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvYXhpb3MuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlscyA9IHJlcXVpcmUoJy4vdXRpbHMnKTtcbnZhciBiaW5kID0gcmVxdWlyZSgnLi9oZWxwZXJzL2JpbmQnKTtcbnZhciBBeGlvcyA9IHJlcXVpcmUoJy4vY29yZS9BeGlvcycpO1xudmFyIGRlZmF1bHRzID0gcmVxdWlyZSgnLi9kZWZhdWx0cycpO1xuXG4vKipcbiAqIENyZWF0ZSBhbiBpbnN0YW5jZSBvZiBBeGlvc1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBkZWZhdWx0Q29uZmlnIFRoZSBkZWZhdWx0IGNvbmZpZyBmb3IgdGhlIGluc3RhbmNlXG4gKiBAcmV0dXJuIHtBeGlvc30gQSBuZXcgaW5zdGFuY2Ugb2YgQXhpb3NcbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW5zdGFuY2UoZGVmYXVsdENvbmZpZykge1xuICB2YXIgY29udGV4dCA9IG5ldyBBeGlvcyhkZWZhdWx0Q29uZmlnKTtcbiAgdmFyIGluc3RhbmNlID0gYmluZChBeGlvcy5wcm90b3R5cGUucmVxdWVzdCwgY29udGV4dCk7XG5cbiAgLy8gQ29weSBheGlvcy5wcm90b3R5cGUgdG8gaW5zdGFuY2VcbiAgdXRpbHMuZXh0ZW5kKGluc3RhbmNlLCBBeGlvcy5wcm90b3R5cGUsIGNvbnRleHQpO1xuXG4gIC8vIENvcHkgY29udGV4dCB0byBpbnN0YW5jZVxuICB1dGlscy5leHRlbmQoaW5zdGFuY2UsIGNvbnRleHQpO1xuXG4gIHJldHVybiBpbnN0YW5jZTtcbn1cblxuLy8gQ3JlYXRlIHRoZSBkZWZhdWx0IGluc3RhbmNlIHRvIGJlIGV4cG9ydGVkXG52YXIgYXhpb3MgPSBjcmVhdGVJbnN0YW5jZShkZWZhdWx0cyk7XG5cbi8vIEV4cG9zZSBBeGlvcyBjbGFzcyB0byBhbGxvdyBjbGFzcyBpbmhlcml0YW5jZVxuYXhpb3MuQXhpb3MgPSBBeGlvcztcblxuLy8gRmFjdG9yeSBmb3IgY3JlYXRpbmcgbmV3IGluc3RhbmNlc1xuYXhpb3MuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKGluc3RhbmNlQ29uZmlnKSB7XG4gIHJldHVybiBjcmVhdGVJbnN0YW5jZSh1dGlscy5tZXJnZShkZWZhdWx0cywgaW5zdGFuY2VDb25maWcpKTtcbn07XG5cbi8vIEV4cG9zZSBDYW5jZWwgJiBDYW5jZWxUb2tlblxuYXhpb3MuQ2FuY2VsID0gcmVxdWlyZSgnLi9jYW5jZWwvQ2FuY2VsJyk7XG5heGlvcy5DYW5jZWxUb2tlbiA9IHJlcXVpcmUoJy4vY2FuY2VsL0NhbmNlbFRva2VuJyk7XG5heGlvcy5pc0NhbmNlbCA9IHJlcXVpcmUoJy4vY2FuY2VsL2lzQ2FuY2VsJyk7XG5cbi8vIEV4cG9zZSBhbGwvc3ByZWFkXG5heGlvcy5hbGwgPSBmdW5jdGlvbiBhbGwocHJvbWlzZXMpIHtcbiAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbn07XG5heGlvcy5zcHJlYWQgPSByZXF1aXJlKCcuL2hlbHBlcnMvc3ByZWFkJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gYXhpb3M7XG5cbi8vIEFsbG93IHVzZSBvZiBkZWZhdWx0IGltcG9ydCBzeW50YXggaW4gVHlwZVNjcmlwdFxubW9kdWxlLmV4cG9ydHMuZGVmYXVsdCA9IGF4aW9zO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2F4aW9zLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvYXhpb3MuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/axios.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/cancel/Cancel.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\n/**\n * A `Cancel` is an object that is thrown when an operation is canceled.\n *\n * @class\n * @param {string=} message The message.\n */\nfunction Cancel(message) {\n this.message = message;\n}\n\nCancel.prototype.toString = function toString() {\n return 'Cancel' + (this.message ? ': ' + this.message : '');\n};\n\nCancel.prototype.__CANCEL__ = true;\n\nmodule.exports = Cancel;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NhbmNlbC9DYW5jZWwuanM/NzU1MyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NhbmNlbC9DYW5jZWwuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQSBgQ2FuY2VsYCBpcyBhbiBvYmplY3QgdGhhdCBpcyB0aHJvd24gd2hlbiBhbiBvcGVyYXRpb24gaXMgY2FuY2VsZWQuXG4gKlxuICogQGNsYXNzXG4gKiBAcGFyYW0ge3N0cmluZz19IG1lc3NhZ2UgVGhlIG1lc3NhZ2UuXG4gKi9cbmZ1bmN0aW9uIENhbmNlbChtZXNzYWdlKSB7XG4gIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG59XG5cbkNhbmNlbC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgcmV0dXJuICdDYW5jZWwnICsgKHRoaXMubWVzc2FnZSA/ICc6ICcgKyB0aGlzLm1lc3NhZ2UgOiAnJyk7XG59O1xuXG5DYW5jZWwucHJvdG90eXBlLl9fQ0FOQ0VMX18gPSB0cnVlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IENhbmNlbDtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jYW5jZWwvQ2FuY2VsLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY2FuY2VsL0NhbmNlbC5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/cancel/Cancel.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/cancel/CancelToken.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar Cancel = __webpack_require__(\"./node_modules/axios/lib/cancel/Cancel.js\");\n\n/**\n * A `CancelToken` is an object that can be used to request cancellation of an operation.\n *\n * @class\n * @param {Function} executor The executor function.\n */\nfunction CancelToken(executor) {\n if (typeof executor !== 'function') {\n throw new TypeError('executor must be a function.');\n }\n\n var resolvePromise;\n this.promise = new Promise(function promiseExecutor(resolve) {\n resolvePromise = resolve;\n });\n\n var token = this;\n executor(function cancel(message) {\n if (token.reason) {\n // Cancellation has already been requested\n return;\n }\n\n token.reason = new Cancel(message);\n resolvePromise(token.reason);\n });\n}\n\n/**\n * Throws a `Cancel` if cancellation has been requested.\n */\nCancelToken.prototype.throwIfRequested = function throwIfRequested() {\n if (this.reason) {\n throw this.reason;\n }\n};\n\n/**\n * Returns an object that contains a new `CancelToken` and a function that, when called,\n * cancels the `CancelToken`.\n */\nCancelToken.source = function source() {\n var cancel;\n var token = new CancelToken(function executor(c) {\n cancel = c;\n });\n return {\n token: token,\n cancel: cancel\n };\n};\n\nmodule.exports = CancelToken;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NhbmNlbC9DYW5jZWxUb2tlbi5qcz83MTZjIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFhOztBQUViLGFBQWEsbUJBQU8sQ0FBQywyQ0FBVTs7QUFFL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jYW5jZWwvQ2FuY2VsVG9rZW4uanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciBDYW5jZWwgPSByZXF1aXJlKCcuL0NhbmNlbCcpO1xuXG4vKipcbiAqIEEgYENhbmNlbFRva2VuYCBpcyBhbiBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB0byByZXF1ZXN0IGNhbmNlbGxhdGlvbiBvZiBhbiBvcGVyYXRpb24uXG4gKlxuICogQGNsYXNzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBleGVjdXRvciBUaGUgZXhlY3V0b3IgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIENhbmNlbFRva2VuKGV4ZWN1dG9yKSB7XG4gIGlmICh0eXBlb2YgZXhlY3V0b3IgIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdleGVjdXRvciBtdXN0IGJlIGEgZnVuY3Rpb24uJyk7XG4gIH1cblxuICB2YXIgcmVzb2x2ZVByb21pc2U7XG4gIHRoaXMucHJvbWlzZSA9IG5ldyBQcm9taXNlKGZ1bmN0aW9uIHByb21pc2VFeGVjdXRvcihyZXNvbHZlKSB7XG4gICAgcmVzb2x2ZVByb21pc2UgPSByZXNvbHZlO1xuICB9KTtcblxuICB2YXIgdG9rZW4gPSB0aGlzO1xuICBleGVjdXRvcihmdW5jdGlvbiBjYW5jZWwobWVzc2FnZSkge1xuICAgIGlmICh0b2tlbi5yZWFzb24pIHtcbiAgICAgIC8vIENhbmNlbGxhdGlvbiBoYXMgYWxyZWFkeSBiZWVuIHJlcXVlc3RlZFxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRva2VuLnJlYXNvbiA9IG5ldyBDYW5jZWwobWVzc2FnZSk7XG4gICAgcmVzb2x2ZVByb21pc2UodG9rZW4ucmVhc29uKTtcbiAgfSk7XG59XG5cbi8qKlxuICogVGhyb3dzIGEgYENhbmNlbGAgaWYgY2FuY2VsbGF0aW9uIGhhcyBiZWVuIHJlcXVlc3RlZC5cbiAqL1xuQ2FuY2VsVG9rZW4ucHJvdG90eXBlLnRocm93SWZSZXF1ZXN0ZWQgPSBmdW5jdGlvbiB0aHJvd0lmUmVxdWVzdGVkKCkge1xuICBpZiAodGhpcy5yZWFzb24pIHtcbiAgICB0aHJvdyB0aGlzLnJlYXNvbjtcbiAgfVxufTtcblxuLyoqXG4gKiBSZXR1cm5zIGFuIG9iamVjdCB0aGF0IGNvbnRhaW5zIGEgbmV3IGBDYW5jZWxUb2tlbmAgYW5kIGEgZnVuY3Rpb24gdGhhdCwgd2hlbiBjYWxsZWQsXG4gKiBjYW5jZWxzIHRoZSBgQ2FuY2VsVG9rZW5gLlxuICovXG5DYW5jZWxUb2tlbi5zb3VyY2UgPSBmdW5jdGlvbiBzb3VyY2UoKSB7XG4gIHZhciBjYW5jZWw7XG4gIHZhciB0b2tlbiA9IG5ldyBDYW5jZWxUb2tlbihmdW5jdGlvbiBleGVjdXRvcihjKSB7XG4gICAgY2FuY2VsID0gYztcbiAgfSk7XG4gIHJldHVybiB7XG4gICAgdG9rZW46IHRva2VuLFxuICAgIGNhbmNlbDogY2FuY2VsXG4gIH07XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IENhbmNlbFRva2VuO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NhbmNlbC9DYW5jZWxUb2tlbi5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NhbmNlbC9DYW5jZWxUb2tlbi5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/cancel/CancelToken.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/cancel/isCancel.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nmodule.exports = function isCancel(value) {\n return !!(value && value.__CANCEL__);\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NhbmNlbC9pc0NhbmNlbC5qcz9hNDFiIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFhOztBQUViO0FBQ0E7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY2FuY2VsL2lzQ2FuY2VsLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzQ2FuY2VsKHZhbHVlKSB7XG4gIHJldHVybiAhISh2YWx1ZSAmJiB2YWx1ZS5fX0NBTkNFTF9fKTtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY2FuY2VsL2lzQ2FuY2VsLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY2FuY2VsL2lzQ2FuY2VsLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/cancel/isCancel.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/core/Axios.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar defaults = __webpack_require__(\"./node_modules/axios/lib/defaults.js\");\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\nvar InterceptorManager = __webpack_require__(\"./node_modules/axios/lib/core/InterceptorManager.js\");\nvar dispatchRequest = __webpack_require__(\"./node_modules/axios/lib/core/dispatchRequest.js\");\n\n/**\n * Create a new instance of Axios\n *\n * @param {Object} instanceConfig The default config for the instance\n */\nfunction Axios(instanceConfig) {\n this.defaults = instanceConfig;\n this.interceptors = {\n request: new InterceptorManager(),\n response: new InterceptorManager()\n };\n}\n\n/**\n * Dispatch a request\n *\n * @param {Object} config The config specific for this request (merged with this.defaults)\n */\nAxios.prototype.request = function request(config) {\n /*eslint no-param-reassign:0*/\n // Allow for axios('example/url'[, config]) a la fetch API\n if (typeof config === 'string') {\n config = utils.merge({\n url: arguments[0]\n }, arguments[1]);\n }\n\n config = utils.merge(defaults, {method: 'get'}, this.defaults, config);\n config.method = config.method.toLowerCase();\n\n // Hook up interceptors middleware\n var chain = [dispatchRequest, undefined];\n var promise = Promise.resolve(config);\n\n this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {\n chain.unshift(interceptor.fulfilled, interceptor.rejected);\n });\n\n this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {\n chain.push(interceptor.fulfilled, interceptor.rejected);\n });\n\n while (chain.length) {\n promise = promise.then(chain.shift(), chain.shift());\n }\n\n return promise;\n};\n\n// Provide aliases for supported request methods\nutils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {\n /*eslint func-names:0*/\n Axios.prototype[method] = function(url, config) {\n return this.request(utils.merge(config || {}, {\n method: method,\n url: url\n }));\n };\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n /*eslint func-names:0*/\n Axios.prototype[method] = function(url, data, config) {\n return this.request(utils.merge(config || {}, {\n method: method,\n url: url,\n data: data\n }));\n };\n});\n\nmodule.exports = Axios;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvQXhpb3MuanM/NWU2NSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBYTs7QUFFYixlQUFlLG1CQUFPLENBQUMsc0NBQWU7QUFDdEMsWUFBWSxtQkFBTyxDQUFDLG1DQUFZO0FBQ2hDLHlCQUF5QixtQkFBTyxDQUFDLHFEQUFzQjtBQUN2RCxzQkFBc0IsbUJBQU8sQ0FBQyxrREFBbUI7O0FBRWpEO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQSxrQ0FBa0MsY0FBYztBQUNoRDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0Q7QUFDaEQ7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdEO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLENBQUM7O0FBRUQiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvQXhpb3MuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciBkZWZhdWx0cyA9IHJlcXVpcmUoJy4vLi4vZGVmYXVsdHMnKTtcbnZhciB1dGlscyA9IHJlcXVpcmUoJy4vLi4vdXRpbHMnKTtcbnZhciBJbnRlcmNlcHRvck1hbmFnZXIgPSByZXF1aXJlKCcuL0ludGVyY2VwdG9yTWFuYWdlcicpO1xudmFyIGRpc3BhdGNoUmVxdWVzdCA9IHJlcXVpcmUoJy4vZGlzcGF0Y2hSZXF1ZXN0Jyk7XG5cbi8qKlxuICogQ3JlYXRlIGEgbmV3IGluc3RhbmNlIG9mIEF4aW9zXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGluc3RhbmNlQ29uZmlnIFRoZSBkZWZhdWx0IGNvbmZpZyBmb3IgdGhlIGluc3RhbmNlXG4gKi9cbmZ1bmN0aW9uIEF4aW9zKGluc3RhbmNlQ29uZmlnKSB7XG4gIHRoaXMuZGVmYXVsdHMgPSBpbnN0YW5jZUNvbmZpZztcbiAgdGhpcy5pbnRlcmNlcHRvcnMgPSB7XG4gICAgcmVxdWVzdDogbmV3IEludGVyY2VwdG9yTWFuYWdlcigpLFxuICAgIHJlc3BvbnNlOiBuZXcgSW50ZXJjZXB0b3JNYW5hZ2VyKClcbiAgfTtcbn1cblxuLyoqXG4gKiBEaXNwYXRjaCBhIHJlcXVlc3RcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIFRoZSBjb25maWcgc3BlY2lmaWMgZm9yIHRoaXMgcmVxdWVzdCAobWVyZ2VkIHdpdGggdGhpcy5kZWZhdWx0cylcbiAqL1xuQXhpb3MucHJvdG90eXBlLnJlcXVlc3QgPSBmdW5jdGlvbiByZXF1ZXN0KGNvbmZpZykge1xuICAvKmVzbGludCBuby1wYXJhbS1yZWFzc2lnbjowKi9cbiAgLy8gQWxsb3cgZm9yIGF4aW9zKCdleGFtcGxlL3VybCdbLCBjb25maWddKSBhIGxhIGZldGNoIEFQSVxuICBpZiAodHlwZW9mIGNvbmZpZyA9PT0gJ3N0cmluZycpIHtcbiAgICBjb25maWcgPSB1dGlscy5tZXJnZSh7XG4gICAgICB1cmw6IGFyZ3VtZW50c1swXVxuICAgIH0sIGFyZ3VtZW50c1sxXSk7XG4gIH1cblxuICBjb25maWcgPSB1dGlscy5tZXJnZShkZWZhdWx0cywge21ldGhvZDogJ2dldCd9LCB0aGlzLmRlZmF1bHRzLCBjb25maWcpO1xuICBjb25maWcubWV0aG9kID0gY29uZmlnLm1ldGhvZC50b0xvd2VyQ2FzZSgpO1xuXG4gIC8vIEhvb2sgdXAgaW50ZXJjZXB0b3JzIG1pZGRsZXdhcmVcbiAgdmFyIGNoYWluID0gW2Rpc3BhdGNoUmVxdWVzdCwgdW5kZWZpbmVkXTtcbiAgdmFyIHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoY29uZmlnKTtcblxuICB0aGlzLmludGVyY2VwdG9ycy5yZXF1ZXN0LmZvckVhY2goZnVuY3Rpb24gdW5zaGlmdFJlcXVlc3RJbnRlcmNlcHRvcnMoaW50ZXJjZXB0b3IpIHtcbiAgICBjaGFpbi51bnNoaWZ0KGludGVyY2VwdG9yLmZ1bGZpbGxlZCwgaW50ZXJjZXB0b3IucmVqZWN0ZWQpO1xuICB9KTtcblxuICB0aGlzLmludGVyY2VwdG9ycy5yZXNwb25zZS5mb3JFYWNoKGZ1bmN0aW9uIHB1c2hSZXNwb25zZUludGVyY2VwdG9ycyhpbnRlcmNlcHRvcikge1xuICAgIGNoYWluLnB1c2goaW50ZXJjZXB0b3IuZnVsZmlsbGVkLCBpbnRlcmNlcHRvci5yZWplY3RlZCk7XG4gIH0pO1xuXG4gIHdoaWxlIChjaGFpbi5sZW5ndGgpIHtcbiAgICBwcm9taXNlID0gcHJvbWlzZS50aGVuKGNoYWluLnNoaWZ0KCksIGNoYWluLnNoaWZ0KCkpO1xuICB9XG5cbiAgcmV0dXJuIHByb21pc2U7XG59O1xuXG4vLyBQcm92aWRlIGFsaWFzZXMgZm9yIHN1cHBvcnRlZCByZXF1ZXN0IG1ldGhvZHNcbnV0aWxzLmZvckVhY2goWydkZWxldGUnLCAnZ2V0JywgJ2hlYWQnLCAnb3B0aW9ucyddLCBmdW5jdGlvbiBmb3JFYWNoTWV0aG9kTm9EYXRhKG1ldGhvZCkge1xuICAvKmVzbGludCBmdW5jLW5hbWVzOjAqL1xuICBBeGlvcy5wcm90b3R5cGVbbWV0aG9kXSA9IGZ1bmN0aW9uKHVybCwgY29uZmlnKSB7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdCh1dGlscy5tZXJnZShjb25maWcgfHwge30sIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgdXJsOiB1cmxcbiAgICB9KSk7XG4gIH07XG59KTtcblxudXRpbHMuZm9yRWFjaChbJ3Bvc3QnLCAncHV0JywgJ3BhdGNoJ10sIGZ1bmN0aW9uIGZvckVhY2hNZXRob2RXaXRoRGF0YShtZXRob2QpIHtcbiAgLyplc2xpbnQgZnVuYy1uYW1lczowKi9cbiAgQXhpb3MucHJvdG90eXBlW21ldGhvZF0gPSBmdW5jdGlvbih1cmwsIGRhdGEsIGNvbmZpZykge1xuICAgIHJldHVybiB0aGlzLnJlcXVlc3QodXRpbHMubWVyZ2UoY29uZmlnIHx8IHt9LCB7XG4gICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgIHVybDogdXJsLFxuICAgICAgZGF0YTogZGF0YVxuICAgIH0pKTtcbiAgfTtcbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEF4aW9zO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvQXhpb3MuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL0F4aW9zLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/core/Axios.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/core/InterceptorManager.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\n\nfunction InterceptorManager() {\n this.handlers = [];\n}\n\n/**\n * Add a new interceptor to the stack\n *\n * @param {Function} fulfilled The function to handle `then` for a `Promise`\n * @param {Function} rejected The function to handle `reject` for a `Promise`\n *\n * @return {Number} An ID used to remove interceptor later\n */\nInterceptorManager.prototype.use = function use(fulfilled, rejected) {\n this.handlers.push({\n fulfilled: fulfilled,\n rejected: rejected\n });\n return this.handlers.length - 1;\n};\n\n/**\n * Remove an interceptor from the stack\n *\n * @param {Number} id The ID that was returned by `use`\n */\nInterceptorManager.prototype.eject = function eject(id) {\n if (this.handlers[id]) {\n this.handlers[id] = null;\n }\n};\n\n/**\n * Iterate over all the registered interceptors\n *\n * This method is particularly useful for skipping over any\n * interceptors that may have become `null` calling `eject`.\n *\n * @param {Function} fn The function to call for each interceptor\n */\nInterceptorManager.prototype.forEach = function forEach(fn) {\n utils.forEach(this.handlers, function forEachHandler(h) {\n if (h !== null) {\n fn(h);\n }\n });\n};\n\nmodule.exports = InterceptorManager;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvSW50ZXJjZXB0b3JNYW5hZ2VyLmpzPzdlZTEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWIsWUFBWSxtQkFBTyxDQUFDLG1DQUFZOztBQUVoQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCLFdBQVcsU0FBUztBQUNwQjtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL0ludGVyY2VwdG9yTWFuYWdlci5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzID0gcmVxdWlyZSgnLi8uLi91dGlscycpO1xuXG5mdW5jdGlvbiBJbnRlcmNlcHRvck1hbmFnZXIoKSB7XG4gIHRoaXMuaGFuZGxlcnMgPSBbXTtcbn1cblxuLyoqXG4gKiBBZGQgYSBuZXcgaW50ZXJjZXB0b3IgdG8gdGhlIHN0YWNrXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVsZmlsbGVkIFRoZSBmdW5jdGlvbiB0byBoYW5kbGUgYHRoZW5gIGZvciBhIGBQcm9taXNlYFxuICogQHBhcmFtIHtGdW5jdGlvbn0gcmVqZWN0ZWQgVGhlIGZ1bmN0aW9uIHRvIGhhbmRsZSBgcmVqZWN0YCBmb3IgYSBgUHJvbWlzZWBcbiAqXG4gKiBAcmV0dXJuIHtOdW1iZXJ9IEFuIElEIHVzZWQgdG8gcmVtb3ZlIGludGVyY2VwdG9yIGxhdGVyXG4gKi9cbkludGVyY2VwdG9yTWFuYWdlci5wcm90b3R5cGUudXNlID0gZnVuY3Rpb24gdXNlKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpIHtcbiAgdGhpcy5oYW5kbGVycy5wdXNoKHtcbiAgICBmdWxmaWxsZWQ6IGZ1bGZpbGxlZCxcbiAgICByZWplY3RlZDogcmVqZWN0ZWRcbiAgfSk7XG4gIHJldHVybiB0aGlzLmhhbmRsZXJzLmxlbmd0aCAtIDE7XG59O1xuXG4vKipcbiAqIFJlbW92ZSBhbiBpbnRlcmNlcHRvciBmcm9tIHRoZSBzdGFja1xuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBpZCBUaGUgSUQgdGhhdCB3YXMgcmV0dXJuZWQgYnkgYHVzZWBcbiAqL1xuSW50ZXJjZXB0b3JNYW5hZ2VyLnByb3RvdHlwZS5lamVjdCA9IGZ1bmN0aW9uIGVqZWN0KGlkKSB7XG4gIGlmICh0aGlzLmhhbmRsZXJzW2lkXSkge1xuICAgIHRoaXMuaGFuZGxlcnNbaWRdID0gbnVsbDtcbiAgfVxufTtcblxuLyoqXG4gKiBJdGVyYXRlIG92ZXIgYWxsIHRoZSByZWdpc3RlcmVkIGludGVyY2VwdG9yc1xuICpcbiAqIFRoaXMgbWV0aG9kIGlzIHBhcnRpY3VsYXJseSB1c2VmdWwgZm9yIHNraXBwaW5nIG92ZXIgYW55XG4gKiBpbnRlcmNlcHRvcnMgdGhhdCBtYXkgaGF2ZSBiZWNvbWUgYG51bGxgIGNhbGxpbmcgYGVqZWN0YC5cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmbiBUaGUgZnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCBpbnRlcmNlcHRvclxuICovXG5JbnRlcmNlcHRvck1hbmFnZXIucHJvdG90eXBlLmZvckVhY2ggPSBmdW5jdGlvbiBmb3JFYWNoKGZuKSB7XG4gIHV0aWxzLmZvckVhY2godGhpcy5oYW5kbGVycywgZnVuY3Rpb24gZm9yRWFjaEhhbmRsZXIoaCkge1xuICAgIGlmIChoICE9PSBudWxsKSB7XG4gICAgICBmbihoKTtcbiAgICB9XG4gIH0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBJbnRlcmNlcHRvck1hbmFnZXI7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9JbnRlcmNlcHRvck1hbmFnZXIuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL0ludGVyY2VwdG9yTWFuYWdlci5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/core/InterceptorManager.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/core/createError.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar enhanceError = __webpack_require__(\"./node_modules/axios/lib/core/enhanceError.js\");\n\n/**\n * Create an Error with the specified message, config, error code, request and response.\n *\n * @param {string} message The error message.\n * @param {Object} config The config.\n * @param {string} [code] The error code (for example, 'ECONNABORTED').\n * @param {Object} [request] The request.\n * @param {Object} [response] The response.\n * @returns {Error} The created error.\n */\nmodule.exports = function createError(message, config, code, request, response) {\n var error = new Error(message);\n return enhanceError(error, config, code, request, response);\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvY3JlYXRlRXJyb3IuanM/MTZkMCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBYTs7QUFFYixtQkFBbUIsbUJBQU8sQ0FBQywrQ0FBZ0I7O0FBRTNDO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsYUFBYSxNQUFNO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvY3JlYXRlRXJyb3IuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciBlbmhhbmNlRXJyb3IgPSByZXF1aXJlKCcuL2VuaGFuY2VFcnJvcicpO1xuXG4vKipcbiAqIENyZWF0ZSBhbiBFcnJvciB3aXRoIHRoZSBzcGVjaWZpZWQgbWVzc2FnZSwgY29uZmlnLCBlcnJvciBjb2RlLCByZXF1ZXN0IGFuZCByZXNwb25zZS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSBUaGUgZXJyb3IgbWVzc2FnZS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgVGhlIGNvbmZpZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbY29kZV0gVGhlIGVycm9yIGNvZGUgKGZvciBleGFtcGxlLCAnRUNPTk5BQk9SVEVEJykuXG4gKiBAcGFyYW0ge09iamVjdH0gW3JlcXVlc3RdIFRoZSByZXF1ZXN0LlxuICogQHBhcmFtIHtPYmplY3R9IFtyZXNwb25zZV0gVGhlIHJlc3BvbnNlLlxuICogQHJldHVybnMge0Vycm9yfSBUaGUgY3JlYXRlZCBlcnJvci5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcmVhdGVFcnJvcihtZXNzYWdlLCBjb25maWcsIGNvZGUsIHJlcXVlc3QsIHJlc3BvbnNlKSB7XG4gIHZhciBlcnJvciA9IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgcmV0dXJuIGVuaGFuY2VFcnJvcihlcnJvciwgY29uZmlnLCBjb2RlLCByZXF1ZXN0LCByZXNwb25zZSk7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvY3JlYXRlRXJyb3IuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL2NyZWF0ZUVycm9yLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/core/createError.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/core/dispatchRequest.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\nvar transformData = __webpack_require__(\"./node_modules/axios/lib/core/transformData.js\");\nvar isCancel = __webpack_require__(\"./node_modules/axios/lib/cancel/isCancel.js\");\nvar defaults = __webpack_require__(\"./node_modules/axios/lib/defaults.js\");\nvar isAbsoluteURL = __webpack_require__(\"./node_modules/axios/lib/helpers/isAbsoluteURL.js\");\nvar combineURLs = __webpack_require__(\"./node_modules/axios/lib/helpers/combineURLs.js\");\n\n/**\n * Throws a `Cancel` if cancellation has been requested.\n */\nfunction throwIfCancellationRequested(config) {\n if (config.cancelToken) {\n config.cancelToken.throwIfRequested();\n }\n}\n\n/**\n * Dispatch a request to the server using the configured adapter.\n *\n * @param {object} config The config that is to be used for the request\n * @returns {Promise} The Promise to be fulfilled\n */\nmodule.exports = function dispatchRequest(config) {\n throwIfCancellationRequested(config);\n\n // Support baseURL config\n if (config.baseURL && !isAbsoluteURL(config.url)) {\n config.url = combineURLs(config.baseURL, config.url);\n }\n\n // Ensure headers exist\n config.headers = config.headers || {};\n\n // Transform request data\n config.data = transformData(\n config.data,\n config.headers,\n config.transformRequest\n );\n\n // Flatten headers\n config.headers = utils.merge(\n config.headers.common || {},\n config.headers[config.method] || {},\n config.headers || {}\n );\n\n utils.forEach(\n ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],\n function cleanHeaderConfig(method) {\n delete config.headers[method];\n }\n );\n\n var adapter = config.adapter || defaults.adapter;\n\n return adapter(config).then(function onAdapterResolution(response) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n response.data = transformData(\n response.data,\n response.headers,\n config.transformResponse\n );\n\n return response;\n }, function onAdapterRejection(reason) {\n if (!isCancel(reason)) {\n throwIfCancellationRequested(config);\n\n // Transform response data\n if (reason && reason.response) {\n reason.response.data = transformData(\n reason.response.data,\n reason.response.headers,\n config.transformResponse\n );\n }\n }\n\n return Promise.reject(reason);\n });\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvZGlzcGF0Y2hSZXF1ZXN0LmpzP2M0YmIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWIsWUFBWSxtQkFBTyxDQUFDLG1DQUFZO0FBQ2hDLG9CQUFvQixtQkFBTyxDQUFDLGdEQUFpQjtBQUM3QyxlQUFlLG1CQUFPLENBQUMsNkNBQW9CO0FBQzNDLGVBQWUsbUJBQU8sQ0FBQyxzQ0FBYTtBQUNwQyxvQkFBb0IsbUJBQU8sQ0FBQyxtREFBNEI7QUFDeEQsa0JBQWtCLG1CQUFPLENBQUMsaURBQTBCOztBQUVwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0IsdUNBQXVDO0FBQ3ZDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL2Rpc3BhdGNoUmVxdWVzdC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzID0gcmVxdWlyZSgnLi8uLi91dGlscycpO1xudmFyIHRyYW5zZm9ybURhdGEgPSByZXF1aXJlKCcuL3RyYW5zZm9ybURhdGEnKTtcbnZhciBpc0NhbmNlbCA9IHJlcXVpcmUoJy4uL2NhbmNlbC9pc0NhbmNlbCcpO1xudmFyIGRlZmF1bHRzID0gcmVxdWlyZSgnLi4vZGVmYXVsdHMnKTtcbnZhciBpc0Fic29sdXRlVVJMID0gcmVxdWlyZSgnLi8uLi9oZWxwZXJzL2lzQWJzb2x1dGVVUkwnKTtcbnZhciBjb21iaW5lVVJMcyA9IHJlcXVpcmUoJy4vLi4vaGVscGVycy9jb21iaW5lVVJMcycpO1xuXG4vKipcbiAqIFRocm93cyBhIGBDYW5jZWxgIGlmIGNhbmNlbGxhdGlvbiBoYXMgYmVlbiByZXF1ZXN0ZWQuXG4gKi9cbmZ1bmN0aW9uIHRocm93SWZDYW5jZWxsYXRpb25SZXF1ZXN0ZWQoY29uZmlnKSB7XG4gIGlmIChjb25maWcuY2FuY2VsVG9rZW4pIHtcbiAgICBjb25maWcuY2FuY2VsVG9rZW4udGhyb3dJZlJlcXVlc3RlZCgpO1xuICB9XG59XG5cbi8qKlxuICogRGlzcGF0Y2ggYSByZXF1ZXN0IHRvIHRoZSBzZXJ2ZXIgdXNpbmcgdGhlIGNvbmZpZ3VyZWQgYWRhcHRlci5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gY29uZmlnIFRoZSBjb25maWcgdGhhdCBpcyB0byBiZSB1c2VkIGZvciB0aGUgcmVxdWVzdFxuICogQHJldHVybnMge1Byb21pc2V9IFRoZSBQcm9taXNlIHRvIGJlIGZ1bGZpbGxlZFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGRpc3BhdGNoUmVxdWVzdChjb25maWcpIHtcbiAgdGhyb3dJZkNhbmNlbGxhdGlvblJlcXVlc3RlZChjb25maWcpO1xuXG4gIC8vIFN1cHBvcnQgYmFzZVVSTCBjb25maWdcbiAgaWYgKGNvbmZpZy5iYXNlVVJMICYmICFpc0Fic29sdXRlVVJMKGNvbmZpZy51cmwpKSB7XG4gICAgY29uZmlnLnVybCA9IGNvbWJpbmVVUkxzKGNvbmZpZy5iYXNlVVJMLCBjb25maWcudXJsKTtcbiAgfVxuXG4gIC8vIEVuc3VyZSBoZWFkZXJzIGV4aXN0XG4gIGNvbmZpZy5oZWFkZXJzID0gY29uZmlnLmhlYWRlcnMgfHwge307XG5cbiAgLy8gVHJhbnNmb3JtIHJlcXVlc3QgZGF0YVxuICBjb25maWcuZGF0YSA9IHRyYW5zZm9ybURhdGEoXG4gICAgY29uZmlnLmRhdGEsXG4gICAgY29uZmlnLmhlYWRlcnMsXG4gICAgY29uZmlnLnRyYW5zZm9ybVJlcXVlc3RcbiAgKTtcblxuICAvLyBGbGF0dGVuIGhlYWRlcnNcbiAgY29uZmlnLmhlYWRlcnMgPSB1dGlscy5tZXJnZShcbiAgICBjb25maWcuaGVhZGVycy5jb21tb24gfHwge30sXG4gICAgY29uZmlnLmhlYWRlcnNbY29uZmlnLm1ldGhvZF0gfHwge30sXG4gICAgY29uZmlnLmhlYWRlcnMgfHwge31cbiAgKTtcblxuICB1dGlscy5mb3JFYWNoKFxuICAgIFsnZGVsZXRlJywgJ2dldCcsICdoZWFkJywgJ3Bvc3QnLCAncHV0JywgJ3BhdGNoJywgJ2NvbW1vbiddLFxuICAgIGZ1bmN0aW9uIGNsZWFuSGVhZGVyQ29uZmlnKG1ldGhvZCkge1xuICAgICAgZGVsZXRlIGNvbmZpZy5oZWFkZXJzW21ldGhvZF07XG4gICAgfVxuICApO1xuXG4gIHZhciBhZGFwdGVyID0gY29uZmlnLmFkYXB0ZXIgfHwgZGVmYXVsdHMuYWRhcHRlcjtcblxuICByZXR1cm4gYWRhcHRlcihjb25maWcpLnRoZW4oZnVuY3Rpb24gb25BZGFwdGVyUmVzb2x1dGlvbihyZXNwb25zZSkge1xuICAgIHRocm93SWZDYW5jZWxsYXRpb25SZXF1ZXN0ZWQoY29uZmlnKTtcblxuICAgIC8vIFRyYW5zZm9ybSByZXNwb25zZSBkYXRhXG4gICAgcmVzcG9uc2UuZGF0YSA9IHRyYW5zZm9ybURhdGEoXG4gICAgICByZXNwb25zZS5kYXRhLFxuICAgICAgcmVzcG9uc2UuaGVhZGVycyxcbiAgICAgIGNvbmZpZy50cmFuc2Zvcm1SZXNwb25zZVxuICAgICk7XG5cbiAgICByZXR1cm4gcmVzcG9uc2U7XG4gIH0sIGZ1bmN0aW9uIG9uQWRhcHRlclJlamVjdGlvbihyZWFzb24pIHtcbiAgICBpZiAoIWlzQ2FuY2VsKHJlYXNvbikpIHtcbiAgICAgIHRocm93SWZDYW5jZWxsYXRpb25SZXF1ZXN0ZWQoY29uZmlnKTtcblxuICAgICAgLy8gVHJhbnNmb3JtIHJlc3BvbnNlIGRhdGFcbiAgICAgIGlmIChyZWFzb24gJiYgcmVhc29uLnJlc3BvbnNlKSB7XG4gICAgICAgIHJlYXNvbi5yZXNwb25zZS5kYXRhID0gdHJhbnNmb3JtRGF0YShcbiAgICAgICAgICByZWFzb24ucmVzcG9uc2UuZGF0YSxcbiAgICAgICAgICByZWFzb24ucmVzcG9uc2UuaGVhZGVycyxcbiAgICAgICAgICBjb25maWcudHJhbnNmb3JtUmVzcG9uc2VcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QocmVhc29uKTtcbiAgfSk7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvZGlzcGF0Y2hSZXF1ZXN0LmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9kaXNwYXRjaFJlcXVlc3QuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/core/dispatchRequest.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/core/enhanceError.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\n/**\n * Update an Error with the specified config, error code, and response.\n *\n * @param {Error} error The error to update.\n * @param {Object} config The config.\n * @param {string} [code] The error code (for example, 'ECONNABORTED').\n * @param {Object} [request] The request.\n * @param {Object} [response] The response.\n * @returns {Error} The error.\n */\nmodule.exports = function enhanceError(error, config, code, request, response) {\n error.config = config;\n if (code) {\n error.code = code;\n }\n error.request = request;\n error.response = response;\n return error;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvZW5oYW5jZUVycm9yLmpzP2I3Y2EiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0EsV0FBVyxNQUFNO0FBQ2pCLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixhQUFhLE1BQU07QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvZW5oYW5jZUVycm9yLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIFVwZGF0ZSBhbiBFcnJvciB3aXRoIHRoZSBzcGVjaWZpZWQgY29uZmlnLCBlcnJvciBjb2RlLCBhbmQgcmVzcG9uc2UuXG4gKlxuICogQHBhcmFtIHtFcnJvcn0gZXJyb3IgVGhlIGVycm9yIHRvIHVwZGF0ZS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgVGhlIGNvbmZpZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbY29kZV0gVGhlIGVycm9yIGNvZGUgKGZvciBleGFtcGxlLCAnRUNPTk5BQk9SVEVEJykuXG4gKiBAcGFyYW0ge09iamVjdH0gW3JlcXVlc3RdIFRoZSByZXF1ZXN0LlxuICogQHBhcmFtIHtPYmplY3R9IFtyZXNwb25zZV0gVGhlIHJlc3BvbnNlLlxuICogQHJldHVybnMge0Vycm9yfSBUaGUgZXJyb3IuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZW5oYW5jZUVycm9yKGVycm9yLCBjb25maWcsIGNvZGUsIHJlcXVlc3QsIHJlc3BvbnNlKSB7XG4gIGVycm9yLmNvbmZpZyA9IGNvbmZpZztcbiAgaWYgKGNvZGUpIHtcbiAgICBlcnJvci5jb2RlID0gY29kZTtcbiAgfVxuICBlcnJvci5yZXF1ZXN0ID0gcmVxdWVzdDtcbiAgZXJyb3IucmVzcG9uc2UgPSByZXNwb25zZTtcbiAgcmV0dXJuIGVycm9yO1xufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL2VuaGFuY2VFcnJvci5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvZW5oYW5jZUVycm9yLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/core/enhanceError.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/core/settle.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar createError = __webpack_require__(\"./node_modules/axios/lib/core/createError.js\");\n\n/**\n * Resolve or reject a Promise based on response status.\n *\n * @param {Function} resolve A function that resolves the promise.\n * @param {Function} reject A function that rejects the promise.\n * @param {object} response The response.\n */\nmodule.exports = function settle(resolve, reject, response) {\n var validateStatus = response.config.validateStatus;\n // Note: status is not exposed by XDomainRequest\n if (!response.status || !validateStatus || validateStatus(response.status)) {\n resolve(response);\n } else {\n reject(createError(\n 'Request failed with status code ' + response.status,\n response.config,\n null,\n response.request,\n response\n ));\n }\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvc2V0dGxlLmpzP2RiNTIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWIsa0JBQWtCLG1CQUFPLENBQUMsOENBQWU7O0FBRXpDO0FBQ0E7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQixXQUFXLFNBQVM7QUFDcEIsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvc2V0dGxlLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgY3JlYXRlRXJyb3IgPSByZXF1aXJlKCcuL2NyZWF0ZUVycm9yJyk7XG5cbi8qKlxuICogUmVzb2x2ZSBvciByZWplY3QgYSBQcm9taXNlIGJhc2VkIG9uIHJlc3BvbnNlIHN0YXR1cy5cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSByZXNvbHZlIEEgZnVuY3Rpb24gdGhhdCByZXNvbHZlcyB0aGUgcHJvbWlzZS5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IHJlamVjdCBBIGZ1bmN0aW9uIHRoYXQgcmVqZWN0cyB0aGUgcHJvbWlzZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSByZXNwb25zZSBUaGUgcmVzcG9uc2UuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgcmVzcG9uc2UpIHtcbiAgdmFyIHZhbGlkYXRlU3RhdHVzID0gcmVzcG9uc2UuY29uZmlnLnZhbGlkYXRlU3RhdHVzO1xuICAvLyBOb3RlOiBzdGF0dXMgaXMgbm90IGV4cG9zZWQgYnkgWERvbWFpblJlcXVlc3RcbiAgaWYgKCFyZXNwb25zZS5zdGF0dXMgfHwgIXZhbGlkYXRlU3RhdHVzIHx8IHZhbGlkYXRlU3RhdHVzKHJlc3BvbnNlLnN0YXR1cykpIHtcbiAgICByZXNvbHZlKHJlc3BvbnNlKTtcbiAgfSBlbHNlIHtcbiAgICByZWplY3QoY3JlYXRlRXJyb3IoXG4gICAgICAnUmVxdWVzdCBmYWlsZWQgd2l0aCBzdGF0dXMgY29kZSAnICsgcmVzcG9uc2Uuc3RhdHVzLFxuICAgICAgcmVzcG9uc2UuY29uZmlnLFxuICAgICAgbnVsbCxcbiAgICAgIHJlc3BvbnNlLnJlcXVlc3QsXG4gICAgICByZXNwb25zZVxuICAgICkpO1xuICB9XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvc2V0dGxlLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9zZXR0bGUuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/core/settle.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/core/transformData.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\n\n/**\n * Transform the data for a request or a response\n *\n * @param {Object|String} data The data to be transformed\n * @param {Array} headers The headers for the request or response\n * @param {Array|Function} fns A single function or Array of functions\n * @returns {*} The resulting transformed data\n */\nmodule.exports = function transformData(data, headers, fns) {\n /*eslint no-param-reassign:0*/\n utils.forEach(fns, function transform(fn) {\n data = fn(data, headers);\n });\n\n return data;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvdHJhbnNmb3JtRGF0YS5qcz80Y2Q1Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFhOztBQUViLFlBQVksbUJBQU8sQ0FBQyxtQ0FBWTs7QUFFaEM7QUFDQTtBQUNBO0FBQ0EsV0FBVyxjQUFjO0FBQ3pCLFdBQVcsTUFBTTtBQUNqQixXQUFXLGVBQWU7QUFDMUIsYUFBYSxFQUFFO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS90cmFuc2Zvcm1EYXRhLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLy4uL3V0aWxzJyk7XG5cbi8qKlxuICogVHJhbnNmb3JtIHRoZSBkYXRhIGZvciBhIHJlcXVlc3Qgb3IgYSByZXNwb25zZVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fFN0cmluZ30gZGF0YSBUaGUgZGF0YSB0byBiZSB0cmFuc2Zvcm1lZFxuICogQHBhcmFtIHtBcnJheX0gaGVhZGVycyBUaGUgaGVhZGVycyBmb3IgdGhlIHJlcXVlc3Qgb3IgcmVzcG9uc2VcbiAqIEBwYXJhbSB7QXJyYXl8RnVuY3Rpb259IGZucyBBIHNpbmdsZSBmdW5jdGlvbiBvciBBcnJheSBvZiBmdW5jdGlvbnNcbiAqIEByZXR1cm5zIHsqfSBUaGUgcmVzdWx0aW5nIHRyYW5zZm9ybWVkIGRhdGFcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB0cmFuc2Zvcm1EYXRhKGRhdGEsIGhlYWRlcnMsIGZucykge1xuICAvKmVzbGludCBuby1wYXJhbS1yZWFzc2lnbjowKi9cbiAgdXRpbHMuZm9yRWFjaChmbnMsIGZ1bmN0aW9uIHRyYW5zZm9ybShmbikge1xuICAgIGRhdGEgPSBmbihkYXRhLCBoZWFkZXJzKTtcbiAgfSk7XG5cbiAgcmV0dXJuIGRhdGE7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvdHJhbnNmb3JtRGF0YS5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvdHJhbnNmb3JtRGF0YS5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/core/transformData.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/defaults.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("/* WEBPACK VAR INJECTION */(function(process) {\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\nvar normalizeHeaderName = __webpack_require__(\"./node_modules/axios/lib/helpers/normalizeHeaderName.js\");\n\nvar DEFAULT_CONTENT_TYPE = {\n 'Content-Type': 'application/x-www-form-urlencoded'\n};\n\nfunction setContentTypeIfUnset(headers, value) {\n if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {\n headers['Content-Type'] = value;\n }\n}\n\nfunction getDefaultAdapter() {\n var adapter;\n if (typeof XMLHttpRequest !== 'undefined') {\n // For browsers use XHR adapter\n adapter = __webpack_require__(\"./node_modules/axios/lib/adapters/xhr.js\");\n } else if (typeof process !== 'undefined') {\n // For node use HTTP adapter\n adapter = __webpack_require__(\"./node_modules/axios/lib/adapters/xhr.js\");\n }\n return adapter;\n}\n\nvar defaults = {\n adapter: getDefaultAdapter(),\n\n transformRequest: [function transformRequest(data, headers) {\n normalizeHeaderName(headers, 'Content-Type');\n if (utils.isFormData(data) ||\n utils.isArrayBuffer(data) ||\n utils.isBuffer(data) ||\n utils.isStream(data) ||\n utils.isFile(data) ||\n utils.isBlob(data)\n ) {\n return data;\n }\n if (utils.isArrayBufferView(data)) {\n return data.buffer;\n }\n if (utils.isURLSearchParams(data)) {\n setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');\n return data.toString();\n }\n if (utils.isObject(data)) {\n setContentTypeIfUnset(headers, 'application/json;charset=utf-8');\n return JSON.stringify(data);\n }\n return data;\n }],\n\n transformResponse: [function transformResponse(data) {\n /*eslint no-param-reassign:0*/\n if (typeof data === 'string') {\n try {\n data = JSON.parse(data);\n } catch (e) { /* Ignore */ }\n }\n return data;\n }],\n\n /**\n * A timeout in milliseconds to abort a request. If set to 0 (default) a\n * timeout is not created.\n */\n timeout: 0,\n\n xsrfCookieName: 'XSRF-TOKEN',\n xsrfHeaderName: 'X-XSRF-TOKEN',\n\n maxContentLength: -1,\n\n validateStatus: function validateStatus(status) {\n return status >= 200 && status < 300;\n }\n};\n\ndefaults.headers = {\n common: {\n 'Accept': 'application/json, text/plain, */*'\n }\n};\n\nutils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {\n defaults.headers[method] = {};\n});\n\nutils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {\n defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);\n});\n\nmodule.exports = defaults;\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(\"./node_modules/process/browser.js\")))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2RlZmF1bHRzLmpzPzI4MjIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQWE7O0FBRWIsWUFBWSxtQkFBTyxDQUFDLG1DQUFTO0FBQzdCLDBCQUEwQixtQkFBTyxDQUFDLHlEQUErQjs7QUFFakU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLG1CQUFPLENBQUMsMENBQWdCO0FBQ3RDLEdBQUc7QUFDSDtBQUNBLGNBQWMsbUJBQU8sQ0FBQywwQ0FBaUI7QUFDdkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0VBQXdFO0FBQ3hFO0FBQ0E7QUFDQTtBQUNBLHVEQUF1RDtBQUN2RDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLFlBQVk7QUFDbkI7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBLENBQUM7O0FBRUQiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2RlZmF1bHRzLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuL3V0aWxzJyk7XG52YXIgbm9ybWFsaXplSGVhZGVyTmFtZSA9IHJlcXVpcmUoJy4vaGVscGVycy9ub3JtYWxpemVIZWFkZXJOYW1lJyk7XG5cbnZhciBERUZBVUxUX0NPTlRFTlRfVFlQRSA9IHtcbiAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnXG59O1xuXG5mdW5jdGlvbiBzZXRDb250ZW50VHlwZUlmVW5zZXQoaGVhZGVycywgdmFsdWUpIHtcbiAgaWYgKCF1dGlscy5pc1VuZGVmaW5lZChoZWFkZXJzKSAmJiB1dGlscy5pc1VuZGVmaW5lZChoZWFkZXJzWydDb250ZW50LVR5cGUnXSkpIHtcbiAgICBoZWFkZXJzWydDb250ZW50LVR5cGUnXSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldERlZmF1bHRBZGFwdGVyKCkge1xuICB2YXIgYWRhcHRlcjtcbiAgaWYgKHR5cGVvZiBYTUxIdHRwUmVxdWVzdCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAvLyBGb3IgYnJvd3NlcnMgdXNlIFhIUiBhZGFwdGVyXG4gICAgYWRhcHRlciA9IHJlcXVpcmUoJy4vYWRhcHRlcnMveGhyJyk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgLy8gRm9yIG5vZGUgdXNlIEhUVFAgYWRhcHRlclxuICAgIGFkYXB0ZXIgPSByZXF1aXJlKCcuL2FkYXB0ZXJzL2h0dHAnKTtcbiAgfVxuICByZXR1cm4gYWRhcHRlcjtcbn1cblxudmFyIGRlZmF1bHRzID0ge1xuICBhZGFwdGVyOiBnZXREZWZhdWx0QWRhcHRlcigpLFxuXG4gIHRyYW5zZm9ybVJlcXVlc3Q6IFtmdW5jdGlvbiB0cmFuc2Zvcm1SZXF1ZXN0KGRhdGEsIGhlYWRlcnMpIHtcbiAgICBub3JtYWxpemVIZWFkZXJOYW1lKGhlYWRlcnMsICdDb250ZW50LVR5cGUnKTtcbiAgICBpZiAodXRpbHMuaXNGb3JtRGF0YShkYXRhKSB8fFxuICAgICAgdXRpbHMuaXNBcnJheUJ1ZmZlcihkYXRhKSB8fFxuICAgICAgdXRpbHMuaXNCdWZmZXIoZGF0YSkgfHxcbiAgICAgIHV0aWxzLmlzU3RyZWFtKGRhdGEpIHx8XG4gICAgICB1dGlscy5pc0ZpbGUoZGF0YSkgfHxcbiAgICAgIHV0aWxzLmlzQmxvYihkYXRhKVxuICAgICkge1xuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICAgIGlmICh1dGlscy5pc0FycmF5QnVmZmVyVmlldyhkYXRhKSkge1xuICAgICAgcmV0dXJuIGRhdGEuYnVmZmVyO1xuICAgIH1cbiAgICBpZiAodXRpbHMuaXNVUkxTZWFyY2hQYXJhbXMoZGF0YSkpIHtcbiAgICAgIHNldENvbnRlbnRUeXBlSWZVbnNldChoZWFkZXJzLCAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkO2NoYXJzZXQ9dXRmLTgnKTtcbiAgICAgIHJldHVybiBkYXRhLnRvU3RyaW5nKCk7XG4gICAgfVxuICAgIGlmICh1dGlscy5pc09iamVjdChkYXRhKSkge1xuICAgICAgc2V0Q29udGVudFR5cGVJZlVuc2V0KGhlYWRlcnMsICdhcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ9dXRmLTgnKTtcbiAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShkYXRhKTtcbiAgICB9XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1dLFxuXG4gIHRyYW5zZm9ybVJlc3BvbnNlOiBbZnVuY3Rpb24gdHJhbnNmb3JtUmVzcG9uc2UoZGF0YSkge1xuICAgIC8qZXNsaW50IG5vLXBhcmFtLXJlYXNzaWduOjAqL1xuICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgfSBjYXRjaCAoZSkgeyAvKiBJZ25vcmUgKi8gfVxuICAgIH1cbiAgICByZXR1cm4gZGF0YTtcbiAgfV0sXG5cbiAgLyoqXG4gICAqIEEgdGltZW91dCBpbiBtaWxsaXNlY29uZHMgdG8gYWJvcnQgYSByZXF1ZXN0LiBJZiBzZXQgdG8gMCAoZGVmYXVsdCkgYVxuICAgKiB0aW1lb3V0IGlzIG5vdCBjcmVhdGVkLlxuICAgKi9cbiAgdGltZW91dDogMCxcblxuICB4c3JmQ29va2llTmFtZTogJ1hTUkYtVE9LRU4nLFxuICB4c3JmSGVhZGVyTmFtZTogJ1gtWFNSRi1UT0tFTicsXG5cbiAgbWF4Q29udGVudExlbmd0aDogLTEsXG5cbiAgdmFsaWRhdGVTdGF0dXM6IGZ1bmN0aW9uIHZhbGlkYXRlU3RhdHVzKHN0YXR1cykge1xuICAgIHJldHVybiBzdGF0dXMgPj0gMjAwICYmIHN0YXR1cyA8IDMwMDtcbiAgfVxufTtcblxuZGVmYXVsdHMuaGVhZGVycyA9IHtcbiAgY29tbW9uOiB7XG4gICAgJ0FjY2VwdCc6ICdhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L3BsYWluLCAqLyonXG4gIH1cbn07XG5cbnV0aWxzLmZvckVhY2goWydkZWxldGUnLCAnZ2V0JywgJ2hlYWQnXSwgZnVuY3Rpb24gZm9yRWFjaE1ldGhvZE5vRGF0YShtZXRob2QpIHtcbiAgZGVmYXVsdHMuaGVhZGVyc1ttZXRob2RdID0ge307XG59KTtcblxudXRpbHMuZm9yRWFjaChbJ3Bvc3QnLCAncHV0JywgJ3BhdGNoJ10sIGZ1bmN0aW9uIGZvckVhY2hNZXRob2RXaXRoRGF0YShtZXRob2QpIHtcbiAgZGVmYXVsdHMuaGVhZGVyc1ttZXRob2RdID0gdXRpbHMubWVyZ2UoREVGQVVMVF9DT05URU5UX1RZUEUpO1xufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gZGVmYXVsdHM7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvZGVmYXVsdHMuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9kZWZhdWx0cy5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/defaults.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/helpers/bind.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nmodule.exports = function bind(fn, thisArg) {\n return function wrap() {\n var args = new Array(arguments.length);\n for (var i = 0; i < args.length; i++) {\n args[i] = arguments[i];\n }\n return fn.apply(thisArg, args);\n };\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYmluZC5qcz8yNGZmIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixpQkFBaUI7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9iaW5kLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGJpbmQoZm4sIHRoaXNBcmcpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHdyYXAoKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhcmdzW2ldID0gYXJndW1lbnRzW2ldO1xuICAgIH1cbiAgICByZXR1cm4gZm4uYXBwbHkodGhpc0FyZywgYXJncyk7XG4gIH07XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYmluZC5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYmluZC5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/bind.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/helpers/buildURL.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\n\nfunction encode(val) {\n return encodeURIComponent(val).\n replace(/%40/gi, '@').\n replace(/%3A/gi, ':').\n replace(/%24/g, '$').\n replace(/%2C/gi, ',').\n replace(/%20/g, '+').\n replace(/%5B/gi, '[').\n replace(/%5D/gi, ']');\n}\n\n/**\n * Build a URL by appending params to the end\n *\n * @param {string} url The base of the url (e.g., http://www.google.com)\n * @param {object} [params] The params to be appended\n * @returns {string} The formatted url\n */\nmodule.exports = function buildURL(url, params, paramsSerializer) {\n /*eslint no-param-reassign:0*/\n if (!params) {\n return url;\n }\n\n var serializedParams;\n if (paramsSerializer) {\n serializedParams = paramsSerializer(params);\n } else if (utils.isURLSearchParams(params)) {\n serializedParams = params.toString();\n } else {\n var parts = [];\n\n utils.forEach(params, function serialize(val, key) {\n if (val === null || typeof val === 'undefined') {\n return;\n }\n\n if (utils.isArray(val)) {\n key = key + '[]';\n } else {\n val = [val];\n }\n\n utils.forEach(val, function parseValue(v) {\n if (utils.isDate(v)) {\n v = v.toISOString();\n } else if (utils.isObject(v)) {\n v = JSON.stringify(v);\n }\n parts.push(encode(key) + '=' + encode(v));\n });\n });\n\n serializedParams = parts.join('&');\n }\n\n if (serializedParams) {\n url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;\n }\n\n return url;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYnVpbGRVUkwuanM/MGQwMCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBYTs7QUFFYixZQUFZLG1CQUFPLENBQUMsbUNBQVk7O0FBRWhDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9oZWxwZXJzL2J1aWxkVVJMLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLy4uL3V0aWxzJyk7XG5cbmZ1bmN0aW9uIGVuY29kZSh2YWwpIHtcbiAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudCh2YWwpLlxuICAgIHJlcGxhY2UoLyU0MC9naSwgJ0AnKS5cbiAgICByZXBsYWNlKC8lM0EvZ2ksICc6JykuXG4gICAgcmVwbGFjZSgvJTI0L2csICckJykuXG4gICAgcmVwbGFjZSgvJTJDL2dpLCAnLCcpLlxuICAgIHJlcGxhY2UoLyUyMC9nLCAnKycpLlxuICAgIHJlcGxhY2UoLyU1Qi9naSwgJ1snKS5cbiAgICByZXBsYWNlKC8lNUQvZ2ksICddJyk7XG59XG5cbi8qKlxuICogQnVpbGQgYSBVUkwgYnkgYXBwZW5kaW5nIHBhcmFtcyB0byB0aGUgZW5kXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHVybCBUaGUgYmFzZSBvZiB0aGUgdXJsIChlLmcuLCBodHRwOi8vd3d3Lmdvb2dsZS5jb20pXG4gKiBAcGFyYW0ge29iamVjdH0gW3BhcmFtc10gVGhlIHBhcmFtcyB0byBiZSBhcHBlbmRlZFxuICogQHJldHVybnMge3N0cmluZ30gVGhlIGZvcm1hdHRlZCB1cmxcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBidWlsZFVSTCh1cmwsIHBhcmFtcywgcGFyYW1zU2VyaWFsaXplcikge1xuICAvKmVzbGludCBuby1wYXJhbS1yZWFzc2lnbjowKi9cbiAgaWYgKCFwYXJhbXMpIHtcbiAgICByZXR1cm4gdXJsO1xuICB9XG5cbiAgdmFyIHNlcmlhbGl6ZWRQYXJhbXM7XG4gIGlmIChwYXJhbXNTZXJpYWxpemVyKSB7XG4gICAgc2VyaWFsaXplZFBhcmFtcyA9IHBhcmFtc1NlcmlhbGl6ZXIocGFyYW1zKTtcbiAgfSBlbHNlIGlmICh1dGlscy5pc1VSTFNlYXJjaFBhcmFtcyhwYXJhbXMpKSB7XG4gICAgc2VyaWFsaXplZFBhcmFtcyA9IHBhcmFtcy50b1N0cmluZygpO1xuICB9IGVsc2Uge1xuICAgIHZhciBwYXJ0cyA9IFtdO1xuXG4gICAgdXRpbHMuZm9yRWFjaChwYXJhbXMsIGZ1bmN0aW9uIHNlcmlhbGl6ZSh2YWwsIGtleSkge1xuICAgICAgaWYgKHZhbCA9PT0gbnVsbCB8fCB0eXBlb2YgdmFsID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICh1dGlscy5pc0FycmF5KHZhbCkpIHtcbiAgICAgICAga2V5ID0ga2V5ICsgJ1tdJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhbCA9IFt2YWxdO1xuICAgICAgfVxuXG4gICAgICB1dGlscy5mb3JFYWNoKHZhbCwgZnVuY3Rpb24gcGFyc2VWYWx1ZSh2KSB7XG4gICAgICAgIGlmICh1dGlscy5pc0RhdGUodikpIHtcbiAgICAgICAgICB2ID0gdi50b0lTT1N0cmluZygpO1xuICAgICAgICB9IGVsc2UgaWYgKHV0aWxzLmlzT2JqZWN0KHYpKSB7XG4gICAgICAgICAgdiA9IEpTT04uc3RyaW5naWZ5KHYpO1xuICAgICAgICB9XG4gICAgICAgIHBhcnRzLnB1c2goZW5jb2RlKGtleSkgKyAnPScgKyBlbmNvZGUodikpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICBzZXJpYWxpemVkUGFyYW1zID0gcGFydHMuam9pbignJicpO1xuICB9XG5cbiAgaWYgKHNlcmlhbGl6ZWRQYXJhbXMpIHtcbiAgICB1cmwgKz0gKHVybC5pbmRleE9mKCc/JykgPT09IC0xID8gJz8nIDogJyYnKSArIHNlcmlhbGl6ZWRQYXJhbXM7XG4gIH1cblxuICByZXR1cm4gdXJsO1xufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9oZWxwZXJzL2J1aWxkVVJMLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9idWlsZFVSTC5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/buildURL.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/helpers/combineURLs.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\n/**\n * Creates a new URL by combining the specified URLs\n *\n * @param {string} baseURL The base URL\n * @param {string} relativeURL The relative URL\n * @returns {string} The combined URL\n */\nmodule.exports = function combineURLs(baseURL, relativeURL) {\n return relativeURL\n ? baseURL.replace(/\\/+$/, '') + '/' + relativeURL.replace(/^\\/+/, '')\n : baseURL;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvY29tYmluZVVSTHMuanM/YTkxNyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvY29tYmluZVVSTHMuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBVUkwgYnkgY29tYmluaW5nIHRoZSBzcGVjaWZpZWQgVVJMc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlVVJMIFRoZSBiYXNlIFVSTFxuICogQHBhcmFtIHtzdHJpbmd9IHJlbGF0aXZlVVJMIFRoZSByZWxhdGl2ZSBVUkxcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjb21iaW5lZCBVUkxcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjb21iaW5lVVJMcyhiYXNlVVJMLCByZWxhdGl2ZVVSTCkge1xuICByZXR1cm4gcmVsYXRpdmVVUkxcbiAgICA/IGJhc2VVUkwucmVwbGFjZSgvXFwvKyQvLCAnJykgKyAnLycgKyByZWxhdGl2ZVVSTC5yZXBsYWNlKC9eXFwvKy8sICcnKVxuICAgIDogYmFzZVVSTDtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9jb21iaW5lVVJMcy5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvY29tYmluZVVSTHMuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/combineURLs.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/helpers/cookies.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\n\nmodule.exports = (\n utils.isStandardBrowserEnv() ?\n\n // Standard browser envs support document.cookie\n (function standardBrowserEnv() {\n return {\n write: function write(name, value, expires, path, domain, secure) {\n var cookie = [];\n cookie.push(name + '=' + encodeURIComponent(value));\n\n if (utils.isNumber(expires)) {\n cookie.push('expires=' + new Date(expires).toGMTString());\n }\n\n if (utils.isString(path)) {\n cookie.push('path=' + path);\n }\n\n if (utils.isString(domain)) {\n cookie.push('domain=' + domain);\n }\n\n if (secure === true) {\n cookie.push('secure');\n }\n\n document.cookie = cookie.join('; ');\n },\n\n read: function read(name) {\n var match = document.cookie.match(new RegExp('(^|;\\\\s*)(' + name + ')=([^;]*)'));\n return (match ? decodeURIComponent(match[3]) : null);\n },\n\n remove: function remove(name) {\n this.write(name, '', Date.now() - 86400000);\n }\n };\n })() :\n\n // Non standard browser env (web workers, react-native) lack needed support.\n (function nonStandardBrowserEnv() {\n return {\n write: function write() {},\n read: function read() { return null; },\n remove: function remove() {}\n };\n })()\n);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvY29va2llcy5qcz9hNzU2Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFhOztBQUViLFlBQVksbUJBQU8sQ0FBQyxtQ0FBWTs7QUFFaEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHdDQUF3QztBQUN4QyxPQUFPOztBQUVQO0FBQ0EsMERBQTBELHdCQUF3QjtBQUNsRjtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQztBQUNoQyw2QkFBNkIsYUFBYSxFQUFFO0FBQzVDO0FBQ0E7QUFDQSxHQUFHO0FBQ0giLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvY29va2llcy5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzID0gcmVxdWlyZSgnLi8uLi91dGlscycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IChcbiAgdXRpbHMuaXNTdGFuZGFyZEJyb3dzZXJFbnYoKSA/XG5cbiAgLy8gU3RhbmRhcmQgYnJvd3NlciBlbnZzIHN1cHBvcnQgZG9jdW1lbnQuY29va2llXG4gIChmdW5jdGlvbiBzdGFuZGFyZEJyb3dzZXJFbnYoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHdyaXRlOiBmdW5jdGlvbiB3cml0ZShuYW1lLCB2YWx1ZSwgZXhwaXJlcywgcGF0aCwgZG9tYWluLCBzZWN1cmUpIHtcbiAgICAgICAgdmFyIGNvb2tpZSA9IFtdO1xuICAgICAgICBjb29raWUucHVzaChuYW1lICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKSk7XG5cbiAgICAgICAgaWYgKHV0aWxzLmlzTnVtYmVyKGV4cGlyZXMpKSB7XG4gICAgICAgICAgY29va2llLnB1c2goJ2V4cGlyZXM9JyArIG5ldyBEYXRlKGV4cGlyZXMpLnRvR01UU3RyaW5nKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHV0aWxzLmlzU3RyaW5nKHBhdGgpKSB7XG4gICAgICAgICAgY29va2llLnB1c2goJ3BhdGg9JyArIHBhdGgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHV0aWxzLmlzU3RyaW5nKGRvbWFpbikpIHtcbiAgICAgICAgICBjb29raWUucHVzaCgnZG9tYWluPScgKyBkb21haW4pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNlY3VyZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgIGNvb2tpZS5wdXNoKCdzZWN1cmUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRvY3VtZW50LmNvb2tpZSA9IGNvb2tpZS5qb2luKCc7ICcpO1xuICAgICAgfSxcblxuICAgICAgcmVhZDogZnVuY3Rpb24gcmVhZChuYW1lKSB7XG4gICAgICAgIHZhciBtYXRjaCA9IGRvY3VtZW50LmNvb2tpZS5tYXRjaChuZXcgUmVnRXhwKCcoXnw7XFxcXHMqKSgnICsgbmFtZSArICcpPShbXjtdKiknKSk7XG4gICAgICAgIHJldHVybiAobWF0Y2ggPyBkZWNvZGVVUklDb21wb25lbnQobWF0Y2hbM10pIDogbnVsbCk7XG4gICAgICB9LFxuXG4gICAgICByZW1vdmU6IGZ1bmN0aW9uIHJlbW92ZShuYW1lKSB7XG4gICAgICAgIHRoaXMud3JpdGUobmFtZSwgJycsIERhdGUubm93KCkgLSA4NjQwMDAwMCk7XG4gICAgICB9XG4gICAgfTtcbiAgfSkoKSA6XG5cbiAgLy8gTm9uIHN0YW5kYXJkIGJyb3dzZXIgZW52ICh3ZWIgd29ya2VycywgcmVhY3QtbmF0aXZlKSBsYWNrIG5lZWRlZCBzdXBwb3J0LlxuICAoZnVuY3Rpb24gbm9uU3RhbmRhcmRCcm93c2VyRW52KCkge1xuICAgIHJldHVybiB7XG4gICAgICB3cml0ZTogZnVuY3Rpb24gd3JpdGUoKSB7fSxcbiAgICAgIHJlYWQ6IGZ1bmN0aW9uIHJlYWQoKSB7IHJldHVybiBudWxsOyB9LFxuICAgICAgcmVtb3ZlOiBmdW5jdGlvbiByZW1vdmUoKSB7fVxuICAgIH07XG4gIH0pKClcbik7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9jb29raWVzLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9jb29raWVzLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/cookies.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/helpers/isAbsoluteURL.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\n/**\n * Determines whether the specified URL is absolute\n *\n * @param {string} url The URL to test\n * @returns {boolean} True if the specified URL is absolute, otherwise false\n */\nmodule.exports = function isAbsoluteURL(url) {\n // A URL is considered absolute if it begins with \"<scheme>://\" or \"//\" (protocol-relative URL).\n // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed\n // by any combination of letters, digits, plus, period, or hyphen.\n return /^([a-z][a-z\\d\\+\\-\\.]*:)?\\/\\//i.test(url);\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNBYnNvbHV0ZVVSTC5qcz83NDhjIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNBYnNvbHV0ZVVSTC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlIHNwZWNpZmllZCBVUkwgaXMgYWJzb2x1dGVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIFRoZSBVUkwgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHNwZWNpZmllZCBVUkwgaXMgYWJzb2x1dGUsIG90aGVyd2lzZSBmYWxzZVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzQWJzb2x1dGVVUkwodXJsKSB7XG4gIC8vIEEgVVJMIGlzIGNvbnNpZGVyZWQgYWJzb2x1dGUgaWYgaXQgYmVnaW5zIHdpdGggXCI8c2NoZW1lPjovL1wiIG9yIFwiLy9cIiAocHJvdG9jb2wtcmVsYXRpdmUgVVJMKS5cbiAgLy8gUkZDIDM5ODYgZGVmaW5lcyBzY2hlbWUgbmFtZSBhcyBhIHNlcXVlbmNlIG9mIGNoYXJhY3RlcnMgYmVnaW5uaW5nIHdpdGggYSBsZXR0ZXIgYW5kIGZvbGxvd2VkXG4gIC8vIGJ5IGFueSBjb21iaW5hdGlvbiBvZiBsZXR0ZXJzLCBkaWdpdHMsIHBsdXMsIHBlcmlvZCwgb3IgaHlwaGVuLlxuICByZXR1cm4gL14oW2Etel1bYS16XFxkXFwrXFwtXFwuXSo6KT9cXC9cXC8vaS50ZXN0KHVybCk7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNBYnNvbHV0ZVVSTC5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNBYnNvbHV0ZVVSTC5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/isAbsoluteURL.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/helpers/isURLSameOrigin.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\n\nmodule.exports = (\n utils.isStandardBrowserEnv() ?\n\n // Standard browser envs have full support of the APIs needed to test\n // whether the request URL is of the same origin as current location.\n (function standardBrowserEnv() {\n var msie = /(msie|trident)/i.test(navigator.userAgent);\n var urlParsingNode = document.createElement('a');\n var originURL;\n\n /**\n * Parse a URL to discover it's components\n *\n * @param {String} url The URL to be parsed\n * @returns {Object}\n */\n function resolveURL(url) {\n var href = url;\n\n if (msie) {\n // IE needs attribute set twice to normalize properties\n urlParsingNode.setAttribute('href', href);\n href = urlParsingNode.href;\n }\n\n urlParsingNode.setAttribute('href', href);\n\n // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils\n return {\n href: urlParsingNode.href,\n protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',\n host: urlParsingNode.host,\n search: urlParsingNode.search ? urlParsingNode.search.replace(/^\\?/, '') : '',\n hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',\n hostname: urlParsingNode.hostname,\n port: urlParsingNode.port,\n pathname: (urlParsingNode.pathname.charAt(0) === '/') ?\n urlParsingNode.pathname :\n '/' + urlParsingNode.pathname\n };\n }\n\n originURL = resolveURL(window.location.href);\n\n /**\n * Determine if a URL shares the same origin as the current location\n *\n * @param {String} requestURL The URL to test\n * @returns {boolean} True if URL shares the same origin, otherwise false\n */\n return function isURLSameOrigin(requestURL) {\n var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;\n return (parsed.protocol === originURL.protocol &&\n parsed.host === originURL.host);\n };\n })() :\n\n // Non standard browser envs (web workers, react-native) lack needed support.\n (function nonStandardBrowserEnv() {\n return function isURLSameOrigin() {\n return true;\n };\n })()\n);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNVUkxTYW1lT3JpZ2luLmpzPzE4NzAiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWIsWUFBWSxtQkFBTyxDQUFDLG1DQUFZOztBQUVoQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsZ0JBQWdCO0FBQ2hCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGdCQUFnQixRQUFRO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9pc1VSTFNhbWVPcmlnaW4uanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlscyA9IHJlcXVpcmUoJy4vLi4vdXRpbHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSAoXG4gIHV0aWxzLmlzU3RhbmRhcmRCcm93c2VyRW52KCkgP1xuXG4gIC8vIFN0YW5kYXJkIGJyb3dzZXIgZW52cyBoYXZlIGZ1bGwgc3VwcG9ydCBvZiB0aGUgQVBJcyBuZWVkZWQgdG8gdGVzdFxuICAvLyB3aGV0aGVyIHRoZSByZXF1ZXN0IFVSTCBpcyBvZiB0aGUgc2FtZSBvcmlnaW4gYXMgY3VycmVudCBsb2NhdGlvbi5cbiAgKGZ1bmN0aW9uIHN0YW5kYXJkQnJvd3NlckVudigpIHtcbiAgICB2YXIgbXNpZSA9IC8obXNpZXx0cmlkZW50KS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgdmFyIHVybFBhcnNpbmdOb2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgIHZhciBvcmlnaW5VUkw7XG5cbiAgICAvKipcbiAgICAqIFBhcnNlIGEgVVJMIHRvIGRpc2NvdmVyIGl0J3MgY29tcG9uZW50c1xuICAgICpcbiAgICAqIEBwYXJhbSB7U3RyaW5nfSB1cmwgVGhlIFVSTCB0byBiZSBwYXJzZWRcbiAgICAqIEByZXR1cm5zIHtPYmplY3R9XG4gICAgKi9cbiAgICBmdW5jdGlvbiByZXNvbHZlVVJMKHVybCkge1xuICAgICAgdmFyIGhyZWYgPSB1cmw7XG5cbiAgICAgIGlmIChtc2llKSB7XG4gICAgICAgIC8vIElFIG5lZWRzIGF0dHJpYnV0ZSBzZXQgdHdpY2UgdG8gbm9ybWFsaXplIHByb3BlcnRpZXNcbiAgICAgICAgdXJsUGFyc2luZ05vZGUuc2V0QXR0cmlidXRlKCdocmVmJywgaHJlZik7XG4gICAgICAgIGhyZWYgPSB1cmxQYXJzaW5nTm9kZS5ocmVmO1xuICAgICAgfVxuXG4gICAgICB1cmxQYXJzaW5nTm9kZS5zZXRBdHRyaWJ1dGUoJ2hyZWYnLCBocmVmKTtcblxuICAgICAgLy8gdXJsUGFyc2luZ05vZGUgcHJvdmlkZXMgdGhlIFVybFV0aWxzIGludGVyZmFjZSAtIGh0dHA6Ly91cmwuc3BlYy53aGF0d2cub3JnLyN1cmx1dGlsc1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaHJlZjogdXJsUGFyc2luZ05vZGUuaHJlZixcbiAgICAgICAgcHJvdG9jb2w6IHVybFBhcnNpbmdOb2RlLnByb3RvY29sID8gdXJsUGFyc2luZ05vZGUucHJvdG9jb2wucmVwbGFjZSgvOiQvLCAnJykgOiAnJyxcbiAgICAgICAgaG9zdDogdXJsUGFyc2luZ05vZGUuaG9zdCxcbiAgICAgICAgc2VhcmNoOiB1cmxQYXJzaW5nTm9kZS5zZWFyY2ggPyB1cmxQYXJzaW5nTm9kZS5zZWFyY2gucmVwbGFjZSgvXlxcPy8sICcnKSA6ICcnLFxuICAgICAgICBoYXNoOiB1cmxQYXJzaW5nTm9kZS5oYXNoID8gdXJsUGFyc2luZ05vZGUuaGFzaC5yZXBsYWNlKC9eIy8sICcnKSA6ICcnLFxuICAgICAgICBob3N0bmFtZTogdXJsUGFyc2luZ05vZGUuaG9zdG5hbWUsXG4gICAgICAgIHBvcnQ6IHVybFBhcnNpbmdOb2RlLnBvcnQsXG4gICAgICAgIHBhdGhuYW1lOiAodXJsUGFyc2luZ05vZGUucGF0aG5hbWUuY2hhckF0KDApID09PSAnLycpID9cbiAgICAgICAgICAgICAgICAgIHVybFBhcnNpbmdOb2RlLnBhdGhuYW1lIDpcbiAgICAgICAgICAgICAgICAgICcvJyArIHVybFBhcnNpbmdOb2RlLnBhdGhuYW1lXG4gICAgICB9O1xuICAgIH1cblxuICAgIG9yaWdpblVSTCA9IHJlc29sdmVVUkwod2luZG93LmxvY2F0aW9uLmhyZWYpO1xuXG4gICAgLyoqXG4gICAgKiBEZXRlcm1pbmUgaWYgYSBVUkwgc2hhcmVzIHRoZSBzYW1lIG9yaWdpbiBhcyB0aGUgY3VycmVudCBsb2NhdGlvblxuICAgICpcbiAgICAqIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0VVJMIFRoZSBVUkwgdG8gdGVzdFxuICAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgVVJMIHNoYXJlcyB0aGUgc2FtZSBvcmlnaW4sIG90aGVyd2lzZSBmYWxzZVxuICAgICovXG4gICAgcmV0dXJuIGZ1bmN0aW9uIGlzVVJMU2FtZU9yaWdpbihyZXF1ZXN0VVJMKSB7XG4gICAgICB2YXIgcGFyc2VkID0gKHV0aWxzLmlzU3RyaW5nKHJlcXVlc3RVUkwpKSA/IHJlc29sdmVVUkwocmVxdWVzdFVSTCkgOiByZXF1ZXN0VVJMO1xuICAgICAgcmV0dXJuIChwYXJzZWQucHJvdG9jb2wgPT09IG9yaWdpblVSTC5wcm90b2NvbCAmJlxuICAgICAgICAgICAgcGFyc2VkLmhvc3QgPT09IG9yaWdpblVSTC5ob3N0KTtcbiAgICB9O1xuICB9KSgpIDpcblxuICAvLyBOb24gc3RhbmRhcmQgYnJvd3NlciBlbnZzICh3ZWIgd29ya2VycywgcmVhY3QtbmF0aXZlKSBsYWNrIG5lZWRlZCBzdXBwb3J0LlxuICAoZnVuY3Rpb24gbm9uU3RhbmRhcmRCcm93c2VyRW52KCkge1xuICAgIHJldHVybiBmdW5jdGlvbiBpc1VSTFNhbWVPcmlnaW4oKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICB9KSgpXG4pO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNVUkxTYW1lT3JpZ2luLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9pc1VSTFNhbWVPcmlnaW4uanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/isURLSameOrigin.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/helpers/normalizeHeaderName.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\n\nmodule.exports = function normalizeHeaderName(headers, normalizedName) {\n utils.forEach(headers, function processHeader(value, name) {\n if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {\n headers[normalizedName] = value;\n delete headers[name];\n }\n });\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvbm9ybWFsaXplSGVhZGVyTmFtZS5qcz9lNTU0Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFhOztBQUViLFlBQVksbUJBQU8sQ0FBQyxtQ0FBVTs7QUFFOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9oZWxwZXJzL25vcm1hbGl6ZUhlYWRlck5hbWUuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlscyA9IHJlcXVpcmUoJy4uL3V0aWxzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbm9ybWFsaXplSGVhZGVyTmFtZShoZWFkZXJzLCBub3JtYWxpemVkTmFtZSkge1xuICB1dGlscy5mb3JFYWNoKGhlYWRlcnMsIGZ1bmN0aW9uIHByb2Nlc3NIZWFkZXIodmFsdWUsIG5hbWUpIHtcbiAgICBpZiAobmFtZSAhPT0gbm9ybWFsaXplZE5hbWUgJiYgbmFtZS50b1VwcGVyQ2FzZSgpID09PSBub3JtYWxpemVkTmFtZS50b1VwcGVyQ2FzZSgpKSB7XG4gICAgICBoZWFkZXJzW25vcm1hbGl6ZWROYW1lXSA9IHZhbHVlO1xuICAgICAgZGVsZXRlIGhlYWRlcnNbbmFtZV07XG4gICAgfVxuICB9KTtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9ub3JtYWxpemVIZWFkZXJOYW1lLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9ub3JtYWxpemVIZWFkZXJOYW1lLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/normalizeHeaderName.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/helpers/parseHeaders.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar utils = __webpack_require__(\"./node_modules/axios/lib/utils.js\");\n\n// Headers whose duplicates are ignored by node\n// c.f. https://nodejs.org/api/http.html#http_message_headers\nvar ignoreDuplicateOf = [\n 'age', 'authorization', 'content-length', 'content-type', 'etag',\n 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',\n 'last-modified', 'location', 'max-forwards', 'proxy-authorization',\n 'referer', 'retry-after', 'user-agent'\n];\n\n/**\n * Parse headers into an object\n *\n * ```\n * Date: Wed, 27 Aug 2014 08:58:49 GMT\n * Content-Type: application/json\n * Connection: keep-alive\n * Transfer-Encoding: chunked\n * ```\n *\n * @param {String} headers Headers needing to be parsed\n * @returns {Object} Headers parsed into an object\n */\nmodule.exports = function parseHeaders(headers) {\n var parsed = {};\n var key;\n var val;\n var i;\n\n if (!headers) { return parsed; }\n\n utils.forEach(headers.split('\\n'), function parser(line) {\n i = line.indexOf(':');\n key = utils.trim(line.substr(0, i)).toLowerCase();\n val = utils.trim(line.substr(i + 1));\n\n if (key) {\n if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {\n return;\n }\n if (key === 'set-cookie') {\n parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]);\n } else {\n parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;\n }\n }\n });\n\n return parsed;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvcGFyc2VIZWFkZXJzLmpzP2EwOTkiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWIsWUFBWSxtQkFBTyxDQUFDLG1DQUFZOztBQUVoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLGVBQWU7O0FBRWhDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvcGFyc2VIZWFkZXJzLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLy4uL3V0aWxzJyk7XG5cbi8vIEhlYWRlcnMgd2hvc2UgZHVwbGljYXRlcyBhcmUgaWdub3JlZCBieSBub2RlXG4vLyBjLmYuIGh0dHBzOi8vbm9kZWpzLm9yZy9hcGkvaHR0cC5odG1sI2h0dHBfbWVzc2FnZV9oZWFkZXJzXG52YXIgaWdub3JlRHVwbGljYXRlT2YgPSBbXG4gICdhZ2UnLCAnYXV0aG9yaXphdGlvbicsICdjb250ZW50LWxlbmd0aCcsICdjb250ZW50LXR5cGUnLCAnZXRhZycsXG4gICdleHBpcmVzJywgJ2Zyb20nLCAnaG9zdCcsICdpZi1tb2RpZmllZC1zaW5jZScsICdpZi11bm1vZGlmaWVkLXNpbmNlJyxcbiAgJ2xhc3QtbW9kaWZpZWQnLCAnbG9jYXRpb24nLCAnbWF4LWZvcndhcmRzJywgJ3Byb3h5LWF1dGhvcml6YXRpb24nLFxuICAncmVmZXJlcicsICdyZXRyeS1hZnRlcicsICd1c2VyLWFnZW50J1xuXTtcblxuLyoqXG4gKiBQYXJzZSBoZWFkZXJzIGludG8gYW4gb2JqZWN0XG4gKlxuICogYGBgXG4gKiBEYXRlOiBXZWQsIDI3IEF1ZyAyMDE0IDA4OjU4OjQ5IEdNVFxuICogQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uXG4gKiBDb25uZWN0aW9uOiBrZWVwLWFsaXZlXG4gKiBUcmFuc2Zlci1FbmNvZGluZzogY2h1bmtlZFxuICogYGBgXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGhlYWRlcnMgSGVhZGVycyBuZWVkaW5nIHRvIGJlIHBhcnNlZFxuICogQHJldHVybnMge09iamVjdH0gSGVhZGVycyBwYXJzZWQgaW50byBhbiBvYmplY3RcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYXJzZUhlYWRlcnMoaGVhZGVycykge1xuICB2YXIgcGFyc2VkID0ge307XG4gIHZhciBrZXk7XG4gIHZhciB2YWw7XG4gIHZhciBpO1xuXG4gIGlmICghaGVhZGVycykgeyByZXR1cm4gcGFyc2VkOyB9XG5cbiAgdXRpbHMuZm9yRWFjaChoZWFkZXJzLnNwbGl0KCdcXG4nKSwgZnVuY3Rpb24gcGFyc2VyKGxpbmUpIHtcbiAgICBpID0gbGluZS5pbmRleE9mKCc6Jyk7XG4gICAga2V5ID0gdXRpbHMudHJpbShsaW5lLnN1YnN0cigwLCBpKSkudG9Mb3dlckNhc2UoKTtcbiAgICB2YWwgPSB1dGlscy50cmltKGxpbmUuc3Vic3RyKGkgKyAxKSk7XG5cbiAgICBpZiAoa2V5KSB7XG4gICAgICBpZiAocGFyc2VkW2tleV0gJiYgaWdub3JlRHVwbGljYXRlT2YuaW5kZXhPZihrZXkpID49IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGtleSA9PT0gJ3NldC1jb29raWUnKSB7XG4gICAgICAgIHBhcnNlZFtrZXldID0gKHBhcnNlZFtrZXldID8gcGFyc2VkW2tleV0gOiBbXSkuY29uY2F0KFt2YWxdKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhcnNlZFtrZXldID0gcGFyc2VkW2tleV0gPyBwYXJzZWRba2V5XSArICcsICcgKyB2YWwgOiB2YWw7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gcGFyc2VkO1xufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9oZWxwZXJzL3BhcnNlSGVhZGVycy5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvcGFyc2VIZWFkZXJzLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/parseHeaders.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/helpers/spread.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\n/**\n * Syntactic sugar for invoking a function and expanding an array for arguments.\n *\n * Common use case would be to use `Function.prototype.apply`.\n *\n * ```js\n * function f(x, y, z) {}\n * var args = [1, 2, 3];\n * f.apply(null, args);\n * ```\n *\n * With `spread` this example can be re-written.\n *\n * ```js\n * spread(function(x, y, z) {})([1, 2, 3]);\n * ```\n *\n * @param {Function} callback\n * @returns {Function}\n */\nmodule.exports = function spread(callback) {\n return function wrap(arr) {\n return callback.apply(null, arr);\n };\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvc3ByZWFkLmpzP2E3MTEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvc3ByZWFkLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIFN5bnRhY3RpYyBzdWdhciBmb3IgaW52b2tpbmcgYSBmdW5jdGlvbiBhbmQgZXhwYW5kaW5nIGFuIGFycmF5IGZvciBhcmd1bWVudHMuXG4gKlxuICogQ29tbW9uIHVzZSBjYXNlIHdvdWxkIGJlIHRvIHVzZSBgRnVuY3Rpb24ucHJvdG90eXBlLmFwcGx5YC5cbiAqXG4gKiAgYGBganNcbiAqICBmdW5jdGlvbiBmKHgsIHksIHopIHt9XG4gKiAgdmFyIGFyZ3MgPSBbMSwgMiwgM107XG4gKiAgZi5hcHBseShudWxsLCBhcmdzKTtcbiAqICBgYGBcbiAqXG4gKiBXaXRoIGBzcHJlYWRgIHRoaXMgZXhhbXBsZSBjYW4gYmUgcmUtd3JpdHRlbi5cbiAqXG4gKiAgYGBganNcbiAqICBzcHJlYWQoZnVuY3Rpb24oeCwgeSwgeikge30pKFsxLCAyLCAzXSk7XG4gKiAgYGBgXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn1cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzcHJlYWQoY2FsbGJhY2spIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHdyYXAoYXJyKSB7XG4gICAgcmV0dXJuIGNhbGxiYWNrLmFwcGx5KG51bGwsIGFycik7XG4gIH07XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvc3ByZWFkLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9zcHJlYWQuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/spread.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/utils.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\nvar bind = __webpack_require__(\"./node_modules/axios/lib/helpers/bind.js\");\nvar isBuffer = __webpack_require__(\"./node_modules/axios/node_modules/is-buffer/index.js\");\n\n/*global toString:true*/\n\n// utils is a library of generic helper functions non-specific to axios\n\nvar toString = Object.prototype.toString;\n\n/**\n * Determine if a value is an Array\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an Array, otherwise false\n */\nfunction isArray(val) {\n return toString.call(val) === '[object Array]';\n}\n\n/**\n * Determine if a value is an ArrayBuffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an ArrayBuffer, otherwise false\n */\nfunction isArrayBuffer(val) {\n return toString.call(val) === '[object ArrayBuffer]';\n}\n\n/**\n * Determine if a value is a FormData\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an FormData, otherwise false\n */\nfunction isFormData(val) {\n return (typeof FormData !== 'undefined') && (val instanceof FormData);\n}\n\n/**\n * Determine if a value is a view on an ArrayBuffer\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false\n */\nfunction isArrayBufferView(val) {\n var result;\n if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {\n result = ArrayBuffer.isView(val);\n } else {\n result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);\n }\n return result;\n}\n\n/**\n * Determine if a value is a String\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a String, otherwise false\n */\nfunction isString(val) {\n return typeof val === 'string';\n}\n\n/**\n * Determine if a value is a Number\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Number, otherwise false\n */\nfunction isNumber(val) {\n return typeof val === 'number';\n}\n\n/**\n * Determine if a value is undefined\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if the value is undefined, otherwise false\n */\nfunction isUndefined(val) {\n return typeof val === 'undefined';\n}\n\n/**\n * Determine if a value is an Object\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is an Object, otherwise false\n */\nfunction isObject(val) {\n return val !== null && typeof val === 'object';\n}\n\n/**\n * Determine if a value is a Date\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Date, otherwise false\n */\nfunction isDate(val) {\n return toString.call(val) === '[object Date]';\n}\n\n/**\n * Determine if a value is a File\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a File, otherwise false\n */\nfunction isFile(val) {\n return toString.call(val) === '[object File]';\n}\n\n/**\n * Determine if a value is a Blob\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Blob, otherwise false\n */\nfunction isBlob(val) {\n return toString.call(val) === '[object Blob]';\n}\n\n/**\n * Determine if a value is a Function\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Function, otherwise false\n */\nfunction isFunction(val) {\n return toString.call(val) === '[object Function]';\n}\n\n/**\n * Determine if a value is a Stream\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a Stream, otherwise false\n */\nfunction isStream(val) {\n return isObject(val) && isFunction(val.pipe);\n}\n\n/**\n * Determine if a value is a URLSearchParams object\n *\n * @param {Object} val The value to test\n * @returns {boolean} True if value is a URLSearchParams object, otherwise false\n */\nfunction isURLSearchParams(val) {\n return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;\n}\n\n/**\n * Trim excess whitespace off the beginning and end of a string\n *\n * @param {String} str The String to trim\n * @returns {String} The String freed of excess whitespace\n */\nfunction trim(str) {\n return str.replace(/^\\s*/, '').replace(/\\s*$/, '');\n}\n\n/**\n * Determine if we're running in a standard browser environment\n *\n * This allows axios to run in a web worker, and react-native.\n * Both environments support XMLHttpRequest, but not fully standard globals.\n *\n * web workers:\n * typeof window -> undefined\n * typeof document -> undefined\n *\n * react-native:\n * navigator.product -> 'ReactNative'\n */\nfunction isStandardBrowserEnv() {\n if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {\n return false;\n }\n return (\n typeof window !== 'undefined' &&\n typeof document !== 'undefined'\n );\n}\n\n/**\n * Iterate over an Array or an Object invoking a function for each item.\n *\n * If `obj` is an Array callback will be called passing\n * the value, index, and complete array for each item.\n *\n * If 'obj' is an Object callback will be called passing\n * the value, key, and complete object for each property.\n *\n * @param {Object|Array} obj The object to iterate\n * @param {Function} fn The callback to invoke for each item\n */\nfunction forEach(obj, fn) {\n // Don't bother if no value provided\n if (obj === null || typeof obj === 'undefined') {\n return;\n }\n\n // Force an array if not already something iterable\n if (typeof obj !== 'object') {\n /*eslint no-param-reassign:0*/\n obj = [obj];\n }\n\n if (isArray(obj)) {\n // Iterate over array values\n for (var i = 0, l = obj.length; i < l; i++) {\n fn.call(null, obj[i], i, obj);\n }\n } else {\n // Iterate over object keys\n for (var key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n fn.call(null, obj[key], key, obj);\n }\n }\n }\n}\n\n/**\n * Accepts varargs expecting each argument to be an object, then\n * immutably merges the properties of each object and returns result.\n *\n * When multiple objects contain the same key the later object in\n * the arguments list will take precedence.\n *\n * Example:\n *\n * ```js\n * var result = merge({foo: 123}, {foo: 456});\n * console.log(result.foo); // outputs 456\n * ```\n *\n * @param {Object} obj1 Object to merge\n * @returns {Object} Result of all merge properties\n */\nfunction merge(/* obj1, obj2, obj3, ... */) {\n var result = {};\n function assignValue(val, key) {\n if (typeof result[key] === 'object' && typeof val === 'object') {\n result[key] = merge(result[key], val);\n } else {\n result[key] = val;\n }\n }\n\n for (var i = 0, l = arguments.length; i < l; i++) {\n forEach(arguments[i], assignValue);\n }\n return result;\n}\n\n/**\n * Extends object a by mutably adding to it the properties of object b.\n *\n * @param {Object} a The object to be extended\n * @param {Object} b The object to copy properties from\n * @param {Object} thisArg The object to bind function to\n * @return {Object} The resulting value of object a\n */\nfunction extend(a, b, thisArg) {\n forEach(b, function assignValue(val, key) {\n if (thisArg && typeof val === 'function') {\n a[key] = bind(val, thisArg);\n } else {\n a[key] = val;\n }\n });\n return a;\n}\n\nmodule.exports = {\n isArray: isArray,\n isArrayBuffer: isArrayBuffer,\n isBuffer: isBuffer,\n isFormData: isFormData,\n isArrayBufferView: isArrayBufferView,\n isString: isString,\n isNumber: isNumber,\n isObject: isObject,\n isUndefined: isUndefined,\n isDate: isDate,\n isFile: isFile,\n isBlob: isBlob,\n isFunction: isFunction,\n isStream: isStream,\n isURLSearchParams: isURLSearchParams,\n isStandardBrowserEnv: isStandardBrowserEnv,\n forEach: forEach,\n merge: merge,\n extend: extend,\n trim: trim\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL3V0aWxzLmpzPzcwNjEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQWE7O0FBRWIsV0FBVyxtQkFBTyxDQUFDLDBDQUFnQjtBQUNuQyxlQUFlLG1CQUFPLENBQUMsc0RBQVc7O0FBRWxDOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxhQUFhO0FBQ3hCLFdBQVcsU0FBUztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUNBQW1DLE9BQU87QUFDMUM7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLFNBQVMsR0FBRyxTQUFTO0FBQzVDLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBLHVDQUF1QyxPQUFPO0FBQzlDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvdXRpbHMuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciBiaW5kID0gcmVxdWlyZSgnLi9oZWxwZXJzL2JpbmQnKTtcbnZhciBpc0J1ZmZlciA9IHJlcXVpcmUoJ2lzLWJ1ZmZlcicpO1xuXG4vKmdsb2JhbCB0b1N0cmluZzp0cnVlKi9cblxuLy8gdXRpbHMgaXMgYSBsaWJyYXJ5IG9mIGdlbmVyaWMgaGVscGVyIGZ1bmN0aW9ucyBub24tc3BlY2lmaWMgdG8gYXhpb3NcblxudmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhbiBBcnJheVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGFuIEFycmF5LCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNBcnJheSh2YWwpIHtcbiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwodmFsKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhbiBBcnJheUJ1ZmZlclxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGFuIEFycmF5QnVmZmVyLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNBcnJheUJ1ZmZlcih2YWwpIHtcbiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwodmFsKSA9PT0gJ1tvYmplY3QgQXJyYXlCdWZmZXJdJztcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIEZvcm1EYXRhXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYW4gRm9ybURhdGEsIG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0Zvcm1EYXRhKHZhbCkge1xuICByZXR1cm4gKHR5cGVvZiBGb3JtRGF0YSAhPT0gJ3VuZGVmaW5lZCcpICYmICh2YWwgaW5zdGFuY2VvZiBGb3JtRGF0YSk7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSB2aWV3IG9uIGFuIEFycmF5QnVmZmVyXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSB2aWV3IG9uIGFuIEFycmF5QnVmZmVyLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNBcnJheUJ1ZmZlclZpZXcodmFsKSB7XG4gIHZhciByZXN1bHQ7XG4gIGlmICgodHlwZW9mIEFycmF5QnVmZmVyICE9PSAndW5kZWZpbmVkJykgJiYgKEFycmF5QnVmZmVyLmlzVmlldykpIHtcbiAgICByZXN1bHQgPSBBcnJheUJ1ZmZlci5pc1ZpZXcodmFsKTtcbiAgfSBlbHNlIHtcbiAgICByZXN1bHQgPSAodmFsKSAmJiAodmFsLmJ1ZmZlcikgJiYgKHZhbC5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcik7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIFN0cmluZ1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGEgU3RyaW5nLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNTdHJpbmcodmFsKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsID09PSAnc3RyaW5nJztcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIE51bWJlclxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGEgTnVtYmVyLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNOdW1iZXIodmFsKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsID09PSAnbnVtYmVyJztcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyB1bmRlZmluZWRcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgdW5kZWZpbmVkLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNVbmRlZmluZWQodmFsKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsID09PSAndW5kZWZpbmVkJztcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhbiBPYmplY3RcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhbiBPYmplY3QsIG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdCh2YWwpIHtcbiAgcmV0dXJuIHZhbCAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0Jztcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIERhdGVcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIERhdGUsIG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0RhdGUodmFsKSB7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKHZhbCkgPT09ICdbb2JqZWN0IERhdGVdJztcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIEZpbGVcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIEZpbGUsIG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0ZpbGUodmFsKSB7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKHZhbCkgPT09ICdbb2JqZWN0IEZpbGVdJztcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIEJsb2JcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIEJsb2IsIG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0Jsb2IodmFsKSB7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKHZhbCkgPT09ICdbb2JqZWN0IEJsb2JdJztcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIEZ1bmN0aW9uXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBGdW5jdGlvbiwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzRnVuY3Rpb24odmFsKSB7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKHZhbCkgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBTdHJlYW1cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIFN0cmVhbSwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzU3RyZWFtKHZhbCkge1xuICByZXR1cm4gaXNPYmplY3QodmFsKSAmJiBpc0Z1bmN0aW9uKHZhbC5waXBlKTtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgYSB2YWx1ZSBpcyBhIFVSTFNlYXJjaFBhcmFtcyBvYmplY3RcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIFVSTFNlYXJjaFBhcmFtcyBvYmplY3QsIG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiBpc1VSTFNlYXJjaFBhcmFtcyh2YWwpIHtcbiAgcmV0dXJuIHR5cGVvZiBVUkxTZWFyY2hQYXJhbXMgIT09ICd1bmRlZmluZWQnICYmIHZhbCBpbnN0YW5jZW9mIFVSTFNlYXJjaFBhcmFtcztcbn1cblxuLyoqXG4gKiBUcmltIGV4Y2VzcyB3aGl0ZXNwYWNlIG9mZiB0aGUgYmVnaW5uaW5nIGFuZCBlbmQgb2YgYSBzdHJpbmdcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBTdHJpbmcgdG8gdHJpbVxuICogQHJldHVybnMge1N0cmluZ30gVGhlIFN0cmluZyBmcmVlZCBvZiBleGNlc3Mgd2hpdGVzcGFjZVxuICovXG5mdW5jdGlvbiB0cmltKHN0cikge1xuICByZXR1cm4gc3RyLnJlcGxhY2UoL15cXHMqLywgJycpLnJlcGxhY2UoL1xccyokLywgJycpO1xufVxuXG4vKipcbiAqIERldGVybWluZSBpZiB3ZSdyZSBydW5uaW5nIGluIGEgc3RhbmRhcmQgYnJvd3NlciBlbnZpcm9ubWVudFxuICpcbiAqIFRoaXMgYWxsb3dzIGF4aW9zIHRvIHJ1biBpbiBhIHdlYiB3b3JrZXIsIGFuZCByZWFjdC1uYXRpdmUuXG4gKiBCb3RoIGVudmlyb25tZW50cyBzdXBwb3J0IFhNTEh0dHBSZXF1ZXN0LCBidXQgbm90IGZ1bGx5IHN0YW5kYXJkIGdsb2JhbHMuXG4gKlxuICogd2ViIHdvcmtlcnM6XG4gKiAgdHlwZW9mIHdpbmRvdyAtPiB1bmRlZmluZWRcbiAqICB0eXBlb2YgZG9jdW1lbnQgLT4gdW5kZWZpbmVkXG4gKlxuICogcmVhY3QtbmF0aXZlOlxuICogIG5hdmlnYXRvci5wcm9kdWN0IC0+ICdSZWFjdE5hdGl2ZSdcbiAqL1xuZnVuY3Rpb24gaXNTdGFuZGFyZEJyb3dzZXJFbnYoKSB7XG4gIGlmICh0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJiBuYXZpZ2F0b3IucHJvZHVjdCA9PT0gJ1JlYWN0TmF0aXZlJykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gKFxuICAgIHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmXG4gICAgdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJ1xuICApO1xufVxuXG4vKipcbiAqIEl0ZXJhdGUgb3ZlciBhbiBBcnJheSBvciBhbiBPYmplY3QgaW52b2tpbmcgYSBmdW5jdGlvbiBmb3IgZWFjaCBpdGVtLlxuICpcbiAqIElmIGBvYmpgIGlzIGFuIEFycmF5IGNhbGxiYWNrIHdpbGwgYmUgY2FsbGVkIHBhc3NpbmdcbiAqIHRoZSB2YWx1ZSwgaW5kZXgsIGFuZCBjb21wbGV0ZSBhcnJheSBmb3IgZWFjaCBpdGVtLlxuICpcbiAqIElmICdvYmonIGlzIGFuIE9iamVjdCBjYWxsYmFjayB3aWxsIGJlIGNhbGxlZCBwYXNzaW5nXG4gKiB0aGUgdmFsdWUsIGtleSwgYW5kIGNvbXBsZXRlIG9iamVjdCBmb3IgZWFjaCBwcm9wZXJ0eS5cbiAqXG4gKiBAcGFyYW0ge09iamVjdHxBcnJheX0gb2JqIFRoZSBvYmplY3QgdG8gaXRlcmF0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGNhbGxiYWNrIHRvIGludm9rZSBmb3IgZWFjaCBpdGVtXG4gKi9cbmZ1bmN0aW9uIGZvckVhY2gob2JqLCBmbikge1xuICAvLyBEb24ndCBib3RoZXIgaWYgbm8gdmFsdWUgcHJvdmlkZWRcbiAgaWYgKG9iaiA9PT0gbnVsbCB8fCB0eXBlb2Ygb2JqID09PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIEZvcmNlIGFuIGFycmF5IGlmIG5vdCBhbHJlYWR5IHNvbWV0aGluZyBpdGVyYWJsZVxuICBpZiAodHlwZW9mIG9iaiAhPT0gJ29iamVjdCcpIHtcbiAgICAvKmVzbGludCBuby1wYXJhbS1yZWFzc2lnbjowKi9cbiAgICBvYmogPSBbb2JqXTtcbiAgfVxuXG4gIGlmIChpc0FycmF5KG9iaikpIHtcbiAgICAvLyBJdGVyYXRlIG92ZXIgYXJyYXkgdmFsdWVzXG4gICAgZm9yICh2YXIgaSA9IDAsIGwgPSBvYmoubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICBmbi5jYWxsKG51bGwsIG9ialtpXSwgaSwgb2JqKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gSXRlcmF0ZSBvdmVyIG9iamVjdCBrZXlzXG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleSkpIHtcbiAgICAgICAgZm4uY2FsbChudWxsLCBvYmpba2V5XSwga2V5LCBvYmopO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEFjY2VwdHMgdmFyYXJncyBleHBlY3RpbmcgZWFjaCBhcmd1bWVudCB0byBiZSBhbiBvYmplY3QsIHRoZW5cbiAqIGltbXV0YWJseSBtZXJnZXMgdGhlIHByb3BlcnRpZXMgb2YgZWFjaCBvYmplY3QgYW5kIHJldHVybnMgcmVzdWx0LlxuICpcbiAqIFdoZW4gbXVsdGlwbGUgb2JqZWN0cyBjb250YWluIHRoZSBzYW1lIGtleSB0aGUgbGF0ZXIgb2JqZWN0IGluXG4gKiB0aGUgYXJndW1lbnRzIGxpc3Qgd2lsbCB0YWtlIHByZWNlZGVuY2UuXG4gKlxuICogRXhhbXBsZTpcbiAqXG4gKiBgYGBqc1xuICogdmFyIHJlc3VsdCA9IG1lcmdlKHtmb286IDEyM30sIHtmb286IDQ1Nn0pO1xuICogY29uc29sZS5sb2cocmVzdWx0LmZvbyk7IC8vIG91dHB1dHMgNDU2XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqMSBPYmplY3QgdG8gbWVyZ2VcbiAqIEByZXR1cm5zIHtPYmplY3R9IFJlc3VsdCBvZiBhbGwgbWVyZ2UgcHJvcGVydGllc1xuICovXG5mdW5jdGlvbiBtZXJnZSgvKiBvYmoxLCBvYmoyLCBvYmozLCAuLi4gKi8pIHtcbiAgdmFyIHJlc3VsdCA9IHt9O1xuICBmdW5jdGlvbiBhc3NpZ25WYWx1ZSh2YWwsIGtleSkge1xuICAgIGlmICh0eXBlb2YgcmVzdWx0W2tleV0gPT09ICdvYmplY3QnICYmIHR5cGVvZiB2YWwgPT09ICdvYmplY3QnKSB7XG4gICAgICByZXN1bHRba2V5XSA9IG1lcmdlKHJlc3VsdFtrZXldLCB2YWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHRba2V5XSA9IHZhbDtcbiAgICB9XG4gIH1cblxuICBmb3IgKHZhciBpID0gMCwgbCA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICBmb3JFYWNoKGFyZ3VtZW50c1tpXSwgYXNzaWduVmFsdWUpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogRXh0ZW5kcyBvYmplY3QgYSBieSBtdXRhYmx5IGFkZGluZyB0byBpdCB0aGUgcHJvcGVydGllcyBvZiBvYmplY3QgYi5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gYSBUaGUgb2JqZWN0IHRvIGJlIGV4dGVuZGVkXG4gKiBAcGFyYW0ge09iamVjdH0gYiBUaGUgb2JqZWN0IHRvIGNvcHkgcHJvcGVydGllcyBmcm9tXG4gKiBAcGFyYW0ge09iamVjdH0gdGhpc0FyZyBUaGUgb2JqZWN0IHRvIGJpbmQgZnVuY3Rpb24gdG9cbiAqIEByZXR1cm4ge09iamVjdH0gVGhlIHJlc3VsdGluZyB2YWx1ZSBvZiBvYmplY3QgYVxuICovXG5mdW5jdGlvbiBleHRlbmQoYSwgYiwgdGhpc0FyZykge1xuICBmb3JFYWNoKGIsIGZ1bmN0aW9uIGFzc2lnblZhbHVlKHZhbCwga2V5KSB7XG4gICAgaWYgKHRoaXNBcmcgJiYgdHlwZW9mIHZhbCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgYVtrZXldID0gYmluZCh2YWwsIHRoaXNBcmcpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhW2tleV0gPSB2YWw7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIGE7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBpc0FycmF5OiBpc0FycmF5LFxuICBpc0FycmF5QnVmZmVyOiBpc0FycmF5QnVmZmVyLFxuICBpc0J1ZmZlcjogaXNCdWZmZXIsXG4gIGlzRm9ybURhdGE6IGlzRm9ybURhdGEsXG4gIGlzQXJyYXlCdWZmZXJWaWV3OiBpc0FycmF5QnVmZmVyVmlldyxcbiAgaXNTdHJpbmc6IGlzU3RyaW5nLFxuICBpc051bWJlcjogaXNOdW1iZXIsXG4gIGlzT2JqZWN0OiBpc09iamVjdCxcbiAgaXNVbmRlZmluZWQ6IGlzVW5kZWZpbmVkLFxuICBpc0RhdGU6IGlzRGF0ZSxcbiAgaXNGaWxlOiBpc0ZpbGUsXG4gIGlzQmxvYjogaXNCbG9iLFxuICBpc0Z1bmN0aW9uOiBpc0Z1bmN0aW9uLFxuICBpc1N0cmVhbTogaXNTdHJlYW0sXG4gIGlzVVJMU2VhcmNoUGFyYW1zOiBpc1VSTFNlYXJjaFBhcmFtcyxcbiAgaXNTdGFuZGFyZEJyb3dzZXJFbnY6IGlzU3RhbmRhcmRCcm93c2VyRW52LFxuICBmb3JFYWNoOiBmb3JFYWNoLFxuICBtZXJnZTogbWVyZ2UsXG4gIGV4dGVuZDogZXh0ZW5kLFxuICB0cmltOiB0cmltXG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL3V0aWxzLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvdXRpbHMuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/utils.js\n");
/***/ }),
/***/ "./node_modules/axios/node_modules/is-buffer/index.js":
/***/ (function(module, exports) {
eval("/*!\n * Determine if an object is a Buffer\n *\n * @author Feross Aboukhadijeh <https://feross.org>\n * @license MIT\n */\n\nmodule.exports = function isBuffer (obj) {\n return obj != null && obj.constructor != null &&\n typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3Mvbm9kZV9tb2R1bGVzL2lzLWJ1ZmZlci9pbmRleC5qcz9kNThhIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9ub2RlX21vZHVsZXMvaXMtYnVmZmVyL2luZGV4LmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBEZXRlcm1pbmUgaWYgYW4gb2JqZWN0IGlzIGEgQnVmZmVyXG4gKlxuICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGh0dHBzOi8vZmVyb3NzLm9yZz5cbiAqIEBsaWNlbnNlICBNSVRcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzQnVmZmVyIChvYmopIHtcbiAgcmV0dXJuIG9iaiAhPSBudWxsICYmIG9iai5jb25zdHJ1Y3RvciAhPSBudWxsICYmXG4gICAgdHlwZW9mIG9iai5jb25zdHJ1Y3Rvci5pc0J1ZmZlciA9PT0gJ2Z1bmN0aW9uJyAmJiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIob2JqKVxufVxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3Mvbm9kZV9tb2R1bGVzL2lzLWJ1ZmZlci9pbmRleC5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3Mvbm9kZV9tb2R1bGVzL2lzLWJ1ZmZlci9pbmRleC5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/axios/node_modules/is-buffer/index.js\n");
/***/ }),
/***/ "./node_modules/geolib/dist/geolib.js":
/***/ (function(module, exports, __webpack_require__) {
eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! geolib 2.0.23 by Manuel Bieh\r\n* Library to provide geo functions like distance calculation,\r\n* conversion of decimal coordinates to sexagesimal and vice versa, etc.\r\n* WGS 84 (World Geodetic System 1984)\r\n* \r\n* @author Manuel Bieh\r\n* @url http://www.manuelbieh.com/\r\n* @version 2.0.23\r\n* @license MIT \r\n**/;(function(global, undefined) {\n\n \"use strict\";\n\n function Geolib() {}\n\n // Constants\n Geolib.TO_RAD = Math.PI / 180;\n Geolib.TO_DEG = 180 / Math.PI;\n Geolib.PI_X2 = Math.PI * 2;\n Geolib.PI_DIV4 = Math.PI / 4;\n\n // Setting readonly defaults\n var geolib = Object.create(Geolib.prototype, {\n version: {\n value: \"2.0.23\"\n },\n radius: {\n value: 6378137\n },\n minLat: {\n value: -90\n },\n maxLat: {\n value: 90\n },\n minLon: {\n value: -180\n },\n maxLon: {\n value: 180\n },\n sexagesimalPattern: {\n value: /^([0-9]{1,3})°\\s*([0-9]{1,3}(?:\\.(?:[0-9]{1,2}))?)'\\s*(([0-9]{1,3}(\\.([0-9]{1,4}))?)\"\\s*)?([NEOSW]?)$/\n },\n measures: {\n value: Object.create(Object.prototype, {\n \"m\" : {value: 1},\n \"km\": {value: 0.001},\n \"cm\": {value: 100},\n \"mm\": {value: 1000},\n \"mi\": {value: (1 / 1609.344)},\n \"sm\": {value: (1 / 1852.216)},\n \"ft\": {value: (100 / 30.48)},\n \"in\": {value: (100 / 2.54)},\n \"yd\": {value: (1 / 0.9144)}\n })\n },\n prototype: {\n value: Geolib.prototype\n },\n extend: {\n value: function(methods, overwrite) {\n for(var prop in methods) {\n if(typeof geolib.prototype[prop] === 'undefined' || overwrite === true) {\n if(typeof methods[prop] === 'function' && typeof methods[prop].bind === 'function') {\n geolib.prototype[prop] = methods[prop].bind(geolib);\n } else {\n geolib.prototype[prop] = methods[prop];\n }\n }\n }\n }\n }\n });\n\n if (typeof(Number.prototype.toRad) === 'undefined') {\n Number.prototype.toRad = function() {\n return this * Geolib.TO_RAD;\n };\n }\n\n if (typeof(Number.prototype.toDeg) === 'undefined') {\n Number.prototype.toDeg = function() {\n return this * Geolib.TO_DEG;\n };\n }\n\n // Here comes the magic\n geolib.extend({\n\n decimal: {},\n\n sexagesimal: {},\n\n distance: null,\n\n getKeys: function(point) {\n\n // GeoJSON Array [longitude, latitude(, elevation)]\n if(Object.prototype.toString.call(point) == '[object Array]') {\n\n return {\n longitude: point.length >= 1 ? 0 : undefined,\n latitude: point.length >= 2 ? 1 : undefined,\n elevation: point.length >= 3 ? 2 : undefined\n };\n\n }\n\n var getKey = function(possibleValues) {\n\n var key;\n\n possibleValues.every(function(val) {\n // TODO: check if point is an object\n if(typeof point != 'object') {\n return true;\n }\n return point.hasOwnProperty(val) ? (function() { key = val; return false; }()) : true;\n });\n\n return key;\n\n };\n\n var longitude = getKey(['lng', 'lon', 'longitude']);\n var latitude = getKey(['lat', 'latitude']);\n var elevation = getKey(['alt', 'altitude', 'elevation', 'elev']);\n\n // return undefined if not at least one valid property was found\n if(typeof latitude == 'undefined' &&\n typeof longitude == 'undefined' &&\n typeof elevation == 'undefined') {\n return undefined;\n }\n\n return {\n latitude: latitude,\n longitude: longitude,\n elevation: elevation\n };\n\n },\n\n // returns latitude of a given point, converted to decimal\n // set raw to true to avoid conversion\n getLat: function(point, raw) {\n return raw === true ? point[this.getKeys(point).latitude] : this.useDecimal(point[this.getKeys(point).latitude]);\n },\n\n // Alias for getLat\n latitude: function(point) {\n return this.getLat.call(this, point);\n },\n\n // returns longitude of a given point, converted to decimal\n // set raw to true to avoid conversion\n getLon: function(point, raw) {\n return raw === true ? point[this.getKeys(point).longitude] : this.useDecimal(point[this.getKeys(point).longitude]);\n },\n\n // Alias for getLon\n longitude: function(point) {\n return this.getLon.call(this, point);\n },\n\n getElev: function(point) {\n return point[this.getKeys(point).elevation];\n },\n\n // Alias for getElev\n elevation: function(point) {\n return this.getElev.call(this, point);\n },\n\n coords: function(point, raw) {\n\n var retval = {\n latitude: raw === true ? point[this.getKeys(point).latitude] : this.useDecimal(point[this.getKeys(point).latitude]),\n longitude: raw === true ? point[this.getKeys(point).longitude] : this.useDecimal(point[this.getKeys(point).longitude])\n };\n\n var elev = point[this.getKeys(point).elevation];\n\n if(typeof elev !== 'undefined') {\n retval['elevation'] = elev;\n }\n\n return retval;\n\n },\n\n // Alias for coords\n ll: function(point, raw) {\n return this.coords.call(this, point, raw);\n },\n\n\n // checks if a variable contains a valid latlong object\n validate: function(point) {\n\n var keys = this.getKeys(point);\n\n if(typeof keys === 'undefined' || typeof keys.latitude === 'undefined' || keys.longitude === 'undefined') {\n return false;\n }\n\n var lat = point[keys.latitude];\n var lng = point[keys.longitude];\n\n if(typeof lat === 'undefined' || !this.isDecimal(lat) && !this.isSexagesimal(lat)) {\n return false;\n }\n\n if(typeof lng === 'undefined' || !this.isDecimal(lng) && !this.isSexagesimal(lng)) {\n return false;\n }\n\n lat = this.useDecimal(lat);\n lng = this.useDecimal(lng);\n\n if(lat < this.minLat || lat > this.maxLat || lng < this.minLon || lng > this.maxLon) {\n return false;\n }\n\n return true;\n\n },\n\n /**\n * Calculates geodetic distance between two points specified by latitude/longitude using\n * Vincenty inverse formula for ellipsoids\n * Vincenty Inverse Solution of Geodesics on the Ellipsoid (c) Chris Veness 2002-2010\n * (Licensed under CC BY 3.0)\n *\n * @param object Start position {latitude: 123, longitude: 123}\n * @param object End position {latitude: 123, longitude: 123}\n * @param integer Accuracy (in meters)\n * @param integer Precision (in decimal cases)\n * @return integer Distance (in meters)\n */\n getDistance: function(start, end, accuracy, precision) {\n\n accuracy = Math.floor(accuracy) || 1;\n precision = Math.floor(precision) || 0;\n\n var s = this.coords(start);\n var e = this.coords(end);\n\n var a = 6378137, b = 6356752.314245, f = 1/298.257223563; // WGS-84 ellipsoid params\n var L = (e['longitude']-s['longitude']).toRad();\n\n var cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM, sinSigma;\n\n var U1 = Math.atan((1-f) * Math.tan(parseFloat(s['latitude']).toRad()));\n var U2 = Math.atan((1-f) * Math.tan(parseFloat(e['latitude']).toRad()));\n var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);\n var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);\n\n var lambda = L, lambdaP, iterLimit = 100;\n do {\n var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);\n sinSigma = (\n Math.sqrt(\n (\n cosU2 * sinLambda\n ) * (\n cosU2 * sinLambda\n ) + (\n cosU1 * sinU2 - sinU1 * cosU2 * cosLambda\n ) * (\n cosU1 * sinU2 - sinU1 * cosU2 * cosLambda\n )\n )\n );\n if (sinSigma === 0) {\n return geolib.distance = 0; // co-incident points\n }\n\n cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;\n sigma = Math.atan2(sinSigma, cosSigma);\n sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;\n cosSqAlpha = 1 - sinAlpha * sinAlpha;\n cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;\n\n if (isNaN(cos2SigmaM)) {\n cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (§6)\n }\n var C = (\n f / 16 * cosSqAlpha * (\n 4 + f * (\n 4 - 3 * cosSqAlpha\n )\n )\n );\n lambdaP = lambda;\n lambda = (\n L + (\n 1 - C\n ) * f * sinAlpha * (\n sigma + C * sinSigma * (\n cos2SigmaM + C * cosSigma * (\n -1 + 2 * cos2SigmaM * cos2SigmaM\n )\n )\n )\n );\n\n } while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0);\n\n if (iterLimit === 0) {\n return NaN; // formula failed to converge\n }\n\n var uSq = (\n cosSqAlpha * (\n a * a - b * b\n ) / (\n b*b\n )\n );\n\n var A = (\n 1 + uSq / 16384 * (\n 4096 + uSq * (\n -768 + uSq * (\n 320 - 175 * uSq\n )\n )\n )\n );\n\n var B = (\n uSq / 1024 * (\n 256 + uSq * (\n -128 + uSq * (\n 74-47 * uSq\n )\n )\n )\n );\n\n var deltaSigma = (\n B * sinSigma * (\n cos2SigmaM + B / 4 * (\n cosSigma * (\n -1 + 2 * cos2SigmaM * cos2SigmaM\n ) -B / 6 * cos2SigmaM * (\n -3 + 4 * sinSigma * sinSigma\n ) * (\n -3 + 4 * cos2SigmaM * cos2SigmaM\n )\n )\n )\n );\n\n var distance = b * A * (sigma - deltaSigma);\n\n distance = distance.toFixed(precision); // round to 1mm precision\n\n //if (start.hasOwnProperty(elevation) && end.hasOwnProperty(elevation)) {\n if (typeof this.elevation(start) !== 'undefined' && typeof this.elevation(end) !== 'undefined') {\n var climb = Math.abs(this.elevation(start) - this.elevation(end));\n distance = Math.sqrt(distance * distance + climb * climb);\n }\n\n return this.distance = Math.round(distance * Math.pow(10, precision) / accuracy) * accuracy / Math.pow(10, precision);\n\n /*\n // note: to return initial/final bearings in addition to distance, use something like:\n var fwdAz = Math.atan2(cosU2*sinLambda, cosU1*sinU2-sinU1*cosU2*cosLambda);\n var revAz = Math.atan2(cosU1*sinLambda, -sinU1*cosU2+cosU1*sinU2*cosLambda);\n\n return { distance: s, initialBearing: fwdAz.toDeg(), finalBearing: revAz.toDeg() };\n */\n\n },\n\n\n /**\n * Calculates the distance between two spots.\n * This method is more simple but also far more inaccurate\n *\n * @param object Start position {latitude: 123, longitude: 123}\n * @param object End position {latitude: 123, longitude: 123}\n * @param integer Accuracy (in meters)\n * @return integer Distance (in meters)\n */\n getDistanceSimple: function(start, end, accuracy) {\n\n accuracy = Math.floor(accuracy) || 1;\n\n var distance =\n Math.round(\n Math.acos(\n Math.sin(\n this.latitude(end).toRad()\n ) *\n Math.sin(\n this.latitude(start).toRad()\n ) +\n Math.cos(\n this.latitude(end).toRad()\n ) *\n Math.cos(\n this.latitude(start).toRad()\n ) *\n Math.cos(\n this.longitude(start).toRad() - this.longitude(end).toRad()\n )\n ) * this.radius\n );\n\n return geolib.distance = Math.floor(Math.round(distance/accuracy)*accuracy);\n\n },\n\n\n /**\n * Calculates the center of a collection of geo coordinates\n *\n * @param array Collection of coords [{latitude: 51.510, longitude: 7.1321}, {latitude: 49.1238, longitude: \"8° 30' W\"}, ...]\n * @return object {latitude: centerLat, longitude: centerLng}\n */\n getCenter: function(coords) {\n\n var coordsArray = coords;\n if(typeof coords === 'object' && !(coords instanceof Array)) {\n\n coordsArray = [];\n\n for(var key in coords) {\n coordsArray.push(\n this.coords(coords[key])\n );\n }\n\n }\n\n if(!coordsArray.length) {\n return false;\n }\n\n var X = 0.0;\n var Y = 0.0;\n var Z = 0.0;\n var lat, lon, hyp;\n\n coordsArray.forEach(function(coord) {\n\n lat = this.latitude(coord).toRad();\n lon = this.longitude(coord).toRad();\n\n X += Math.cos(lat) * Math.cos(lon);\n Y += Math.cos(lat) * Math.sin(lon);\n Z += Math.sin(lat);\n\n }, this);\n\n var nb_coords = coordsArray.length;\n X = X / nb_coords;\n Y = Y / nb_coords;\n Z = Z / nb_coords;\n\n lon = Math.atan2(Y, X);\n hyp = Math.sqrt(X * X + Y * Y);\n lat = Math.atan2(Z, hyp);\n\n return {\n latitude: (lat * Geolib.TO_DEG).toFixed(6),\n longitude: (lon * Geolib.TO_DEG).toFixed(6)\n };\n\n },\n\n\n /**\n * Gets the max and min, latitude, longitude, and elevation (if provided).\n * @param array array with coords e.g. [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...]\n * @return object {maxLat: maxLat,\n * minLat: minLat\n * maxLng: maxLng,\n * minLng: minLng,\n * maxElev: maxElev,\n * minElev: minElev}\n */\n getBounds: function(coords) {\n\n if (!coords.length) {\n return false;\n }\n\n var useElevation = this.elevation(coords[0]);\n\n var stats = {\n maxLat: -Infinity,\n minLat: Infinity,\n maxLng: -Infinity,\n minLng: Infinity\n };\n\n if (typeof useElevation != 'undefined') {\n stats.maxElev = 0;\n stats.minElev = Infinity;\n }\n\n for (var i = 0, l = coords.length; i < l; ++i) {\n\n stats.maxLat = Math.max(this.latitude(coords[i]), stats.maxLat);\n stats.minLat = Math.min(this.latitude(coords[i]), stats.minLat);\n stats.maxLng = Math.max(this.longitude(coords[i]), stats.maxLng);\n stats.minLng = Math.min(this.longitude(coords[i]), stats.minLng);\n\n if (useElevation) {\n stats.maxElev = Math.max(this.elevation(coords[i]), stats.maxElev);\n stats.minElev = Math.min(this.elevation(coords[i]), stats.minElev);\n }\n\n }\n\n return stats;\n\n },\n\n /**\n * Calculates the center of the bounds of geo coordinates.\n *\n * On polygons like political borders (eg. states)\n * this may gives a closer result to human expectation, than `getCenter`,\n * because that function can be disturbed by uneven distribution of\n * point in different sides.\n * Imagine the US state Oklahoma: `getCenter` on that gives a southern\n * point, because the southern border contains a lot more nodes,\n * than the others.\n *\n * @param array Collection of coords [{latitude: 51.510, longitude: 7.1321}, {latitude: 49.1238, longitude: \"8° 30' W\"}, ...]\n * @return object {latitude: centerLat, longitude: centerLng}\n */\n getCenterOfBounds: function(coords) {\n var b = this.getBounds(coords);\n var latitude = b.minLat + ((b.maxLat - b.minLat) / 2);\n var longitude = b.minLng + ((b.maxLng - b.minLng) / 2);\n return {\n latitude: parseFloat(latitude.toFixed(6)),\n longitude: parseFloat(longitude.toFixed(6))\n };\n },\n\n\n /**\n * Computes the bounding coordinates of all points on the surface\n * of the earth less than or equal to the specified great circle\n * distance.\n *\n * @param object Point position {latitude: 123, longitude: 123}\n * @param number Distance (in meters).\n * @return array Collection of two points defining the SW and NE corners.\n */\n getBoundsOfDistance: function(point, distance) {\n\n var latitude = this.latitude(point);\n var longitude = this.longitude(point);\n\n var radLat = latitude.toRad();\n var radLon = longitude.toRad();\n\n var radDist = distance / this.radius;\n var minLat = radLat - radDist;\n var maxLat = radLat + radDist;\n\n var MAX_LAT_RAD = this.maxLat.toRad();\n var MIN_LAT_RAD = this.minLat.toRad();\n var MAX_LON_RAD = this.maxLon.toRad();\n var MIN_LON_RAD = this.minLon.toRad();\n\n var minLon;\n var maxLon;\n\n if (minLat > MIN_LAT_RAD && maxLat < MAX_LAT_RAD) {\n\n var deltaLon = Math.asin(Math.sin(radDist) / Math.cos(radLat));\n minLon = radLon - deltaLon;\n\n if (minLon < MIN_LON_RAD) {\n minLon += Geolib.PI_X2;\n }\n\n maxLon = radLon + deltaLon;\n\n if (maxLon > MAX_LON_RAD) {\n maxLon -= Geolib.PI_X2;\n }\n\n } else {\n // A pole is within the distance.\n minLat = Math.max(minLat, MIN_LAT_RAD);\n maxLat = Math.min(maxLat, MAX_LAT_RAD);\n minLon = MIN_LON_RAD;\n maxLon = MAX_LON_RAD;\n }\n\n return [\n // Southwest\n {\n latitude: minLat.toDeg(),\n longitude: minLon.toDeg()\n },\n // Northeast\n {\n latitude: maxLat.toDeg(),\n longitude: maxLon.toDeg()\n }\n ];\n\n },\n\n\n /**\n * Checks whether a point is inside of a polygon or not.\n * Note that the polygon coords must be in correct order!\n *\n * @param object coordinate to check e.g. {latitude: 51.5023, longitude: 7.3815}\n * @param array array with coords e.g. [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...]\n * @return bool true if the coordinate is inside the given polygon\n */\n isPointInside: function(latlng, coords) {\n\n for(var c = false, i = -1, l = coords.length, j = l - 1; ++i < l; j = i) {\n\n if(\n (\n (this.longitude(coords[i]) <= this.longitude(latlng) && this.longitude(latlng) < this.longitude(coords[j])) ||\n (this.longitude(coords[j]) <= this.longitude(latlng) && this.longitude(latlng) < this.longitude(coords[i]))\n ) &&\n (\n this.latitude(latlng) < (this.latitude(coords[j]) - this.latitude(coords[i])) *\n (this.longitude(latlng) - this.longitude(coords[i])) /\n (this.longitude(coords[j]) - this.longitude(coords[i])) +\n this.latitude(coords[i])\n )\n ) {\n c = !c;\n }\n\n }\n\n return c;\n\n },\n\n\n /**\n * Pre calculate the polygon coords, to speed up the point inside check.\n * Use this function before calling isPointInsideWithPreparedPolygon()\n * @see Algorythm from http://alienryderflex.com/polygon/\n * @param array array with coords e.g. [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...]\n */\n preparePolygonForIsPointInsideOptimized: function(coords) {\n\n for(var i = 0, j = coords.length-1; i < coords.length; i++) {\n\n if(this.longitude(coords[j]) === this.longitude(coords[i])) {\n\n coords[i].constant = this.latitude(coords[i]);\n coords[i].multiple = 0;\n\n } else {\n\n coords[i].constant = this.latitude(coords[i]) - (\n this.longitude(coords[i]) * this.latitude(coords[j])\n ) / (\n this.longitude(coords[j]) - this.longitude(coords[i])\n ) + (\n this.longitude(coords[i])*this.latitude(coords[i])\n ) / (\n this.longitude(coords[j])-this.longitude(coords[i])\n );\n\n coords[i].multiple = (\n this.latitude(coords[j])-this.latitude(coords[i])\n ) / (\n this.longitude(coords[j])-this.longitude(coords[i])\n );\n\n }\n\n j=i;\n\n }\n\n },\n\n /**\n * Checks whether a point is inside of a polygon or not.\n * \"This is useful if you have many points that need to be tested against the same (static) polygon.\"\n * Please call the function preparePolygonForIsPointInsideOptimized() with the same coords object before using this function.\n * Note that the polygon coords must be in correct order!\n *\n * @see Algorythm from http://alienryderflex.com/polygon/\n *\n * @param object coordinate to check e.g. {latitude: 51.5023, longitude: 7.3815}\n * @param array array with coords e.g. [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...]\n * @return bool true if the coordinate is inside the given polygon\n */\n isPointInsideWithPreparedPolygon: function(point, coords) {\n\n var flgPointInside = false,\n y = this.longitude(point),\n x = this.latitude(point);\n\n for(var i = 0, j = coords.length-1; i < coords.length; i++) {\n\n if ((this.longitude(coords[i]) < y && this.longitude(coords[j]) >=y ||\n this.longitude(coords[j]) < y && this.longitude(coords[i]) >= y)) {\n\n flgPointInside^=(y*coords[i].multiple+coords[i].constant < x);\n\n }\n\n j=i;\n\n }\n\n return flgPointInside;\n\n },\n\n\n /**\n * Shortcut for geolib.isPointInside()\n */\n isInside: function() {\n return this.isPointInside.apply(this, arguments);\n },\n\n\n /**\n * Checks whether a point is inside of a circle or not.\n *\n * @param object coordinate to check (e.g. {latitude: 51.5023, longitude: 7.3815})\n * @param object coordinate of the circle's center (e.g. {latitude: 51.4812, longitude: 7.4025})\n * @param integer maximum radius in meters\n * @return bool true if the coordinate is within the given radius\n */\n isPointInCircle: function(latlng, center, radius) {\n return this.getDistance(latlng, center) < radius;\n },\n\n\n /**\n * Shortcut for geolib.isPointInCircle()\n */\n withinRadius: function() {\n return this.isPointInCircle.apply(this, arguments);\n },\n\n\n /**\n * Gets rhumb line bearing of two points. Find out about the difference between rhumb line and\n * great circle bearing on Wikipedia. It's quite complicated. Rhumb line should be fine in most cases:\n *\n * http://en.wikipedia.org/wiki/Rhumb_line#General_and_mathematical_description\n *\n * Function heavily based on Doug Vanderweide's great PHP version (licensed under GPL 3.0)\n * http://www.dougv.com/2009/07/13/calculating-the-bearing-and-compass-rose-direction-between-two-latitude-longitude-coordinates-in-php/\n *\n * @param object origin coordinate (e.g. {latitude: 51.5023, longitude: 7.3815})\n * @param object destination coordinate\n * @return integer calculated bearing\n */\n getRhumbLineBearing: function(originLL, destLL) {\n\n // difference of longitude coords\n var diffLon = this.longitude(destLL).toRad() - this.longitude(originLL).toRad();\n\n // difference latitude coords phi\n var diffPhi = Math.log(\n Math.tan(\n this.latitude(destLL).toRad() / 2 + Geolib.PI_DIV4\n ) /\n Math.tan(\n this.latitude(originLL).toRad() / 2 + Geolib.PI_DIV4\n )\n );\n\n // recalculate diffLon if it is greater than pi\n if(Math.abs(diffLon) > Math.PI) {\n if(diffLon > 0) {\n diffLon = (Geolib.PI_X2 - diffLon) * -1;\n }\n else {\n diffLon = Geolib.PI_X2 + diffLon;\n }\n }\n\n //return the angle, normalized\n return (Math.atan2(diffLon, diffPhi).toDeg() + 360) % 360;\n\n },\n\n\n /**\n * Gets great circle bearing of two points. See description of getRhumbLineBearing for more information\n *\n * @param object origin coordinate (e.g. {latitude: 51.5023, longitude: 7.3815})\n * @param object destination coordinate\n * @return integer calculated bearing\n */\n getBearing: function(originLL, destLL) {\n\n destLL['latitude'] = this.latitude(destLL);\n destLL['longitude'] = this.longitude(destLL);\n originLL['latitude'] = this.latitude(originLL);\n originLL['longitude'] = this.longitude(originLL);\n\n var bearing = (\n (\n Math.atan2(\n Math.sin(\n destLL['longitude'].toRad() -\n originLL['longitude'].toRad()\n ) *\n Math.cos(\n destLL['latitude'].toRad()\n ),\n Math.cos(\n originLL['latitude'].toRad()\n ) *\n Math.sin(\n destLL['latitude'].toRad()\n ) -\n Math.sin(\n originLL['latitude'].toRad()\n ) *\n Math.cos(\n destLL['latitude'].toRad()\n ) *\n Math.cos(\n destLL['longitude'].toRad() - originLL['longitude'].toRad()\n )\n )\n ).toDeg() + 360\n ) % 360;\n\n return bearing;\n\n },\n\n\n /**\n * Gets the compass direction from an origin coordinate to a destination coordinate.\n *\n * @param object origin coordinate (e.g. {latitude: 51.5023, longitude: 7.3815})\n * @param object destination coordinate\n * @param string Bearing mode. Can be either circle or rhumbline\n * @return object Returns an object with a rough (NESW) and an exact direction (NNE, NE, ENE, E, ESE, etc).\n */\n getCompassDirection: function(originLL, destLL, bearingMode) {\n\n var direction;\n var bearing;\n\n if(bearingMode == 'circle') {\n // use great circle bearing\n bearing = this.getBearing(originLL, destLL);\n } else {\n // default is rhumb line bearing\n bearing = this.getRhumbLineBearing(originLL, destLL);\n }\n\n switch(Math.round(bearing/22.5)) {\n case 1:\n direction = {exact: \"NNE\", rough: \"N\"};\n break;\n case 2:\n direction = {exact: \"NE\", rough: \"N\"};\n break;\n case 3:\n direction = {exact: \"ENE\", rough: \"E\"};\n break;\n case 4:\n direction = {exact: \"E\", rough: \"E\"};\n break;\n case 5:\n direction = {exact: \"ESE\", rough: \"E\"};\n break;\n case 6:\n direction = {exact: \"SE\", rough: \"E\"};\n break;\n case 7:\n direction = {exact: \"SSE\", rough: \"S\"};\n break;\n case 8:\n direction = {exact: \"S\", rough: \"S\"};\n break;\n case 9:\n direction = {exact: \"SSW\", rough: \"S\"};\n break;\n case 10:\n direction = {exact: \"SW\", rough: \"S\"};\n break;\n case 11:\n direction = {exact: \"WSW\", rough: \"W\"};\n break;\n case 12:\n direction = {exact: \"W\", rough: \"W\"};\n break;\n case 13:\n direction = {exact: \"WNW\", rough: \"W\"};\n break;\n case 14:\n direction = {exact: \"NW\", rough: \"W\"};\n break;\n case 15:\n direction = {exact: \"NNW\", rough: \"N\"};\n break;\n default:\n direction = {exact: \"N\", rough: \"N\"};\n }\n\n direction['bearing'] = bearing;\n return direction;\n\n },\n\n\n /**\n * Shortcut for getCompassDirection\n */\n getDirection: function(originLL, destLL, bearingMode) {\n return this.getCompassDirection.apply(this, arguments);\n },\n\n\n /**\n * Sorts an array of coords by distance from a reference coordinate\n *\n * @param object reference coordinate e.g. {latitude: 51.5023, longitude: 7.3815}\n * @param mixed array or object with coords [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...]\n * @return array ordered array\n */\n orderByDistance: function(latlng, coords) {\n\n var coordsArray = Object.keys(coords).map(function(idx) {\n var distance = this.getDistance(latlng, coords[idx]);\n var augmentedCoord = Object.create(coords[idx]);\n augmentedCoord.distance = distance;\n augmentedCoord.key = idx;\n return augmentedCoord;\n }, this);\n\n return coordsArray.sort(function(a, b) {\n return a.distance - b.distance;\n });\n\n },\n\n /**\n * Check if a point lies in line created by two other points\n *\n * @param object Point to check: {latitude: 123, longitude: 123}\n * @param object Start of line {latitude: 123, longitude: 123}\n * @param object End of line {latitude: 123, longitude: 123}\n * @return boolean\n */\n isPointInLine: function(point, start, end) {\n\n return (this.getDistance(start, point, 1, 3)+this.getDistance(point, end, 1, 3)).toFixed(3)==this.getDistance(start, end, 1, 3);\n },\n\n /**\n * Check if a point lies within a given distance from a line created by two other points\n *\n * @param object Point to check: {latitude: 123, longitude: 123}\n * @param object Start of line {latitude: 123, longitude: 123}\n * @param object End of line {latitude: 123, longitude: 123}\n * @pararm float maximum distance from line\n * @return boolean\n */\n isPointNearLine: function(point, start, end, distance) {\n return this.getDistanceFromLine(point, start, end) < distance;\n },\n\n /**\n * return the minimum distance from a point to a line\n *\n * @param object Point away from line\n * @param object Start of line {latitude: 123, longitude: 123}\n * @param object End of line {latitude: 123, longitude: 123}\n * @return float distance from point to line\n */\n getDistanceFromLine: function(point, start, end) {\n var d1 = this.getDistance(start, point, 1, 3);\n var d2 = this.getDistance(point, end, 1, 3);\n var d3 = this.getDistance(start, end, 1, 3);\n var distance = 0;\n\n // alpha is the angle between the line from start to point, and from start to end //\n var alpha = Math.acos((d1*d1 + d3*d3 - d2*d2)/(2*d1*d3));\n // beta is the angle between the line from end to point and from end to start //\n var beta = Math.acos((d2*d2 + d3*d3 - d1*d1)/(2*d2*d3));\n\n // if the angle is greater than 90 degrees, then the minimum distance is the\n // line from the start to the point //\n if(alpha>Math.PI/2) {\n distance = d1;\n }\n // same for the beta //\n else if(beta > Math.PI/2) {\n distance = d2;\n }\n // otherwise the minimum distance is achieved through a line perpendular to the start-end line,\n // which goes from the start-end line to the point //\n else {\n distance = Math.sin(alpha) * d1;\n }\n\n return distance;\n },\n\n /**\n * Finds the nearest coordinate to a reference coordinate\n *\n * @param object reference coordinate e.g. {latitude: 51.5023, longitude: 7.3815}\n * @param mixed array or object with coords [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...]\n * @return array ordered array\n */\n findNearest: function(latlng, coords, offset, limit) {\n\n offset = offset || 0;\n limit = limit || 1;\n var ordered = this.orderByDistance(latlng, coords);\n\n if(limit === 1) {\n return ordered[offset];\n } else {\n return ordered.splice(offset, limit);\n }\n\n },\n\n\n /**\n * Calculates the length of a given path\n *\n * @param mixed array or object with coords [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...]\n * @return integer length of the path (in meters)\n */\n getPathLength: function(coords) {\n\n var dist = 0;\n var last;\n\n for (var i = 0, l = coords.length; i < l; ++i) {\n if(last) {\n //console.log(coords[i], last, this.getDistance(coords[i], last));\n dist += this.getDistance(this.coords(coords[i]), last);\n }\n last = this.coords(coords[i]);\n }\n\n return dist;\n\n },\n\n\n /**\n * Calculates the speed between to points within a given time span.\n *\n * @param object coords with javascript timestamp {latitude: 51.5143, longitude: 7.4138, time: 1360231200880}\n * @param object coords with javascript timestamp {latitude: 51.5502, longitude: 7.4323, time: 1360245600460}\n * @param object options (currently \"unit\" is the only option. Default: km(h));\n * @return float speed in unit per hour\n */\n getSpeed: function(start, end, options) {\n\n var unit = options && options.unit || 'km';\n\n if(unit == 'mph') {\n unit = 'mi';\n } else if(unit == 'kmh') {\n unit = 'km';\n }\n\n var distance = geolib.getDistance(start, end);\n var time = ((end.time*1)/1000) - ((start.time*1)/1000);\n var mPerHr = (distance/time)*3600;\n var speed = Math.round(mPerHr * this.measures[unit] * 10000)/10000;\n return speed;\n\n },\n\n\n /**\n * Computes the destination point given an initial point, a distance\n * and a bearing\n *\n * see http://www.movable-type.co.uk/scripts/latlong.html for the original code\n *\n * @param object start coordinate (e.g. {latitude: 51.5023, longitude: 7.3815})\n * @param float longitude of the inital point in degree\n * @param float distance to go from the inital point in meter\n * @param float bearing in degree of the direction to go, e.g. 0 = north, 180 = south\n * @param float optional (in meter), defaults to mean radius of the earth\n * @return object {latitude: destLat (in degree), longitude: destLng (in degree)}\n */\n computeDestinationPoint: function(start, distance, bearing, radius) {\n\n var lat = this.latitude(start);\n var lng = this.longitude(start);\n\n radius = (typeof radius === 'undefined') ? this.radius : Number(radius);\n\n var δ = Number(distance) / radius; // angular distance in radians\n var θ = Number(bearing).toRad();\n\n var φ1 = Number(lat).toRad();\n var λ1 = Number(lng).toRad();\n\n var φ2 = Math.asin( Math.sin(φ1)*Math.cos(δ) +\n Math.cos(φ1)*Math.sin(δ)*Math.cos(θ) );\n var λ2 = λ1 + Math.atan2(Math.sin(θ)*Math.sin(δ)*Math.cos(φ1),\n Math.cos(δ)-Math.sin(φ1)*Math.sin(φ2));\n λ2 = (λ2+3*Math.PI) % (2*Math.PI) - Math.PI; // normalise to -180..+180°\n\n return {\n latitude: φ2.toDeg(),\n longitude: λ2.toDeg()\n };\n\n },\n\n\n /**\n * Converts a distance from meters to km, mm, cm, mi, ft, in or yd\n *\n * @param string Format to be converted in\n * @param float Distance in meters\n * @param float Decimal places for rounding (default: 4)\n * @return float Converted distance\n */\n convertUnit: function(unit, distance, round) {\n\n if(distance === 0) {\n\n return 0;\n\n } else if(typeof distance === 'undefined') {\n\n if(this.distance === null) {\n throw new Error('No distance was given');\n } else if(this.distance === 0) {\n return 0;\n } else {\n distance = this.distance;\n }\n\n }\n\n unit = unit || 'm';\n round = (null == round ? 4 : round);\n\n if(typeof this.measures[unit] !== 'undefined') {\n return this.round(distance * this.measures[unit], round);\n } else {\n throw new Error('Unknown unit for conversion.');\n }\n\n },\n\n\n /**\n * Checks if a value is in decimal format or, if neccessary, converts to decimal\n *\n * @param mixed Value(s) to be checked/converted (array of latlng objects, latlng object, sexagesimal string, float)\n * @return float Input data in decimal format\n */\n useDecimal: function(value) {\n\n if(Object.prototype.toString.call(value) === '[object Array]') {\n\n var geolib = this;\n\n value = value.map(function(val) {\n\n //if(!isNaN(parseFloat(val))) {\n if(geolib.isDecimal(val)) {\n\n return geolib.useDecimal(val);\n\n } else if(typeof val == 'object') {\n\n if(geolib.validate(val)) {\n\n return geolib.coords(val);\n\n } else {\n\n for(var prop in val) {\n val[prop] = geolib.useDecimal(val[prop]);\n }\n\n return val;\n\n }\n\n } else if(geolib.isSexagesimal(val)) {\n\n return geolib.sexagesimal2decimal(val);\n\n } else {\n\n return val;\n\n }\n\n });\n\n return value;\n\n } else if(typeof value === 'object' && this.validate(value)) {\n\n return this.coords(value);\n\n } else if(typeof value === 'object') {\n\n for(var prop in value) {\n value[prop] = this.useDecimal(value[prop]);\n }\n\n return value;\n\n }\n\n\n if (this.isDecimal(value)) {\n\n return parseFloat(value);\n\n } else if(this.isSexagesimal(value) === true) {\n\n return parseFloat(this.sexagesimal2decimal(value));\n\n }\n\n throw new Error('Unknown format.');\n\n },\n\n /**\n * Converts a decimal coordinate value to sexagesimal format\n *\n * @param float decimal\n * @return string Sexagesimal value (XX° YY' ZZ\")\n */\n decimal2sexagesimal: function(dec) {\n\n if (dec in this.sexagesimal) {\n return this.sexagesimal[dec];\n }\n\n var tmp = dec.toString().split('.');\n\n var deg = Math.abs(tmp[0]);\n var min = ('0.' + (tmp[1] || 0))*60;\n var sec = min.toString().split('.');\n\n min = Math.floor(min);\n sec = (('0.' + (sec[1] || 0)) * 60).toFixed(2);\n\n this.sexagesimal[dec] = (deg + '° ' + min + \"' \" + sec + '\"');\n\n return this.sexagesimal[dec];\n\n },\n\n\n /**\n * Converts a sexagesimal coordinate to decimal format\n *\n * @param float Sexagesimal coordinate\n * @return string Decimal value (XX.XXXXXXXX)\n */\n sexagesimal2decimal: function(sexagesimal) {\n\n if (sexagesimal in this.decimal) {\n return this.decimal[sexagesimal];\n }\n\n var regEx = new RegExp(this.sexagesimalPattern);\n var data = regEx.exec(sexagesimal);\n var min = 0, sec = 0;\n\n if(data) {\n min = parseFloat(data[2]/60);\n sec = parseFloat(data[4]/3600) || 0;\n }\n\n var dec = ((parseFloat(data[1]) + min + sec)).toFixed(8);\n //var dec = ((parseFloat(data[1]) + min + sec));\n\n // South and West are negative decimals\n dec = (data[7] == 'S' || data[7] == 'W') ? parseFloat(-dec) : parseFloat(dec);\n //dec = (data[7] == 'S' || data[7] == 'W') ? -dec : dec;\n\n this.decimal[sexagesimal] = dec;\n\n return dec;\n\n },\n\n\n /**\n * Checks if a value is in decimal format\n *\n * @param string Value to be checked\n * @return bool True if in sexagesimal format\n */\n isDecimal: function(value) {\n\n value = value.toString().replace(/\\s*/, '');\n\n // looks silly but works as expected\n // checks if value is in decimal format\n return (!isNaN(parseFloat(value)) && parseFloat(value) == value);\n\n },\n\n\n /**\n * Checks if a value is in sexagesimal format\n *\n * @param string Value to be checked\n * @return bool True if in sexagesimal format\n */\n isSexagesimal: function(value) {\n\n value = value.toString().replace(/\\s*/, '');\n\n return this.sexagesimalPattern.test(value);\n\n },\n\n round: function(value, n) {\n var decPlace = Math.pow(10, n);\n return Math.round(value * decPlace)/decPlace;\n }\n\n });\n\n // Node module\n if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {\n\n module.exports = geolib;\n\n // react native\n if (typeof global === 'object') {\n global.geolib = geolib;\n }\n\n // AMD module\n } else if (true) {\n\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () {\n return geolib;\n }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\n // we're in a browser\n } else {\n\n global.geolib = geolib;\n\n }\n\n}(this));\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvZ2VvbGliL2Rpc3QvZ2VvbGliLmpzPzcwNmYiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLDRCQUE0QixJQUFJLFlBQVksSUFBSSxjQUFjLElBQUksZ0JBQWdCLElBQUksVUFBVSxJQUFJO0FBQ3BHLFNBQVM7QUFDVDtBQUNBO0FBQ0EsdUJBQXVCLFNBQVM7QUFDaEMsdUJBQXVCLGFBQWE7QUFDcEMsdUJBQXVCLFdBQVc7QUFDbEMsdUJBQXVCLFlBQVk7QUFDbkMsdUJBQXVCLHNCQUFzQjtBQUM3Qyx1QkFBdUIsc0JBQXNCO0FBQzdDLHVCQUF1QixxQkFBcUI7QUFDNUMsdUJBQXVCLG9CQUFvQjtBQUMzQyx1QkFBdUI7QUFDdkIsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG1CQUFtQjs7QUFFbkIsdUJBQXVCOztBQUV2Qjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9FQUFvRSxXQUFXLGNBQWMsRUFBRTtBQUMvRixpQkFBaUI7O0FBRWpCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7O0FBR1Q7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDO0FBQzlDLDRDQUE0QztBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxzRUFBc0U7QUFDdEU7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQztBQUMvQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUNBQW1DO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsYUFBYTs7QUFFYjtBQUNBLDJCQUEyQjtBQUMzQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1EQUFtRDs7QUFFbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQkFBb0I7QUFDcEI7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUMsNENBQTRDO0FBQzVDO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0EsMkRBQTJELG9DQUFvQyxHQUFHLHlDQUF5QztBQUMzSSxxQ0FBcUM7QUFDckM7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQSw2REFBNkQscUNBQXFDLEdBQUcsOEJBQThCO0FBQ25JLGlDQUFpQztBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhDQUE4QyxPQUFPOztBQUVyRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQsb0NBQW9DLEdBQUcseUNBQXlDO0FBQzNJLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhEQUE4RDtBQUM5RCw2REFBNkQscUNBQXFDLEdBQUcsOEJBQThCO0FBQ25JO0FBQ0E7QUFDQTs7QUFFQSxvRUFBb0UsU0FBUzs7QUFFN0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZEQUE2RCxxQ0FBcUMsR0FBRyw4QkFBOEI7QUFDbkk7QUFDQTs7QUFFQSwrQ0FBK0MsbUJBQW1COztBQUVsRTs7QUFFQTtBQUNBOztBQUVBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUEsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMERBQTBEO0FBQzFELHlEQUF5RCxxQ0FBcUMsR0FBRyw4QkFBOEI7QUFDL0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwrQ0FBK0MsbUJBQW1COztBQUVsRTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQSwrREFBK0QscUNBQXFDO0FBQ3BHLDZFQUE2RSxxQ0FBcUM7QUFDbEg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2REFBNkQscUNBQXFDO0FBQ2xHO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBLDZEQUE2RCxxQ0FBcUM7QUFDbEc7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0EsNkRBQTZELHFDQUFxQztBQUNsRztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDOztBQUVBO0FBQ0E7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBLCtEQUErRDtBQUMvRCxrRUFBa0UscUNBQXFDLEdBQUcsOEJBQThCO0FBQ3hJO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQSxhQUFhOztBQUViLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsK0NBQStDO0FBQy9DLDZDQUE2QztBQUM3QywyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0M7QUFDL0MsNkNBQTZDO0FBQzdDLDJDQUEyQztBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QztBQUM3QywyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsK0RBQStEO0FBQy9ELGtFQUFrRSxxQ0FBcUMsR0FBRyw4QkFBOEI7QUFDeEk7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0Esa0VBQWtFLHFDQUFxQyxHQUFHLDhCQUE4QjtBQUN4STtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSw4Q0FBOEMsT0FBTztBQUNyRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0Esc0VBQXNFO0FBQ3RFLHNFQUFzRTtBQUN0RTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQscUNBQXFDO0FBQ2pHO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSw4Q0FBOEM7QUFDOUM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdEQUF3RDs7QUFFeEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLGFBQWE7O0FBRWI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEscUJBQXFCOztBQUVyQjs7QUFFQTs7QUFFQSx5QkFBeUI7O0FBRXpCO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxxQkFBcUI7O0FBRXJCOztBQUVBLHFCQUFxQjs7QUFFckI7O0FBRUE7O0FBRUEsaUJBQWlCOztBQUVqQjs7QUFFQSxhQUFhOztBQUViOztBQUVBLGFBQWE7O0FBRWI7QUFDQTtBQUNBOztBQUVBOztBQUVBOzs7QUFHQTs7QUFFQTs7QUFFQSxhQUFhOztBQUViOztBQUVBOztBQUVBOztBQUVBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSyxVQUFVLElBQTBDOztBQUV6RCxRQUFRLGlDQUFpQixFQUFFLG1DQUFFO0FBQzdCO0FBQ0EsU0FBUztBQUFBLG9HQUFDOztBQUVWO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTs7QUFFQSxDQUFDIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2dlb2xpYi9kaXN0L2dlb2xpYi5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qISBnZW9saWIgMi4wLjIzIGJ5IE1hbnVlbCBCaWVoXHJcbiogTGlicmFyeSB0byBwcm92aWRlIGdlbyBmdW5jdGlvbnMgbGlrZSBkaXN0YW5jZSBjYWxjdWxhdGlvbixcclxuKiBjb252ZXJzaW9uIG9mIGRlY2ltYWwgY29vcmRpbmF0ZXMgdG8gc2V4YWdlc2ltYWwgYW5kIHZpY2UgdmVyc2EsIGV0Yy5cclxuKiBXR1MgODQgKFdvcmxkIEdlb2RldGljIFN5c3RlbSAxOTg0KVxyXG4qIFxyXG4qIEBhdXRob3IgTWFudWVsIEJpZWhcclxuKiBAdXJsIGh0dHA6Ly93d3cubWFudWVsYmllaC5jb20vXHJcbiogQHZlcnNpb24gMi4wLjIzXHJcbiogQGxpY2Vuc2UgTUlUIFxyXG4qKi87KGZ1bmN0aW9uKGdsb2JhbCwgdW5kZWZpbmVkKSB7XG5cbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIGZ1bmN0aW9uIEdlb2xpYigpIHt9XG5cbiAgICAvLyBDb25zdGFudHNcbiAgICBHZW9saWIuVE9fUkFEID0gTWF0aC5QSSAvIDE4MDtcbiAgICBHZW9saWIuVE9fREVHID0gMTgwIC8gTWF0aC5QSTtcbiAgICBHZW9saWIuUElfWDIgPSBNYXRoLlBJICogMjtcbiAgICBHZW9saWIuUElfRElWNCA9IE1hdGguUEkgLyA0O1xuXG4gICAgLy8gU2V0dGluZyByZWFkb25seSBkZWZhdWx0c1xuICAgIHZhciBnZW9saWIgPSBPYmplY3QuY3JlYXRlKEdlb2xpYi5wcm90b3R5cGUsIHtcbiAgICAgICAgdmVyc2lvbjoge1xuICAgICAgICAgICAgdmFsdWU6IFwiMi4wLjIzXCJcbiAgICAgICAgfSxcbiAgICAgICAgcmFkaXVzOiB7XG4gICAgICAgICAgICB2YWx1ZTogNjM3ODEzN1xuICAgICAgICB9LFxuICAgICAgICBtaW5MYXQ6IHtcbiAgICAgICAgICAgIHZhbHVlOiAtOTBcbiAgICAgICAgfSxcbiAgICAgICAgbWF4TGF0OiB7XG4gICAgICAgICAgICB2YWx1ZTogOTBcbiAgICAgICAgfSxcbiAgICAgICAgbWluTG9uOiB7XG4gICAgICAgICAgICB2YWx1ZTogLTE4MFxuICAgICAgICB9LFxuICAgICAgICBtYXhMb246IHtcbiAgICAgICAgICAgIHZhbHVlOiAxODBcbiAgICAgICAgfSxcbiAgICAgICAgc2V4YWdlc2ltYWxQYXR0ZXJuOiB7XG4gICAgICAgICAgICB2YWx1ZTogL14oWzAtOV17MSwzfSnCsFxccyooWzAtOV17MSwzfSg/OlxcLig/OlswLTldezEsMn0pKT8pJ1xccyooKFswLTldezEsM30oXFwuKFswLTldezEsNH0pKT8pXCJcXHMqKT8oW05FT1NXXT8pJC9cbiAgICAgICAgfSxcbiAgICAgICAgbWVhc3VyZXM6IHtcbiAgICAgICAgICAgIHZhbHVlOiBPYmplY3QuY3JlYXRlKE9iamVjdC5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgICAgICBcIm1cIiA6IHt2YWx1ZTogMX0sXG4gICAgICAgICAgICAgICAgXCJrbVwiOiB7dmFsdWU6IDAuMDAxfSxcbiAgICAgICAgICAgICAgICBcImNtXCI6IHt2YWx1ZTogMTAwfSxcbiAgICAgICAgICAgICAgICBcIm1tXCI6IHt2YWx1ZTogMTAwMH0sXG4gICAgICAgICAgICAgICAgXCJtaVwiOiB7dmFsdWU6ICgxIC8gMTYwOS4zNDQpfSxcbiAgICAgICAgICAgICAgICBcInNtXCI6IHt2YWx1ZTogKDEgLyAxODUyLjIxNil9LFxuICAgICAgICAgICAgICAgIFwiZnRcIjoge3ZhbHVlOiAoMTAwIC8gMzAuNDgpfSxcbiAgICAgICAgICAgICAgICBcImluXCI6IHt2YWx1ZTogKDEwMCAvIDIuNTQpfSxcbiAgICAgICAgICAgICAgICBcInlkXCI6IHt2YWx1ZTogKDEgLyAwLjkxNDQpfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfSxcbiAgICAgICAgcHJvdG90eXBlOiB7XG4gICAgICAgICAgICB2YWx1ZTogR2VvbGliLnByb3RvdHlwZVxuICAgICAgICB9LFxuICAgICAgICBleHRlbmQ6IHtcbiAgICAgICAgICAgIHZhbHVlOiBmdW5jdGlvbihtZXRob2RzLCBvdmVyd3JpdGUpIHtcbiAgICAgICAgICAgICAgICBmb3IodmFyIHByb3AgaW4gbWV0aG9kcykge1xuICAgICAgICAgICAgICAgICAgICBpZih0eXBlb2YgZ2VvbGliLnByb3RvdHlwZVtwcm9wXSA9PT0gJ3VuZGVmaW5lZCcgfHwgb3ZlcndyaXRlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZih0eXBlb2YgbWV0aG9kc1twcm9wXSA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgbWV0aG9kc1twcm9wXS5iaW5kID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbGliLnByb3RvdHlwZVtwcm9wXSA9IG1ldGhvZHNbcHJvcF0uYmluZChnZW9saWIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZW9saWIucHJvdG90eXBlW3Byb3BdID0gbWV0aG9kc1twcm9wXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKHR5cGVvZihOdW1iZXIucHJvdG90eXBlLnRvUmFkKSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgTnVtYmVyLnByb3RvdHlwZS50b1JhZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMgKiBHZW9saWIuVE9fUkFEO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YoTnVtYmVyLnByb3RvdHlwZS50b0RlZykgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIE51bWJlci5wcm90b3R5cGUudG9EZWcgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzICogR2VvbGliLlRPX0RFRztcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBIZXJlIGNvbWVzIHRoZSBtYWdpY1xuICAgIGdlb2xpYi5leHRlbmQoe1xuXG4gICAgICAgIGRlY2ltYWw6IHt9LFxuXG4gICAgICAgIHNleGFnZXNpbWFsOiB7fSxcblxuICAgICAgICBkaXN0YW5jZTogbnVsbCxcblxuICAgICAgICBnZXRLZXlzOiBmdW5jdGlvbihwb2ludCkge1xuXG4gICAgICAgICAgICAvLyBHZW9KU09OIEFycmF5IFtsb25naXR1ZGUsIGxhdGl0dWRlKCwgZWxldmF0aW9uKV1cbiAgICAgICAgICAgIGlmKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChwb2ludCkgPT0gJ1tvYmplY3QgQXJyYXldJykge1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgbG9uZ2l0dWRlOiBwb2ludC5sZW5ndGggPj0gMSA/IDAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgIGxhdGl0dWRlOiBwb2ludC5sZW5ndGggPj0gMiA/IDEgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgICAgIGVsZXZhdGlvbjogcG9pbnQubGVuZ3RoID49IDMgPyAyIDogdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZ2V0S2V5ID0gZnVuY3Rpb24ocG9zc2libGVWYWx1ZXMpIHtcblxuICAgICAgICAgICAgICAgIHZhciBrZXk7XG5cbiAgICAgICAgICAgICAgICBwb3NzaWJsZVZhbHVlcy5ldmVyeShmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogY2hlY2sgaWYgcG9pbnQgaXMgYW4gb2JqZWN0XG4gICAgICAgICAgICAgICAgICAgIGlmKHR5cGVvZiBwb2ludCAhPSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50Lmhhc093blByb3BlcnR5KHZhbCkgPyAoZnVuY3Rpb24oKSB7IGtleSA9IHZhbDsgcmV0dXJuIGZhbHNlOyB9KCkpIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBrZXk7XG5cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHZhciBsb25naXR1ZGUgPSBnZXRLZXkoWydsbmcnLCAnbG9uJywgJ2xvbmdpdHVkZSddKTtcbiAgICAgICAgICAgIHZhciBsYXRpdHVkZSA9IGdldEtleShbJ2xhdCcsICdsYXRpdHVkZSddKTtcbiAgICAgICAgICAgIHZhciBlbGV2YXRpb24gPSBnZXRLZXkoWydhbHQnLCAnYWx0aXR1ZGUnLCAnZWxldmF0aW9uJywgJ2VsZXYnXSk7XG5cbiAgICAgICAgICAgIC8vIHJldHVybiB1bmRlZmluZWQgaWYgbm90IGF0IGxlYXN0IG9uZSB2YWxpZCBwcm9wZXJ0eSB3YXMgZm91bmRcbiAgICAgICAgICAgIGlmKHR5cGVvZiBsYXRpdHVkZSA9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgIHR5cGVvZiBsb25naXR1ZGUgPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgICAgICAgICB0eXBlb2YgZWxldmF0aW9uID09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBsYXRpdHVkZTogbGF0aXR1ZGUsXG4gICAgICAgICAgICAgICAgbG9uZ2l0dWRlOiBsb25naXR1ZGUsXG4gICAgICAgICAgICAgICAgZWxldmF0aW9uOiBlbGV2YXRpb25cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgfSxcblxuICAgICAgICAvLyByZXR1cm5zIGxhdGl0dWRlIG9mIGEgZ2l2ZW4gcG9pbnQsIGNvbnZlcnRlZCB0byBkZWNpbWFsXG4gICAgICAgIC8vIHNldCByYXcgdG8gdHJ1ZSB0byBhdm9pZCBjb252ZXJzaW9uXG4gICAgICAgIGdldExhdDogZnVuY3Rpb24ocG9pbnQsIHJhdykge1xuICAgICAgICAgICAgcmV0dXJuIHJhdyA9PT0gdHJ1ZSA/IHBvaW50W3RoaXMuZ2V0S2V5cyhwb2ludCkubGF0aXR1ZGVdIDogdGhpcy51c2VEZWNpbWFsKHBvaW50W3RoaXMuZ2V0S2V5cyhwb2ludCkubGF0aXR1ZGVdKTtcbiAgICAgICAgfSxcblxuICAgICAgICAvLyBBbGlhcyBmb3IgZ2V0TGF0XG4gICAgICAgIGxhdGl0dWRlOiBmdW5jdGlvbihwb2ludCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TGF0LmNhbGwodGhpcywgcG9pbnQpO1xuICAgICAgICB9LFxuXG4gICAgICAgIC8vIHJldHVybnMgbG9uZ2l0dWRlIG9mIGEgZ2l2ZW4gcG9pbnQsIGNvbnZlcnRlZCB0byBkZWNpbWFsXG4gICAgICAgIC8vIHNldCByYXcgdG8gdHJ1ZSB0byBhdm9pZCBjb252ZXJzaW9uXG4gICAgICAgIGdldExvbjogZnVuY3Rpb24ocG9pbnQsIHJhdykge1xuICAgICAgICAgICAgcmV0dXJuIHJhdyA9PT0gdHJ1ZSA/IHBvaW50W3RoaXMuZ2V0S2V5cyhwb2ludCkubG9uZ2l0dWRlXSA6IHRoaXMudXNlRGVjaW1hbChwb2ludFt0aGlzLmdldEtleXMocG9pbnQpLmxvbmdpdHVkZV0pO1xuICAgICAgICB9LFxuXG4gICAgICAgIC8vIEFsaWFzIGZvciBnZXRMb25cbiAgICAgICAgbG9uZ2l0dWRlOiBmdW5jdGlvbihwb2ludCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TG9uLmNhbGwodGhpcywgcG9pbnQpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGdldEVsZXY6IGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgICAgICAgICByZXR1cm4gcG9pbnRbdGhpcy5nZXRLZXlzKHBvaW50KS5lbGV2YXRpb25dO1xuICAgICAgICB9LFxuXG4gICAgICAgIC8vIEFsaWFzIGZvciBnZXRFbGV2XG4gICAgICAgIGVsZXZhdGlvbjogZnVuY3Rpb24ocG9pbnQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldEVsZXYuY2FsbCh0aGlzLCBwb2ludCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgY29vcmRzOiBmdW5jdGlvbihwb2ludCwgcmF3KSB7XG5cbiAgICAgICAgICAgIHZhciByZXR2YWwgPSB7XG4gICAgICAgICAgICAgICAgbGF0aXR1ZGU6IHJhdyA9PT0gdHJ1ZSA/IHBvaW50W3RoaXMuZ2V0S2V5cyhwb2ludCkubGF0aXR1ZGVdIDogdGhpcy51c2VEZWNpbWFsKHBvaW50W3RoaXMuZ2V0S2V5cyhwb2ludCkubGF0aXR1ZGVdKSxcbiAgICAgICAgICAgICAgICBsb25naXR1ZGU6IHJhdyA9PT0gdHJ1ZSA/IHBvaW50W3RoaXMuZ2V0S2V5cyhwb2ludCkubG9uZ2l0dWRlXSA6IHRoaXMudXNlRGVjaW1hbChwb2ludFt0aGlzLmdldEtleXMocG9pbnQpLmxvbmdpdHVkZV0pXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB2YXIgZWxldiA9IHBvaW50W3RoaXMuZ2V0S2V5cyhwb2ludCkuZWxldmF0aW9uXTtcblxuICAgICAgICAgICAgaWYodHlwZW9mIGVsZXYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dmFsWydlbGV2YXRpb24nXSA9IGVsZXY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXR2YWw7XG5cbiAgICAgICAgfSxcblxuICAgICAgICAvLyBBbGlhcyBmb3IgY29vcmRzXG4gICAgICAgIGxsOiBmdW5jdGlvbihwb2ludCwgcmF3KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb29yZHMuY2FsbCh0aGlzLCBwb2ludCwgcmF3KTtcbiAgICAgICAgfSxcblxuXG4gICAgICAgIC8vIGNoZWNrcyBpZiBhIHZhcmlhYmxlIGNvbnRhaW5zIGEgdmFsaWQgbGF0bG9uZyBvYmplY3RcbiAgICAgICAgdmFsaWRhdGU6IGZ1bmN0aW9uKHBvaW50KSB7XG5cbiAgICAgICAgICAgIHZhciBrZXlzID0gdGhpcy5nZXRLZXlzKHBvaW50KTtcblxuICAgICAgICAgICAgaWYodHlwZW9mIGtleXMgPT09ICd1bmRlZmluZWQnIHx8IHR5cGVvZiBrZXlzLmxhdGl0dWRlID09PSAndW5kZWZpbmVkJyB8fCBrZXlzLmxvbmdpdHVkZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBsYXQgPSBwb2ludFtrZXlzLmxhdGl0dWRlXTtcbiAgICAgICAgICAgIHZhciBsbmcgPSBwb2ludFtrZXlzLmxvbmdpdHVkZV07XG5cbiAgICAgICAgICAgIGlmKHR5cGVvZiBsYXQgPT09ICd1bmRlZmluZWQnIHx8ICF0aGlzLmlzRGVjaW1hbChsYXQpICYmICF0aGlzLmlzU2V4YWdlc2ltYWwobGF0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYodHlwZW9mIGxuZyA9PT0gJ3VuZGVmaW5lZCcgfHwgIXRoaXMuaXNEZWNpbWFsKGxuZykgJiYgIXRoaXMuaXNTZXhhZ2VzaW1hbChsbmcpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsYXQgPSB0aGlzLnVzZURlY2ltYWwobGF0KTtcbiAgICAgICAgICAgIGxuZyA9IHRoaXMudXNlRGVjaW1hbChsbmcpO1xuXG4gICAgICAgICAgICBpZihsYXQgPCB0aGlzLm1pbkxhdCB8fCBsYXQgPiB0aGlzLm1heExhdCB8fCBsbmcgPCB0aGlzLm1pbkxvbiB8fCBsbmcgPiB0aGlzLm1heExvbikge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG5cbiAgICAgICAgfSxcblxuICAgICAgICAvKipcbiAgICAgICAgKiBDYWxjdWxhdGVzIGdlb2RldGljIGRpc3RhbmNlIGJldHdlZW4gdHdvIHBvaW50cyBzcGVjaWZpZWQgYnkgbGF0aXR1ZGUvbG9uZ2l0dWRlIHVzaW5nXG4gICAgICAgICogVmluY2VudHkgaW52ZXJzZSBmb3JtdWxhIGZvciBlbGxpcHNvaWRzXG4gICAgICAgICogVmluY2VudHkgSW52ZXJzZSBTb2x1dGlvbiBvZiBHZW9kZXNpY3Mgb24gdGhlIEVsbGlwc29pZCAoYykgQ2hyaXMgVmVuZXNzIDIwMDItMjAxMFxuICAgICAgICAqIChMaWNlbnNlZCB1bmRlciBDQyBCWSAzLjApXG4gICAgICAgICpcbiAgICAgICAgKiBAcGFyYW0gICAgb2JqZWN0ICAgIFN0YXJ0IHBvc2l0aW9uIHtsYXRpdHVkZTogMTIzLCBsb25naXR1ZGU6IDEyM31cbiAgICAgICAgKiBAcGFyYW0gICAgb2JqZWN0ICAgIEVuZCBwb3NpdGlvbiB7bGF0aXR1ZGU6IDEyMywgbG9uZ2l0dWRlOiAxMjN9XG4gICAgICAgICogQHBhcmFtICAgIGludGVnZXIgICBBY2N1cmFjeSAoaW4gbWV0ZXJzKVxuICAgICAgICAqIEBwYXJhbSAgICBpbnRlZ2VyICAgUHJlY2lzaW9uIChpbiBkZWNpbWFsIGNhc2VzKVxuICAgICAgICAqIEByZXR1cm4gICBpbnRlZ2VyICAgRGlzdGFuY2UgKGluIG1ldGVycylcbiAgICAgICAgKi9cbiAgICAgICAgZ2V0RGlzdGFuY2U6IGZ1bmN0aW9uKHN0YXJ0LCBlbmQsIGFjY3VyYWN5LCBwcmVjaXNpb24pIHtcblxuICAgICAgICAgICAgYWNjdXJhY3kgPSBNYXRoLmZsb29yKGFjY3VyYWN5KSB8fCAxO1xuICAgICAgICAgICAgcHJlY2lzaW9uID0gTWF0aC5mbG9vcihwcmVjaXNpb24pIHx8IDA7XG5cbiAgICAgICAgICAgIHZhciBzID0gdGhpcy5jb29yZHMoc3RhcnQpO1xuICAgICAgICAgICAgdmFyIGUgPSB0aGlzLmNvb3JkcyhlbmQpO1xuXG4gICAgICAgICAgICB2YXIgYSA9IDYzNzgxMzcsIGIgPSA2MzU2NzUyLjMxNDI0NSwgIGYgPSAxLzI5OC4yNTcyMjM1NjM7ICAvLyBXR1MtODQgZWxsaXBzb2lkIHBhcmFtc1xuICAgICAgICAgICAgdmFyIEwgPSAoZVsnbG9uZ2l0dWRlJ10tc1snbG9uZ2l0dWRlJ10pLnRvUmFkKCk7XG5cbiAgICAgICAgICAgIHZhciBjb3NTaWdtYSwgc2lnbWEsIHNpbkFscGhhLCBjb3NTcUFscGhhLCBjb3MyU2lnbWFNLCBzaW5TaWdtYTtcblxuICAgICAgICAgICAgdmFyIFUxID0gTWF0aC5hdGFuKCgxLWYpICogTWF0aC50YW4ocGFyc2VGbG9hdChzWydsYXRpdHVkZSddKS50b1JhZCgpKSk7XG4gICAgICAgICAgICB2YXIgVTIgPSBNYXRoLmF0YW4oKDEtZikgKiBNYXRoLnRhbihwYXJzZUZsb2F0KGVbJ2xhdGl0dWRlJ10pLnRvUmFkKCkpKTtcbiAgICAgICAgICAgIHZhciBzaW5VMSA9IE1hdGguc2luKFUxKSwgY29zVTEgPSBNYXRoLmNvcyhVMSk7XG4gICAgICAgICAgICB2YXIgc2luVTIgPSBNYXRoLnNpbihVMiksIGNvc1UyID0gTWF0aC5jb3MoVTIpO1xuXG4gICAgICAgICAgICB2YXIgbGFtYmRhID0gTCwgbGFtYmRhUCwgaXRlckxpbWl0ID0gMTAwO1xuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIHZhciBzaW5MYW1iZGEgPSBNYXRoLnNpbihsYW1iZGEpLCBjb3NMYW1iZGEgPSBNYXRoLmNvcyhsYW1iZGEpO1xuICAgICAgICAgICAgICAgIHNpblNpZ21hID0gKFxuICAgICAgICAgICAgICAgICAgICBNYXRoLnNxcnQoXG4gICAgICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29zVTIgKiBzaW5MYW1iZGFcbiAgICAgICAgICAgICAgICAgICAgICAgICkgKiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29zVTIgKiBzaW5MYW1iZGFcbiAgICAgICAgICAgICAgICAgICAgICAgICkgKyAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29zVTEgKiBzaW5VMiAtIHNpblUxICogY29zVTIgKiBjb3NMYW1iZGFcbiAgICAgICAgICAgICAgICAgICAgICAgICkgKiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29zVTEgKiBzaW5VMiAtIHNpblUxICogY29zVTIgKiBjb3NMYW1iZGFcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgaWYgKHNpblNpZ21hID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBnZW9saWIuZGlzdGFuY2UgPSAwOyAgLy8gY28taW5jaWRlbnQgcG9pbnRzXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29zU2lnbWEgPSBzaW5VMSAqIHNpblUyICsgY29zVTEgKiBjb3NVMiAqIGNvc0xhbWJkYTtcbiAgICAgICAgICAgICAgICBzaWdtYSA9IE1hdGguYXRhbjIoc2luU2lnbWEsIGNvc1NpZ21hKTtcbiAgICAgICAgICAgICAgICBzaW5BbHBoYSA9IGNvc1UxICogY29zVTIgKiBzaW5MYW1iZGEgLyBzaW5TaWdtYTtcbiAgICAgICAgICAgICAgICBjb3NTcUFscGhhID0gMSAtIHNpbkFscGhhICogc2luQWxwaGE7XG4gICAgICAgICAgICAgICAgY29zMlNpZ21hTSA9IGNvc1NpZ21hIC0gMiAqIHNpblUxICogc2luVTIgLyBjb3NTcUFscGhhO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzTmFOKGNvczJTaWdtYU0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvczJTaWdtYU0gPSAwOyAgLy8gZXF1YXRvcmlhbCBsaW5lOiBjb3NTcUFscGhhPTAgKMKnNilcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIEMgPSAoXG4gICAgICAgICAgICAgICAgICAgIGYgLyAxNiAqIGNvc1NxQWxwaGEgKiAoXG4gICAgICAgICAgICAgICAgICAgICAgICA0ICsgZiAqIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA0IC0gMyAqIGNvc1NxQWxwaGFcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgbGFtYmRhUCA9IGxhbWJkYTtcbiAgICAgICAgICAgICAgICBsYW1iZGEgPSAoXG4gICAgICAgICAgICAgICAgICAgIEwgKyAoXG4gICAgICAgICAgICAgICAgICAgICAgICAxIC0gQ1xuICAgICAgICAgICAgICAgICAgICApICogZiAqIHNpbkFscGhhICogKFxuICAgICAgICAgICAgICAgICAgICAgICAgc2lnbWEgKyBDICogc2luU2lnbWEgKiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29zMlNpZ21hTSArIEMgKiBjb3NTaWdtYSAqIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLTEgKyAyICogY29zMlNpZ21hTSAqIGNvczJTaWdtYU1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICB9IHdoaWxlIChNYXRoLmFicyhsYW1iZGEtbGFtYmRhUCkgPiAxZS0xMiAmJiAtLWl0ZXJMaW1pdD4wKTtcblxuICAgICAgICAgICAgaWYgKGl0ZXJMaW1pdCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYU47ICAvLyBmb3JtdWxhIGZhaWxlZCB0byBjb252ZXJnZVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgdVNxID0gKFxuICAgICAgICAgICAgICAgIGNvc1NxQWxwaGEgKiAoXG4gICAgICAgICAgICAgICAgICAgIGEgKiBhIC0gYiAqIGJcbiAgICAgICAgICAgICAgICApIC8gKFxuICAgICAgICAgICAgICAgICAgICBiKmJcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICB2YXIgQSA9IChcbiAgICAgICAgICAgICAgICAxICsgdVNxIC8gMTYzODQgKiAoXG4gICAgICAgICAgICAgICAgICAgIDQwOTYgKyB1U3EgKiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAtNzY4ICsgdVNxICogKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDMyMCAtIDE3NSAqIHVTcVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgdmFyIEIgPSAoXG4gICAgICAgICAgICAgICAgdVNxIC8gMTAyNCAqIChcbiAgICAgICAgICAgICAgICAgICAgMjU2ICsgdVNxICogKFxuICAgICAgICAgICAgICAgICAgICAgICAgLTEyOCArIHVTcSAqIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA3NC00NyAqIHVTcVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgdmFyIGRlbHRhU2lnbWEgPSAoXG4gICAgICAgICAgICAgICAgQiAqIHNpblNpZ21hICogKFxuICAgICAgICAgICAgICAgICAgICBjb3MyU2lnbWFNICsgQiAvIDQgKiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBjb3NTaWdtYSAqIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAtMSArIDIgKiBjb3MyU2lnbWFNICogY29zMlNpZ21hTVxuICAgICAgICAgICAgICAgICAgICAgICAgKSAtQiAvIDYgKiBjb3MyU2lnbWFNICogKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC0zICsgNCAqIHNpblNpZ21hICogc2luU2lnbWFcbiAgICAgICAgICAgICAgICAgICAgICAgICkgKiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLTMgKyA0ICogY29zMlNpZ21hTSAqIGNvczJTaWdtYU1cbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIHZhciBkaXN0YW5jZSA9IGIgKiBBICogKHNpZ21hIC0gZGVsdGFTaWdtYSk7XG5cbiAgICAgICAgICAgIGRpc3RhbmNlID0gZGlzdGFuY2UudG9GaXhlZChwcmVjaXNpb24pOyAvLyByb3VuZCB0byAxbW0gcHJlY2lzaW9uXG5cbiAgICAgICAgICAgIC8vaWYgKHN0YXJ0Lmhhc093blByb3BlcnR5KGVsZXZhdGlvbikgJiYgZW5kLmhhc093blByb3BlcnR5KGVsZXZhdGlvbikpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5lbGV2YXRpb24oc3RhcnQpICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgdGhpcy5lbGV2YXRpb24oZW5kKSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2xpbWIgPSBNYXRoLmFicyh0aGlzLmVsZXZhdGlvbihzdGFydCkgLSB0aGlzLmVsZXZhdGlvbihlbmQpKTtcbiAgICAgICAgICAgICAgICBkaXN0YW5jZSA9IE1hdGguc3FydChkaXN0YW5jZSAqIGRpc3RhbmNlICsgY2xpbWIgKiBjbGltYik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRpc3RhbmNlID0gTWF0aC5yb3VuZChkaXN0YW5jZSAqIE1hdGgucG93KDEwLCBwcmVjaXNpb24pIC8gYWNjdXJhY3kpICogYWNjdXJhY3kgLyBNYXRoLnBvdygxMCwgcHJlY2lzaW9uKTtcblxuICAgICAgICAgICAgLypcbiAgICAgICAgICAgIC8vIG5vdGU6IHRvIHJldHVybiBpbml0aWFsL2ZpbmFsIGJlYXJpbmdzIGluIGFkZGl0aW9uIHRvIGRpc3RhbmNlLCB1c2Ugc29tZXRoaW5nIGxpa2U6XG4gICAgICAgICAgICB2YXIgZndkQXogPSBNYXRoLmF0YW4yKGNvc1UyKnNpbkxhbWJkYSwgIGNvc1UxKnNpblUyLXNpblUxKmNvc1UyKmNvc0xhbWJkYSk7XG4gICAgICAgICAgICB2YXIgcmV2QXogPSBNYXRoLmF0YW4yKGNvc1UxKnNpbkxhbWJkYSwgLXNpblUxKmNvc1UyK2Nvc1UxKnNpblUyKmNvc0xhbWJkYSk7XG5cbiAgICAgICAgICAgIHJldHVybiB7IGRpc3RhbmNlOiBzLCBpbml0aWFsQmVhcmluZzogZndkQXoudG9EZWcoKSwgZmluYWxCZWFyaW5nOiByZXZBei50b0RlZygpIH07XG4gICAgICAgICAgICAqL1xuXG4gICAgICAgIH0sXG5cblxuICAgICAgICAvKipcbiAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBzcG90cy5cbiAgICAgICAgKiBUaGlzIG1ldGhvZCBpcyBtb3JlIHNpbXBsZSBidXQgYWxzbyBmYXIgbW9yZSBpbmFjY3VyYXRlXG4gICAgICAgICpcbiAgICAgICAgKiBAcGFyYW0gICAgb2JqZWN0ICAgIFN0YXJ0IHBvc2l0aW9uIHtsYXRpdHVkZTogMTIzLCBsb25naXR1ZGU6IDEyM31cbiAgICAgICAgKiBAcGFyYW0gICAgb2JqZWN0ICAgIEVuZCBwb3NpdGlvbiB7bGF0aXR1ZGU6IDEyMywgbG9uZ2l0dWRlOiAxMjN9XG4gICAgICAgICogQHBhcmFtICAgIGludGVnZXIgICBBY2N1cmFjeSAoaW4gbWV0ZXJzKVxuICAgICAgICAqIEByZXR1cm4gICBpbnRlZ2VyICAgRGlzdGFuY2UgKGluIG1ldGVycylcbiAgICAgICAgKi9cbiAgICAgICAgZ2V0RGlzdGFuY2VTaW1wbGU6IGZ1bmN0aW9uKHN0YXJ0LCBlbmQsIGFjY3VyYWN5KSB7XG5cbiAgICAgICAgICAgIGFjY3VyYWN5ID0gTWF0aC5mbG9vcihhY2N1cmFjeSkgfHwgMTtcblxuICAgICAgICAgICAgdmFyIGRpc3RhbmNlID1cbiAgICAgICAgICAgICAgICBNYXRoLnJvdW5kKFxuICAgICAgICAgICAgICAgICAgICBNYXRoLmFjb3MoXG4gICAgICAgICAgICAgICAgICAgICAgICBNYXRoLnNpbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxhdGl0dWRlKGVuZCkudG9SYWQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSAqXG4gICAgICAgICAgICAgICAgICAgICAgICBNYXRoLnNpbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxhdGl0dWRlKHN0YXJ0KS50b1JhZCgpXG4gICAgICAgICAgICAgICAgICAgICAgICApICtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hdGguY29zKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGF0aXR1ZGUoZW5kKS50b1JhZCgpXG4gICAgICAgICAgICAgICAgICAgICAgICApICpcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hdGguY29zKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGF0aXR1ZGUoc3RhcnQpLnRvUmFkKClcbiAgICAgICAgICAgICAgICAgICAgICAgICkgKlxuICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5jb3MoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb25naXR1ZGUoc3RhcnQpLnRvUmFkKCkgLSB0aGlzLmxvbmdpdHVkZShlbmQpLnRvUmFkKClcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgKSAqIHRoaXMucmFkaXVzXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgcmV0dXJuIGdlb2xpYi5kaXN0YW5jZSA9IE1hdGguZmxvb3IoTWF0aC5yb3VuZChkaXN0YW5jZS9hY2N1cmFjeSkqYWNjdXJhY3kpO1xuXG4gICAgICAgIH0sXG5cblxuICAgIC8qKlxuICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIGNlbnRlciBvZiBhIGNvbGxlY3Rpb24gb2YgZ2VvIGNvb3JkaW5hdGVzXG4gICAgICAgICpcbiAgICAgICAgKiBAcGFyYW0gICAgICAgIGFycmF5ICAgICAgIENvbGxlY3Rpb24gb2YgY29vcmRzIFt7bGF0aXR1ZGU6IDUxLjUxMCwgbG9uZ2l0dWRlOiA3LjEzMjF9LCB7bGF0aXR1ZGU6IDQ5LjEyMzgsIGxvbmdpdHVkZTogXCI4wrAgMzAnIFdcIn0sIC4uLl1cbiAgICAgICAgKiBAcmV0dXJuICAgICAgIG9iamVjdCAgICAgIHtsYXRpdHVkZTogY2VudGVyTGF0LCBsb25naXR1ZGU6IGNlbnRlckxuZ31cbiAgICAgICAgKi9cbiAgICAgICAgZ2V0Q2VudGVyOiBmdW5jdGlvbihjb29yZHMpIHtcblxuICAgICAgICAgICAgdmFyIGNvb3Jkc0FycmF5ID0gY29vcmRzO1xuICAgICAgICAgICAgaWYodHlwZW9mIGNvb3JkcyA9PT0gJ29iamVjdCcgJiYgIShjb29yZHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcblxuICAgICAgICAgICAgICAgIGNvb3Jkc0FycmF5ID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IodmFyIGtleSBpbiBjb29yZHMpIHtcbiAgICAgICAgICAgICAgICAgICAgY29vcmRzQXJyYXkucHVzaChcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29vcmRzKGNvb3Jkc1trZXldKVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZighY29vcmRzQXJyYXkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgWCA9IDAuMDtcbiAgICAgICAgICAgIHZhciBZID0gMC4wO1xuICAgICAgICAgICAgdmFyIFogPSAwLjA7XG4gICAgICAgICAgICB2YXIgbGF0LCBsb24sIGh5cDtcblxuICAgICAgICAgICAgY29vcmRzQXJyYXkuZm9yRWFjaChmdW5jdGlvbihjb29yZCkge1xuXG4gICAgICAgICAgICAgICAgbGF0ID0gdGhpcy5sYXRpdHVkZShjb29yZCkudG9SYWQoKTtcbiAgICAgICAgICAgICAgICBsb24gPSB0aGlzLmxvbmdpdHVkZShjb29yZCkudG9SYWQoKTtcblxuICAgICAgICAgICAgICAgIFggKz0gTWF0aC5jb3MobGF0KSAqIE1hdGguY29zKGxvbik7XG4gICAgICAgICAgICAgICAgWSArPSBNYXRoLmNvcyhsYXQpICogTWF0aC5zaW4obG9uKTtcbiAgICAgICAgICAgICAgICBaICs9IE1hdGguc2luKGxhdCk7XG5cbiAgICAgICAgICAgIH0sIHRoaXMpO1xuXG4gICAgICAgICAgICB2YXIgbmJfY29vcmRzID0gY29vcmRzQXJyYXkubGVuZ3RoO1xuICAgICAgICAgICAgWCA9IFggLyBuYl9jb29yZHM7XG4gICAgICAgICAgICBZID0gWSAvIG5iX2Nvb3JkcztcbiAgICAgICAgICAgIFogPSBaIC8gbmJfY29vcmRzO1xuXG4gICAgICAgICAgICBsb24gPSBNYXRoLmF0YW4yKFksIFgpO1xuICAgICAgICAgICAgaHlwID0gTWF0aC5zcXJ0KFggKiBYICsgWSAqIFkpO1xuICAgICAgICAgICAgbGF0ID0gTWF0aC5hdGFuMihaLCBoeXApO1xuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGxhdGl0dWRlOiAobGF0ICogR2VvbGliLlRPX0RFRykudG9GaXhlZCg2KSxcbiAgICAgICAgICAgICAgICBsb25naXR1ZGU6IChsb24gKiBHZW9saWIuVE9fREVHKS50b0ZpeGVkKDYpXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgIH0sXG5cblxuICAgICAgICAvKipcbiAgICAgICAgKiBHZXRzIHRoZSBtYXggYW5kIG1pbiwgbGF0aXR1ZGUsIGxvbmdpdHVkZSwgYW5kIGVsZXZhdGlvbiAoaWYgcHJvdmlkZWQpLlxuICAgICAgICAqIEBwYXJhbSAgICAgICAgYXJyYXkgICAgICAgYXJyYXkgd2l0aCBjb29yZHMgZS5nLiBbe2xhdGl0dWRlOiA1MS41MTQzLCBsb25naXR1ZGU6IDcuNDEzOH0sIHtsYXRpdHVkZTogMTIzLCBsb25naXR1ZGU6IDEyM30sIC4uLl1cbiAgICAgICAgKiBAcmV0dXJuICAgb2JqZWN0ICAgICAge21heExhdDogbWF4TGF0LFxuICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgbWluTGF0OiBtaW5MYXRcbiAgICAgICAgKiAgICAgICAgICAgICAgICAgICAgIG1heExuZzogbWF4TG5nLFxuICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgbWluTG5nOiBtaW5MbmcsXG4gICAgICAgICogICAgICAgICAgICAgICAgICAgICBtYXhFbGV2OiBtYXhFbGV2LFxuICAgICAgICAqICAgICAgICAgICAgICAgICAgICAgbWluRWxldjogbWluRWxldn1cbiAgICAgICAgKi9cbiAgICAgICAgZ2V0Qm91bmRzOiBmdW5jdGlvbihjb29yZHMpIHtcblxuICAgICAgICAgICAgaWYgKCFjb29yZHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgdXNlRWxldmF0aW9uID0gdGhpcy5lbGV2YXRpb24oY29vcmRzWzBdKTtcblxuICAgICAgICAgICAgdmFyIHN0YXRzID0ge1xuICAgICAgICAgICAgICAgIG1heExhdDogLUluZmluaXR5LFxuICAgICAgICAgICAgICAgIG1pbkxhdDogSW5maW5pdHksXG4gICAgICAgICAgICAgICAgbWF4TG5nOiAtSW5maW5pdHksXG4gICAgICAgICAgICAgICAgbWluTG5nOiBJbmZpbml0eVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB1c2VFbGV2YXRpb24gIT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBzdGF0cy5tYXhFbGV2ID0gMDtcbiAgICAgICAgICAgICAgICBzdGF0cy5taW5FbGV2ID0gSW5maW5pdHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gY29vcmRzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuXG4gICAgICAgICAgICAgICAgc3RhdHMubWF4TGF0ID0gTWF0aC5tYXgodGhpcy5sYXRpdHVkZShjb29yZHNbaV0pLCBzdGF0cy5tYXhMYXQpO1xuICAgICAgICAgICAgICAgIHN0YXRzLm1pbkxhdCA9IE1hdGgubWluKHRoaXMubGF0aXR1ZGUoY29vcmRzW2ldKSwgc3RhdHMubWluTGF0KTtcbiAgICAgICAgICAgICAgICBzdGF0cy5tYXhMbmcgPSBNYXRoLm1heCh0aGlzLmxvbmdpdHVkZShjb29yZHNbaV0pLCBzdGF0cy5tYXhMbmcpO1xuICAgICAgICAgICAgICAgIHN0YXRzLm1pbkxuZyA9IE1hdGgubWluKHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tpXSksIHN0YXRzLm1pbkxuZyk7XG5cbiAgICAgICAgICAgICAgICBpZiAodXNlRWxldmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRzLm1heEVsZXYgPSBNYXRoLm1heCh0aGlzLmVsZXZhdGlvbihjb29yZHNbaV0pLCBzdGF0cy5tYXhFbGV2KTtcbiAgICAgICAgICAgICAgICAgICAgc3RhdHMubWluRWxldiA9IE1hdGgubWluKHRoaXMuZWxldmF0aW9uKGNvb3Jkc1tpXSksIHN0YXRzLm1pbkVsZXYpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gc3RhdHM7XG5cbiAgICAgICAgfSxcblxuICAgICAgICAvKipcbiAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBjZW50ZXIgb2YgdGhlIGJvdW5kcyBvZiBnZW8gY29vcmRpbmF0ZXMuXG4gICAgICAgICpcbiAgICAgICAgKiBPbiBwb2x5Z29ucyBsaWtlIHBvbGl0aWNhbCBib3JkZXJzIChlZy4gc3RhdGVzKVxuICAgICAgICAqIHRoaXMgbWF5IGdpdmVzIGEgY2xvc2VyIHJlc3VsdCB0byBodW1hbiBleHBlY3RhdGlvbiwgdGhhbiBgZ2V0Q2VudGVyYCxcbiAgICAgICAgKiBiZWNhdXNlIHRoYXQgZnVuY3Rpb24gY2FuIGJlIGRpc3R1cmJlZCBieSB1bmV2ZW4gZGlzdHJpYnV0aW9uIG9mXG4gICAgICAgICogcG9pbnQgaW4gZGlmZmVyZW50IHNpZGVzLlxuICAgICAgICAqIEltYWdpbmUgdGhlIFVTIHN0YXRlIE9rbGFob21hOiBgZ2V0Q2VudGVyYCBvbiB0aGF0IGdpdmVzIGEgc291dGhlcm5cbiAgICAgICAgKiBwb2ludCwgYmVjYXVzZSB0aGUgc291dGhlcm4gYm9yZGVyIGNvbnRhaW5zIGEgbG90IG1vcmUgbm9kZXMsXG4gICAgICAgICogdGhhbiB0aGUgb3RoZXJzLlxuICAgICAgICAqXG4gICAgICAgICogQHBhcmFtICAgICAgICBhcnJheSAgICAgICBDb2xsZWN0aW9uIG9mIGNvb3JkcyBbe2xhdGl0dWRlOiA1MS41MTAsIGxvbmdpdHVkZTogNy4xMzIxfSwge2xhdGl0dWRlOiA0OS4xMjM4LCBsb25naXR1ZGU6IFwiOMKwIDMwJyBXXCJ9LCAuLi5dXG4gICAgICAgICogQHJldHVybiAgICAgICBvYmplY3QgICAgICB7bGF0aXR1ZGU6IGNlbnRlckxhdCwgbG9uZ2l0dWRlOiBjZW50ZXJMbmd9XG4gICAgICAgICovXG4gICAgICAgIGdldENlbnRlck9mQm91bmRzOiBmdW5jdGlvbihjb29yZHMpIHtcbiAgICAgICAgICAgIHZhciBiID0gdGhpcy5nZXRCb3VuZHMoY29vcmRzKTtcbiAgICAgICAgICAgIHZhciBsYXRpdHVkZSA9IGIubWluTGF0ICsgKChiLm1heExhdCAtIGIubWluTGF0KSAvIDIpO1xuICAgICAgICAgICAgdmFyIGxvbmdpdHVkZSA9IGIubWluTG5nICsgKChiLm1heExuZyAtIGIubWluTG5nKSAvIDIpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBsYXRpdHVkZTogcGFyc2VGbG9hdChsYXRpdHVkZS50b0ZpeGVkKDYpKSxcbiAgICAgICAgICAgICAgICBsb25naXR1ZGU6IHBhcnNlRmxvYXQobG9uZ2l0dWRlLnRvRml4ZWQoNikpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogQ29tcHV0ZXMgdGhlIGJvdW5kaW5nIGNvb3JkaW5hdGVzIG9mIGFsbCBwb2ludHMgb24gdGhlIHN1cmZhY2VcbiAgICAgICAgKiBvZiB0aGUgZWFydGggbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHRoZSBzcGVjaWZpZWQgZ3JlYXQgY2lyY2xlXG4gICAgICAgICogZGlzdGFuY2UuXG4gICAgICAgICpcbiAgICAgICAgKiBAcGFyYW0gb2JqZWN0IFBvaW50IHBvc2l0aW9uIHtsYXRpdHVkZTogMTIzLCBsb25naXR1ZGU6IDEyM31cbiAgICAgICAgKiBAcGFyYW0gbnVtYmVyIERpc3RhbmNlIChpbiBtZXRlcnMpLlxuICAgICAgICAqIEByZXR1cm4gYXJyYXkgQ29sbGVjdGlvbiBvZiB0d28gcG9pbnRzIGRlZmluaW5nIHRoZSBTVyBhbmQgTkUgY29ybmVycy5cbiAgICAgICAgKi9cbiAgICAgICAgZ2V0Qm91bmRzT2ZEaXN0YW5jZTogZnVuY3Rpb24ocG9pbnQsIGRpc3RhbmNlKSB7XG5cbiAgICAgICAgICAgIHZhciBsYXRpdHVkZSA9IHRoaXMubGF0aXR1ZGUocG9pbnQpO1xuICAgICAgICAgICAgdmFyIGxvbmdpdHVkZSA9IHRoaXMubG9uZ2l0dWRlKHBvaW50KTtcblxuICAgICAgICAgICAgdmFyIHJhZExhdCA9IGxhdGl0dWRlLnRvUmFkKCk7XG4gICAgICAgICAgICB2YXIgcmFkTG9uID0gbG9uZ2l0dWRlLnRvUmFkKCk7XG5cbiAgICAgICAgICAgIHZhciByYWREaXN0ID0gZGlzdGFuY2UgLyB0aGlzLnJhZGl1cztcbiAgICAgICAgICAgIHZhciBtaW5MYXQgPSByYWRMYXQgLSByYWREaXN0O1xuICAgICAgICAgICAgdmFyIG1heExhdCA9IHJhZExhdCArIHJhZERpc3Q7XG5cbiAgICAgICAgICAgIHZhciBNQVhfTEFUX1JBRCA9IHRoaXMubWF4TGF0LnRvUmFkKCk7XG4gICAgICAgICAgICB2YXIgTUlOX0xBVF9SQUQgPSB0aGlzLm1pbkxhdC50b1JhZCgpO1xuICAgICAgICAgICAgdmFyIE1BWF9MT05fUkFEID0gdGhpcy5tYXhMb24udG9SYWQoKTtcbiAgICAgICAgICAgIHZhciBNSU5fTE9OX1JBRCA9IHRoaXMubWluTG9uLnRvUmFkKCk7XG5cbiAgICAgICAgICAgIHZhciBtaW5Mb247XG4gICAgICAgICAgICB2YXIgbWF4TG9uO1xuXG4gICAgICAgICAgICBpZiAobWluTGF0ID4gTUlOX0xBVF9SQUQgJiYgbWF4TGF0IDwgTUFYX0xBVF9SQUQpIHtcblxuICAgICAgICAgICAgICAgIHZhciBkZWx0YUxvbiA9IE1hdGguYXNpbihNYXRoLnNpbihyYWREaXN0KSAvIE1hdGguY29zKHJhZExhdCkpO1xuICAgICAgICAgICAgICAgIG1pbkxvbiA9IHJhZExvbiAtIGRlbHRhTG9uO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1pbkxvbiA8IE1JTl9MT05fUkFEKSB7XG4gICAgICAgICAgICAgICAgICAgIG1pbkxvbiArPSBHZW9saWIuUElfWDI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbWF4TG9uID0gcmFkTG9uICsgZGVsdGFMb247XG5cbiAgICAgICAgICAgICAgICBpZiAobWF4TG9uID4gTUFYX0xPTl9SQUQpIHtcbiAgICAgICAgICAgICAgICAgICAgbWF4TG9uIC09IEdlb2xpYi5QSV9YMjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gQSBwb2xlIGlzIHdpdGhpbiB0aGUgZGlzdGFuY2UuXG4gICAgICAgICAgICAgICAgbWluTGF0ID0gTWF0aC5tYXgobWluTGF0LCBNSU5fTEFUX1JBRCk7XG4gICAgICAgICAgICAgICAgbWF4TGF0ID0gTWF0aC5taW4obWF4TGF0LCBNQVhfTEFUX1JBRCk7XG4gICAgICAgICAgICAgICAgbWluTG9uID0gTUlOX0xPTl9SQUQ7XG4gICAgICAgICAgICAgICAgbWF4TG9uID0gTUFYX0xPTl9SQUQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAgICAgLy8gU291dGh3ZXN0XG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZTogbWluTGF0LnRvRGVnKCksXG4gICAgICAgICAgICAgICAgICAgIGxvbmdpdHVkZTogbWluTG9uLnRvRGVnKClcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIC8vIE5vcnRoZWFzdFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgbGF0aXR1ZGU6IG1heExhdC50b0RlZygpLFxuICAgICAgICAgICAgICAgICAgICBsb25naXR1ZGU6IG1heExvbi50b0RlZygpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXTtcblxuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogQ2hlY2tzIHdoZXRoZXIgYSBwb2ludCBpcyBpbnNpZGUgb2YgYSBwb2x5Z29uIG9yIG5vdC5cbiAgICAgICAgKiBOb3RlIHRoYXQgdGhlIHBvbHlnb24gY29vcmRzIG11c3QgYmUgaW4gY29ycmVjdCBvcmRlciFcbiAgICAgICAgKlxuICAgICAgICAqIEBwYXJhbSAgICAgICAgb2JqZWN0ICAgICAgY29vcmRpbmF0ZSB0byBjaGVjayBlLmcuIHtsYXRpdHVkZTogNTEuNTAyMywgbG9uZ2l0dWRlOiA3LjM4MTV9XG4gICAgICAgICogQHBhcmFtICAgICAgICBhcnJheSAgICAgICBhcnJheSB3aXRoIGNvb3JkcyBlLmcuIFt7bGF0aXR1ZGU6IDUxLjUxNDMsIGxvbmdpdHVkZTogNy40MTM4fSwge2xhdGl0dWRlOiAxMjMsIGxvbmdpdHVkZTogMTIzfSwgLi4uXVxuICAgICAgICAqIEByZXR1cm4gICAgICAgYm9vbCAgICAgICAgdHJ1ZSBpZiB0aGUgY29vcmRpbmF0ZSBpcyBpbnNpZGUgdGhlIGdpdmVuIHBvbHlnb25cbiAgICAgICAgKi9cbiAgICAgICAgaXNQb2ludEluc2lkZTogZnVuY3Rpb24obGF0bG5nLCBjb29yZHMpIHtcblxuICAgICAgICAgICAgZm9yKHZhciBjID0gZmFsc2UsIGkgPSAtMSwgbCA9IGNvb3Jkcy5sZW5ndGgsIGogPSBsIC0gMTsgKytpIDwgbDsgaiA9IGkpIHtcblxuICAgICAgICAgICAgICAgIGlmKFxuICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICAodGhpcy5sb25naXR1ZGUoY29vcmRzW2ldKSA8PSB0aGlzLmxvbmdpdHVkZShsYXRsbmcpICYmIHRoaXMubG9uZ2l0dWRlKGxhdGxuZykgPCB0aGlzLmxvbmdpdHVkZShjb29yZHNbal0pKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgKHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tqXSkgPD0gdGhpcy5sb25naXR1ZGUobGF0bG5nKSAmJiB0aGlzLmxvbmdpdHVkZShsYXRsbmcpIDwgdGhpcy5sb25naXR1ZGUoY29vcmRzW2ldKSlcbiAgICAgICAgICAgICAgICAgICAgKSAmJlxuICAgICAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxhdGl0dWRlKGxhdGxuZykgPCAodGhpcy5sYXRpdHVkZShjb29yZHNbal0pIC0gdGhpcy5sYXRpdHVkZShjb29yZHNbaV0pKSAqXG4gICAgICAgICAgICAgICAgICAgICAgICAodGhpcy5sb25naXR1ZGUobGF0bG5nKSAtIHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tpXSkpIC9cbiAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzLmxvbmdpdHVkZShjb29yZHNbal0pIC0gdGhpcy5sb25naXR1ZGUoY29vcmRzW2ldKSkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXRpdHVkZShjb29yZHNbaV0pXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgYyA9ICFjO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gYztcblxuICAgICAgICB9LFxuXG5cbiAgICAgICAvKipcbiAgICAgICAgKiBQcmUgY2FsY3VsYXRlIHRoZSBwb2x5Z29uIGNvb3JkcywgdG8gc3BlZWQgdXAgdGhlIHBvaW50IGluc2lkZSBjaGVjay5cbiAgICAgICAgKiBVc2UgdGhpcyBmdW5jdGlvbiBiZWZvcmUgY2FsbGluZyBpc1BvaW50SW5zaWRlV2l0aFByZXBhcmVkUG9seWdvbigpXG4gICAgICAgICogQHNlZSAgICAgICAgICBBbGdvcnl0aG0gZnJvbSBodHRwOi8vYWxpZW5yeWRlcmZsZXguY29tL3BvbHlnb24vXG4gICAgICAgICogQHBhcmFtICAgICAgICBhcnJheSAgICAgICBhcnJheSB3aXRoIGNvb3JkcyBlLmcuIFt7bGF0aXR1ZGU6IDUxLjUxNDMsIGxvbmdpdHVkZTogNy40MTM4fSwge2xhdGl0dWRlOiAxMjMsIGxvbmdpdHVkZTogMTIzfSwgLi4uXVxuICAgICAgICAqL1xuICAgICAgICBwcmVwYXJlUG9seWdvbkZvcklzUG9pbnRJbnNpZGVPcHRpbWl6ZWQ6IGZ1bmN0aW9uKGNvb3Jkcykge1xuXG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwLCBqID0gY29vcmRzLmxlbmd0aC0xOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgIGlmKHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tqXSkgPT09IHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tpXSkpIHtcblxuICAgICAgICAgICAgICAgICAgICBjb29yZHNbaV0uY29uc3RhbnQgPSB0aGlzLmxhdGl0dWRlKGNvb3Jkc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgIGNvb3Jkc1tpXS5tdWx0aXBsZSA9IDA7XG5cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXG4gICAgICAgICAgICAgICAgICAgIGNvb3Jkc1tpXS5jb25zdGFudCA9IHRoaXMubGF0aXR1ZGUoY29vcmRzW2ldKSAtIChcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tpXSkgKiB0aGlzLmxhdGl0dWRlKGNvb3Jkc1tqXSlcbiAgICAgICAgICAgICAgICAgICAgKSAvIChcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tqXSkgLSB0aGlzLmxvbmdpdHVkZShjb29yZHNbaV0pXG4gICAgICAgICAgICAgICAgICAgICkgKyAoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvbmdpdHVkZShjb29yZHNbaV0pKnRoaXMubGF0aXR1ZGUoY29vcmRzW2ldKVxuICAgICAgICAgICAgICAgICAgICApIC8gKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb25naXR1ZGUoY29vcmRzW2pdKS10aGlzLmxvbmdpdHVkZShjb29yZHNbaV0pXG4gICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgY29vcmRzW2ldLm11bHRpcGxlID0gKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXRpdHVkZShjb29yZHNbal0pLXRoaXMubGF0aXR1ZGUoY29vcmRzW2ldKVxuICAgICAgICAgICAgICAgICAgICApIC8gKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb25naXR1ZGUoY29vcmRzW2pdKS10aGlzLmxvbmdpdHVkZShjb29yZHNbaV0pXG4gICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBqPWk7XG5cbiAgICAgICAgICAgIH1cblxuICAgICAgICB9LFxuXG4gICAgICAvKipcbiAgICAgICAqIENoZWNrcyB3aGV0aGVyIGEgcG9pbnQgaXMgaW5zaWRlIG9mIGEgcG9seWdvbiBvciBub3QuXG4gICAgICAgKiBcIlRoaXMgaXMgdXNlZnVsIGlmIHlvdSBoYXZlIG1hbnkgcG9pbnRzIHRoYXQgbmVlZCB0byBiZSB0ZXN0ZWQgYWdhaW5zdCB0aGUgc2FtZSAoc3RhdGljKSBwb2x5Z29uLlwiXG4gICAgICAgKiBQbGVhc2UgY2FsbCB0aGUgZnVuY3Rpb24gcHJlcGFyZVBvbHlnb25Gb3JJc1BvaW50SW5zaWRlT3B0aW1pemVkKCkgd2l0aCB0aGUgc2FtZSBjb29yZHMgb2JqZWN0IGJlZm9yZSB1c2luZyB0aGlzIGZ1bmN0aW9uLlxuICAgICAgICogTm90ZSB0aGF0IHRoZSBwb2x5Z29uIGNvb3JkcyBtdXN0IGJlIGluIGNvcnJlY3Qgb3JkZXIhXG4gICAgICAgKlxuICAgICAgICogQHNlZSAgICAgICAgICBBbGdvcnl0aG0gZnJvbSBodHRwOi8vYWxpZW5yeWRlcmZsZXguY29tL3BvbHlnb24vXG4gICAgICAgKlxuICAgICAgICogQHBhcmFtICAgICBvYmplY3QgICAgICBjb29yZGluYXRlIHRvIGNoZWNrIGUuZy4ge2xhdGl0dWRlOiA1MS41MDIzLCBsb25naXR1ZGU6IDcuMzgxNX1cbiAgICAgICAqIEBwYXJhbSAgICAgYXJyYXkgICAgICAgYXJyYXkgd2l0aCBjb29yZHMgZS5nLiBbe2xhdGl0dWRlOiA1MS41MTQzLCBsb25naXR1ZGU6IDcuNDEzOH0sIHtsYXRpdHVkZTogMTIzLCBsb25naXR1ZGU6IDEyM30sIC4uLl1cbiAgICAgICAqIEByZXR1cm4gICAgICAgIGJvb2wgICAgICAgIHRydWUgaWYgdGhlIGNvb3JkaW5hdGUgaXMgaW5zaWRlIHRoZSBnaXZlbiBwb2x5Z29uXG4gICAgICAgKi9cbiAgICAgICAgaXNQb2ludEluc2lkZVdpdGhQcmVwYXJlZFBvbHlnb246IGZ1bmN0aW9uKHBvaW50LCBjb29yZHMpIHtcblxuICAgICAgICAgICAgdmFyIGZsZ1BvaW50SW5zaWRlID0gZmFsc2UsXG4gICAgICAgICAgICB5ID0gdGhpcy5sb25naXR1ZGUocG9pbnQpLFxuICAgICAgICAgICAgeCA9IHRoaXMubGF0aXR1ZGUocG9pbnQpO1xuXG4gICAgICAgICAgICBmb3IodmFyIGkgPSAwLCBqID0gY29vcmRzLmxlbmd0aC0xOyBpIDwgY29vcmRzLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgICAgICAgICBpZiAoKHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tpXSkgPCB5ICYmIHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tqXSkgPj15IHx8XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tqXSkgPCB5ICYmIHRoaXMubG9uZ2l0dWRlKGNvb3Jkc1tpXSkgPj0geSkpIHtcblxuICAgICAgICAgICAgICAgICAgICBmbGdQb2ludEluc2lkZV49KHkqY29vcmRzW2ldLm11bHRpcGxlK2Nvb3Jkc1tpXS5jb25zdGFudCA8IHgpO1xuXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaj1pO1xuXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmbGdQb2ludEluc2lkZTtcblxuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogU2hvcnRjdXQgZm9yIGdlb2xpYi5pc1BvaW50SW5zaWRlKClcbiAgICAgICAgKi9cbiAgICAgICAgaXNJbnNpZGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNQb2ludEluc2lkZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogQ2hlY2tzIHdoZXRoZXIgYSBwb2ludCBpcyBpbnNpZGUgb2YgYSBjaXJjbGUgb3Igbm90LlxuICAgICAgICAqXG4gICAgICAgICogQHBhcmFtICAgICAgICBvYmplY3QgICAgICBjb29yZGluYXRlIHRvIGNoZWNrIChlLmcuIHtsYXRpdHVkZTogNTEuNTAyMywgbG9uZ2l0dWRlOiA3LjM4MTV9KVxuICAgICAgICAqIEBwYXJhbSAgICAgICAgb2JqZWN0ICAgICAgY29vcmRpbmF0ZSBvZiB0aGUgY2lyY2xlJ3MgY2VudGVyIChlLmcuIHtsYXRpdHVkZTogNTEuNDgxMiwgbG9uZ2l0dWRlOiA3LjQwMjV9KVxuICAgICAgICAqIEBwYXJhbSAgICAgICAgaW50ZWdlciAgICAgbWF4aW11bSByYWRpdXMgaW4gbWV0ZXJzXG4gICAgICAgICogQHJldHVybiAgICAgICBib29sICAgICAgICB0cnVlIGlmIHRoZSBjb29yZGluYXRlIGlzIHdpdGhpbiB0aGUgZ2l2ZW4gcmFkaXVzXG4gICAgICAgICovXG4gICAgICAgIGlzUG9pbnRJbkNpcmNsZTogZnVuY3Rpb24obGF0bG5nLCBjZW50ZXIsIHJhZGl1cykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RGlzdGFuY2UobGF0bG5nLCBjZW50ZXIpIDwgcmFkaXVzO1xuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogU2hvcnRjdXQgZm9yIGdlb2xpYi5pc1BvaW50SW5DaXJjbGUoKVxuICAgICAgICAqL1xuICAgICAgICB3aXRoaW5SYWRpdXM6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNQb2ludEluQ2lyY2xlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH0sXG5cblxuICAgICAgICAvKipcbiAgICAgICAgKiBHZXRzIHJodW1iIGxpbmUgYmVhcmluZyBvZiB0d28gcG9pbnRzLiBGaW5kIG91dCBhYm91dCB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHJodW1iIGxpbmUgYW5kXG4gICAgICAgICogZ3JlYXQgY2lyY2xlIGJlYXJpbmcgb24gV2lraXBlZGlhLiBJdCdzIHF1aXRlIGNvbXBsaWNhdGVkLiBSaHVtYiBsaW5lIHNob3VsZCBiZSBmaW5lIGluIG1vc3QgY2FzZXM6XG4gICAgICAgICpcbiAgICAgICAgKiBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1JodW1iX2xpbmUjR2VuZXJhbF9hbmRfbWF0aGVtYXRpY2FsX2Rlc2NyaXB0aW9uXG4gICAgICAgICpcbiAgICAgICAgKiBGdW5jdGlvbiBoZWF2aWx5IGJhc2VkIG9uIERvdWcgVmFuZGVyd2VpZGUncyBncmVhdCBQSFAgdmVyc2lvbiAobGljZW5zZWQgdW5kZXIgR1BMIDMuMClcbiAgICAgICAgKiBodHRwOi8vd3d3LmRvdWd2LmNvbS8yMDA5LzA3LzEzL2NhbGN1bGF0aW5nLXRoZS1iZWFyaW5nLWFuZC1jb21wYXNzLXJvc2UtZGlyZWN0aW9uLWJldHdlZW4tdHdvLWxhdGl0dWRlLWxvbmdpdHVkZS1jb29yZGluYXRlcy1pbi1waHAvXG4gICAgICAgICpcbiAgICAgICAgKiBAcGFyYW0gICAgICAgIG9iamVjdCAgICAgIG9yaWdpbiBjb29yZGluYXRlIChlLmcuIHtsYXRpdHVkZTogNTEuNTAyMywgbG9uZ2l0dWRlOiA3LjM4MTV9KVxuICAgICAgICAqIEBwYXJhbSAgICAgICAgb2JqZWN0ICAgICAgZGVzdGluYXRpb24gY29vcmRpbmF0ZVxuICAgICAgICAqIEByZXR1cm4gICAgICAgaW50ZWdlciAgICAgY2FsY3VsYXRlZCBiZWFyaW5nXG4gICAgICAgICovXG4gICAgICAgIGdldFJodW1iTGluZUJlYXJpbmc6IGZ1bmN0aW9uKG9yaWdpbkxMLCBkZXN0TEwpIHtcblxuICAgICAgICAgICAgLy8gZGlmZmVyZW5jZSBvZiBsb25naXR1ZGUgY29vcmRzXG4gICAgICAgICAgICB2YXIgZGlmZkxvbiA9IHRoaXMubG9uZ2l0dWRlKGRlc3RMTCkudG9SYWQoKSAtIHRoaXMubG9uZ2l0dWRlKG9yaWdpbkxMKS50b1JhZCgpO1xuXG4gICAgICAgICAgICAvLyBkaWZmZXJlbmNlIGxhdGl0dWRlIGNvb3JkcyBwaGlcbiAgICAgICAgICAgIHZhciBkaWZmUGhpID0gTWF0aC5sb2coXG4gICAgICAgICAgICAgICAgTWF0aC50YW4oXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGF0aXR1ZGUoZGVzdExMKS50b1JhZCgpIC8gMiArIEdlb2xpYi5QSV9ESVY0XG4gICAgICAgICAgICAgICAgKSAvXG4gICAgICAgICAgICAgICAgTWF0aC50YW4oXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGF0aXR1ZGUob3JpZ2luTEwpLnRvUmFkKCkgLyAyICsgR2VvbGliLlBJX0RJVjRcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyByZWNhbGN1bGF0ZSBkaWZmTG9uIGlmIGl0IGlzIGdyZWF0ZXIgdGhhbiBwaVxuICAgICAgICAgICAgaWYoTWF0aC5hYnMoZGlmZkxvbikgPiBNYXRoLlBJKSB7XG4gICAgICAgICAgICAgICAgaWYoZGlmZkxvbiA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZGlmZkxvbiA9IChHZW9saWIuUElfWDIgLSBkaWZmTG9uKSAqIC0xO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZGlmZkxvbiA9IEdlb2xpYi5QSV9YMiArIGRpZmZMb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvL3JldHVybiB0aGUgYW5nbGUsIG5vcm1hbGl6ZWRcbiAgICAgICAgICAgIHJldHVybiAoTWF0aC5hdGFuMihkaWZmTG9uLCBkaWZmUGhpKS50b0RlZygpICsgMzYwKSAlIDM2MDtcblxuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogR2V0cyBncmVhdCBjaXJjbGUgYmVhcmluZyBvZiB0d28gcG9pbnRzLiBTZWUgZGVzY3JpcHRpb24gb2YgZ2V0Umh1bWJMaW5lQmVhcmluZyBmb3IgbW9yZSBpbmZvcm1hdGlvblxuICAgICAgICAqXG4gICAgICAgICogQHBhcmFtICAgICAgICBvYmplY3QgICAgICBvcmlnaW4gY29vcmRpbmF0ZSAoZS5nLiB7bGF0aXR1ZGU6IDUxLjUwMjMsIGxvbmdpdHVkZTogNy4zODE1fSlcbiAgICAgICAgKiBAcGFyYW0gICAgICAgIG9iamVjdCAgICAgIGRlc3RpbmF0aW9uIGNvb3JkaW5hdGVcbiAgICAgICAgKiBAcmV0dXJuICAgICAgIGludGVnZXIgICAgIGNhbGN1bGF0ZWQgYmVhcmluZ1xuICAgICAgICAqL1xuICAgICAgICBnZXRCZWFyaW5nOiBmdW5jdGlvbihvcmlnaW5MTCwgZGVzdExMKSB7XG5cbiAgICAgICAgICAgIGRlc3RMTFsnbGF0aXR1ZGUnXSA9IHRoaXMubGF0aXR1ZGUoZGVzdExMKTtcbiAgICAgICAgICAgIGRlc3RMTFsnbG9uZ2l0dWRlJ10gPSB0aGlzLmxvbmdpdHVkZShkZXN0TEwpO1xuICAgICAgICAgICAgb3JpZ2luTExbJ2xhdGl0dWRlJ10gPSB0aGlzLmxhdGl0dWRlKG9yaWdpbkxMKTtcbiAgICAgICAgICAgIG9yaWdpbkxMWydsb25naXR1ZGUnXSA9IHRoaXMubG9uZ2l0dWRlKG9yaWdpbkxMKTtcblxuICAgICAgICAgICAgdmFyIGJlYXJpbmcgPSAoXG4gICAgICAgICAgICAgICAgKFxuICAgICAgICAgICAgICAgICAgICBNYXRoLmF0YW4yKFxuICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5zaW4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdExMWydsb25naXR1ZGUnXS50b1JhZCgpIC1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmlnaW5MTFsnbG9uZ2l0dWRlJ10udG9SYWQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSAqXG4gICAgICAgICAgICAgICAgICAgICAgICBNYXRoLmNvcyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0TExbJ2xhdGl0dWRlJ10udG9SYWQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hdGguY29zKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yaWdpbkxMWydsYXRpdHVkZSddLnRvUmFkKClcbiAgICAgICAgICAgICAgICAgICAgICAgICkgKlxuICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5zaW4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzdExMWydsYXRpdHVkZSddLnRvUmFkKClcbiAgICAgICAgICAgICAgICAgICAgICAgICkgLVxuICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5zaW4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luTExbJ2xhdGl0dWRlJ10udG9SYWQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSAqXG4gICAgICAgICAgICAgICAgICAgICAgICBNYXRoLmNvcyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0TExbJ2xhdGl0dWRlJ10udG9SYWQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgKSAqXG4gICAgICAgICAgICAgICAgICAgICAgICBNYXRoLmNvcyhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXN0TExbJ2xvbmdpdHVkZSddLnRvUmFkKCkgLSBvcmlnaW5MTFsnbG9uZ2l0dWRlJ10udG9SYWQoKVxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKS50b0RlZygpICsgMzYwXG4gICAgICAgICAgICApICUgMzYwO1xuXG4gICAgICAgICAgICByZXR1cm4gYmVhcmluZztcblxuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogR2V0cyB0aGUgY29tcGFzcyBkaXJlY3Rpb24gZnJvbSBhbiBvcmlnaW4gY29vcmRpbmF0ZSB0byBhIGRlc3RpbmF0aW9uIGNvb3JkaW5hdGUuXG4gICAgICAgICpcbiAgICAgICAgKiBAcGFyYW0gICAgICAgIG9iamVjdCAgICAgIG9yaWdpbiBjb29yZGluYXRlIChlLmcuIHtsYXRpdHVkZTogNTEuNTAyMywgbG9uZ2l0dWRlOiA3LjM4MTV9KVxuICAgICAgICAqIEBwYXJhbSAgICAgICAgb2JqZWN0ICAgICAgZGVzdGluYXRpb24gY29vcmRpbmF0ZVxuICAgICAgICAqIEBwYXJhbSAgICAgICAgc3RyaW5nICAgICAgQmVhcmluZyBtb2RlLiBDYW4gYmUgZWl0aGVyIGNpcmNsZSBvciByaHVtYmxpbmVcbiAgICAgICAgKiBAcmV0dXJuICAgICAgIG9iamVjdCAgICAgIFJldHVybnMgYW4gb2JqZWN0IHdpdGggYSByb3VnaCAoTkVTVykgYW5kIGFuIGV4YWN0IGRpcmVjdGlvbiAoTk5FLCBORSwgRU5FLCBFLCBFU0UsIGV0YykuXG4gICAgICAgICovXG4gICAgICAgIGdldENvbXBhc3NEaXJlY3Rpb246IGZ1bmN0aW9uKG9yaWdpbkxMLCBkZXN0TEwsIGJlYXJpbmdNb2RlKSB7XG5cbiAgICAgICAgICAgIHZhciBkaXJlY3Rpb247XG4gICAgICAgICAgICB2YXIgYmVhcmluZztcblxuICAgICAgICAgICAgaWYoYmVhcmluZ01vZGUgPT0gJ2NpcmNsZScpIHtcbiAgICAgICAgICAgICAgICAvLyB1c2UgZ3JlYXQgY2lyY2xlIGJlYXJpbmdcbiAgICAgICAgICAgICAgICBiZWFyaW5nID0gdGhpcy5nZXRCZWFyaW5nKG9yaWdpbkxMLCBkZXN0TEwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBkZWZhdWx0IGlzIHJodW1iIGxpbmUgYmVhcmluZ1xuICAgICAgICAgICAgICAgIGJlYXJpbmcgPSB0aGlzLmdldFJodW1iTGluZUJlYXJpbmcob3JpZ2luTEwsIGRlc3RMTCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN3aXRjaChNYXRoLnJvdW5kKGJlYXJpbmcvMjIuNSkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IHtleGFjdDogXCJOTkVcIiwgcm91Z2g6IFwiTlwifTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSB7ZXhhY3Q6IFwiTkVcIiwgcm91Z2g6IFwiTlwifTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSB7ZXhhY3Q6IFwiRU5FXCIsIHJvdWdoOiBcIkVcIn07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0ge2V4YWN0OiBcIkVcIiwgcm91Z2g6IFwiRVwifTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSB7ZXhhY3Q6IFwiRVNFXCIsIHJvdWdoOiBcIkVcIn07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0ge2V4YWN0OiBcIlNFXCIsIHJvdWdoOiBcIkVcIn07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNzpcbiAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0ge2V4YWN0OiBcIlNTRVwiLCByb3VnaDogXCJTXCJ9O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IHtleGFjdDogXCJTXCIsIHJvdWdoOiBcIlNcIn07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgOTpcbiAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0ge2V4YWN0OiBcIlNTV1wiLCByb3VnaDogXCJTXCJ9O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSB7ZXhhY3Q6IFwiU1dcIiwgcm91Z2g6IFwiU1wifTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAxMTpcbiAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0ge2V4YWN0OiBcIldTV1wiLCByb3VnaDogXCJXXCJ9O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDEyOlxuICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSB7ZXhhY3Q6IFwiV1wiLCByb3VnaDogXCJXXCJ9O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDEzOlxuICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSB7ZXhhY3Q6IFwiV05XXCIsIHJvdWdoOiBcIldcIn07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTQ6XG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IHtleGFjdDogXCJOV1wiLCByb3VnaDogXCJXXCJ9O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDE1OlxuICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSB7ZXhhY3Q6IFwiTk5XXCIsIHJvdWdoOiBcIk5cIn07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IHtleGFjdDogXCJOXCIsIHJvdWdoOiBcIk5cIn07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRpcmVjdGlvblsnYmVhcmluZyddID0gYmVhcmluZztcbiAgICAgICAgICAgIHJldHVybiBkaXJlY3Rpb247XG5cbiAgICAgICAgfSxcblxuXG4gICAgICAgIC8qKlxuICAgICAgICAqIFNob3J0Y3V0IGZvciBnZXRDb21wYXNzRGlyZWN0aW9uXG4gICAgICAgICovXG4gICAgICAgIGdldERpcmVjdGlvbjogZnVuY3Rpb24ob3JpZ2luTEwsIGRlc3RMTCwgYmVhcmluZ01vZGUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmdldENvbXBhc3NEaXJlY3Rpb24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfSxcblxuXG4gICAgICAgIC8qKlxuICAgICAgICAqIFNvcnRzIGFuIGFycmF5IG9mIGNvb3JkcyBieSBkaXN0YW5jZSBmcm9tIGEgcmVmZXJlbmNlIGNvb3JkaW5hdGVcbiAgICAgICAgKlxuICAgICAgICAqIEBwYXJhbSAgICAgICAgb2JqZWN0ICAgICAgcmVmZXJlbmNlIGNvb3JkaW5hdGUgZS5nLiB7bGF0aXR1ZGU6IDUxLjUwMjMsIGxvbmdpdHVkZTogNy4zODE1fVxuICAgICAgICAqIEBwYXJhbSAgICAgICAgbWl4ZWQgICAgICAgYXJyYXkgb3Igb2JqZWN0IHdpdGggY29vcmRzIFt7bGF0aXR1ZGU6IDUxLjUxNDMsIGxvbmdpdHVkZTogNy40MTM4fSwge2xhdGl0dWRlOiAxMjMsIGxvbmdpdHVkZTogMTIzfSwgLi4uXVxuICAgICAgICAqIEByZXR1cm4gICAgICAgYXJyYXkgICAgICAgb3JkZXJlZCBhcnJheVxuICAgICAgICAqL1xuICAgICAgICBvcmRlckJ5RGlzdGFuY2U6IGZ1bmN0aW9uKGxhdGxuZywgY29vcmRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjb29yZHNBcnJheSA9IE9iamVjdC5rZXlzKGNvb3JkcykubWFwKGZ1bmN0aW9uKGlkeCkge1xuICAgICAgICAgICAgICAgIHZhciBkaXN0YW5jZSA9IHRoaXMuZ2V0RGlzdGFuY2UobGF0bG5nLCBjb29yZHNbaWR4XSk7XG4gICAgICAgICAgICAgICAgdmFyIGF1Z21lbnRlZENvb3JkID0gT2JqZWN0LmNyZWF0ZShjb29yZHNbaWR4XSk7XG4gICAgICAgICAgICAgICAgYXVnbWVudGVkQ29vcmQuZGlzdGFuY2UgPSBkaXN0YW5jZTtcbiAgICAgICAgICAgICAgICBhdWdtZW50ZWRDb29yZC5rZXkgPSBpZHg7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGF1Z21lbnRlZENvb3JkO1xuICAgICAgICAgICAgfSwgdGhpcyk7XG5cbiAgICAgICAgICAgIHJldHVybiBjb29yZHNBcnJheS5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYS5kaXN0YW5jZSAtIGIuZGlzdGFuY2U7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICB9LFxuXG4gICAgICAgIC8qKlxuICAgICAgICAqIENoZWNrIGlmIGEgcG9pbnQgbGllcyBpbiBsaW5lIGNyZWF0ZWQgYnkgdHdvIG90aGVyIHBvaW50c1xuICAgICAgICAqXG4gICAgICAgICogQHBhcmFtICAgIG9iamVjdCAgICBQb2ludCB0byBjaGVjazoge2xhdGl0dWRlOiAxMjMsIGxvbmdpdHVkZTogMTIzfVxuICAgICAgICAqIEBwYXJhbSAgICBvYmplY3QgICAgU3RhcnQgb2YgbGluZSB7bGF0aXR1ZGU6IDEyMywgbG9uZ2l0dWRlOiAxMjN9XG4gICAgICAgICogQHBhcmFtICAgIG9iamVjdCAgICBFbmQgb2YgbGluZSB7bGF0aXR1ZGU6IDEyMywgbG9uZ2l0dWRlOiAxMjN9XG4gICAgICAgICogQHJldHVybiAgIGJvb2xlYW5cbiAgICAgICAgKi9cbiAgICAgICAgaXNQb2ludEluTGluZTogZnVuY3Rpb24ocG9pbnQsIHN0YXJ0LCBlbmQpIHtcblxuICAgICAgICAgICAgcmV0dXJuICh0aGlzLmdldERpc3RhbmNlKHN0YXJ0LCBwb2ludCwgMSwgMykrdGhpcy5nZXREaXN0YW5jZShwb2ludCwgZW5kLCAxLCAzKSkudG9GaXhlZCgzKT09dGhpcy5nZXREaXN0YW5jZShzdGFydCwgZW5kLCAxLCAzKTtcbiAgICAgICAgfSxcblxuICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAqIENoZWNrIGlmIGEgcG9pbnQgbGllcyB3aXRoaW4gYSBnaXZlbiBkaXN0YW5jZSBmcm9tIGEgbGluZSBjcmVhdGVkIGJ5IHR3byBvdGhlciBwb2ludHNcbiAgICAgICAgKlxuICAgICAgICAqIEBwYXJhbSAgICBvYmplY3QgICAgUG9pbnQgdG8gY2hlY2s6IHtsYXRpdHVkZTogMTIzLCBsb25naXR1ZGU6IDEyM31cbiAgICAgICAgKiBAcGFyYW0gICAgb2JqZWN0ICAgIFN0YXJ0IG9mIGxpbmUge2xhdGl0dWRlOiAxMjMsIGxvbmdpdHVkZTogMTIzfVxuICAgICAgICAqIEBwYXJhbSAgICBvYmplY3QgICAgRW5kIG9mIGxpbmUge2xhdGl0dWRlOiAxMjMsIGxvbmdpdHVkZTogMTIzfVxuICAgICAgICAqIEBwYXJhcm0gICBmbG9hdCAgICAgbWF4aW11bSBkaXN0YW5jZSBmcm9tIGxpbmVcbiAgICAgICAgKiBAcmV0dXJuICAgYm9vbGVhblxuICAgICAgICAqL1xuICAgICAgICBpc1BvaW50TmVhckxpbmU6IGZ1bmN0aW9uKHBvaW50LCBzdGFydCwgZW5kLCBkaXN0YW5jZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0RGlzdGFuY2VGcm9tTGluZShwb2ludCwgc3RhcnQsIGVuZCkgPCBkaXN0YW5jZTtcbiAgICAgICAgfSxcblxuICAgICAgICAgICAgICAgICAgICAgLyoqXG4gICAgICAgICogcmV0dXJuIHRoZSBtaW5pbXVtIGRpc3RhbmNlIGZyb20gYSBwb2ludCB0byBhIGxpbmVcbiAgICAgICAgKlxuICAgICAgICAqIEBwYXJhbSAgICBvYmplY3QgICAgUG9pbnQgYXdheSBmcm9tIGxpbmVcbiAgICAgICAgKiBAcGFyYW0gICAgb2JqZWN0ICAgIFN0YXJ0IG9mIGxpbmUge2xhdGl0dWRlOiAxMjMsIGxvbmdpdHVkZTogMTIzfVxuICAgICAgICAqIEBwYXJhbSAgICBvYmplY3QgICAgRW5kIG9mIGxpbmUge2xhdGl0dWRlOiAxMjMsIGxvbmdpdHVkZTogMTIzfVxuICAgICAgICAqIEByZXR1cm4gICBmbG9hdCAgICAgZGlzdGFuY2UgZnJvbSBwb2ludCB0byBsaW5lXG4gICAgICAgICovXG4gICAgICAgIGdldERpc3RhbmNlRnJvbUxpbmU6IGZ1bmN0aW9uKHBvaW50LCBzdGFydCwgZW5kKSB7XG4gICAgICAgICAgICB2YXIgZDEgPSB0aGlzLmdldERpc3RhbmNlKHN0YXJ0LCBwb2ludCwgMSwgMyk7XG4gICAgICAgICAgICB2YXIgZDIgPSB0aGlzLmdldERpc3RhbmNlKHBvaW50LCBlbmQsIDEsIDMpO1xuICAgICAgICAgICAgdmFyIGQzID0gdGhpcy5nZXREaXN0YW5jZShzdGFydCwgZW5kLCAxLCAzKTtcbiAgICAgICAgICAgIHZhciBkaXN0YW5jZSA9IDA7XG5cbiAgICAgICAgICAgIC8vIGFscGhhIGlzIHRoZSBhbmdsZSBiZXR3ZWVuIHRoZSBsaW5lIGZyb20gc3RhcnQgdG8gcG9pbnQsIGFuZCBmcm9tIHN0YXJ0IHRvIGVuZCAvL1xuICAgICAgICAgICAgdmFyIGFscGhhID0gTWF0aC5hY29zKChkMSpkMSArIGQzKmQzIC0gZDIqZDIpLygyKmQxKmQzKSk7XG4gICAgICAgICAgICAvLyBiZXRhIGlzIHRoZSBhbmdsZSBiZXR3ZWVuIHRoZSBsaW5lIGZyb20gZW5kIHRvIHBvaW50IGFuZCBmcm9tIGVuZCB0byBzdGFydCAvL1xuICAgICAgICAgICAgdmFyIGJldGEgPSBNYXRoLmFjb3MoKGQyKmQyICsgZDMqZDMgLSBkMSpkMSkvKDIqZDIqZDMpKTtcblxuICAgICAgICAgICAgLy8gaWYgdGhlIGFuZ2xlIGlzIGdyZWF0ZXIgdGhhbiA5MCBkZWdyZWVzLCB0aGVuIHRoZSBtaW5pbXVtIGRpc3RhbmNlIGlzIHRoZVxuICAgICAgICAgICAgLy8gbGluZSBmcm9tIHRoZSBzdGFydCB0byB0aGUgcG9pbnQgLy9cbiAgICAgICAgICAgIGlmKGFscGhhPk1hdGguUEkvMikge1xuICAgICAgICAgICAgICAgIGRpc3RhbmNlID0gZDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBzYW1lIGZvciB0aGUgYmV0YSAvL1xuICAgICAgICAgICAgZWxzZSBpZihiZXRhID4gTWF0aC5QSS8yKSB7XG4gICAgICAgICAgICAgICAgZGlzdGFuY2UgPSBkMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIG90aGVyd2lzZSB0aGUgbWluaW11bSBkaXN0YW5jZSBpcyBhY2hpZXZlZCB0aHJvdWdoIGEgbGluZSBwZXJwZW5kdWxhciB0byB0aGUgc3RhcnQtZW5kIGxpbmUsXG4gICAgICAgICAgICAvLyB3aGljaCBnb2VzIGZyb20gdGhlIHN0YXJ0LWVuZCBsaW5lIHRvIHRoZSBwb2ludCAvL1xuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgZGlzdGFuY2UgPSBNYXRoLnNpbihhbHBoYSkgKiBkMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGRpc3RhbmNlO1xuICAgICAgICB9LFxuXG4gICAgICAgIC8qKlxuICAgICAgICAqIEZpbmRzIHRoZSBuZWFyZXN0IGNvb3JkaW5hdGUgdG8gYSByZWZlcmVuY2UgY29vcmRpbmF0ZVxuICAgICAgICAqXG4gICAgICAgICogQHBhcmFtICAgICAgICBvYmplY3QgICAgICByZWZlcmVuY2UgY29vcmRpbmF0ZSBlLmcuIHtsYXRpdHVkZTogNTEuNTAyMywgbG9uZ2l0dWRlOiA3LjM4MTV9XG4gICAgICAgICogQHBhcmFtICAgICAgICBtaXhlZCAgICAgICBhcnJheSBvciBvYmplY3Qgd2l0aCBjb29yZHMgW3tsYXRpdHVkZTogNTEuNTE0MywgbG9uZ2l0dWRlOiA3LjQxMzh9LCB7bGF0aXR1ZGU6IDEyMywgbG9uZ2l0dWRlOiAxMjN9LCAuLi5dXG4gICAgICAgICogQHJldHVybiAgICAgICBhcnJheSAgICAgICBvcmRlcmVkIGFycmF5XG4gICAgICAgICovXG4gICAgICAgIGZpbmROZWFyZXN0OiBmdW5jdGlvbihsYXRsbmcsIGNvb3Jkcywgb2Zmc2V0LCBsaW1pdCkge1xuXG4gICAgICAgICAgICBvZmZzZXQgPSBvZmZzZXQgfHwgMDtcbiAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgfHwgMTtcbiAgICAgICAgICAgIHZhciBvcmRlcmVkID0gdGhpcy5vcmRlckJ5RGlzdGFuY2UobGF0bG5nLCBjb29yZHMpO1xuXG4gICAgICAgICAgICBpZihsaW1pdCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvcmRlcmVkW29mZnNldF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBvcmRlcmVkLnNwbGljZShvZmZzZXQsIGxpbWl0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogQ2FsY3VsYXRlcyB0aGUgbGVuZ3RoIG9mIGEgZ2l2ZW4gcGF0aFxuICAgICAgICAqXG4gICAgICAgICogQHBhcmFtICAgICAgICBtaXhlZCAgICAgICBhcnJheSBvciBvYmplY3Qgd2l0aCBjb29yZHMgW3tsYXRpdHVkZTogNTEuNTE0MywgbG9uZ2l0dWRlOiA3LjQxMzh9LCB7bGF0aXR1ZGU6IDEyMywgbG9uZ2l0dWRlOiAxMjN9LCAuLi5dXG4gICAgICAgICogQHJldHVybiAgICAgICBpbnRlZ2VyICAgICBsZW5ndGggb2YgdGhlIHBhdGggKGluIG1ldGVycylcbiAgICAgICAgKi9cbiAgICAgICAgZ2V0UGF0aExlbmd0aDogZnVuY3Rpb24oY29vcmRzKSB7XG5cbiAgICAgICAgICAgIHZhciBkaXN0ID0gMDtcbiAgICAgICAgICAgIHZhciBsYXN0O1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGNvb3Jkcy5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgICAgICBpZihsYXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coY29vcmRzW2ldLCBsYXN0LCB0aGlzLmdldERpc3RhbmNlKGNvb3Jkc1tpXSwgbGFzdCkpO1xuICAgICAgICAgICAgICAgICAgICBkaXN0ICs9IHRoaXMuZ2V0RGlzdGFuY2UodGhpcy5jb29yZHMoY29vcmRzW2ldKSwgbGFzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxhc3QgPSB0aGlzLmNvb3Jkcyhjb29yZHNbaV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZGlzdDtcblxuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogQ2FsY3VsYXRlcyB0aGUgc3BlZWQgYmV0d2VlbiB0byBwb2ludHMgd2l0aGluIGEgZ2l2ZW4gdGltZSBzcGFuLlxuICAgICAgICAqXG4gICAgICAgICogQHBhcmFtICAgICAgICBvYmplY3QgICAgICBjb29yZHMgd2l0aCBqYXZhc2NyaXB0IHRpbWVzdGFtcCB7bGF0aXR1ZGU6IDUxLjUxNDMsIGxvbmdpdHVkZTogNy40MTM4LCB0aW1lOiAxMzYwMjMxMjAwODgwfVxuICAgICAgICAqIEBwYXJhbSAgICAgICAgb2JqZWN0ICAgICAgY29vcmRzIHdpdGggamF2YXNjcmlwdCB0aW1lc3RhbXAge2xhdGl0dWRlOiA1MS41NTAyLCBsb25naXR1ZGU6IDcuNDMyMywgdGltZTogMTM2MDI0NTYwMDQ2MH1cbiAgICAgICAgKiBAcGFyYW0gICAgICAgIG9iamVjdCAgICAgIG9wdGlvbnMgKGN1cnJlbnRseSBcInVuaXRcIiBpcyB0aGUgb25seSBvcHRpb24uIERlZmF1bHQ6IGttKGgpKTtcbiAgICAgICAgKiBAcmV0dXJuICAgICAgIGZsb2F0ICAgICAgIHNwZWVkIGluIHVuaXQgcGVyIGhvdXJcbiAgICAgICAgKi9cbiAgICAgICAgZ2V0U3BlZWQ6IGZ1bmN0aW9uKHN0YXJ0LCBlbmQsIG9wdGlvbnMpIHtcblxuICAgICAgICAgICAgdmFyIHVuaXQgPSBvcHRpb25zICYmIG9wdGlvbnMudW5pdCB8fCAna20nO1xuXG4gICAgICAgICAgICBpZih1bml0ID09ICdtcGgnKSB7XG4gICAgICAgICAgICAgICAgdW5pdCA9ICdtaSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYodW5pdCA9PSAna21oJykge1xuICAgICAgICAgICAgICAgIHVuaXQgPSAna20nO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZGlzdGFuY2UgPSBnZW9saWIuZ2V0RGlzdGFuY2Uoc3RhcnQsIGVuZCk7XG4gICAgICAgICAgICB2YXIgdGltZSA9ICgoZW5kLnRpbWUqMSkvMTAwMCkgLSAoKHN0YXJ0LnRpbWUqMSkvMTAwMCk7XG4gICAgICAgICAgICB2YXIgbVBlckhyID0gKGRpc3RhbmNlL3RpbWUpKjM2MDA7XG4gICAgICAgICAgICB2YXIgc3BlZWQgPSBNYXRoLnJvdW5kKG1QZXJIciAqIHRoaXMubWVhc3VyZXNbdW5pdF0gKiAxMDAwMCkvMTAwMDA7XG4gICAgICAgICAgICByZXR1cm4gc3BlZWQ7XG5cbiAgICAgICAgfSxcblxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb21wdXRlcyB0aGUgZGVzdGluYXRpb24gcG9pbnQgZ2l2ZW4gYW4gaW5pdGlhbCBwb2ludCwgYSBkaXN0YW5jZVxuICAgICAgICAgKiBhbmQgYSBiZWFyaW5nXG4gICAgICAgICAqXG4gICAgICAgICAqIHNlZSBodHRwOi8vd3d3Lm1vdmFibGUtdHlwZS5jby51ay9zY3JpcHRzL2xhdGxvbmcuaHRtbCBmb3IgdGhlIG9yaWdpbmFsIGNvZGVcbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtICAgICAgICBvYmplY3QgICAgIHN0YXJ0IGNvb3JkaW5hdGUgKGUuZy4ge2xhdGl0dWRlOiA1MS41MDIzLCBsb25naXR1ZGU6IDcuMzgxNX0pXG4gICAgICAgICAqIEBwYXJhbSAgICAgICAgZmxvYXQgICAgICBsb25naXR1ZGUgb2YgdGhlIGluaXRhbCBwb2ludCBpbiBkZWdyZWVcbiAgICAgICAgICogQHBhcmFtICAgICAgICBmbG9hdCAgICAgIGRpc3RhbmNlIHRvIGdvIGZyb20gdGhlIGluaXRhbCBwb2ludCBpbiBtZXRlclxuICAgICAgICAgKiBAcGFyYW0gICAgICAgIGZsb2F0ICAgICAgYmVhcmluZyBpbiBkZWdyZWUgb2YgdGhlIGRpcmVjdGlvbiB0byBnbywgZS5nLiAwID0gbm9ydGgsIDE4MCA9IHNvdXRoXG4gICAgICAgICAqIEBwYXJhbSAgICAgICAgZmxvYXQgICAgICBvcHRpb25hbCAoaW4gbWV0ZXIpLCBkZWZhdWx0cyB0byBtZWFuIHJhZGl1cyBvZiB0aGUgZWFydGhcbiAgICAgICAgICogQHJldHVybiAgICAgICBvYmplY3QgICAgIHtsYXRpdHVkZTogZGVzdExhdCAoaW4gZGVncmVlKSwgbG9uZ2l0dWRlOiBkZXN0TG5nIChpbiBkZWdyZWUpfVxuICAgICAgICAgKi9cbiAgICAgICAgY29tcHV0ZURlc3RpbmF0aW9uUG9pbnQ6IGZ1bmN0aW9uKHN0YXJ0LCBkaXN0YW5jZSwgYmVhcmluZywgcmFkaXVzKSB7XG5cbiAgICAgICAgICAgIHZhciBsYXQgPSB0aGlzLmxhdGl0dWRlKHN0YXJ0KTtcbiAgICAgICAgICAgIHZhciBsbmcgPSB0aGlzLmxvbmdpdHVkZShzdGFydCk7XG5cbiAgICAgICAgICAgIHJhZGl1cyA9ICh0eXBlb2YgcmFkaXVzID09PSAndW5kZWZpbmVkJykgPyB0aGlzLnJhZGl1cyA6IE51bWJlcihyYWRpdXMpO1xuXG4gICAgICAgICAgICB2YXIgzrQgPSBOdW1iZXIoZGlzdGFuY2UpIC8gcmFkaXVzOyAvLyBhbmd1bGFyIGRpc3RhbmNlIGluIHJhZGlhbnNcbiAgICAgICAgICAgIHZhciDOuCA9IE51bWJlcihiZWFyaW5nKS50b1JhZCgpO1xuXG4gICAgICAgICAgICB2YXIgz4YxID0gTnVtYmVyKGxhdCkudG9SYWQoKTtcbiAgICAgICAgICAgIHZhciDOuzEgPSBOdW1iZXIobG5nKS50b1JhZCgpO1xuXG4gICAgICAgICAgICB2YXIgz4YyID0gTWF0aC5hc2luKCBNYXRoLnNpbijPhjEpKk1hdGguY29zKM60KSArXG4gICAgICAgICAgICAgICAgTWF0aC5jb3Moz4YxKSpNYXRoLnNpbijOtCkqTWF0aC5jb3MozrgpICk7XG4gICAgICAgICAgICB2YXIgzrsyID0gzrsxICsgTWF0aC5hdGFuMihNYXRoLnNpbijOuCkqTWF0aC5zaW4ozrQpKk1hdGguY29zKM+GMSksXG4gICAgICAgICAgICAgICAgICAgIE1hdGguY29zKM60KS1NYXRoLnNpbijPhjEpKk1hdGguc2luKM+GMikpO1xuICAgICAgICAgICAgzrsyID0gKM67MiszKk1hdGguUEkpICUgKDIqTWF0aC5QSSkgLSBNYXRoLlBJOyAvLyBub3JtYWxpc2UgdG8gLTE4MC4uKzE4MMKwXG5cbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgbGF0aXR1ZGU6IM+GMi50b0RlZygpLFxuICAgICAgICAgICAgICAgIGxvbmdpdHVkZTogzrsyLnRvRGVnKClcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgfSxcblxuXG4gICAgICAgIC8qKlxuICAgICAgICAqIENvbnZlcnRzIGEgZGlzdGFuY2UgZnJvbSBtZXRlcnMgdG8ga20sIG1tLCBjbSwgbWksIGZ0LCBpbiBvciB5ZFxuICAgICAgICAqXG4gICAgICAgICogQHBhcmFtICAgICAgICBzdHJpbmcgICAgICBGb3JtYXQgdG8gYmUgY29udmVydGVkIGluXG4gICAgICAgICogQHBhcmFtICAgICAgICBmbG9hdCAgICAgICBEaXN0YW5jZSBpbiBtZXRlcnNcbiAgICAgICAgKiBAcGFyYW0gICAgICAgIGZsb2F0ICAgICAgIERlY2ltYWwgcGxhY2VzIGZvciByb3VuZGluZyAoZGVmYXVsdDogNClcbiAgICAgICAgKiBAcmV0dXJuICAgICAgIGZsb2F0ICAgICAgIENvbnZlcnRlZCBkaXN0YW5jZVxuICAgICAgICAqL1xuICAgICAgICBjb252ZXJ0VW5pdDogZnVuY3Rpb24odW5pdCwgZGlzdGFuY2UsIHJvdW5kKSB7XG5cbiAgICAgICAgICAgIGlmKGRpc3RhbmNlID09PSAwKSB7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcblxuICAgICAgICAgICAgfSBlbHNlIGlmKHR5cGVvZiBkaXN0YW5jZSA9PT0gJ3VuZGVmaW5lZCcpIHtcblxuICAgICAgICAgICAgICAgIGlmKHRoaXMuZGlzdGFuY2UgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBkaXN0YW5jZSB3YXMgZ2l2ZW4nKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYodGhpcy5kaXN0YW5jZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkaXN0YW5jZSA9IHRoaXMuZGlzdGFuY2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHVuaXQgPSB1bml0IHx8ICdtJztcbiAgICAgICAgICAgIHJvdW5kID0gKG51bGwgPT0gcm91bmQgPyA0IDogcm91bmQpO1xuXG4gICAgICAgICAgICBpZih0eXBlb2YgdGhpcy5tZWFzdXJlc1t1bml0XSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yb3VuZChkaXN0YW5jZSAqIHRoaXMubWVhc3VyZXNbdW5pdF0sIHJvdW5kKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIHVuaXQgZm9yIGNvbnZlcnNpb24uJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfSxcblxuXG4gICAgICAgIC8qKlxuICAgICAgICAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGluIGRlY2ltYWwgZm9ybWF0IG9yLCBpZiBuZWNjZXNzYXJ5LCBjb252ZXJ0cyB0byBkZWNpbWFsXG4gICAgICAgICpcbiAgICAgICAgKiBAcGFyYW0gICAgICAgIG1peGVkICAgICAgIFZhbHVlKHMpIHRvIGJlIGNoZWNrZWQvY29udmVydGVkIChhcnJheSBvZiBsYXRsbmcgb2JqZWN0cywgbGF0bG5nIG9iamVjdCwgc2V4YWdlc2ltYWwgc3RyaW5nLCBmbG9hdClcbiAgICAgICAgKiBAcmV0dXJuICAgICAgIGZsb2F0ICAgICAgIElucHV0IGRhdGEgaW4gZGVjaW1hbCBmb3JtYXRcbiAgICAgICAgKi9cbiAgICAgICAgdXNlRGVjaW1hbDogZnVuY3Rpb24odmFsdWUpIHtcblxuICAgICAgICAgICAgaWYoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PT0gJ1tvYmplY3QgQXJyYXldJykge1xuXG4gICAgICAgICAgICAgICAgdmFyIGdlb2xpYiA9IHRoaXM7XG5cbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLm1hcChmdW5jdGlvbih2YWwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvL2lmKCFpc05hTihwYXJzZUZsb2F0KHZhbCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGdlb2xpYi5pc0RlY2ltYWwodmFsKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZ2VvbGliLnVzZURlY2ltYWwodmFsKTtcblxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYodHlwZW9mIHZhbCA9PSAnb2JqZWN0Jykge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZihnZW9saWIudmFsaWRhdGUodmFsKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdlb2xpYi5jb29yZHModmFsKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcih2YXIgcHJvcCBpbiB2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsW3Byb3BdID0gZ2VvbGliLnVzZURlY2ltYWwodmFsW3Byb3BdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmKGdlb2xpYi5pc1NleGFnZXNpbWFsKHZhbCkpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdlb2xpYi5zZXhhZ2VzaW1hbDJkZWNpbWFsKHZhbCk7XG5cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbDtcblxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdGhpcy52YWxpZGF0ZSh2YWx1ZSkpIHtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvb3Jkcyh2YWx1ZSk7XG5cbiAgICAgICAgICAgIH0gZWxzZSBpZih0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG5cbiAgICAgICAgICAgICAgICBmb3IodmFyIHByb3AgaW4gdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVbcHJvcF0gPSB0aGlzLnVzZURlY2ltYWwodmFsdWVbcHJvcF0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcblxuICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgIGlmICh0aGlzLmlzRGVjaW1hbCh2YWx1ZSkpIHtcblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHZhbHVlKTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmKHRoaXMuaXNTZXhhZ2VzaW1hbCh2YWx1ZSkgPT09IHRydWUpIHtcblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHRoaXMuc2V4YWdlc2ltYWwyZGVjaW1hbCh2YWx1ZSkpO1xuXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBmb3JtYXQuJyk7XG5cbiAgICAgICAgfSxcblxuICAgICAgICAvKipcbiAgICAgICAgKiBDb252ZXJ0cyBhIGRlY2ltYWwgY29vcmRpbmF0ZSB2YWx1ZSB0byBzZXhhZ2VzaW1hbCBmb3JtYXRcbiAgICAgICAgKlxuICAgICAgICAqIEBwYXJhbSAgICAgICAgZmxvYXQgICAgICAgZGVjaW1hbFxuICAgICAgICAqIEByZXR1cm4gICAgICAgc3RyaW5nICAgICAgU2V4YWdlc2ltYWwgdmFsdWUgKFhYwrAgWVknIFpaXCIpXG4gICAgICAgICovXG4gICAgICAgIGRlY2ltYWwyc2V4YWdlc2ltYWw6IGZ1bmN0aW9uKGRlYykge1xuXG4gICAgICAgICAgICBpZiAoZGVjIGluIHRoaXMuc2V4YWdlc2ltYWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zZXhhZ2VzaW1hbFtkZWNdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgdG1wID0gZGVjLnRvU3RyaW5nKCkuc3BsaXQoJy4nKTtcblxuICAgICAgICAgICAgdmFyIGRlZyA9IE1hdGguYWJzKHRtcFswXSk7XG4gICAgICAgICAgICB2YXIgbWluID0gKCcwLicgKyAodG1wWzFdIHx8IDApKSo2MDtcbiAgICAgICAgICAgIHZhciBzZWMgPSBtaW4udG9TdHJpbmcoKS5zcGxpdCgnLicpO1xuXG4gICAgICAgICAgICBtaW4gPSBNYXRoLmZsb29yKG1pbik7XG4gICAgICAgICAgICBzZWMgPSAoKCcwLicgKyAoc2VjWzFdIHx8IDApKSAqIDYwKS50b0ZpeGVkKDIpO1xuXG4gICAgICAgICAgICB0aGlzLnNleGFnZXNpbWFsW2RlY10gPSAoZGVnICsgJ8KwICcgKyBtaW4gKyBcIicgXCIgKyBzZWMgKyAnXCInKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2V4YWdlc2ltYWxbZGVjXTtcblxuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogQ29udmVydHMgYSBzZXhhZ2VzaW1hbCBjb29yZGluYXRlIHRvIGRlY2ltYWwgZm9ybWF0XG4gICAgICAgICpcbiAgICAgICAgKiBAcGFyYW0gICAgICAgIGZsb2F0ICAgICAgIFNleGFnZXNpbWFsIGNvb3JkaW5hdGVcbiAgICAgICAgKiBAcmV0dXJuICAgICAgIHN0cmluZyAgICAgIERlY2ltYWwgdmFsdWUgKFhYLlhYWFhYWFhYKVxuICAgICAgICAqL1xuICAgICAgICBzZXhhZ2VzaW1hbDJkZWNpbWFsOiBmdW5jdGlvbihzZXhhZ2VzaW1hbCkge1xuXG4gICAgICAgICAgICBpZiAoc2V4YWdlc2ltYWwgaW4gdGhpcy5kZWNpbWFsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjaW1hbFtzZXhhZ2VzaW1hbF07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciByZWdFeCA9IG5ldyBSZWdFeHAodGhpcy5zZXhhZ2VzaW1hbFBhdHRlcm4pO1xuICAgICAgICAgICAgdmFyIGRhdGEgPSByZWdFeC5leGVjKHNleGFnZXNpbWFsKTtcbiAgICAgICAgICAgIHZhciBtaW4gPSAwLCBzZWMgPSAwO1xuXG4gICAgICAgICAgICBpZihkYXRhKSB7XG4gICAgICAgICAgICAgICAgbWluID0gcGFyc2VGbG9hdChkYXRhWzJdLzYwKTtcbiAgICAgICAgICAgICAgICBzZWMgPSBwYXJzZUZsb2F0KGRhdGFbNF0vMzYwMCkgfHwgMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGRlYyA9ICgocGFyc2VGbG9hdChkYXRhWzFdKSArIG1pbiArIHNlYykpLnRvRml4ZWQoOCk7XG4gICAgICAgICAgICAvL3ZhciAgIGRlYyA9ICgocGFyc2VGbG9hdChkYXRhWzFdKSArIG1pbiArIHNlYykpO1xuXG4gICAgICAgICAgICAgICAgLy8gU291dGggYW5kIFdlc3QgYXJlIG5lZ2F0aXZlIGRlY2ltYWxzXG4gICAgICAgICAgICAgICAgZGVjID0gKGRhdGFbN10gPT0gJ1MnIHx8IGRhdGFbN10gPT0gJ1cnKSA/IHBhcnNlRmxvYXQoLWRlYykgOiBwYXJzZUZsb2F0KGRlYyk7XG4gICAgICAgICAgICAgICAgLy9kZWMgPSAoZGF0YVs3XSA9PSAnUycgfHwgZGF0YVs3XSA9PSAnVycpID8gLWRlYyA6IGRlYztcblxuICAgICAgICAgICAgdGhpcy5kZWNpbWFsW3NleGFnZXNpbWFsXSA9IGRlYztcblxuICAgICAgICAgICAgcmV0dXJuIGRlYztcblxuICAgICAgICB9LFxuXG5cbiAgICAgICAgLyoqXG4gICAgICAgICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgaW4gZGVjaW1hbCBmb3JtYXRcbiAgICAgICAgKlxuICAgICAgICAqIEBwYXJhbSAgICAgICAgc3RyaW5nICAgICAgVmFsdWUgdG8gYmUgY2hlY2tlZFxuICAgICAgICAqIEByZXR1cm4gICAgICAgYm9vbCAgICAgICAgVHJ1ZSBpZiBpbiBzZXhhZ2VzaW1hbCBmb3JtYXRcbiAgICAgICAgKi9cbiAgICAgICAgaXNEZWNpbWFsOiBmdW5jdGlvbih2YWx1ZSkge1xuXG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCkucmVwbGFjZSgvXFxzKi8sICcnKTtcblxuICAgICAgICAgICAgLy8gbG9va3Mgc2lsbHkgYnV0IHdvcmtzIGFzIGV4cGVjdGVkXG4gICAgICAgICAgICAvLyBjaGVja3MgaWYgdmFsdWUgaXMgaW4gZGVjaW1hbCBmb3JtYXRcbiAgICAgICAgICAgIHJldHVybiAoIWlzTmFOKHBhcnNlRmxvYXQodmFsdWUpKSAmJiBwYXJzZUZsb2F0KHZhbHVlKSA9PSB2YWx1ZSk7XG5cbiAgICAgICAgfSxcblxuXG4gICAgICAgIC8qKlxuICAgICAgICAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGluIHNleGFnZXNpbWFsIGZvcm1hdFxuICAgICAgICAqXG4gICAgICAgICogQHBhcmFtICAgICAgICBzdHJpbmcgICAgICBWYWx1ZSB0byBiZSBjaGVja2VkXG4gICAgICAgICogQHJldHVybiAgICAgICBib29sICAgICAgICBUcnVlIGlmIGluIHNleGFnZXNpbWFsIGZvcm1hdFxuICAgICAgICAqL1xuICAgICAgICBpc1NleGFnZXNpbWFsOiBmdW5jdGlvbih2YWx1ZSkge1xuXG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCkucmVwbGFjZSgvXFxzKi8sICcnKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2V4YWdlc2ltYWxQYXR0ZXJuLnRlc3QodmFsdWUpO1xuXG4gICAgICAgIH0sXG5cbiAgICAgICAgcm91bmQ6IGZ1bmN0aW9uKHZhbHVlLCBuKSB7XG4gICAgICAgICAgICB2YXIgZGVjUGxhY2UgPSBNYXRoLnBvdygxMCwgbik7XG4gICAgICAgICAgICByZXR1cm4gTWF0aC5yb3VuZCh2YWx1ZSAqIGRlY1BsYWNlKS9kZWNQbGFjZTtcbiAgICAgICAgfVxuXG4gICAgfSk7XG5cbiAgICAvLyBOb2RlIG1vZHVsZVxuICAgIGlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgbW9kdWxlLmV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XG5cbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBnZW9saWI7XG5cbiAgICAgICAgLy8gcmVhY3QgbmF0aXZlXG4gICAgICAgIGlmICh0eXBlb2YgZ2xvYmFsID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgIGdsb2JhbC5nZW9saWIgPSBnZW9saWI7XG4gICAgICAgIH1cblxuICAgIC8vIEFNRCBtb2R1bGVcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG5cbiAgICAgICAgZGVmaW5lKFwiZ2VvbGliXCIsIFtdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gZ2VvbGliO1xuICAgICAgICB9KTtcblxuICAgIC8vIHdlJ3JlIGluIGEgYnJvd3NlclxuICAgIH0gZWxzZSB7XG5cbiAgICAgICAgZ2xvYmFsLmdlb2xpYiA9IGdlb2xpYjtcblxuICAgIH1cblxufSh0aGlzKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9nZW9saWIvZGlzdC9nZW9saWIuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2dlb2xpYi9kaXN0L2dlb2xpYi5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/geolib/dist/geolib.js\n");
/***/ }),
/***/ "./node_modules/leaflet-providers/leaflet-providers.js":
/***/ (function(module, exports) {
eval("(function () {\n\t'use strict';\n\n\tL.TileLayer.Provider = L.TileLayer.extend({\n\t\tinitialize: function (arg, options) {\n\t\t\tvar providers = L.TileLayer.Provider.providers;\n\n\t\t\tvar parts = arg.split('.');\n\n\t\t\tvar providerName = parts[0];\n\t\t\tvar variantName = parts[1];\n\n\t\t\tif (!providers[providerName]) {\n\t\t\t\tthrow 'No such provider (' + providerName + ')';\n\t\t\t}\n\n\t\t\tvar provider = {\n\t\t\t\turl: providers[providerName].url,\n\t\t\t\toptions: providers[providerName].options\n\t\t\t};\n\n\t\t\t// overwrite values in provider from variant.\n\t\t\tif (variantName && 'variants' in providers[providerName]) {\n\t\t\t\tif (!(variantName in providers[providerName].variants)) {\n\t\t\t\t\tthrow 'No such variant of ' + providerName + ' (' + variantName + ')';\n\t\t\t\t}\n\t\t\t\tvar variant = providers[providerName].variants[variantName];\n\t\t\t\tvar variantOptions;\n\t\t\t\tif (typeof variant === 'string') {\n\t\t\t\t\tvariantOptions = {\n\t\t\t\t\t\tvariant: variant\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tvariantOptions = variant.options;\n\t\t\t\t}\n\t\t\t\tprovider = {\n\t\t\t\t\turl: variant.url || provider.url,\n\t\t\t\t\toptions: L.Util.extend({}, provider.options, variantOptions)\n\t\t\t\t};\n\t\t\t} else if (typeof provider.url === 'function') {\n\t\t\t\tprovider.url = provider.url(parts.splice(1, parts.length - 1).join('.'));\n\t\t\t}\n\n\t\t\tvar forceHTTP = window.location.protocol === 'file:' || provider.options.forceHTTP;\n\t\t\tif (provider.url.indexOf('//') === 0 && forceHTTP) {\n\t\t\t\tprovider.url = 'http:' + provider.url;\n\t\t\t}\n\n\t\t\t// replace attribution placeholders with their values from toplevel provider attribution,\n\t\t\t// recursively\n\t\t\tvar attributionReplacer = function (attr) {\n\t\t\t\tif (attr.indexOf('{attribution.') === -1) {\n\t\t\t\t\treturn attr;\n\t\t\t\t}\n\t\t\t\treturn attr.replace(/\\{attribution.(\\w*)\\}/,\n\t\t\t\t\tfunction (match, attributionName) {\n\t\t\t\t\t\treturn attributionReplacer(providers[attributionName].options.attribution);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t};\n\t\t\tprovider.options.attribution = attributionReplacer(provider.options.attribution);\n\n\t\t\t// Compute final options combining provider options with any user overrides\n\t\t\tvar layerOpts = L.Util.extend({}, provider.options, options);\n\t\t\tL.TileLayer.prototype.initialize.call(this, provider.url, layerOpts);\n\t\t}\n\t});\n\n\t/**\n\t * Definition of providers.\n\t * see http://leafletjs.com/reference.html#tilelayer for options in the options map.\n\t */\n\n\tL.TileLayer.Provider.providers = {\n\t\tOpenStreetMap: {\n\t\t\turl: '//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tmaxZoom: 19,\n\t\t\t\tattribution:\n\t\t\t\t\t'&copy; <a href=\"http://www.openstreetmap.org/copyright\">OpenStreetMap</a>'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tMapnik: {},\n\t\t\t\tBlackAndWhite: {\n\t\t\t\t\turl: 'http://{s}.tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png',\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tmaxZoom: 18\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tDE: {\n\t\t\t\t\turl: 'http://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png',\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tmaxZoom: 18\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tFrance: {\n\t\t\t\t\turl: 'http://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png',\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tattribution: '&copy; Openstreetmap France | {attribution.OpenStreetMap}'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tHOT: {\n\t\t\t\t\turl: 'http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png',\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tattribution: '{attribution.OpenStreetMap}, Tiles courtesy of <a href=\"http://hot.openstreetmap.org/\" target=\"_blank\">Humanitarian OpenStreetMap Team</a>'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tOpenSeaMap: {\n\t\t\turl: 'http://tiles.openseamap.org/seamark/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tattribution: 'Map data: &copy; <a href=\"http://www.openseamap.org\">OpenSeaMap</a> contributors'\n\t\t\t}\n\t\t},\n\t\tOpenTopoMap: {\n\t\t\turl: '//{s}.tile.opentopomap.org/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tmaxZoom: 16,\n\t\t\t\tattribution: 'Map data: {attribution.OpenStreetMap}, <a href=\"http://viewfinderpanoramas.org\">SRTM</a> | Map style: &copy; <a href=\"https://opentopomap.org\">OpenTopoMap</a> (<a href=\"https://creativecommons.org/licenses/by-sa/3.0/\">CC-BY-SA</a>)'\n\t\t\t}\n\t\t},\n\t\tThunderforest: {\n\t\t\turl: '//{s}.tile.thunderforest.com/{variant}/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tattribution:\n\t\t\t\t\t'&copy; <a href=\"http://www.opencyclemap.org\">OpenCycleMap</a>, {attribution.OpenStreetMap}',\n\t\t\t\tvariant: 'cycle'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tOpenCycleMap: 'cycle',\n\t\t\t\tTransport: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'transport',\n\t\t\t\t\t\tmaxZoom: 19\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tTransportDark: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'transport-dark',\n\t\t\t\t\t\tmaxZoom: 19\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tLandscape: 'landscape',\n\t\t\t\tOutdoors: 'outdoors'\n\t\t\t}\n\t\t},\n\t\tOpenMapSurfer: {\n\t\t\turl: 'http://openmapsurfer.uni-hd.de/tiles/{variant}/x={x}&y={y}&z={z}',\n\t\t\toptions: {\n\t\t\t\tmaxZoom: 20,\n\t\t\t\tvariant: 'roads',\n\t\t\t\tattribution: 'Imagery from <a href=\"http://giscience.uni-hd.de/\">GIScience Research Group @ University of Heidelberg</a> &mdash; Map data {attribution.OpenStreetMap}'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tRoads: 'roads',\n\t\t\t\tAdminBounds: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'adminb',\n\t\t\t\t\t\tmaxZoom: 19\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tGrayscale: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'roadsg',\n\t\t\t\t\t\tmaxZoom: 19\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tHydda: {\n\t\t\turl: 'http://{s}.tile.openstreetmap.se/hydda/{variant}/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tvariant: 'full',\n\t\t\t\tattribution: 'Tiles courtesy of <a href=\"http://openstreetmap.se/\" target=\"_blank\">OpenStreetMap Sweden</a> &mdash; Map data {attribution.OpenStreetMap}'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tFull: 'full',\n\t\t\t\tBase: 'base',\n\t\t\t\tRoadsAndLabels: 'roads_and_labels'\n\t\t\t}\n\t\t},\n\t\tMapQuestOpen: {\n\t\t\t/* Mapquest does support https, but with a different subdomain:\n\t\t\t * https://otile{s}-s.mqcdn.com/tiles/1.0.0/{type}/{z}/{x}/{y}.{ext}\n\t\t\t * which makes implementing protocol relativity impossible.\n\t\t\t */\n\t\t\turl: 'http://otile{s}.mqcdn.com/tiles/1.0.0/{type}/{z}/{x}/{y}.{ext}',\n\t\t\toptions: {\n\t\t\t\ttype: 'map',\n\t\t\t\text: 'jpg',\n\t\t\t\tattribution:\n\t\t\t\t\t'Tiles Courtesy of <a href=\"http://www.mapquest.com/\">MapQuest</a> &mdash; ' +\n\t\t\t\t\t'Map data {attribution.OpenStreetMap}',\n\t\t\t\tsubdomains: '1234'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tOSM: {},\n\t\t\t\tAerial: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\ttype: 'sat',\n\t\t\t\t\t\tattribution:\n\t\t\t\t\t\t\t'Tiles Courtesy of <a href=\"http://www.mapquest.com/\">MapQuest</a> &mdash; ' +\n\t\t\t\t\t\t\t'Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tHybridOverlay: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\ttype: 'hyb',\n\t\t\t\t\t\text: 'png',\n\t\t\t\t\t\topacity: 0.9\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tMapBox: {\n\t\t\turl: function (id) {\n\t\t\t\treturn '//{s}.tiles.mapbox.com/v3/' + id + '/{z}/{x}/{y}.png';\n\t\t\t},\n\t\t\toptions: {\n\t\t\t\tattribution:\n\t\t\t\t\t'Imagery from <a href=\"http://mapbox.com/about/maps/\">MapBox</a> &mdash; ' +\n\t\t\t\t\t'Map data {attribution.OpenStreetMap}',\n\t\t\t\tsubdomains: 'abcd'\n\t\t\t}\n\t\t},\n\t\tStamen: {\n\t\t\turl: '//stamen-tiles-{s}.a.ssl.fastly.net/{variant}/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tattribution:\n\t\t\t\t\t'Map tiles by <a href=\"http://stamen.com\">Stamen Design</a>, ' +\n\t\t\t\t\t'<a href=\"http://creativecommons.org/licenses/by/3.0\">CC BY 3.0</a> &mdash; ' +\n\t\t\t\t\t'Map data {attribution.OpenStreetMap}',\n\t\t\t\tsubdomains: 'abcd',\n\t\t\t\tminZoom: 0,\n\t\t\t\tmaxZoom: 20,\n\t\t\t\tvariant: 'toner',\n\t\t\t\text: 'png'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tToner: 'toner',\n\t\t\t\tTonerBackground: 'toner-background',\n\t\t\t\tTonerHybrid: 'toner-hybrid',\n\t\t\t\tTonerLines: 'toner-lines',\n\t\t\t\tTonerLabels: 'toner-labels',\n\t\t\t\tTonerLite: 'toner-lite',\n\t\t\t\tWatercolor: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'watercolor',\n\t\t\t\t\t\tminZoom: 1,\n\t\t\t\t\t\tmaxZoom: 16\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tTerrain: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'terrain',\n\t\t\t\t\t\tminZoom: 4,\n\t\t\t\t\t\tmaxZoom: 18,\n\t\t\t\t\t\tbounds: [[22, -132], [70, -56]]\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tTerrainBackground: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'terrain-background',\n\t\t\t\t\t\tminZoom: 4,\n\t\t\t\t\t\tmaxZoom: 18,\n\t\t\t\t\t\tbounds: [[22, -132], [70, -56]]\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tTopOSMRelief: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'toposm-color-relief',\n\t\t\t\t\t\text: 'jpg',\n\t\t\t\t\t\tbounds: [[22, -132], [51, -56]]\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tTopOSMFeatures: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'toposm-features',\n\t\t\t\t\t\tbounds: [[22, -132], [51, -56]],\n\t\t\t\t\t\topacity: 0.9\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tEsri: {\n\t\t\turl: '//server.arcgisonline.com/ArcGIS/rest/services/{variant}/MapServer/tile/{z}/{y}/{x}',\n\t\t\toptions: {\n\t\t\t\tvariant: 'World_Street_Map',\n\t\t\t\tattribution: 'Tiles &copy; Esri'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tWorldStreetMap: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tattribution:\n\t\t\t\t\t\t\t'{attribution.Esri} &mdash; ' +\n\t\t\t\t\t\t\t'Source: Esri, DeLorme, NAVTEQ, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand), TomTom, 2012'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tDeLorme: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'Specialty/DeLorme_World_Base_Map',\n\t\t\t\t\t\tminZoom: 1,\n\t\t\t\t\t\tmaxZoom: 11,\n\t\t\t\t\t\tattribution: '{attribution.Esri} &mdash; Copyright: &copy;2012 DeLorme'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tWorldTopoMap: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'World_Topo_Map',\n\t\t\t\t\t\tattribution:\n\t\t\t\t\t\t\t'{attribution.Esri} &mdash; ' +\n\t\t\t\t\t\t\t'Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tWorldImagery: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'World_Imagery',\n\t\t\t\t\t\tattribution:\n\t\t\t\t\t\t\t'{attribution.Esri} &mdash; ' +\n\t\t\t\t\t\t\t'Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tWorldTerrain: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'World_Terrain_Base',\n\t\t\t\t\t\tmaxZoom: 13,\n\t\t\t\t\t\tattribution:\n\t\t\t\t\t\t\t'{attribution.Esri} &mdash; ' +\n\t\t\t\t\t\t\t'Source: USGS, Esri, TANA, DeLorme, and NPS'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tWorldShadedRelief: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'World_Shaded_Relief',\n\t\t\t\t\t\tmaxZoom: 13,\n\t\t\t\t\t\tattribution: '{attribution.Esri} &mdash; Source: Esri'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tWorldPhysical: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'World_Physical_Map',\n\t\t\t\t\t\tmaxZoom: 8,\n\t\t\t\t\t\tattribution: '{attribution.Esri} &mdash; Source: US National Park Service'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tOceanBasemap: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'Ocean_Basemap',\n\t\t\t\t\t\tmaxZoom: 13,\n\t\t\t\t\t\tattribution: '{attribution.Esri} &mdash; Sources: GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ, and Esri'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tNatGeoWorldMap: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'NatGeo_World_Map',\n\t\t\t\t\t\tmaxZoom: 16,\n\t\t\t\t\t\tattribution: '{attribution.Esri} &mdash; National Geographic, Esri, DeLorme, NAVTEQ, UNEP-WCMC, USGS, NASA, ESA, METI, NRCAN, GEBCO, NOAA, iPC'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tWorldGrayCanvas: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'Canvas/World_Light_Gray_Base',\n\t\t\t\t\t\tmaxZoom: 16,\n\t\t\t\t\t\tattribution: '{attribution.Esri} &mdash; Esri, DeLorme, NAVTEQ'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tOpenWeatherMap: {\n\t\t\turl: 'http://{s}.tile.openweathermap.org/map/{variant}/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tmaxZoom: 19,\n\t\t\t\tattribution: 'Map data &copy; <a href=\"http://openweathermap.org\">OpenWeatherMap</a>',\n\t\t\t\topacity: 0.5\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tClouds: 'clouds',\n\t\t\t\tCloudsClassic: 'clouds_cls',\n\t\t\t\tPrecipitation: 'precipitation',\n\t\t\t\tPrecipitationClassic: 'precipitation_cls',\n\t\t\t\tRain: 'rain',\n\t\t\t\tRainClassic: 'rain_cls',\n\t\t\t\tPressure: 'pressure',\n\t\t\t\tPressureContour: 'pressure_cntr',\n\t\t\t\tWind: 'wind',\n\t\t\t\tTemperature: 'temp',\n\t\t\t\tSnow: 'snow'\n\t\t\t}\n\t\t},\n\t\tHERE: {\n\t\t\t/*\n\t\t\t * HERE maps, formerly Nokia maps.\n\t\t\t * These basemaps are free, but you need an API key. Please sign up at\n\t\t\t * http://developer.here.com/getting-started\n\t\t\t *\n\t\t\t * Note that the base urls contain '.cit' whichs is HERE's\n\t\t\t * 'Customer Integration Testing' environment. Please remove for production\n\t\t\t * envirionments.\n\t\t\t */\n\t\t\turl:\n\t\t\t\t'//{s}.{base}.maps.cit.api.here.com/maptile/2.1/' +\n\t\t\t\t'maptile/{mapID}/{variant}/{z}/{x}/{y}/256/png8?' +\n\t\t\t\t'app_id={app_id}&app_code={app_code}',\n\t\t\toptions: {\n\t\t\t\tattribution:\n\t\t\t\t\t'Map &copy; 1987-2014 <a href=\"http://developer.here.com\">HERE</a>',\n\t\t\t\tsubdomains: '1234',\n\t\t\t\tmapID: 'newest',\n\t\t\t\t'app_id': '<insert your app_id here>',\n\t\t\t\t'app_code': '<insert your app_code here>',\n\t\t\t\tbase: 'base',\n\t\t\t\tvariant: 'normal.day',\n\t\t\t\tmaxZoom: 20\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tnormalDay: 'normal.day',\n\t\t\t\tnormalDayCustom: 'normal.day.custom',\n\t\t\t\tnormalDayGrey: 'normal.day.grey',\n\t\t\t\tnormalDayMobile: 'normal.day.mobile',\n\t\t\t\tnormalDayGreyMobile: 'normal.day.grey.mobile',\n\t\t\t\tnormalDayTransit: 'normal.day.transit',\n\t\t\t\tnormalDayTransitMobile: 'normal.day.transit.mobile',\n\t\t\t\tnormalNight: 'normal.night',\n\t\t\t\tnormalNightMobile: 'normal.night.mobile',\n\t\t\t\tnormalNightGrey: 'normal.night.grey',\n\t\t\t\tnormalNightGreyMobile: 'normal.night.grey.mobile',\n\n\t\t\t\tcarnavDayGrey: 'carnav.day.grey',\n\t\t\t\thybridDay: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tbase: 'aerial',\n\t\t\t\t\t\tvariant: 'hybrid.day'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\thybridDayMobile: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tbase: 'aerial',\n\t\t\t\t\t\tvariant: 'hybrid.day.mobile'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tpedestrianDay: 'pedestrian.day',\n\t\t\t\tpedestrianNight: 'pedestrian.night',\n\t\t\t\tsatelliteDay: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tbase: 'aerial',\n\t\t\t\t\t\tvariant: 'satellite.day'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tterrainDay: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tbase: 'aerial',\n\t\t\t\t\t\tvariant: 'terrain.day'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tterrainDayMobile: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tbase: 'aerial',\n\t\t\t\t\t\tvariant: 'terrain.day.mobile'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tAcetate: {\n\t\t\turl: 'http://a{s}.acetate.geoiq.com/tiles/{variant}/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tattribution:\n\t\t\t\t\t'&copy;2012 Esri & Stamen, Data from OSM and Natural Earth',\n\t\t\t\tsubdomains: '0123',\n\t\t\t\tminZoom: 2,\n\t\t\t\tmaxZoom: 18,\n\t\t\t\tvariant: 'acetate-base'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tbasemap: 'acetate-base',\n\t\t\t\tterrain: 'terrain',\n\t\t\t\tall: 'acetate-hillshading',\n\t\t\t\tforeground: 'acetate-fg',\n\t\t\t\troads: 'acetate-roads',\n\t\t\t\tlabels: 'acetate-labels',\n\t\t\t\thillshading: 'hillshading'\n\t\t\t}\n\t\t},\n\t\tFreeMapSK: {\n\t\t\turl: 'http://{s}.freemap.sk/T/{z}/{x}/{y}.jpeg',\n\t\t\toptions: {\n\t\t\t\tminZoom: 8,\n\t\t\t\tmaxZoom: 16,\n\t\t\t\tsubdomains: ['t1', 't2', 't3', 't4'],\n\t\t\t\tattribution:\n\t\t\t\t\t'{attribution.OpenStreetMap}, vizualization CC-By-SA 2.0 <a href=\"http://freemap.sk\">Freemap.sk</a>'\n\t\t\t}\n\t\t},\n\t\tMtbMap: {\n\t\t\turl: 'http://tile.mtbmap.cz/mtbmap_tiles/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tattribution:\n\t\t\t\t\t'{attribution.OpenStreetMap} &amp; USGS'\n\t\t\t}\n\t\t},\n\t\tCartoDB: {\n\t\t\turl: 'http://{s}.basemaps.cartocdn.com/{variant}/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tattribution: '{attribution.OpenStreetMap} &copy; <a href=\"http://cartodb.com/attributions\">CartoDB</a>',\n\t\t\t\tsubdomains: 'abcd',\n\t\t\t\tmaxZoom: 19,\n\t\t\t\tvariant: 'light_all'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tPositron: 'light_all',\n\t\t\t\tPositronNoLabels: 'light_nolabels',\n\t\t\t\tDarkMatter: 'dark_all',\n\t\t\t\tDarkMatterNoLabels: 'dark_nolabels'\n\t\t\t}\n\t\t},\n\t\tHikeBike: {\n\t\t\turl: 'http://{s}.tiles.wmflabs.org/{variant}/{z}/{x}/{y}.png',\n\t\t\toptions: {\n\t\t\t\tmaxZoom: 19,\n\t\t\t\tattribution: '{attribution.OpenStreetMap}',\n\t\t\t\tvariant: 'hikebike'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tHikeBike: {},\n\t\t\t\tHillShading: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tmaxZoom: 15,\n\t\t\t\t\t\tvariant: 'hillshading'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tBasemapAT: {\n\t\t\turl: '//maps{s}.wien.gv.at/basemap/{variant}/normal/google3857/{z}/{y}/{x}.{format}',\n\t\t\toptions: {\n\t\t\t\tmaxZoom: 19,\n\t\t\t\tattribution: 'Datenquelle: <a href=\"www.basemap.at\">basemap.at</a>',\n\t\t\t\tsubdomains: ['', '1', '2', '3', '4'],\n\t\t\t\tformat: 'png',\n\t\t\t\tbounds: [[46.358770, 8.782379], [49.037872, 17.189532]],\n\t\t\t\tvariant: 'geolandbasemap'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tbasemap: 'geolandbasemap',\n\t\t\t\tgrau: 'bmapgrau',\n\t\t\t\toverlay: 'bmapoverlay',\n\t\t\t\thighdpi: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'bmaphidpi',\n\t\t\t\t\t\tformat: 'jpeg'\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\torthofoto: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'bmaporthofoto30cm',\n\t\t\t\t\t\tformat: 'jpeg'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tNASAGIBS: {\n\t\t\turl: '//map1.vis.earthdata.nasa.gov/wmts-webmerc/{variant}/default/{time}/{tilematrixset}{maxZoom}/{z}/{y}/{x}.{format}',\n\t\t\toptions: {\n\t\t\t\tattribution:\n\t\t\t\t\t'Imagery provided by services from the Global Imagery Browse Services (GIBS), operated by the NASA/GSFC/Earth Science Data and Information System ' +\n\t\t\t\t\t'(<a href=\"https://earthdata.nasa.gov\">ESDIS</a>) with funding provided by NASA/HQ.',\n\t\t\t\tbounds: [[-85.0511287776, -179.999999975], [85.0511287776, 179.999999975]],\n\t\t\t\tminZoom: 1,\n\t\t\t\tmaxZoom: 9,\n\t\t\t\tformat: 'jpg',\n\t\t\t\ttime: '',\n\t\t\t\ttilematrixset: 'GoogleMapsCompatible_Level'\n\t\t\t},\n\t\t\tvariants: {\n\t\t\t\tModisTerraTrueColorCR: 'MODIS_Terra_CorrectedReflectance_TrueColor',\n\t\t\t\tModisTerraBands367CR: 'MODIS_Terra_CorrectedReflectance_Bands367',\n\t\t\t\tViirsEarthAtNight2012: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'VIIRS_CityLights_2012',\n\t\t\t\t\t\tmaxZoom: 8\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tModisTerraLSTDay: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'MODIS_Terra_Land_Surface_Temp_Day',\n\t\t\t\t\t\tformat: 'png',\n\t\t\t\t\t\tmaxZoom: 7,\n\t\t\t\t\t\topacity: 0.75\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tModisTerraSnowCover: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'MODIS_Terra_Snow_Cover',\n\t\t\t\t\t\tformat: 'png',\n\t\t\t\t\t\tmaxZoom: 8,\n\t\t\t\t\t\topacity: 0.75\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tModisTerraAOD: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'MODIS_Terra_Aerosol',\n\t\t\t\t\t\tformat: 'png',\n\t\t\t\t\t\tmaxZoom: 6,\n\t\t\t\t\t\topacity: 0.75\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tModisTerraChlorophyll: {\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tvariant: 'MODIS_Terra_Chlorophyll_A',\n\t\t\t\t\t\tformat: 'png',\n\t\t\t\t\t\tmaxZoom: 7,\n\t\t\t\t\t\topacity: 0.75\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tL.tileLayer.provider = function (provider, options) {\n\t\treturn new L.TileLayer.Provider(provider, options);\n\t};\n}());\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbGVhZmxldC1wcm92aWRlcnMvbGVhZmxldC1wcm92aWRlcnMuanM/ZmE0NyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCO0FBQzlCO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQSwyQkFBMkIsbUJBQW1CO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG1DQUFtQztBQUNuQztBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsWUFBWSxFQUFFLHlCQUF5QixFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7QUFDakQ7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaLElBQUk7QUFDSjtBQUNBLGNBQWM7QUFDZDtBQUNBLG1CQUFtQixFQUFFLDhCQUE4QixFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7QUFDN0Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsbUJBQW1CLEVBQUUsb0NBQW9DLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtBQUNuRTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxtQkFBbUIsRUFBRSw4QkFBOEIsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO0FBQzdEO0FBQ0EsMEJBQTBCLHlCQUF5QiwwQkFBMEI7QUFDN0U7QUFDQSxLQUFLO0FBQ0w7QUFDQSxtQkFBbUIsRUFBRSw0QkFBNEIsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO0FBQzNEO0FBQ0EscUJBQXFCLDBCQUEwQjtBQUMvQztBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSw4Q0FBOEMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO0FBQ3hEO0FBQ0Esa0NBQWtDO0FBQ2xDO0FBQ0EsR0FBRztBQUNIO0FBQ0EsWUFBWSxFQUFFLHVCQUF1QixFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7QUFDL0M7QUFDQTtBQUNBLDZCQUE2QiwwQkFBMEIsdUVBQXVFO0FBQzlIO0FBQ0EsR0FBRztBQUNIO0FBQ0EsWUFBWSxFQUFFLHlCQUF5QixRQUFRLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO0FBQzNEO0FBQ0E7QUFDQSxZQUFZLDBEQUEwRCwwQkFBMEI7QUFDaEc7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSwrQ0FBK0MsUUFBUSxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRTtBQUN6RTtBQUNBO0FBQ0E7QUFDQSxvSUFBb0ksV0FBVywwQkFBMEI7QUFDekssSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsaUJBQWlCLEVBQUUsOEJBQThCLFFBQVEsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7QUFDckU7QUFDQTtBQUNBLHVIQUF1SCxXQUFXLDBCQUEwQjtBQUM1SixJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0Esb0JBQW9CLEVBQUUsMEJBQTBCLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtBQUNuRTtBQUNBO0FBQ0Esc0JBQXNCLEVBQUUsd0JBQXdCLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxJQUFJO0FBQ3ZFO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0VBQStFO0FBQy9FLGdCQUFnQiwwQkFBMEI7QUFDMUM7QUFDQSxJQUFJO0FBQ0o7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpRkFBaUY7QUFDakY7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxlQUFlLEVBQUUsaUNBQWlDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtBQUM1RCxJQUFJO0FBQ0o7QUFDQTtBQUNBLDZFQUE2RTtBQUM3RSxnQkFBZ0IsMEJBQTBCO0FBQzFDO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSx5QkFBeUIsRUFBRSxtQkFBbUIsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtBQUNsRTtBQUNBO0FBQ0E7QUFDQSxnRkFBZ0Y7QUFDaEYsZ0JBQWdCLDBCQUEwQjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EseURBQXlELFFBQVEsaUJBQWlCLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtBQUM1RjtBQUNBO0FBQ0EsOEJBQThCO0FBQzlCLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsaUJBQWlCLFFBQVE7QUFDbEM7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGlCQUFpQixRQUFRLGtCQUFrQjtBQUNoRTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsaUJBQWlCLFFBQVE7QUFDbEM7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsaUJBQWlCLFFBQVE7QUFDbEM7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUyxpQkFBaUIsUUFBUTtBQUNsQztBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGlCQUFpQixRQUFRO0FBQzlDO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGlCQUFpQixRQUFRO0FBQzlDO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGlCQUFpQixRQUFRO0FBQzlDO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGlCQUFpQixRQUFRO0FBQzlDO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGlCQUFpQixRQUFRO0FBQzlDO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLGlCQUFpQixFQUFFLDhCQUE4QixRQUFRLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO0FBQ3JFO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsRUFBRSxFQUFFLEtBQUs7QUFDakIsY0FBYyxNQUFNLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtBQUMxQyxhQUFhLE9BQU8sV0FBVyxTQUFTO0FBQ3hDO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxrQkFBa0IsRUFBRSwwQkFBMEIsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtBQUNsRTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLGlCQUFpQixFQUFFLGVBQWUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLDBCQUEwQjtBQUNqQztBQUNBLEdBQUc7QUFDSDtBQUNBLDZDQUE2QyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7QUFDdkQ7QUFDQTtBQUNBLE9BQU8sMEJBQTBCLE1BQU07QUFDdkM7QUFDQSxHQUFHO0FBQ0g7QUFDQSxpQkFBaUIsRUFBRSx3QkFBd0IsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRTtBQUMvRDtBQUNBLG1CQUFtQiwwQkFBMEIsT0FBTztBQUNwRDtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsaUJBQWlCLEVBQUUsb0JBQW9CLFFBQVEsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUU7QUFDM0Q7QUFDQTtBQUNBLG1CQUFtQiwwQkFBMEI7QUFDN0M7QUFDQSxJQUFJO0FBQ0o7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxnQkFBZ0IsRUFBRSxxQkFBcUIsUUFBUSxvQkFBb0IsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsT0FBTztBQUN0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxxREFBcUQsUUFBUSxVQUFVLEtBQUssRUFBRSxlQUFlLFFBQVEsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxPQUFPO0FBQzFIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2xlYWZsZXQtcHJvdmlkZXJzL2xlYWZsZXQtcHJvdmlkZXJzLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uICgpIHtcblx0J3VzZSBzdHJpY3QnO1xuXG5cdEwuVGlsZUxheWVyLlByb3ZpZGVyID0gTC5UaWxlTGF5ZXIuZXh0ZW5kKHtcblx0XHRpbml0aWFsaXplOiBmdW5jdGlvbiAoYXJnLCBvcHRpb25zKSB7XG5cdFx0XHR2YXIgcHJvdmlkZXJzID0gTC5UaWxlTGF5ZXIuUHJvdmlkZXIucHJvdmlkZXJzO1xuXG5cdFx0XHR2YXIgcGFydHMgPSBhcmcuc3BsaXQoJy4nKTtcblxuXHRcdFx0dmFyIHByb3ZpZGVyTmFtZSA9IHBhcnRzWzBdO1xuXHRcdFx0dmFyIHZhcmlhbnROYW1lID0gcGFydHNbMV07XG5cblx0XHRcdGlmICghcHJvdmlkZXJzW3Byb3ZpZGVyTmFtZV0pIHtcblx0XHRcdFx0dGhyb3cgJ05vIHN1Y2ggcHJvdmlkZXIgKCcgKyBwcm92aWRlck5hbWUgKyAnKSc7XG5cdFx0XHR9XG5cblx0XHRcdHZhciBwcm92aWRlciA9IHtcblx0XHRcdFx0dXJsOiBwcm92aWRlcnNbcHJvdmlkZXJOYW1lXS51cmwsXG5cdFx0XHRcdG9wdGlvbnM6IHByb3ZpZGVyc1twcm92aWRlck5hbWVdLm9wdGlvbnNcblx0XHRcdH07XG5cblx0XHRcdC8vIG92ZXJ3cml0ZSB2YWx1ZXMgaW4gcHJvdmlkZXIgZnJvbSB2YXJpYW50LlxuXHRcdFx0aWYgKHZhcmlhbnROYW1lICYmICd2YXJpYW50cycgaW4gcHJvdmlkZXJzW3Byb3ZpZGVyTmFtZV0pIHtcblx0XHRcdFx0aWYgKCEodmFyaWFudE5hbWUgaW4gcHJvdmlkZXJzW3Byb3ZpZGVyTmFtZV0udmFyaWFudHMpKSB7XG5cdFx0XHRcdFx0dGhyb3cgJ05vIHN1Y2ggdmFyaWFudCBvZiAnICsgcHJvdmlkZXJOYW1lICsgJyAoJyArIHZhcmlhbnROYW1lICsgJyknO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHZhciB2YXJpYW50ID0gcHJvdmlkZXJzW3Byb3ZpZGVyTmFtZV0udmFyaWFudHNbdmFyaWFudE5hbWVdO1xuXHRcdFx0XHR2YXIgdmFyaWFudE9wdGlvbnM7XG5cdFx0XHRcdGlmICh0eXBlb2YgdmFyaWFudCA9PT0gJ3N0cmluZycpIHtcblx0XHRcdFx0XHR2YXJpYW50T3B0aW9ucyA9IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6IHZhcmlhbnRcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHZhcmlhbnRPcHRpb25zID0gdmFyaWFudC5vcHRpb25zO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHByb3ZpZGVyID0ge1xuXHRcdFx0XHRcdHVybDogdmFyaWFudC51cmwgfHwgcHJvdmlkZXIudXJsLFxuXHRcdFx0XHRcdG9wdGlvbnM6IEwuVXRpbC5leHRlbmQoe30sIHByb3ZpZGVyLm9wdGlvbnMsIHZhcmlhbnRPcHRpb25zKVxuXHRcdFx0XHR9O1xuXHRcdFx0fSBlbHNlIGlmICh0eXBlb2YgcHJvdmlkZXIudXJsID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHRcdHByb3ZpZGVyLnVybCA9IHByb3ZpZGVyLnVybChwYXJ0cy5zcGxpY2UoMSwgcGFydHMubGVuZ3RoIC0gMSkuam9pbignLicpKTtcblx0XHRcdH1cblxuXHRcdFx0dmFyIGZvcmNlSFRUUCA9IHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbCA9PT0gJ2ZpbGU6JyB8fCBwcm92aWRlci5vcHRpb25zLmZvcmNlSFRUUDtcblx0XHRcdGlmIChwcm92aWRlci51cmwuaW5kZXhPZignLy8nKSA9PT0gMCAmJiBmb3JjZUhUVFApIHtcblx0XHRcdFx0cHJvdmlkZXIudXJsID0gJ2h0dHA6JyArIHByb3ZpZGVyLnVybDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gcmVwbGFjZSBhdHRyaWJ1dGlvbiBwbGFjZWhvbGRlcnMgd2l0aCB0aGVpciB2YWx1ZXMgZnJvbSB0b3BsZXZlbCBwcm92aWRlciBhdHRyaWJ1dGlvbixcblx0XHRcdC8vIHJlY3Vyc2l2ZWx5XG5cdFx0XHR2YXIgYXR0cmlidXRpb25SZXBsYWNlciA9IGZ1bmN0aW9uIChhdHRyKSB7XG5cdFx0XHRcdGlmIChhdHRyLmluZGV4T2YoJ3thdHRyaWJ1dGlvbi4nKSA9PT0gLTEpIHtcblx0XHRcdFx0XHRyZXR1cm4gYXR0cjtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gYXR0ci5yZXBsYWNlKC9cXHthdHRyaWJ1dGlvbi4oXFx3KilcXH0vLFxuXHRcdFx0XHRcdGZ1bmN0aW9uIChtYXRjaCwgYXR0cmlidXRpb25OYW1lKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gYXR0cmlidXRpb25SZXBsYWNlcihwcm92aWRlcnNbYXR0cmlidXRpb25OYW1lXS5vcHRpb25zLmF0dHJpYnV0aW9uKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdCk7XG5cdFx0XHR9O1xuXHRcdFx0cHJvdmlkZXIub3B0aW9ucy5hdHRyaWJ1dGlvbiA9IGF0dHJpYnV0aW9uUmVwbGFjZXIocHJvdmlkZXIub3B0aW9ucy5hdHRyaWJ1dGlvbik7XG5cblx0XHRcdC8vIENvbXB1dGUgZmluYWwgb3B0aW9ucyBjb21iaW5pbmcgcHJvdmlkZXIgb3B0aW9ucyB3aXRoIGFueSB1c2VyIG92ZXJyaWRlc1xuXHRcdFx0dmFyIGxheWVyT3B0cyA9IEwuVXRpbC5leHRlbmQoe30sIHByb3ZpZGVyLm9wdGlvbnMsIG9wdGlvbnMpO1xuXHRcdFx0TC5UaWxlTGF5ZXIucHJvdG90eXBlLmluaXRpYWxpemUuY2FsbCh0aGlzLCBwcm92aWRlci51cmwsIGxheWVyT3B0cyk7XG5cdFx0fVxuXHR9KTtcblxuXHQvKipcblx0ICogRGVmaW5pdGlvbiBvZiBwcm92aWRlcnMuXG5cdCAqIHNlZSBodHRwOi8vbGVhZmxldGpzLmNvbS9yZWZlcmVuY2UuaHRtbCN0aWxlbGF5ZXIgZm9yIG9wdGlvbnMgaW4gdGhlIG9wdGlvbnMgbWFwLlxuXHQgKi9cblxuXHRMLlRpbGVMYXllci5Qcm92aWRlci5wcm92aWRlcnMgPSB7XG5cdFx0T3BlblN0cmVldE1hcDoge1xuXHRcdFx0dXJsOiAnLy97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmcnLFxuXHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRtYXhab29tOiAxOSxcblx0XHRcdFx0YXR0cmlidXRpb246XG5cdFx0XHRcdFx0JyZjb3B5OyA8YSBocmVmPVwiaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy9jb3B5cmlnaHRcIj5PcGVuU3RyZWV0TWFwPC9hPidcblx0XHRcdH0sXG5cdFx0XHR2YXJpYW50czoge1xuXHRcdFx0XHRNYXBuaWs6IHt9LFxuXHRcdFx0XHRCbGFja0FuZFdoaXRlOiB7XG5cdFx0XHRcdFx0dXJsOiAnaHR0cDovL3tzfS50aWxlcy53bWZsYWJzLm9yZy9idy1tYXBuaWsve3p9L3t4fS97eX0ucG5nJyxcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHRtYXhab29tOiAxOFxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0REU6IHtcblx0XHRcdFx0XHR1cmw6ICdodHRwOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5kZS90aWxlcy9vc21kZS97en0ve3h9L3t5fS5wbmcnLFxuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdG1heFpvb206IDE4XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRGcmFuY2U6IHtcblx0XHRcdFx0XHR1cmw6ICdodHRwOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5mci9vc21mci97en0ve3h9L3t5fS5wbmcnLFxuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0aW9uOiAnJmNvcHk7IE9wZW5zdHJlZXRtYXAgRnJhbmNlIHwge2F0dHJpYnV0aW9uLk9wZW5TdHJlZXRNYXB9J1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0SE9UOiB7XG5cdFx0XHRcdFx0dXJsOiAnaHR0cDovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAuZnIvaG90L3t6fS97eH0ve3l9LnBuZycsXG5cdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0YXR0cmlidXRpb246ICd7YXR0cmlidXRpb24uT3BlblN0cmVldE1hcH0sIFRpbGVzIGNvdXJ0ZXN5IG9mIDxhIGhyZWY9XCJodHRwOi8vaG90Lm9wZW5zdHJlZXRtYXAub3JnL1wiIHRhcmdldD1cIl9ibGFua1wiPkh1bWFuaXRhcmlhbiBPcGVuU3RyZWV0TWFwIFRlYW08L2E+J1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cdFx0T3BlblNlYU1hcDoge1xuXHRcdFx0dXJsOiAnaHR0cDovL3RpbGVzLm9wZW5zZWFtYXAub3JnL3NlYW1hcmsve3p9L3t4fS97eX0ucG5nJyxcblx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0YXR0cmlidXRpb246ICdNYXAgZGF0YTogJmNvcHk7IDxhIGhyZWY9XCJodHRwOi8vd3d3Lm9wZW5zZWFtYXAub3JnXCI+T3BlblNlYU1hcDwvYT4gY29udHJpYnV0b3JzJ1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0T3BlblRvcG9NYXA6IHtcblx0XHRcdHVybDogJy8ve3N9LnRpbGUub3BlbnRvcG9tYXAub3JnL3t6fS97eH0ve3l9LnBuZycsXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdG1heFpvb206IDE2LFxuXHRcdFx0XHRhdHRyaWJ1dGlvbjogJ01hcCBkYXRhOiB7YXR0cmlidXRpb24uT3BlblN0cmVldE1hcH0sIDxhIGhyZWY9XCJodHRwOi8vdmlld2ZpbmRlcnBhbm9yYW1hcy5vcmdcIj5TUlRNPC9hPiB8IE1hcCBzdHlsZTogJmNvcHk7IDxhIGhyZWY9XCJodHRwczovL29wZW50b3BvbWFwLm9yZ1wiPk9wZW5Ub3BvTWFwPC9hPiAoPGEgaHJlZj1cImh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS8zLjAvXCI+Q0MtQlktU0E8L2E+KSdcblx0XHRcdH1cblx0XHR9LFxuXHRcdFRodW5kZXJmb3Jlc3Q6IHtcblx0XHRcdHVybDogJy8ve3N9LnRpbGUudGh1bmRlcmZvcmVzdC5jb20ve3ZhcmlhbnR9L3t6fS97eH0ve3l9LnBuZycsXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdGF0dHJpYnV0aW9uOlxuXHRcdFx0XHRcdCcmY29weTsgPGEgaHJlZj1cImh0dHA6Ly93d3cub3BlbmN5Y2xlbWFwLm9yZ1wiPk9wZW5DeWNsZU1hcDwvYT4sIHthdHRyaWJ1dGlvbi5PcGVuU3RyZWV0TWFwfScsXG5cdFx0XHRcdHZhcmlhbnQ6ICdjeWNsZSdcblx0XHRcdH0sXG5cdFx0XHR2YXJpYW50czoge1xuXHRcdFx0XHRPcGVuQ3ljbGVNYXA6ICdjeWNsZScsXG5cdFx0XHRcdFRyYW5zcG9ydDoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICd0cmFuc3BvcnQnLFxuXHRcdFx0XHRcdFx0bWF4Wm9vbTogMTlcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdFRyYW5zcG9ydERhcms6IHtcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHR2YXJpYW50OiAndHJhbnNwb3J0LWRhcmsnLFxuXHRcdFx0XHRcdFx0bWF4Wm9vbTogMTlcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdExhbmRzY2FwZTogJ2xhbmRzY2FwZScsXG5cdFx0XHRcdE91dGRvb3JzOiAnb3V0ZG9vcnMnXG5cdFx0XHR9XG5cdFx0fSxcblx0XHRPcGVuTWFwU3VyZmVyOiB7XG5cdFx0XHR1cmw6ICdodHRwOi8vb3Blbm1hcHN1cmZlci51bmktaGQuZGUvdGlsZXMve3ZhcmlhbnR9L3g9e3h9Jnk9e3l9Jno9e3p9Jyxcblx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0bWF4Wm9vbTogMjAsXG5cdFx0XHRcdHZhcmlhbnQ6ICdyb2FkcycsXG5cdFx0XHRcdGF0dHJpYnV0aW9uOiAnSW1hZ2VyeSBmcm9tIDxhIGhyZWY9XCJodHRwOi8vZ2lzY2llbmNlLnVuaS1oZC5kZS9cIj5HSVNjaWVuY2UgUmVzZWFyY2ggR3JvdXAgQCBVbml2ZXJzaXR5IG9mIEhlaWRlbGJlcmc8L2E+ICZtZGFzaDsgTWFwIGRhdGEge2F0dHJpYnV0aW9uLk9wZW5TdHJlZXRNYXB9J1xuXHRcdFx0fSxcblx0XHRcdHZhcmlhbnRzOiB7XG5cdFx0XHRcdFJvYWRzOiAncm9hZHMnLFxuXHRcdFx0XHRBZG1pbkJvdW5kczoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdhZG1pbmInLFxuXHRcdFx0XHRcdFx0bWF4Wm9vbTogMTlcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdEdyYXlzY2FsZToge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdyb2Fkc2cnLFxuXHRcdFx0XHRcdFx0bWF4Wm9vbTogMTlcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9LFxuXHRcdEh5ZGRhOiB7XG5cdFx0XHR1cmw6ICdodHRwOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5zZS9oeWRkYS97dmFyaWFudH0ve3p9L3t4fS97eX0ucG5nJyxcblx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0dmFyaWFudDogJ2Z1bGwnLFxuXHRcdFx0XHRhdHRyaWJ1dGlvbjogJ1RpbGVzIGNvdXJ0ZXN5IG9mIDxhIGhyZWY9XCJodHRwOi8vb3BlbnN0cmVldG1hcC5zZS9cIiB0YXJnZXQ9XCJfYmxhbmtcIj5PcGVuU3RyZWV0TWFwIFN3ZWRlbjwvYT4gJm1kYXNoOyBNYXAgZGF0YSB7YXR0cmlidXRpb24uT3BlblN0cmVldE1hcH0nXG5cdFx0XHR9LFxuXHRcdFx0dmFyaWFudHM6IHtcblx0XHRcdFx0RnVsbDogJ2Z1bGwnLFxuXHRcdFx0XHRCYXNlOiAnYmFzZScsXG5cdFx0XHRcdFJvYWRzQW5kTGFiZWxzOiAncm9hZHNfYW5kX2xhYmVscydcblx0XHRcdH1cblx0XHR9LFxuXHRcdE1hcFF1ZXN0T3Blbjoge1xuXHRcdFx0LyogTWFwcXVlc3QgZG9lcyBzdXBwb3J0IGh0dHBzLCBidXQgd2l0aCBhIGRpZmZlcmVudCBzdWJkb21haW46XG5cdFx0XHQgKiBodHRwczovL290aWxle3N9LXMubXFjZG4uY29tL3RpbGVzLzEuMC4wL3t0eXBlfS97en0ve3h9L3t5fS57ZXh0fVxuXHRcdFx0ICogd2hpY2ggbWFrZXMgaW1wbGVtZW50aW5nIHByb3RvY29sIHJlbGF0aXZpdHkgaW1wb3NzaWJsZS5cblx0XHRcdCAqL1xuXHRcdFx0dXJsOiAnaHR0cDovL290aWxle3N9Lm1xY2RuLmNvbS90aWxlcy8xLjAuMC97dHlwZX0ve3p9L3t4fS97eX0ue2V4dH0nLFxuXHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHR0eXBlOiAnbWFwJyxcblx0XHRcdFx0ZXh0OiAnanBnJyxcblx0XHRcdFx0YXR0cmlidXRpb246XG5cdFx0XHRcdFx0J1RpbGVzIENvdXJ0ZXN5IG9mIDxhIGhyZWY9XCJodHRwOi8vd3d3Lm1hcHF1ZXN0LmNvbS9cIj5NYXBRdWVzdDwvYT4gJm1kYXNoOyAnICtcblx0XHRcdFx0XHQnTWFwIGRhdGEge2F0dHJpYnV0aW9uLk9wZW5TdHJlZXRNYXB9Jyxcblx0XHRcdFx0c3ViZG9tYWluczogJzEyMzQnXG5cdFx0XHR9LFxuXHRcdFx0dmFyaWFudHM6IHtcblx0XHRcdFx0T1NNOiB7fSxcblx0XHRcdFx0QWVyaWFsOiB7XG5cdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0dHlwZTogJ3NhdCcsXG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGlvbjpcblx0XHRcdFx0XHRcdFx0J1RpbGVzIENvdXJ0ZXN5IG9mIDxhIGhyZWY9XCJodHRwOi8vd3d3Lm1hcHF1ZXN0LmNvbS9cIj5NYXBRdWVzdDwvYT4gJm1kYXNoOyAnICtcblx0XHRcdFx0XHRcdFx0J1BvcnRpb25zIENvdXJ0ZXN5IE5BU0EvSlBMLUNhbHRlY2ggYW5kIFUuUy4gRGVwYXJ0LiBvZiBBZ3JpY3VsdHVyZSwgRmFybSBTZXJ2aWNlIEFnZW5jeSdcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdEh5YnJpZE92ZXJsYXk6IHtcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHR0eXBlOiAnaHliJyxcblx0XHRcdFx0XHRcdGV4dDogJ3BuZycsXG5cdFx0XHRcdFx0XHRvcGFjaXR5OiAwLjlcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9LFxuXHRcdE1hcEJveDoge1xuXHRcdFx0dXJsOiBmdW5jdGlvbiAoaWQpIHtcblx0XHRcdFx0cmV0dXJuICcvL3tzfS50aWxlcy5tYXBib3guY29tL3YzLycgKyBpZCArICcve3p9L3t4fS97eX0ucG5nJztcblx0XHRcdH0sXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdGF0dHJpYnV0aW9uOlxuXHRcdFx0XHRcdCdJbWFnZXJ5IGZyb20gPGEgaHJlZj1cImh0dHA6Ly9tYXBib3guY29tL2Fib3V0L21hcHMvXCI+TWFwQm94PC9hPiAmbWRhc2g7ICcgK1xuXHRcdFx0XHRcdCdNYXAgZGF0YSB7YXR0cmlidXRpb24uT3BlblN0cmVldE1hcH0nLFxuXHRcdFx0XHRzdWJkb21haW5zOiAnYWJjZCdcblx0XHRcdH1cblx0XHR9LFxuXHRcdFN0YW1lbjoge1xuXHRcdFx0dXJsOiAnLy9zdGFtZW4tdGlsZXMte3N9LmEuc3NsLmZhc3RseS5uZXQve3ZhcmlhbnR9L3t6fS97eH0ve3l9LnBuZycsXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdGF0dHJpYnV0aW9uOlxuXHRcdFx0XHRcdCdNYXAgdGlsZXMgYnkgPGEgaHJlZj1cImh0dHA6Ly9zdGFtZW4uY29tXCI+U3RhbWVuIERlc2lnbjwvYT4sICcgK1xuXHRcdFx0XHRcdCc8YSBocmVmPVwiaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnkvMy4wXCI+Q0MgQlkgMy4wPC9hPiAmbWRhc2g7ICcgK1xuXHRcdFx0XHRcdCdNYXAgZGF0YSB7YXR0cmlidXRpb24uT3BlblN0cmVldE1hcH0nLFxuXHRcdFx0XHRzdWJkb21haW5zOiAnYWJjZCcsXG5cdFx0XHRcdG1pblpvb206IDAsXG5cdFx0XHRcdG1heFpvb206IDIwLFxuXHRcdFx0XHR2YXJpYW50OiAndG9uZXInLFxuXHRcdFx0XHRleHQ6ICdwbmcnXG5cdFx0XHR9LFxuXHRcdFx0dmFyaWFudHM6IHtcblx0XHRcdFx0VG9uZXI6ICd0b25lcicsXG5cdFx0XHRcdFRvbmVyQmFja2dyb3VuZDogJ3RvbmVyLWJhY2tncm91bmQnLFxuXHRcdFx0XHRUb25lckh5YnJpZDogJ3RvbmVyLWh5YnJpZCcsXG5cdFx0XHRcdFRvbmVyTGluZXM6ICd0b25lci1saW5lcycsXG5cdFx0XHRcdFRvbmVyTGFiZWxzOiAndG9uZXItbGFiZWxzJyxcblx0XHRcdFx0VG9uZXJMaXRlOiAndG9uZXItbGl0ZScsXG5cdFx0XHRcdFdhdGVyY29sb3I6IHtcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHR2YXJpYW50OiAnd2F0ZXJjb2xvcicsXG5cdFx0XHRcdFx0XHRtaW5ab29tOiAxLFxuXHRcdFx0XHRcdFx0bWF4Wm9vbTogMTZcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdFRlcnJhaW46IHtcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHR2YXJpYW50OiAndGVycmFpbicsXG5cdFx0XHRcdFx0XHRtaW5ab29tOiA0LFxuXHRcdFx0XHRcdFx0bWF4Wm9vbTogMTgsXG5cdFx0XHRcdFx0XHRib3VuZHM6IFtbMjIsIC0xMzJdLCBbNzAsIC01Nl1dXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRUZXJyYWluQmFja2dyb3VuZDoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICd0ZXJyYWluLWJhY2tncm91bmQnLFxuXHRcdFx0XHRcdFx0bWluWm9vbTogNCxcblx0XHRcdFx0XHRcdG1heFpvb206IDE4LFxuXHRcdFx0XHRcdFx0Ym91bmRzOiBbWzIyLCAtMTMyXSwgWzcwLCAtNTZdXVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0VG9wT1NNUmVsaWVmOiB7XG5cdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0dmFyaWFudDogJ3RvcG9zbS1jb2xvci1yZWxpZWYnLFxuXHRcdFx0XHRcdFx0ZXh0OiAnanBnJyxcblx0XHRcdFx0XHRcdGJvdW5kczogW1syMiwgLTEzMl0sIFs1MSwgLTU2XV1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdFRvcE9TTUZlYXR1cmVzOiB7XG5cdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0dmFyaWFudDogJ3RvcG9zbS1mZWF0dXJlcycsXG5cdFx0XHRcdFx0XHRib3VuZHM6IFtbMjIsIC0xMzJdLCBbNTEsIC01Nl1dLFxuXHRcdFx0XHRcdFx0b3BhY2l0eTogMC45XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRFc3JpOiB7XG5cdFx0XHR1cmw6ICcvL3NlcnZlci5hcmNnaXNvbmxpbmUuY29tL0FyY0dJUy9yZXN0L3NlcnZpY2VzL3t2YXJpYW50fS9NYXBTZXJ2ZXIvdGlsZS97en0ve3l9L3t4fScsXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdHZhcmlhbnQ6ICdXb3JsZF9TdHJlZXRfTWFwJyxcblx0XHRcdFx0YXR0cmlidXRpb246ICdUaWxlcyAmY29weTsgRXNyaSdcblx0XHRcdH0sXG5cdFx0XHR2YXJpYW50czoge1xuXHRcdFx0XHRXb3JsZFN0cmVldE1hcDoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdGF0dHJpYnV0aW9uOlxuXHRcdFx0XHRcdFx0XHQne2F0dHJpYnV0aW9uLkVzcml9ICZtZGFzaDsgJyArXG5cdFx0XHRcdFx0XHRcdCdTb3VyY2U6IEVzcmksIERlTG9ybWUsIE5BVlRFUSwgVVNHUywgSW50ZXJtYXAsIGlQQywgTlJDQU4sIEVzcmkgSmFwYW4sIE1FVEksIEVzcmkgQ2hpbmEgKEhvbmcgS29uZyksIEVzcmkgKFRoYWlsYW5kKSwgVG9tVG9tLCAyMDEyJ1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0RGVMb3JtZToge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdTcGVjaWFsdHkvRGVMb3JtZV9Xb3JsZF9CYXNlX01hcCcsXG5cdFx0XHRcdFx0XHRtaW5ab29tOiAxLFxuXHRcdFx0XHRcdFx0bWF4Wm9vbTogMTEsXG5cdFx0XHRcdFx0XHRhdHRyaWJ1dGlvbjogJ3thdHRyaWJ1dGlvbi5Fc3JpfSAmbWRhc2g7IENvcHlyaWdodDogJmNvcHk7MjAxMiBEZUxvcm1lJ1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0V29ybGRUb3BvTWFwOiB7XG5cdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0dmFyaWFudDogJ1dvcmxkX1RvcG9fTWFwJyxcblx0XHRcdFx0XHRcdGF0dHJpYnV0aW9uOlxuXHRcdFx0XHRcdFx0XHQne2F0dHJpYnV0aW9uLkVzcml9ICZtZGFzaDsgJyArXG5cdFx0XHRcdFx0XHRcdCdFc3JpLCBEZUxvcm1lLCBOQVZURVEsIFRvbVRvbSwgSW50ZXJtYXAsIGlQQywgVVNHUywgRkFPLCBOUFMsIE5SQ0FOLCBHZW9CYXNlLCBLYWRhc3RlciBOTCwgT3JkbmFuY2UgU3VydmV5LCBFc3JpIEphcGFuLCBNRVRJLCBFc3JpIENoaW5hIChIb25nIEtvbmcpLCBhbmQgdGhlIEdJUyBVc2VyIENvbW11bml0eSdcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdFdvcmxkSW1hZ2VyeToge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdXb3JsZF9JbWFnZXJ5Jyxcblx0XHRcdFx0XHRcdGF0dHJpYnV0aW9uOlxuXHRcdFx0XHRcdFx0XHQne2F0dHJpYnV0aW9uLkVzcml9ICZtZGFzaDsgJyArXG5cdFx0XHRcdFx0XHRcdCdTb3VyY2U6IEVzcmksIGktY3ViZWQsIFVTREEsIFVTR1MsIEFFWCwgR2VvRXllLCBHZXRtYXBwaW5nLCBBZXJvZ3JpZCwgSUdOLCBJR1AsIFVQUi1FR1AsIGFuZCB0aGUgR0lTIFVzZXIgQ29tbXVuaXR5J1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0V29ybGRUZXJyYWluOiB7XG5cdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0dmFyaWFudDogJ1dvcmxkX1RlcnJhaW5fQmFzZScsXG5cdFx0XHRcdFx0XHRtYXhab29tOiAxMyxcblx0XHRcdFx0XHRcdGF0dHJpYnV0aW9uOlxuXHRcdFx0XHRcdFx0XHQne2F0dHJpYnV0aW9uLkVzcml9ICZtZGFzaDsgJyArXG5cdFx0XHRcdFx0XHRcdCdTb3VyY2U6IFVTR1MsIEVzcmksIFRBTkEsIERlTG9ybWUsIGFuZCBOUFMnXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRXb3JsZFNoYWRlZFJlbGllZjoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdXb3JsZF9TaGFkZWRfUmVsaWVmJyxcblx0XHRcdFx0XHRcdG1heFpvb206IDEzLFxuXHRcdFx0XHRcdFx0YXR0cmlidXRpb246ICd7YXR0cmlidXRpb24uRXNyaX0gJm1kYXNoOyBTb3VyY2U6IEVzcmknXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRXb3JsZFBoeXNpY2FsOiB7XG5cdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0dmFyaWFudDogJ1dvcmxkX1BoeXNpY2FsX01hcCcsXG5cdFx0XHRcdFx0XHRtYXhab29tOiA4LFxuXHRcdFx0XHRcdFx0YXR0cmlidXRpb246ICd7YXR0cmlidXRpb24uRXNyaX0gJm1kYXNoOyBTb3VyY2U6IFVTIE5hdGlvbmFsIFBhcmsgU2VydmljZSdcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdE9jZWFuQmFzZW1hcDoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdPY2Vhbl9CYXNlbWFwJyxcblx0XHRcdFx0XHRcdG1heFpvb206IDEzLFxuXHRcdFx0XHRcdFx0YXR0cmlidXRpb246ICd7YXR0cmlidXRpb24uRXNyaX0gJm1kYXNoOyBTb3VyY2VzOiBHRUJDTywgTk9BQSwgQ0hTLCBPU1UsIFVOSCwgQ1NVTUIsIE5hdGlvbmFsIEdlb2dyYXBoaWMsIERlTG9ybWUsIE5BVlRFUSwgYW5kIEVzcmknXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHROYXRHZW9Xb3JsZE1hcDoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdOYXRHZW9fV29ybGRfTWFwJyxcblx0XHRcdFx0XHRcdG1heFpvb206IDE2LFxuXHRcdFx0XHRcdFx0YXR0cmlidXRpb246ICd7YXR0cmlidXRpb24uRXNyaX0gJm1kYXNoOyBOYXRpb25hbCBHZW9ncmFwaGljLCBFc3JpLCBEZUxvcm1lLCBOQVZURVEsIFVORVAtV0NNQywgVVNHUywgTkFTQSwgRVNBLCBNRVRJLCBOUkNBTiwgR0VCQ08sIE5PQUEsIGlQQydcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdFdvcmxkR3JheUNhbnZhczoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdDYW52YXMvV29ybGRfTGlnaHRfR3JheV9CYXNlJyxcblx0XHRcdFx0XHRcdG1heFpvb206IDE2LFxuXHRcdFx0XHRcdFx0YXR0cmlidXRpb246ICd7YXR0cmlidXRpb24uRXNyaX0gJm1kYXNoOyBFc3JpLCBEZUxvcm1lLCBOQVZURVEnXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRPcGVuV2VhdGhlck1hcDoge1xuXHRcdFx0dXJsOiAnaHR0cDovL3tzfS50aWxlLm9wZW53ZWF0aGVybWFwLm9yZy9tYXAve3ZhcmlhbnR9L3t6fS97eH0ve3l9LnBuZycsXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdG1heFpvb206IDE5LFxuXHRcdFx0XHRhdHRyaWJ1dGlvbjogJ01hcCBkYXRhICZjb3B5OyA8YSBocmVmPVwiaHR0cDovL29wZW53ZWF0aGVybWFwLm9yZ1wiPk9wZW5XZWF0aGVyTWFwPC9hPicsXG5cdFx0XHRcdG9wYWNpdHk6IDAuNVxuXHRcdFx0fSxcblx0XHRcdHZhcmlhbnRzOiB7XG5cdFx0XHRcdENsb3VkczogJ2Nsb3VkcycsXG5cdFx0XHRcdENsb3Vkc0NsYXNzaWM6ICdjbG91ZHNfY2xzJyxcblx0XHRcdFx0UHJlY2lwaXRhdGlvbjogJ3ByZWNpcGl0YXRpb24nLFxuXHRcdFx0XHRQcmVjaXBpdGF0aW9uQ2xhc3NpYzogJ3ByZWNpcGl0YXRpb25fY2xzJyxcblx0XHRcdFx0UmFpbjogJ3JhaW4nLFxuXHRcdFx0XHRSYWluQ2xhc3NpYzogJ3JhaW5fY2xzJyxcblx0XHRcdFx0UHJlc3N1cmU6ICdwcmVzc3VyZScsXG5cdFx0XHRcdFByZXNzdXJlQ29udG91cjogJ3ByZXNzdXJlX2NudHInLFxuXHRcdFx0XHRXaW5kOiAnd2luZCcsXG5cdFx0XHRcdFRlbXBlcmF0dXJlOiAndGVtcCcsXG5cdFx0XHRcdFNub3c6ICdzbm93J1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0SEVSRToge1xuXHRcdFx0Lypcblx0XHRcdCAqIEhFUkUgbWFwcywgZm9ybWVybHkgTm9raWEgbWFwcy5cblx0XHRcdCAqIFRoZXNlIGJhc2VtYXBzIGFyZSBmcmVlLCBidXQgeW91IG5lZWQgYW4gQVBJIGtleS4gUGxlYXNlIHNpZ24gdXAgYXRcblx0XHRcdCAqIGh0dHA6Ly9kZXZlbG9wZXIuaGVyZS5jb20vZ2V0dGluZy1zdGFydGVkXG5cdFx0XHQgKlxuXHRcdFx0ICogTm90ZSB0aGF0IHRoZSBiYXNlIHVybHMgY29udGFpbiAnLmNpdCcgd2hpY2hzIGlzIEhFUkUnc1xuXHRcdFx0ICogJ0N1c3RvbWVyIEludGVncmF0aW9uIFRlc3RpbmcnIGVudmlyb25tZW50LiBQbGVhc2UgcmVtb3ZlIGZvciBwcm9kdWN0aW9uXG5cdFx0XHQgKiBlbnZpcmlvbm1lbnRzLlxuXHRcdFx0ICovXG5cdFx0XHR1cmw6XG5cdFx0XHRcdCcvL3tzfS57YmFzZX0ubWFwcy5jaXQuYXBpLmhlcmUuY29tL21hcHRpbGUvMi4xLycgK1xuXHRcdFx0XHQnbWFwdGlsZS97bWFwSUR9L3t2YXJpYW50fS97en0ve3h9L3t5fS8yNTYvcG5nOD8nICtcblx0XHRcdFx0J2FwcF9pZD17YXBwX2lkfSZhcHBfY29kZT17YXBwX2NvZGV9Jyxcblx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0YXR0cmlidXRpb246XG5cdFx0XHRcdFx0J01hcCAmY29weTsgMTk4Ny0yMDE0IDxhIGhyZWY9XCJodHRwOi8vZGV2ZWxvcGVyLmhlcmUuY29tXCI+SEVSRTwvYT4nLFxuXHRcdFx0XHRzdWJkb21haW5zOiAnMTIzNCcsXG5cdFx0XHRcdG1hcElEOiAnbmV3ZXN0Jyxcblx0XHRcdFx0J2FwcF9pZCc6ICc8aW5zZXJ0IHlvdXIgYXBwX2lkIGhlcmU+Jyxcblx0XHRcdFx0J2FwcF9jb2RlJzogJzxpbnNlcnQgeW91ciBhcHBfY29kZSBoZXJlPicsXG5cdFx0XHRcdGJhc2U6ICdiYXNlJyxcblx0XHRcdFx0dmFyaWFudDogJ25vcm1hbC5kYXknLFxuXHRcdFx0XHRtYXhab29tOiAyMFxuXHRcdFx0fSxcblx0XHRcdHZhcmlhbnRzOiB7XG5cdFx0XHRcdG5vcm1hbERheTogJ25vcm1hbC5kYXknLFxuXHRcdFx0XHRub3JtYWxEYXlDdXN0b206ICdub3JtYWwuZGF5LmN1c3RvbScsXG5cdFx0XHRcdG5vcm1hbERheUdyZXk6ICdub3JtYWwuZGF5LmdyZXknLFxuXHRcdFx0XHRub3JtYWxEYXlNb2JpbGU6ICdub3JtYWwuZGF5Lm1vYmlsZScsXG5cdFx0XHRcdG5vcm1hbERheUdyZXlNb2JpbGU6ICdub3JtYWwuZGF5LmdyZXkubW9iaWxlJyxcblx0XHRcdFx0bm9ybWFsRGF5VHJhbnNpdDogJ25vcm1hbC5kYXkudHJhbnNpdCcsXG5cdFx0XHRcdG5vcm1hbERheVRyYW5zaXRNb2JpbGU6ICdub3JtYWwuZGF5LnRyYW5zaXQubW9iaWxlJyxcblx0XHRcdFx0bm9ybWFsTmlnaHQ6ICdub3JtYWwubmlnaHQnLFxuXHRcdFx0XHRub3JtYWxOaWdodE1vYmlsZTogJ25vcm1hbC5uaWdodC5tb2JpbGUnLFxuXHRcdFx0XHRub3JtYWxOaWdodEdyZXk6ICdub3JtYWwubmlnaHQuZ3JleScsXG5cdFx0XHRcdG5vcm1hbE5pZ2h0R3JleU1vYmlsZTogJ25vcm1hbC5uaWdodC5ncmV5Lm1vYmlsZScsXG5cblx0XHRcdFx0Y2FybmF2RGF5R3JleTogJ2Nhcm5hdi5kYXkuZ3JleScsXG5cdFx0XHRcdGh5YnJpZERheToge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdGJhc2U6ICdhZXJpYWwnLFxuXHRcdFx0XHRcdFx0dmFyaWFudDogJ2h5YnJpZC5kYXknXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRoeWJyaWREYXlNb2JpbGU6IHtcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHRiYXNlOiAnYWVyaWFsJyxcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdoeWJyaWQuZGF5Lm1vYmlsZSdcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHBlZGVzdHJpYW5EYXk6ICdwZWRlc3RyaWFuLmRheScsXG5cdFx0XHRcdHBlZGVzdHJpYW5OaWdodDogJ3BlZGVzdHJpYW4ubmlnaHQnLFxuXHRcdFx0XHRzYXRlbGxpdGVEYXk6IHtcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHRiYXNlOiAnYWVyaWFsJyxcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdzYXRlbGxpdGUuZGF5J1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0dGVycmFpbkRheToge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdGJhc2U6ICdhZXJpYWwnLFxuXHRcdFx0XHRcdFx0dmFyaWFudDogJ3RlcnJhaW4uZGF5J1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0dGVycmFpbkRheU1vYmlsZToge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdGJhc2U6ICdhZXJpYWwnLFxuXHRcdFx0XHRcdFx0dmFyaWFudDogJ3RlcnJhaW4uZGF5Lm1vYmlsZSdcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9LFxuXHRcdEFjZXRhdGU6IHtcblx0XHRcdHVybDogJ2h0dHA6Ly9he3N9LmFjZXRhdGUuZ2VvaXEuY29tL3RpbGVzL3t2YXJpYW50fS97en0ve3h9L3t5fS5wbmcnLFxuXHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRhdHRyaWJ1dGlvbjpcblx0XHRcdFx0XHQnJmNvcHk7MjAxMiBFc3JpICYgU3RhbWVuLCBEYXRhIGZyb20gT1NNIGFuZCBOYXR1cmFsIEVhcnRoJyxcblx0XHRcdFx0c3ViZG9tYWluczogJzAxMjMnLFxuXHRcdFx0XHRtaW5ab29tOiAyLFxuXHRcdFx0XHRtYXhab29tOiAxOCxcblx0XHRcdFx0dmFyaWFudDogJ2FjZXRhdGUtYmFzZSdcblx0XHRcdH0sXG5cdFx0XHR2YXJpYW50czoge1xuXHRcdFx0XHRiYXNlbWFwOiAnYWNldGF0ZS1iYXNlJyxcblx0XHRcdFx0dGVycmFpbjogJ3RlcnJhaW4nLFxuXHRcdFx0XHRhbGw6ICdhY2V0YXRlLWhpbGxzaGFkaW5nJyxcblx0XHRcdFx0Zm9yZWdyb3VuZDogJ2FjZXRhdGUtZmcnLFxuXHRcdFx0XHRyb2FkczogJ2FjZXRhdGUtcm9hZHMnLFxuXHRcdFx0XHRsYWJlbHM6ICdhY2V0YXRlLWxhYmVscycsXG5cdFx0XHRcdGhpbGxzaGFkaW5nOiAnaGlsbHNoYWRpbmcnXG5cdFx0XHR9XG5cdFx0fSxcblx0XHRGcmVlTWFwU0s6IHtcblx0XHRcdHVybDogJ2h0dHA6Ly97c30uZnJlZW1hcC5zay9UL3t6fS97eH0ve3l9LmpwZWcnLFxuXHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRtaW5ab29tOiA4LFxuXHRcdFx0XHRtYXhab29tOiAxNixcblx0XHRcdFx0c3ViZG9tYWluczogWyd0MScsICd0MicsICd0MycsICd0NCddLFxuXHRcdFx0XHRhdHRyaWJ1dGlvbjpcblx0XHRcdFx0XHQne2F0dHJpYnV0aW9uLk9wZW5TdHJlZXRNYXB9LCB2aXp1YWxpemF0aW9uIENDLUJ5LVNBIDIuMCA8YSBocmVmPVwiaHR0cDovL2ZyZWVtYXAuc2tcIj5GcmVlbWFwLnNrPC9hPidcblx0XHRcdH1cblx0XHR9LFxuXHRcdE10Yk1hcDoge1xuXHRcdFx0dXJsOiAnaHR0cDovL3RpbGUubXRibWFwLmN6L210Ym1hcF90aWxlcy97en0ve3h9L3t5fS5wbmcnLFxuXHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRhdHRyaWJ1dGlvbjpcblx0XHRcdFx0XHQne2F0dHJpYnV0aW9uLk9wZW5TdHJlZXRNYXB9ICZhbXA7IFVTR1MnXG5cdFx0XHR9XG5cdFx0fSxcblx0XHRDYXJ0b0RCOiB7XG5cdFx0XHR1cmw6ICdodHRwOi8ve3N9LmJhc2VtYXBzLmNhcnRvY2RuLmNvbS97dmFyaWFudH0ve3p9L3t4fS97eX0ucG5nJyxcblx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0YXR0cmlidXRpb246ICd7YXR0cmlidXRpb24uT3BlblN0cmVldE1hcH0gJmNvcHk7IDxhIGhyZWY9XCJodHRwOi8vY2FydG9kYi5jb20vYXR0cmlidXRpb25zXCI+Q2FydG9EQjwvYT4nLFxuXHRcdFx0XHRzdWJkb21haW5zOiAnYWJjZCcsXG5cdFx0XHRcdG1heFpvb206IDE5LFxuXHRcdFx0XHR2YXJpYW50OiAnbGlnaHRfYWxsJ1xuXHRcdFx0fSxcblx0XHRcdHZhcmlhbnRzOiB7XG5cdFx0XHRcdFBvc2l0cm9uOiAnbGlnaHRfYWxsJyxcblx0XHRcdFx0UG9zaXRyb25Ob0xhYmVsczogJ2xpZ2h0X25vbGFiZWxzJyxcblx0XHRcdFx0RGFya01hdHRlcjogJ2RhcmtfYWxsJyxcblx0XHRcdFx0RGFya01hdHRlck5vTGFiZWxzOiAnZGFya19ub2xhYmVscydcblx0XHRcdH1cblx0XHR9LFxuXHRcdEhpa2VCaWtlOiB7XG5cdFx0XHR1cmw6ICdodHRwOi8ve3N9LnRpbGVzLndtZmxhYnMub3JnL3t2YXJpYW50fS97en0ve3h9L3t5fS5wbmcnLFxuXHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRtYXhab29tOiAxOSxcblx0XHRcdFx0YXR0cmlidXRpb246ICd7YXR0cmlidXRpb24uT3BlblN0cmVldE1hcH0nLFxuXHRcdFx0XHR2YXJpYW50OiAnaGlrZWJpa2UnXG5cdFx0XHR9LFxuXHRcdFx0dmFyaWFudHM6IHtcblx0XHRcdFx0SGlrZUJpa2U6IHt9LFxuXHRcdFx0XHRIaWxsU2hhZGluZzoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdG1heFpvb206IDE1LFxuXHRcdFx0XHRcdFx0dmFyaWFudDogJ2hpbGxzaGFkaW5nJ1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cdFx0QmFzZW1hcEFUOiB7XG5cdFx0XHR1cmw6ICcvL21hcHN7c30ud2llbi5ndi5hdC9iYXNlbWFwL3t2YXJpYW50fS9ub3JtYWwvZ29vZ2xlMzg1Ny97en0ve3l9L3t4fS57Zm9ybWF0fScsXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdG1heFpvb206IDE5LFxuXHRcdFx0XHRhdHRyaWJ1dGlvbjogJ0RhdGVucXVlbGxlOiA8YSBocmVmPVwid3d3LmJhc2VtYXAuYXRcIj5iYXNlbWFwLmF0PC9hPicsXG5cdFx0XHRcdHN1YmRvbWFpbnM6IFsnJywgJzEnLCAnMicsICczJywgJzQnXSxcblx0XHRcdFx0Zm9ybWF0OiAncG5nJyxcblx0XHRcdFx0Ym91bmRzOiBbWzQ2LjM1ODc3MCwgOC43ODIzNzldLCBbNDkuMDM3ODcyLCAxNy4xODk1MzJdXSxcblx0XHRcdFx0dmFyaWFudDogJ2dlb2xhbmRiYXNlbWFwJ1xuXHRcdFx0fSxcblx0XHRcdHZhcmlhbnRzOiB7XG5cdFx0XHRcdGJhc2VtYXA6ICdnZW9sYW5kYmFzZW1hcCcsXG5cdFx0XHRcdGdyYXU6ICdibWFwZ3JhdScsXG5cdFx0XHRcdG92ZXJsYXk6ICdibWFwb3ZlcmxheScsXG5cdFx0XHRcdGhpZ2hkcGk6IHtcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHR2YXJpYW50OiAnYm1hcGhpZHBpJyxcblx0XHRcdFx0XHRcdGZvcm1hdDogJ2pwZWcnXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRvcnRob2ZvdG86IHtcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHR2YXJpYW50OiAnYm1hcG9ydGhvZm90bzMwY20nLFxuXHRcdFx0XHRcdFx0Zm9ybWF0OiAnanBlZydcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9LFxuXHRcdE5BU0FHSUJTOiB7XG5cdFx0XHR1cmw6ICcvL21hcDEudmlzLmVhcnRoZGF0YS5uYXNhLmdvdi93bXRzLXdlYm1lcmMve3ZhcmlhbnR9L2RlZmF1bHQve3RpbWV9L3t0aWxlbWF0cml4c2V0fXttYXhab29tfS97en0ve3l9L3t4fS57Zm9ybWF0fScsXG5cdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdGF0dHJpYnV0aW9uOlxuXHRcdFx0XHRcdCdJbWFnZXJ5IHByb3ZpZGVkIGJ5IHNlcnZpY2VzIGZyb20gdGhlIEdsb2JhbCBJbWFnZXJ5IEJyb3dzZSBTZXJ2aWNlcyAoR0lCUyksIG9wZXJhdGVkIGJ5IHRoZSBOQVNBL0dTRkMvRWFydGggU2NpZW5jZSBEYXRhIGFuZCBJbmZvcm1hdGlvbiBTeXN0ZW0gJyArXG5cdFx0XHRcdFx0Jyg8YSBocmVmPVwiaHR0cHM6Ly9lYXJ0aGRhdGEubmFzYS5nb3ZcIj5FU0RJUzwvYT4pIHdpdGggZnVuZGluZyBwcm92aWRlZCBieSBOQVNBL0hRLicsXG5cdFx0XHRcdGJvdW5kczogW1stODUuMDUxMTI4Nzc3NiwgLTE3OS45OTk5OTk5NzVdLCBbODUuMDUxMTI4Nzc3NiwgMTc5Ljk5OTk5OTk3NV1dLFxuXHRcdFx0XHRtaW5ab29tOiAxLFxuXHRcdFx0XHRtYXhab29tOiA5LFxuXHRcdFx0XHRmb3JtYXQ6ICdqcGcnLFxuXHRcdFx0XHR0aW1lOiAnJyxcblx0XHRcdFx0dGlsZW1hdHJpeHNldDogJ0dvb2dsZU1hcHNDb21wYXRpYmxlX0xldmVsJ1xuXHRcdFx0fSxcblx0XHRcdHZhcmlhbnRzOiB7XG5cdFx0XHRcdE1vZGlzVGVycmFUcnVlQ29sb3JDUjogJ01PRElTX1RlcnJhX0NvcnJlY3RlZFJlZmxlY3RhbmNlX1RydWVDb2xvcicsXG5cdFx0XHRcdE1vZGlzVGVycmFCYW5kczM2N0NSOiAnTU9ESVNfVGVycmFfQ29ycmVjdGVkUmVmbGVjdGFuY2VfQmFuZHMzNjcnLFxuXHRcdFx0XHRWaWlyc0VhcnRoQXROaWdodDIwMTI6IHtcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHR2YXJpYW50OiAnVklJUlNfQ2l0eUxpZ2h0c18yMDEyJyxcblx0XHRcdFx0XHRcdG1heFpvb206IDhcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdE1vZGlzVGVycmFMU1REYXk6IHtcblx0XHRcdFx0XHRvcHRpb25zOiB7XG5cdFx0XHRcdFx0XHR2YXJpYW50OiAnTU9ESVNfVGVycmFfTGFuZF9TdXJmYWNlX1RlbXBfRGF5Jyxcblx0XHRcdFx0XHRcdGZvcm1hdDogJ3BuZycsXG5cdFx0XHRcdFx0XHRtYXhab29tOiA3LFxuXHRcdFx0XHRcdFx0b3BhY2l0eTogMC43NVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0TW9kaXNUZXJyYVNub3dDb3Zlcjoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdNT0RJU19UZXJyYV9Tbm93X0NvdmVyJyxcblx0XHRcdFx0XHRcdGZvcm1hdDogJ3BuZycsXG5cdFx0XHRcdFx0XHRtYXhab29tOiA4LFxuXHRcdFx0XHRcdFx0b3BhY2l0eTogMC43NVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0TW9kaXNUZXJyYUFPRDoge1xuXHRcdFx0XHRcdG9wdGlvbnM6IHtcblx0XHRcdFx0XHRcdHZhcmlhbnQ6ICdNT0RJU19UZXJyYV9BZXJvc29sJyxcblx0XHRcdFx0XHRcdGZvcm1hdDogJ3BuZycsXG5cdFx0XHRcdFx0XHRtYXhab29tOiA2LFxuXHRcdFx0XHRcdFx0b3BhY2l0eTogMC43NVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSxcblx0XHRcdFx0TW9kaXNUZXJyYUNobG9yb3BoeWxsOiB7XG5cdFx0XHRcdFx0b3B0aW9uczoge1xuXHRcdFx0XHRcdFx0dmFyaWFudDogJ01PRElTX1RlcnJhX0NobG9yb3BoeWxsX0EnLFxuXHRcdFx0XHRcdFx0Zm9ybWF0OiAncG5nJyxcblx0XHRcdFx0XHRcdG1heFpvb206IDcsXG5cdFx0XHRcdFx0XHRvcGFjaXR5OiAwLjc1XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9O1xuXG5cdEwudGlsZUxheWVyLnByb3ZpZGVyID0gZnVuY3Rpb24gKHByb3ZpZGVyLCBvcHRpb25zKSB7XG5cdFx0cmV0dXJuIG5ldyBMLlRpbGVMYXllci5Qcm92aWRlcihwcm92aWRlciwgb3B0aW9ucyk7XG5cdH07XG59KCkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbGVhZmxldC1wcm92aWRlcnMvbGVhZmxldC1wcm92aWRlcnMuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2xlYWZsZXQtcHJvdmlkZXJzL2xlYWZsZXQtcHJvdmlkZXJzLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/leaflet-providers/leaflet-providers.js\n");
/***/ }),
/***/ "./node_modules/leaflet-rotatedmarker/leaflet.rotatedMarker.js":
/***/ (function(module, exports) {
eval("(function() {\r\n // save these original methods before they are overwritten\r\n var proto_initIcon = L.Marker.prototype._initIcon;\r\n var proto_setPos = L.Marker.prototype._setPos;\r\n\r\n var oldIE = (L.DomUtil.TRANSFORM === 'msTransform');\r\n\r\n L.Marker.addInitHook(function () {\r\n var iconOptions = this.options.icon && this.options.icon.options;\r\n var iconAnchor = iconOptions && this.options.icon.options.iconAnchor;\r\n if (iconAnchor) {\r\n iconAnchor = (iconAnchor[0] + 'px ' + iconAnchor[1] + 'px');\r\n }\r\n this.options.rotationOrigin = this.options.rotationOrigin || iconAnchor || 'center bottom' ;\r\n this.options.rotationAngle = this.options.rotationAngle || 0;\r\n\r\n // Ensure marker keeps rotated during dragging\r\n this.on('drag', function(e) { e.target._applyRotation(); });\r\n });\r\n\r\n L.Marker.include({\r\n _initIcon: function() {\r\n proto_initIcon.call(this);\r\n },\r\n\r\n _setPos: function (pos) {\r\n proto_setPos.call(this, pos);\r\n this._applyRotation();\r\n },\r\n\r\n _applyRotation: function () {\r\n if(this.options.rotationAngle) {\r\n this._icon.style[L.DomUtil.TRANSFORM+'Origin'] = this.options.rotationOrigin;\r\n\r\n if(oldIE) {\r\n // for IE 9, use the 2D rotation\r\n this._icon.style[L.DomUtil.TRANSFORM] = 'rotate(' + this.options.rotationAngle + 'deg)';\r\n } else {\r\n // for modern browsers, prefer the 3D accelerated version\r\n this._icon.style[L.DomUtil.TRANSFORM] += ' rotateZ(' + this.options.rotationAngle + 'deg)';\r\n }\r\n }\r\n },\r\n\r\n setRotationAngle: function(angle) {\r\n this.options.rotationAngle = angle;\r\n this.update();\r\n return this;\r\n },\r\n\r\n setRotationOrigin: function(origin) {\r\n this.options.rotationOrigin = origin;\r\n this.update();\r\n return this;\r\n }\r\n });\r\n})();\r\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbGVhZmxldC1yb3RhdGVkbWFya2VyL2xlYWZsZXQucm90YXRlZE1hcmtlci5qcz85YjBlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxxQ0FBcUMsMkJBQTJCLEVBQUU7QUFDbEUsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsQ0FBQyIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9sZWFmbGV0LXJvdGF0ZWRtYXJrZXIvbGVhZmxldC5yb3RhdGVkTWFya2VyLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCkge1xyXG4gICAgLy8gc2F2ZSB0aGVzZSBvcmlnaW5hbCBtZXRob2RzIGJlZm9yZSB0aGV5IGFyZSBvdmVyd3JpdHRlblxyXG4gICAgdmFyIHByb3RvX2luaXRJY29uID0gTC5NYXJrZXIucHJvdG90eXBlLl9pbml0SWNvbjtcclxuICAgIHZhciBwcm90b19zZXRQb3MgPSBMLk1hcmtlci5wcm90b3R5cGUuX3NldFBvcztcclxuXHJcbiAgICB2YXIgb2xkSUUgPSAoTC5Eb21VdGlsLlRSQU5TRk9STSA9PT0gJ21zVHJhbnNmb3JtJyk7XHJcblxyXG4gICAgTC5NYXJrZXIuYWRkSW5pdEhvb2soZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBpY29uT3B0aW9ucyA9IHRoaXMub3B0aW9ucy5pY29uICYmIHRoaXMub3B0aW9ucy5pY29uLm9wdGlvbnM7XHJcbiAgICAgICAgdmFyIGljb25BbmNob3IgPSBpY29uT3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMuaWNvbi5vcHRpb25zLmljb25BbmNob3I7XHJcbiAgICAgICAgaWYgKGljb25BbmNob3IpIHtcclxuICAgICAgICAgICAgaWNvbkFuY2hvciA9IChpY29uQW5jaG9yWzBdICsgJ3B4ICcgKyBpY29uQW5jaG9yWzFdICsgJ3B4Jyk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub3B0aW9ucy5yb3RhdGlvbk9yaWdpbiA9IHRoaXMub3B0aW9ucy5yb3RhdGlvbk9yaWdpbiB8fCBpY29uQW5jaG9yIHx8ICdjZW50ZXIgYm90dG9tJyA7XHJcbiAgICAgICAgdGhpcy5vcHRpb25zLnJvdGF0aW9uQW5nbGUgPSB0aGlzLm9wdGlvbnMucm90YXRpb25BbmdsZSB8fCAwO1xyXG5cclxuICAgICAgICAvLyBFbnN1cmUgbWFya2VyIGtlZXBzIHJvdGF0ZWQgZHVyaW5nIGRyYWdnaW5nXHJcbiAgICAgICAgdGhpcy5vbignZHJhZycsIGZ1bmN0aW9uKGUpIHsgZS50YXJnZXQuX2FwcGx5Um90YXRpb24oKTsgfSk7XHJcbiAgICB9KTtcclxuXHJcbiAgICBMLk1hcmtlci5pbmNsdWRlKHtcclxuICAgICAgICBfaW5pdEljb246IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICBwcm90b19pbml0SWNvbi5jYWxsKHRoaXMpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9zZXRQb3M6IGZ1bmN0aW9uIChwb3MpIHtcclxuICAgICAgICAgICAgcHJvdG9fc2V0UG9zLmNhbGwodGhpcywgcG9zKTtcclxuICAgICAgICAgICAgdGhpcy5fYXBwbHlSb3RhdGlvbigpO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIF9hcHBseVJvdGF0aW9uOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmKHRoaXMub3B0aW9ucy5yb3RhdGlvbkFuZ2xlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9pY29uLnN0eWxlW0wuRG9tVXRpbC5UUkFOU0ZPUk0rJ09yaWdpbiddID0gdGhpcy5vcHRpb25zLnJvdGF0aW9uT3JpZ2luO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmKG9sZElFKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gZm9yIElFIDksIHVzZSB0aGUgMkQgcm90YXRpb25cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9pY29uLnN0eWxlW0wuRG9tVXRpbC5UUkFOU0ZPUk1dID0gJ3JvdGF0ZSgnICsgdGhpcy5vcHRpb25zLnJvdGF0aW9uQW5nbGUgKyAnZGVnKSc7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGZvciBtb2Rlcm4gYnJvd3NlcnMsIHByZWZlciB0aGUgM0QgYWNjZWxlcmF0ZWQgdmVyc2lvblxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2ljb24uc3R5bGVbTC5Eb21VdGlsLlRSQU5TRk9STV0gKz0gJyByb3RhdGVaKCcgKyB0aGlzLm9wdGlvbnMucm90YXRpb25BbmdsZSArICdkZWcpJztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHNldFJvdGF0aW9uQW5nbGU6IGZ1bmN0aW9uKGFuZ2xlKSB7XHJcbiAgICAgICAgICAgIHRoaXMub3B0aW9ucy5yb3RhdGlvbkFuZ2xlID0gYW5nbGU7XHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKCk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH0sXHJcblxyXG4gICAgICAgIHNldFJvdGF0aW9uT3JpZ2luOiBmdW5jdGlvbihvcmlnaW4pIHtcclxuICAgICAgICAgICAgdGhpcy5vcHRpb25zLnJvdGF0aW9uT3JpZ2luID0gb3JpZ2luO1xyXG4gICAgICAgICAgICB0aGlzLnVwZGF0ZSgpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcbiAgICB9KTtcclxufSkoKTtcclxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbGVhZmxldC1yb3RhdGVkbWFya2VyL2xlYWZsZXQucm90YXRlZE1hcmtlci5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvbGVhZmxldC1yb3RhdGVkbWFya2VyL2xlYWZsZXQucm90YXRlZE1hcmtlci5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/leaflet-rotatedmarker/leaflet.rotatedMarker.js\n");
/***/ }),
/***/ "./node_modules/leaflet/dist/leaflet-src.js":
/***/ (function(module, exports, __webpack_require__) {
eval("/* @preserve\n * Leaflet 1.5.1+build.2e3e0ff, a JS library for interactive maps. http://leafletjs.com\n * (c) 2010-2018 Vladimir Agafonkin, (c) 2010-2011 CloudMade\n */\n\n(function (global, factory) {\n\t true ? factory(exports) :\n\ttypeof define === 'function' && define.amd ? define(['exports'], factory) :\n\t(factory((global.L = {})));\n}(this, (function (exports) { 'use strict';\n\nvar version = \"1.5.1+build.2e3e0ffb\";\n\n/*\r\n * @namespace Util\r\n *\r\n * Various utility functions, used by Leaflet internally.\r\n */\r\n\r\nvar freeze = Object.freeze;\r\nObject.freeze = function (obj) { return obj; };\r\n\r\n// @function extend(dest: Object, src?: Object): Object\r\n// Merges the properties of the `src` object (or multiple objects) into `dest` object and returns the latter. Has an `L.extend` shortcut.\r\nfunction extend(dest) {\r\n\tvar i, j, len, src;\r\n\r\n\tfor (j = 1, len = arguments.length; j < len; j++) {\r\n\t\tsrc = arguments[j];\r\n\t\tfor (i in src) {\r\n\t\t\tdest[i] = src[i];\r\n\t\t}\r\n\t}\r\n\treturn dest;\r\n}\r\n\r\n// @function create(proto: Object, properties?: Object): Object\r\n// Compatibility polyfill for [Object.create](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/create)\r\nvar create = Object.create || (function () {\r\n\tfunction F() {}\r\n\treturn function (proto) {\r\n\t\tF.prototype = proto;\r\n\t\treturn new F();\r\n\t};\r\n})();\r\n\r\n// @function bind(fn: Function, …): Function\r\n// Returns a new function bound to the arguments passed, like [Function.prototype.bind](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).\r\n// Has a `L.bind()` shortcut.\r\nfunction bind(fn, obj) {\r\n\tvar slice = Array.prototype.slice;\r\n\r\n\tif (fn.bind) {\r\n\t\treturn fn.bind.apply(fn, slice.call(arguments, 1));\r\n\t}\r\n\r\n\tvar args = slice.call(arguments, 2);\r\n\r\n\treturn function () {\r\n\t\treturn fn.apply(obj, args.length ? args.concat(slice.call(arguments)) : arguments);\r\n\t};\r\n}\r\n\r\n// @property lastId: Number\r\n// Last unique ID used by [`stamp()`](#util-stamp)\r\nvar lastId = 0;\r\n\r\n// @function stamp(obj: Object): Number\r\n// Returns the unique ID of an object, assigning it one if it doesn't have it.\r\nfunction stamp(obj) {\r\n\t/*eslint-disable */\r\n\tobj._leaflet_id = obj._leaflet_id || ++lastId;\r\n\treturn obj._leaflet_id;\r\n\t/* eslint-enable */\r\n}\r\n\r\n// @function throttle(fn: Function, time: Number, context: Object): Function\r\n// Returns a function which executes function `fn` with the given scope `context`\r\n// (so that the `this` keyword refers to `context` inside `fn`'s code). The function\r\n// `fn` will be called no more than one time per given amount of `time`. The arguments\r\n// received by the bound function will be any arguments passed when binding the\r\n// function, followed by any arguments passed when invoking the bound function.\r\n// Has an `L.throttle` shortcut.\r\nfunction throttle(fn, time, context) {\r\n\tvar lock, args, wrapperFn, later;\r\n\r\n\tlater = function () {\r\n\t\t// reset lock and call if queued\r\n\t\tlock = false;\r\n\t\tif (args) {\r\n\t\t\twrapperFn.apply(context, args);\r\n\t\t\targs = false;\r\n\t\t}\r\n\t};\r\n\r\n\twrapperFn = function () {\r\n\t\tif (lock) {\r\n\t\t\t// called too soon, queue to call later\r\n\t\t\targs = arguments;\r\n\r\n\t\t} else {\r\n\t\t\t// call and lock until later\r\n\t\t\tfn.apply(context, arguments);\r\n\t\t\tsetTimeout(later, time);\r\n\t\t\tlock = true;\r\n\t\t}\r\n\t};\r\n\r\n\treturn wrapperFn;\r\n}\r\n\r\n// @function wrapNum(num: Number, range: Number[], includeMax?: Boolean): Number\r\n// Returns the number `num` modulo `range` in such a way so it lies within\r\n// `range[0]` and `range[1]`. The returned value will be always smaller than\r\n// `range[1]` unless `includeMax` is set to `true`.\r\nfunction wrapNum(x, range, includeMax) {\r\n\tvar max = range[1],\r\n\t min = range[0],\r\n\t d = max - min;\r\n\treturn x === max && includeMax ? x : ((x - min) % d + d) % d + min;\r\n}\r\n\r\n// @function falseFn(): Function\r\n// Returns a function which always returns `false`.\r\nfunction falseFn() { return false; }\r\n\r\n// @function formatNum(num: Number, digits?: Number): Number\r\n// Returns the number `num` rounded to `digits` decimals, or to 6 decimals by default.\r\nfunction formatNum(num, digits) {\r\n\tdigits = (digits === undefined ? 6 : digits);\r\n\treturn +(Math.round(num + ('e+' + digits)) + ('e-' + digits));\r\n}\r\n\r\n// @function trim(str: String): String\r\n// Compatibility polyfill for [String.prototype.trim](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/Trim)\r\nfunction trim(str) {\r\n\treturn str.trim ? str.trim() : str.replace(/^\\s+|\\s+$/g, '');\r\n}\r\n\r\n// @function splitWords(str: String): String[]\r\n// Trims and splits the string on whitespace and returns the array of parts.\r\nfunction splitWords(str) {\r\n\treturn trim(str).split(/\\s+/);\r\n}\r\n\r\n// @function setOptions(obj: Object, options: Object): Object\r\n// Merges the given properties to the `options` of the `obj` object, returning the resulting options. See `Class options`. Has an `L.setOptions` shortcut.\r\nfunction setOptions(obj, options) {\r\n\tif (!obj.hasOwnProperty('options')) {\r\n\t\tobj.options = obj.options ? create(obj.options) : {};\r\n\t}\r\n\tfor (var i in options) {\r\n\t\tobj.options[i] = options[i];\r\n\t}\r\n\treturn obj.options;\r\n}\r\n\r\n// @function getParamString(obj: Object, existingUrl?: String, uppercase?: Boolean): String\r\n// Converts an object into a parameter URL string, e.g. `{a: \"foo\", b: \"bar\"}`\r\n// translates to `'?a=foo&b=bar'`. If `existingUrl` is set, the parameters will\r\n// be appended at the end. If `uppercase` is `true`, the parameter names will\r\n// be uppercased (e.g. `'?A=foo&B=bar'`)\r\nfunction getParamString(obj, existingUrl, uppercase) {\r\n\tvar params = [];\r\n\tfor (var i in obj) {\r\n\t\tparams.push(encodeURIComponent(uppercase ? i.toUpperCase() : i) + '=' + encodeURIComponent(obj[i]));\r\n\t}\r\n\treturn ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');\r\n}\r\n\r\nvar templateRe = /\\{ *([\\w_-]+) *\\}/g;\r\n\r\n// @function template(str: String, data: Object): String\r\n// Simple templating facility, accepts a template string of the form `'Hello {a}, {b}'`\r\n// and a data object like `{a: 'foo', b: 'bar'}`, returns evaluated string\r\n// `('Hello foo, bar')`. You can also specify functions instead of strings for\r\n// data values — they will be evaluated passing `data` as an argument.\r\nfunction template(str, data) {\r\n\treturn str.replace(templateRe, function (str, key) {\r\n\t\tvar value = data[key];\r\n\r\n\t\tif (value === undefined) {\r\n\t\t\tthrow new Error('No value provided for variable ' + str);\r\n\r\n\t\t} else if (typeof value === 'function') {\r\n\t\t\tvalue = value(data);\r\n\t\t}\r\n\t\treturn value;\r\n\t});\r\n}\r\n\r\n// @function isArray(obj): Boolean\r\n// Compatibility polyfill for [Array.isArray](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray)\r\nvar isArray = Array.isArray || function (obj) {\r\n\treturn (Object.prototype.toString.call(obj) === '[object Array]');\r\n};\r\n\r\n// @function indexOf(array: Array, el: Object): Number\r\n// Compatibility polyfill for [Array.prototype.indexOf](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)\r\nfunction indexOf(array, el) {\r\n\tfor (var i = 0; i < array.length; i++) {\r\n\t\tif (array[i] === el) { return i; }\r\n\t}\r\n\treturn -1;\r\n}\r\n\r\n// @property emptyImageUrl: String\r\n// Data URI string containing a base64-encoded empty GIF image.\r\n// Used as a hack to free memory from unused images on WebKit-powered\r\n// mobile devices (by setting image `src` to this string).\r\nvar emptyImageUrl = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';\r\n\r\n// inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/\r\n\r\nfunction getPrefixed(name) {\r\n\treturn window['webkit' + name] || window['moz' + name] || window['ms' + name];\r\n}\r\n\r\nvar lastTime = 0;\r\n\r\n// fallback for IE 7-8\r\nfunction timeoutDefer(fn) {\r\n\tvar time = +new Date(),\r\n\t timeToCall = Math.max(0, 16 - (time - lastTime));\r\n\r\n\tlastTime = time + timeToCall;\r\n\treturn window.setTimeout(fn, timeToCall);\r\n}\r\n\r\nvar requestFn = window.requestAnimationFrame || getPrefixed('RequestAnimationFrame') || timeoutDefer;\r\nvar cancelFn = window.cancelAnimationFrame || getPrefixed('CancelAnimationFrame') ||\r\n\t\tgetPrefixed('CancelRequestAnimationFrame') || function (id) { window.clearTimeout(id); };\r\n\r\n// @function requestAnimFrame(fn: Function, context?: Object, immediate?: Boolean): Number\r\n// Schedules `fn` to be executed when the browser repaints. `fn` is bound to\r\n// `context` if given. When `immediate` is set, `fn` is called immediately if\r\n// the browser doesn't have native support for\r\n// [`window.requestAnimationFrame`](https://developer.mozilla.org/docs/Web/API/window/requestAnimationFrame),\r\n// otherwise it's delayed. Returns a request ID that can be used to cancel the request.\r\nfunction requestAnimFrame(fn, context, immediate) {\r\n\tif (immediate && requestFn === timeoutDefer) {\r\n\t\tfn.call(context);\r\n\t} else {\r\n\t\treturn requestFn.call(window, bind(fn, context));\r\n\t}\r\n}\r\n\r\n// @function cancelAnimFrame(id: Number): undefined\r\n// Cancels a previous `requestAnimFrame`. See also [window.cancelAnimationFrame](https://developer.mozilla.org/docs/Web/API/window/cancelAnimationFrame).\r\nfunction cancelAnimFrame(id) {\r\n\tif (id) {\r\n\t\tcancelFn.call(window, id);\r\n\t}\r\n}\r\n\n\nvar Util = (Object.freeze || Object)({\n\tfreeze: freeze,\n\textend: extend,\n\tcreate: create,\n\tbind: bind,\n\tlastId: lastId,\n\tstamp: stamp,\n\tthrottle: throttle,\n\twrapNum: wrapNum,\n\tfalseFn: falseFn,\n\tformatNum: formatNum,\n\ttrim: trim,\n\tsplitWords: splitWords,\n\tsetOptions: setOptions,\n\tgetParamString: getParamString,\n\ttemplate: template,\n\tisArray: isArray,\n\tindexOf: indexOf,\n\temptyImageUrl: emptyImageUrl,\n\trequestFn: requestFn,\n\tcancelFn: cancelFn,\n\trequestAnimFrame: requestAnimFrame,\n\tcancelAnimFrame: cancelAnimFrame\n});\n\n// @class Class\r\n// @aka L.Class\r\n\r\n// @section\r\n// @uninheritable\r\n\r\n// Thanks to John Resig and Dean Edwards for inspiration!\r\n\r\nfunction Class() {}\r\n\r\nClass.extend = function (props) {\r\n\r\n\t// @function extend(props: Object): Function\r\n\t// [Extends the current class](#class-inheritance) given the properties to be included.\r\n\t// Returns a Javascript function that is a class constructor (to be called with `new`).\r\n\tvar NewClass = function () {\r\n\r\n\t\t// call the constructor\r\n\t\tif (this.initialize) {\r\n\t\t\tthis.initialize.apply(this, arguments);\r\n\t\t}\r\n\r\n\t\t// call all constructor hooks\r\n\t\tthis.callInitHooks();\r\n\t};\r\n\r\n\tvar parentProto = NewClass.__super__ = this.prototype;\r\n\r\n\tvar proto = create(parentProto);\r\n\tproto.constructor = NewClass;\r\n\r\n\tNewClass.prototype = proto;\r\n\r\n\t// inherit parent's statics\r\n\tfor (var i in this) {\r\n\t\tif (this.hasOwnProperty(i) && i !== 'prototype' && i !== '__super__') {\r\n\t\t\tNewClass[i] = this[i];\r\n\t\t}\r\n\t}\r\n\r\n\t// mix static properties into the class\r\n\tif (props.statics) {\r\n\t\textend(NewClass, props.statics);\r\n\t\tdelete props.statics;\r\n\t}\r\n\r\n\t// mix includes into the prototype\r\n\tif (props.includes) {\r\n\t\tcheckDeprecatedMixinEvents(props.includes);\r\n\t\textend.apply(null, [proto].concat(props.includes));\r\n\t\tdelete props.includes;\r\n\t}\r\n\r\n\t// merge options\r\n\tif (proto.options) {\r\n\t\tprops.options = extend(create(proto.options), props.options);\r\n\t}\r\n\r\n\t// mix given properties into the prototype\r\n\textend(proto, props);\r\n\r\n\tproto._initHooks = [];\r\n\r\n\t// add method for calling all hooks\r\n\tproto.callInitHooks = function () {\r\n\r\n\t\tif (this._initHooksCalled) { return; }\r\n\r\n\t\tif (parentProto.callInitHooks) {\r\n\t\t\tparentProto.callInitHooks.call(this);\r\n\t\t}\r\n\r\n\t\tthis._initHooksCalled = true;\r\n\r\n\t\tfor (var i = 0, len = proto._initHooks.length; i < len; i++) {\r\n\t\t\tproto._initHooks[i].call(this);\r\n\t\t}\r\n\t};\r\n\r\n\treturn NewClass;\r\n};\r\n\r\n\r\n// @function include(properties: Object): this\r\n// [Includes a mixin](#class-includes) into the current class.\r\nClass.include = function (props) {\r\n\textend(this.prototype, props);\r\n\treturn this;\r\n};\r\n\r\n// @function mergeOptions(options: Object): this\r\n// [Merges `options`](#class-options) into the defaults of the class.\r\nClass.mergeOptions = function (options) {\r\n\textend(this.prototype.options, options);\r\n\treturn this;\r\n};\r\n\r\n// @function addInitHook(fn: Function): this\r\n// Adds a [constructor hook](#class-constructor-hooks) to the class.\r\nClass.addInitHook = function (fn) { // (Function) || (String, args...)\r\n\tvar args = Array.prototype.slice.call(arguments, 1);\r\n\r\n\tvar init = typeof fn === 'function' ? fn : function () {\r\n\t\tthis[fn].apply(this, args);\r\n\t};\r\n\r\n\tthis.prototype._initHooks = this.prototype._initHooks || [];\r\n\tthis.prototype._initHooks.push(init);\r\n\treturn this;\r\n};\r\n\r\nfunction checkDeprecatedMixinEvents(includes) {\r\n\tif (typeof L === 'undefined' || !L || !L.Mixin) { return; }\r\n\r\n\tincludes = isArray(includes) ? includes : [includes];\r\n\r\n\tfor (var i = 0; i < includes.length; i++) {\r\n\t\tif (includes[i] === L.Mixin.Events) {\r\n\t\t\tconsole.warn('Deprecated include of L.Mixin.Events: ' +\r\n\t\t\t\t'this property will be removed in future releases, ' +\r\n\t\t\t\t'please inherit from L.Evented instead.', new Error().stack);\r\n\t\t}\r\n\t}\r\n}\n\n/*\r\n * @class Evented\r\n * @aka L.Evented\r\n * @inherits Class\r\n *\r\n * A set of methods shared between event-powered classes (like `Map` and `Marker`). Generally, events allow you to execute some function when something happens with an object (e.g. the user clicks on the map, causing the map to fire `'click'` event).\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * map.on('click', function(e) {\r\n * \talert(e.latlng);\r\n * } );\r\n * ```\r\n *\r\n * Leaflet deals with event listeners by reference, so if you want to add a listener and then remove it, define it as a function:\r\n *\r\n * ```js\r\n * function onClick(e) { ... }\r\n *\r\n * map.on('click', onClick);\r\n * map.off('click', onClick);\r\n * ```\r\n */\r\n\r\nvar Events = {\r\n\t/* @method on(type: String, fn: Function, context?: Object): this\r\n\t * Adds a listener function (`fn`) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. `'click dblclick'`).\r\n\t *\r\n\t * @alternative\r\n\t * @method on(eventMap: Object): this\r\n\t * Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`\r\n\t */\r\n\ton: function (types, fn, context) {\r\n\r\n\t\t// types can be a map of types/handlers\r\n\t\tif (typeof types === 'object') {\r\n\t\t\tfor (var type in types) {\r\n\t\t\t\t// we don't process space-separated events here for performance;\r\n\t\t\t\t// it's a hot path since Layer uses the on(obj) syntax\r\n\t\t\t\tthis._on(type, types[type], fn);\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\t\t\t// types can be a string of space-separated words\r\n\t\t\ttypes = splitWords(types);\r\n\r\n\t\t\tfor (var i = 0, len = types.length; i < len; i++) {\r\n\t\t\t\tthis._on(types[i], fn, context);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t/* @method off(type: String, fn?: Function, context?: Object): this\r\n\t * Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to `on`, you must pass the same context to `off` in order to remove the listener.\r\n\t *\r\n\t * @alternative\r\n\t * @method off(eventMap: Object): this\r\n\t * Removes a set of type/listener pairs.\r\n\t *\r\n\t * @alternative\r\n\t * @method off: this\r\n\t * Removes all listeners to all events on the object. This includes implicitly attached events.\r\n\t */\r\n\toff: function (types, fn, context) {\r\n\r\n\t\tif (!types) {\r\n\t\t\t// clear all listeners if called without arguments\r\n\t\t\tdelete this._events;\r\n\r\n\t\t} else if (typeof types === 'object') {\r\n\t\t\tfor (var type in types) {\r\n\t\t\t\tthis._off(type, types[type], fn);\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\t\t\ttypes = splitWords(types);\r\n\r\n\t\t\tfor (var i = 0, len = types.length; i < len; i++) {\r\n\t\t\t\tthis._off(types[i], fn, context);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// attach listener (without syntactic sugar now)\r\n\t_on: function (type, fn, context) {\r\n\t\tthis._events = this._events || {};\r\n\r\n\t\t/* get/init listeners for type */\r\n\t\tvar typeListeners = this._events[type];\r\n\t\tif (!typeListeners) {\r\n\t\t\ttypeListeners = [];\r\n\t\t\tthis._events[type] = typeListeners;\r\n\t\t}\r\n\r\n\t\tif (context === this) {\r\n\t\t\t// Less memory footprint.\r\n\t\t\tcontext = undefined;\r\n\t\t}\r\n\t\tvar newListener = {fn: fn, ctx: context},\r\n\t\t listeners = typeListeners;\r\n\r\n\t\t// check if fn already there\r\n\t\tfor (var i = 0, len = listeners.length; i < len; i++) {\r\n\t\t\tif (listeners[i].fn === fn && listeners[i].ctx === context) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlisteners.push(newListener);\r\n\t},\r\n\r\n\t_off: function (type, fn, context) {\r\n\t\tvar listeners,\r\n\t\t i,\r\n\t\t len;\r\n\r\n\t\tif (!this._events) { return; }\r\n\r\n\t\tlisteners = this._events[type];\r\n\r\n\t\tif (!listeners) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!fn) {\r\n\t\t\t// Set all removed listeners to noop so they are not called if remove happens in fire\r\n\t\t\tfor (i = 0, len = listeners.length; i < len; i++) {\r\n\t\t\t\tlisteners[i].fn = falseFn;\r\n\t\t\t}\r\n\t\t\t// clear all listeners for a type if function isn't specified\r\n\t\t\tdelete this._events[type];\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (context === this) {\r\n\t\t\tcontext = undefined;\r\n\t\t}\r\n\r\n\t\tif (listeners) {\r\n\r\n\t\t\t// find fn and remove it\r\n\t\t\tfor (i = 0, len = listeners.length; i < len; i++) {\r\n\t\t\t\tvar l = listeners[i];\r\n\t\t\t\tif (l.ctx !== context) { continue; }\r\n\t\t\t\tif (l.fn === fn) {\r\n\r\n\t\t\t\t\t// set the removed listener to noop so that's not called if remove happens in fire\r\n\t\t\t\t\tl.fn = falseFn;\r\n\r\n\t\t\t\t\tif (this._firingCount) {\r\n\t\t\t\t\t\t/* copy array in case events are being fired */\r\n\t\t\t\t\t\tthis._events[type] = listeners = listeners.slice();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tlisteners.splice(i, 1);\r\n\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t// @method fire(type: String, data?: Object, propagate?: Boolean): this\r\n\t// Fires an event of the specified type. You can optionally provide an data\r\n\t// object — the first argument of the listener function will contain its\r\n\t// properties. The event can optionally be propagated to event parents.\r\n\tfire: function (type, data, propagate) {\r\n\t\tif (!this.listens(type, propagate)) { return this; }\r\n\r\n\t\tvar event = extend({}, data, {\r\n\t\t\ttype: type,\r\n\t\t\ttarget: this,\r\n\t\t\tsourceTarget: data && data.sourceTarget || this\r\n\t\t});\r\n\r\n\t\tif (this._events) {\r\n\t\t\tvar listeners = this._events[type];\r\n\r\n\t\t\tif (listeners) {\r\n\t\t\t\tthis._firingCount = (this._firingCount + 1) || 1;\r\n\t\t\t\tfor (var i = 0, len = listeners.length; i < len; i++) {\r\n\t\t\t\t\tvar l = listeners[i];\r\n\t\t\t\t\tl.fn.call(l.ctx || this, event);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis._firingCount--;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (propagate) {\r\n\t\t\t// propagate the event to parents (set with addEventParent)\r\n\t\t\tthis._propagateEvent(event);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method listens(type: String): Boolean\r\n\t// Returns `true` if a particular event type has any listeners attached to it.\r\n\tlistens: function (type, propagate) {\r\n\t\tvar listeners = this._events && this._events[type];\r\n\t\tif (listeners && listeners.length) { return true; }\r\n\r\n\t\tif (propagate) {\r\n\t\t\t// also check parents for listeners if event propagates\r\n\t\t\tfor (var id in this._eventParents) {\r\n\t\t\t\tif (this._eventParents[id].listens(type, propagate)) { return true; }\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t},\r\n\r\n\t// @method once(…): this\r\n\t// Behaves as [`on(…)`](#evented-on), except the listener will only get fired once and then removed.\r\n\tonce: function (types, fn, context) {\r\n\r\n\t\tif (typeof types === 'object') {\r\n\t\t\tfor (var type in types) {\r\n\t\t\t\tthis.once(type, types[type], fn);\r\n\t\t\t}\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tvar handler = bind(function () {\r\n\t\t\tthis\r\n\t\t\t .off(types, fn, context)\r\n\t\t\t .off(types, handler, context);\r\n\t\t}, this);\r\n\r\n\t\t// add a listener that's executed once and removed after that\r\n\t\treturn this\r\n\t\t .on(types, fn, context)\r\n\t\t .on(types, handler, context);\r\n\t},\r\n\r\n\t// @method addEventParent(obj: Evented): this\r\n\t// Adds an event parent - an `Evented` that will receive propagated events\r\n\taddEventParent: function (obj) {\r\n\t\tthis._eventParents = this._eventParents || {};\r\n\t\tthis._eventParents[stamp(obj)] = obj;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method removeEventParent(obj: Evented): this\r\n\t// Removes an event parent, so it will stop receiving propagated events\r\n\tremoveEventParent: function (obj) {\r\n\t\tif (this._eventParents) {\r\n\t\t\tdelete this._eventParents[stamp(obj)];\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_propagateEvent: function (e) {\r\n\t\tfor (var id in this._eventParents) {\r\n\t\t\tthis._eventParents[id].fire(e.type, extend({\r\n\t\t\t\tlayer: e.target,\r\n\t\t\t\tpropagatedFrom: e.target\r\n\t\t\t}, e), true);\r\n\t\t}\r\n\t}\r\n};\r\n\r\n// aliases; we should ditch those eventually\r\n\r\n// @method addEventListener(…): this\r\n// Alias to [`on(…)`](#evented-on)\r\nEvents.addEventListener = Events.on;\r\n\r\n// @method removeEventListener(…): this\r\n// Alias to [`off(…)`](#evented-off)\r\n\r\n// @method clearAllEventListeners(…): this\r\n// Alias to [`off()`](#evented-off)\r\nEvents.removeEventListener = Events.clearAllEventListeners = Events.off;\r\n\r\n// @method addOneTimeEventListener(…): this\r\n// Alias to [`once(…)`](#evented-once)\r\nEvents.addOneTimeEventListener = Events.once;\r\n\r\n// @method fireEvent(…): this\r\n// Alias to [`fire(…)`](#evented-fire)\r\nEvents.fireEvent = Events.fire;\r\n\r\n// @method hasEventListeners(…): Boolean\r\n// Alias to [`listens(…)`](#evented-listens)\r\nEvents.hasEventListeners = Events.listens;\r\n\r\nvar Evented = Class.extend(Events);\n\n/*\r\n * @class Point\r\n * @aka L.Point\r\n *\r\n * Represents a point with `x` and `y` coordinates in pixels.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var point = L.point(200, 300);\r\n * ```\r\n *\r\n * All Leaflet methods and options that accept `Point` objects also accept them in a simple Array form (unless noted otherwise), so these lines are equivalent:\r\n *\r\n * ```js\r\n * map.panBy([200, 300]);\r\n * map.panBy(L.point(200, 300));\r\n * ```\r\n *\r\n * Note that `Point` does not inherit from Leafet's `Class` object,\r\n * which means new classes can't inherit from it, and new methods\r\n * can't be added to it with the `include` function.\r\n */\r\n\r\nfunction Point(x, y, round) {\r\n\t// @property x: Number; The `x` coordinate of the point\r\n\tthis.x = (round ? Math.round(x) : x);\r\n\t// @property y: Number; The `y` coordinate of the point\r\n\tthis.y = (round ? Math.round(y) : y);\r\n}\r\n\r\nvar trunc = Math.trunc || function (v) {\r\n\treturn v > 0 ? Math.floor(v) : Math.ceil(v);\r\n};\r\n\r\nPoint.prototype = {\r\n\r\n\t// @method clone(): Point\r\n\t// Returns a copy of the current point.\r\n\tclone: function () {\r\n\t\treturn new Point(this.x, this.y);\r\n\t},\r\n\r\n\t// @method add(otherPoint: Point): Point\r\n\t// Returns the result of addition of the current and the given points.\r\n\tadd: function (point) {\r\n\t\t// non-destructive, returns a new point\r\n\t\treturn this.clone()._add(toPoint(point));\r\n\t},\r\n\r\n\t_add: function (point) {\r\n\t\t// destructive, used directly for performance in situations where it's safe to modify existing point\r\n\t\tthis.x += point.x;\r\n\t\tthis.y += point.y;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method subtract(otherPoint: Point): Point\r\n\t// Returns the result of subtraction of the given point from the current.\r\n\tsubtract: function (point) {\r\n\t\treturn this.clone()._subtract(toPoint(point));\r\n\t},\r\n\r\n\t_subtract: function (point) {\r\n\t\tthis.x -= point.x;\r\n\t\tthis.y -= point.y;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method divideBy(num: Number): Point\r\n\t// Returns the result of division of the current point by the given number.\r\n\tdivideBy: function (num) {\r\n\t\treturn this.clone()._divideBy(num);\r\n\t},\r\n\r\n\t_divideBy: function (num) {\r\n\t\tthis.x /= num;\r\n\t\tthis.y /= num;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method multiplyBy(num: Number): Point\r\n\t// Returns the result of multiplication of the current point by the given number.\r\n\tmultiplyBy: function (num) {\r\n\t\treturn this.clone()._multiplyBy(num);\r\n\t},\r\n\r\n\t_multiplyBy: function (num) {\r\n\t\tthis.x *= num;\r\n\t\tthis.y *= num;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method scaleBy(scale: Point): Point\r\n\t// Multiply each coordinate of the current point by each coordinate of\r\n\t// `scale`. In linear algebra terms, multiply the point by the\r\n\t// [scaling matrix](https://en.wikipedia.org/wiki/Scaling_%28geometry%29#Matrix_representation)\r\n\t// defined by `scale`.\r\n\tscaleBy: function (point) {\r\n\t\treturn new Point(this.x * point.x, this.y * point.y);\r\n\t},\r\n\r\n\t// @method unscaleBy(scale: Point): Point\r\n\t// Inverse of `scaleBy`. Divide each coordinate of the current point by\r\n\t// each coordinate of `scale`.\r\n\tunscaleBy: function (point) {\r\n\t\treturn new Point(this.x / point.x, this.y / point.y);\r\n\t},\r\n\r\n\t// @method round(): Point\r\n\t// Returns a copy of the current point with rounded coordinates.\r\n\tround: function () {\r\n\t\treturn this.clone()._round();\r\n\t},\r\n\r\n\t_round: function () {\r\n\t\tthis.x = Math.round(this.x);\r\n\t\tthis.y = Math.round(this.y);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method floor(): Point\r\n\t// Returns a copy of the current point with floored coordinates (rounded down).\r\n\tfloor: function () {\r\n\t\treturn this.clone()._floor();\r\n\t},\r\n\r\n\t_floor: function () {\r\n\t\tthis.x = Math.floor(this.x);\r\n\t\tthis.y = Math.floor(this.y);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method ceil(): Point\r\n\t// Returns a copy of the current point with ceiled coordinates (rounded up).\r\n\tceil: function () {\r\n\t\treturn this.clone()._ceil();\r\n\t},\r\n\r\n\t_ceil: function () {\r\n\t\tthis.x = Math.ceil(this.x);\r\n\t\tthis.y = Math.ceil(this.y);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method trunc(): Point\r\n\t// Returns a copy of the current point with truncated coordinates (rounded towards zero).\r\n\ttrunc: function () {\r\n\t\treturn this.clone()._trunc();\r\n\t},\r\n\r\n\t_trunc: function () {\r\n\t\tthis.x = trunc(this.x);\r\n\t\tthis.y = trunc(this.y);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method distanceTo(otherPoint: Point): Number\r\n\t// Returns the cartesian distance between the current and the given points.\r\n\tdistanceTo: function (point) {\r\n\t\tpoint = toPoint(point);\r\n\r\n\t\tvar x = point.x - this.x,\r\n\t\t y = point.y - this.y;\r\n\r\n\t\treturn Math.sqrt(x * x + y * y);\r\n\t},\r\n\r\n\t// @method equals(otherPoint: Point): Boolean\r\n\t// Returns `true` if the given point has the same coordinates.\r\n\tequals: function (point) {\r\n\t\tpoint = toPoint(point);\r\n\r\n\t\treturn point.x === this.x &&\r\n\t\t point.y === this.y;\r\n\t},\r\n\r\n\t// @method contains(otherPoint: Point): Boolean\r\n\t// Returns `true` if both coordinates of the given point are less than the corresponding current point coordinates (in absolute values).\r\n\tcontains: function (point) {\r\n\t\tpoint = toPoint(point);\r\n\r\n\t\treturn Math.abs(point.x) <= Math.abs(this.x) &&\r\n\t\t Math.abs(point.y) <= Math.abs(this.y);\r\n\t},\r\n\r\n\t// @method toString(): String\r\n\t// Returns a string representation of the point for debugging purposes.\r\n\ttoString: function () {\r\n\t\treturn 'Point(' +\r\n\t\t formatNum(this.x) + ', ' +\r\n\t\t formatNum(this.y) + ')';\r\n\t}\r\n};\r\n\r\n// @factory L.point(x: Number, y: Number, round?: Boolean)\r\n// Creates a Point object with the given `x` and `y` coordinates. If optional `round` is set to true, rounds the `x` and `y` values.\r\n\r\n// @alternative\r\n// @factory L.point(coords: Number[])\r\n// Expects an array of the form `[x, y]` instead.\r\n\r\n// @alternative\r\n// @factory L.point(coords: Object)\r\n// Expects a plain object of the form `{x: Number, y: Number}` instead.\r\nfunction toPoint(x, y, round) {\r\n\tif (x instanceof Point) {\r\n\t\treturn x;\r\n\t}\r\n\tif (isArray(x)) {\r\n\t\treturn new Point(x[0], x[1]);\r\n\t}\r\n\tif (x === undefined || x === null) {\r\n\t\treturn x;\r\n\t}\r\n\tif (typeof x === 'object' && 'x' in x && 'y' in x) {\r\n\t\treturn new Point(x.x, x.y);\r\n\t}\r\n\treturn new Point(x, y, round);\r\n}\n\n/*\r\n * @class Bounds\r\n * @aka L.Bounds\r\n *\r\n * Represents a rectangular area in pixel coordinates.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var p1 = L.point(10, 10),\r\n * p2 = L.point(40, 60),\r\n * bounds = L.bounds(p1, p2);\r\n * ```\r\n *\r\n * All Leaflet methods that accept `Bounds` objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:\r\n *\r\n * ```js\r\n * otherBounds.intersects([[10, 10], [40, 60]]);\r\n * ```\r\n *\r\n * Note that `Bounds` does not inherit from Leafet's `Class` object,\r\n * which means new classes can't inherit from it, and new methods\r\n * can't be added to it with the `include` function.\r\n */\r\n\r\nfunction Bounds(a, b) {\r\n\tif (!a) { return; }\r\n\r\n\tvar points = b ? [a, b] : a;\r\n\r\n\tfor (var i = 0, len = points.length; i < len; i++) {\r\n\t\tthis.extend(points[i]);\r\n\t}\r\n}\r\n\r\nBounds.prototype = {\r\n\t// @method extend(point: Point): this\r\n\t// Extends the bounds to contain the given point.\r\n\textend: function (point) { // (Point)\r\n\t\tpoint = toPoint(point);\r\n\r\n\t\t// @property min: Point\r\n\t\t// The top left corner of the rectangle.\r\n\t\t// @property max: Point\r\n\t\t// The bottom right corner of the rectangle.\r\n\t\tif (!this.min && !this.max) {\r\n\t\t\tthis.min = point.clone();\r\n\t\t\tthis.max = point.clone();\r\n\t\t} else {\r\n\t\t\tthis.min.x = Math.min(point.x, this.min.x);\r\n\t\t\tthis.max.x = Math.max(point.x, this.max.x);\r\n\t\t\tthis.min.y = Math.min(point.y, this.min.y);\r\n\t\t\tthis.max.y = Math.max(point.y, this.max.y);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getCenter(round?: Boolean): Point\r\n\t// Returns the center point of the bounds.\r\n\tgetCenter: function (round) {\r\n\t\treturn new Point(\r\n\t\t (this.min.x + this.max.x) / 2,\r\n\t\t (this.min.y + this.max.y) / 2, round);\r\n\t},\r\n\r\n\t// @method getBottomLeft(): Point\r\n\t// Returns the bottom-left point of the bounds.\r\n\tgetBottomLeft: function () {\r\n\t\treturn new Point(this.min.x, this.max.y);\r\n\t},\r\n\r\n\t// @method getTopRight(): Point\r\n\t// Returns the top-right point of the bounds.\r\n\tgetTopRight: function () { // -> Point\r\n\t\treturn new Point(this.max.x, this.min.y);\r\n\t},\r\n\r\n\t// @method getTopLeft(): Point\r\n\t// Returns the top-left point of the bounds (i.e. [`this.min`](#bounds-min)).\r\n\tgetTopLeft: function () {\r\n\t\treturn this.min; // left, top\r\n\t},\r\n\r\n\t// @method getBottomRight(): Point\r\n\t// Returns the bottom-right point of the bounds (i.e. [`this.max`](#bounds-max)).\r\n\tgetBottomRight: function () {\r\n\t\treturn this.max; // right, bottom\r\n\t},\r\n\r\n\t// @method getSize(): Point\r\n\t// Returns the size of the given bounds\r\n\tgetSize: function () {\r\n\t\treturn this.max.subtract(this.min);\r\n\t},\r\n\r\n\t// @method contains(otherBounds: Bounds): Boolean\r\n\t// Returns `true` if the rectangle contains the given one.\r\n\t// @alternative\r\n\t// @method contains(point: Point): Boolean\r\n\t// Returns `true` if the rectangle contains the given point.\r\n\tcontains: function (obj) {\r\n\t\tvar min, max;\r\n\r\n\t\tif (typeof obj[0] === 'number' || obj instanceof Point) {\r\n\t\t\tobj = toPoint(obj);\r\n\t\t} else {\r\n\t\t\tobj = toBounds(obj);\r\n\t\t}\r\n\r\n\t\tif (obj instanceof Bounds) {\r\n\t\t\tmin = obj.min;\r\n\t\t\tmax = obj.max;\r\n\t\t} else {\r\n\t\t\tmin = max = obj;\r\n\t\t}\r\n\r\n\t\treturn (min.x >= this.min.x) &&\r\n\t\t (max.x <= this.max.x) &&\r\n\t\t (min.y >= this.min.y) &&\r\n\t\t (max.y <= this.max.y);\r\n\t},\r\n\r\n\t// @method intersects(otherBounds: Bounds): Boolean\r\n\t// Returns `true` if the rectangle intersects the given bounds. Two bounds\r\n\t// intersect if they have at least one point in common.\r\n\tintersects: function (bounds) { // (Bounds) -> Boolean\r\n\t\tbounds = toBounds(bounds);\r\n\r\n\t\tvar min = this.min,\r\n\t\t max = this.max,\r\n\t\t min2 = bounds.min,\r\n\t\t max2 = bounds.max,\r\n\t\t xIntersects = (max2.x >= min.x) && (min2.x <= max.x),\r\n\t\t yIntersects = (max2.y >= min.y) && (min2.y <= max.y);\r\n\r\n\t\treturn xIntersects && yIntersects;\r\n\t},\r\n\r\n\t// @method overlaps(otherBounds: Bounds): Boolean\r\n\t// Returns `true` if the rectangle overlaps the given bounds. Two bounds\r\n\t// overlap if their intersection is an area.\r\n\toverlaps: function (bounds) { // (Bounds) -> Boolean\r\n\t\tbounds = toBounds(bounds);\r\n\r\n\t\tvar min = this.min,\r\n\t\t max = this.max,\r\n\t\t min2 = bounds.min,\r\n\t\t max2 = bounds.max,\r\n\t\t xOverlaps = (max2.x > min.x) && (min2.x < max.x),\r\n\t\t yOverlaps = (max2.y > min.y) && (min2.y < max.y);\r\n\r\n\t\treturn xOverlaps && yOverlaps;\r\n\t},\r\n\r\n\tisValid: function () {\r\n\t\treturn !!(this.min && this.max);\r\n\t}\r\n};\r\n\r\n\r\n// @factory L.bounds(corner1: Point, corner2: Point)\r\n// Creates a Bounds object from two corners coordinate pairs.\r\n// @alternative\r\n// @factory L.bounds(points: Point[])\r\n// Creates a Bounds object from the given array of points.\r\nfunction toBounds(a, b) {\r\n\tif (!a || a instanceof Bounds) {\r\n\t\treturn a;\r\n\t}\r\n\treturn new Bounds(a, b);\r\n}\n\n/*\r\n * @class LatLngBounds\r\n * @aka L.LatLngBounds\r\n *\r\n * Represents a rectangular geographical area on a map.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var corner1 = L.latLng(40.712, -74.227),\r\n * corner2 = L.latLng(40.774, -74.125),\r\n * bounds = L.latLngBounds(corner1, corner2);\r\n * ```\r\n *\r\n * All Leaflet methods that accept LatLngBounds objects also accept them in a simple Array form (unless noted otherwise), so the bounds example above can be passed like this:\r\n *\r\n * ```js\r\n * map.fitBounds([\r\n * \t[40.712, -74.227],\r\n * \t[40.774, -74.125]\r\n * ]);\r\n * ```\r\n *\r\n * Caution: if the area crosses the antimeridian (often confused with the International Date Line), you must specify corners _outside_ the [-180, 180] degrees longitude range.\r\n *\r\n * Note that `LatLngBounds` does not inherit from Leafet's `Class` object,\r\n * which means new classes can't inherit from it, and new methods\r\n * can't be added to it with the `include` function.\r\n */\r\n\r\nfunction LatLngBounds(corner1, corner2) { // (LatLng, LatLng) or (LatLng[])\r\n\tif (!corner1) { return; }\r\n\r\n\tvar latlngs = corner2 ? [corner1, corner2] : corner1;\r\n\r\n\tfor (var i = 0, len = latlngs.length; i < len; i++) {\r\n\t\tthis.extend(latlngs[i]);\r\n\t}\r\n}\r\n\r\nLatLngBounds.prototype = {\r\n\r\n\t// @method extend(latlng: LatLng): this\r\n\t// Extend the bounds to contain the given point\r\n\r\n\t// @alternative\r\n\t// @method extend(otherBounds: LatLngBounds): this\r\n\t// Extend the bounds to contain the given bounds\r\n\textend: function (obj) {\r\n\t\tvar sw = this._southWest,\r\n\t\t ne = this._northEast,\r\n\t\t sw2, ne2;\r\n\r\n\t\tif (obj instanceof LatLng) {\r\n\t\t\tsw2 = obj;\r\n\t\t\tne2 = obj;\r\n\r\n\t\t} else if (obj instanceof LatLngBounds) {\r\n\t\t\tsw2 = obj._southWest;\r\n\t\t\tne2 = obj._northEast;\r\n\r\n\t\t\tif (!sw2 || !ne2) { return this; }\r\n\r\n\t\t} else {\r\n\t\t\treturn obj ? this.extend(toLatLng(obj) || toLatLngBounds(obj)) : this;\r\n\t\t}\r\n\r\n\t\tif (!sw && !ne) {\r\n\t\t\tthis._southWest = new LatLng(sw2.lat, sw2.lng);\r\n\t\t\tthis._northEast = new LatLng(ne2.lat, ne2.lng);\r\n\t\t} else {\r\n\t\t\tsw.lat = Math.min(sw2.lat, sw.lat);\r\n\t\t\tsw.lng = Math.min(sw2.lng, sw.lng);\r\n\t\t\tne.lat = Math.max(ne2.lat, ne.lat);\r\n\t\t\tne.lng = Math.max(ne2.lng, ne.lng);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method pad(bufferRatio: Number): LatLngBounds\r\n\t// Returns bounds created by extending or retracting the current bounds by a given ratio in each direction.\r\n\t// For example, a ratio of 0.5 extends the bounds by 50% in each direction.\r\n\t// Negative values will retract the bounds.\r\n\tpad: function (bufferRatio) {\r\n\t\tvar sw = this._southWest,\r\n\t\t ne = this._northEast,\r\n\t\t heightBuffer = Math.abs(sw.lat - ne.lat) * bufferRatio,\r\n\t\t widthBuffer = Math.abs(sw.lng - ne.lng) * bufferRatio;\r\n\r\n\t\treturn new LatLngBounds(\r\n\t\t new LatLng(sw.lat - heightBuffer, sw.lng - widthBuffer),\r\n\t\t new LatLng(ne.lat + heightBuffer, ne.lng + widthBuffer));\r\n\t},\r\n\r\n\t// @method getCenter(): LatLng\r\n\t// Returns the center point of the bounds.\r\n\tgetCenter: function () {\r\n\t\treturn new LatLng(\r\n\t\t (this._southWest.lat + this._northEast.lat) / 2,\r\n\t\t (this._southWest.lng + this._northEast.lng) / 2);\r\n\t},\r\n\r\n\t// @method getSouthWest(): LatLng\r\n\t// Returns the south-west point of the bounds.\r\n\tgetSouthWest: function () {\r\n\t\treturn this._southWest;\r\n\t},\r\n\r\n\t// @method getNorthEast(): LatLng\r\n\t// Returns the north-east point of the bounds.\r\n\tgetNorthEast: function () {\r\n\t\treturn this._northEast;\r\n\t},\r\n\r\n\t// @method getNorthWest(): LatLng\r\n\t// Returns the north-west point of the bounds.\r\n\tgetNorthWest: function () {\r\n\t\treturn new LatLng(this.getNorth(), this.getWest());\r\n\t},\r\n\r\n\t// @method getSouthEast(): LatLng\r\n\t// Returns the south-east point of the bounds.\r\n\tgetSouthEast: function () {\r\n\t\treturn new LatLng(this.getSouth(), this.getEast());\r\n\t},\r\n\r\n\t// @method getWest(): Number\r\n\t// Returns the west longitude of the bounds\r\n\tgetWest: function () {\r\n\t\treturn this._southWest.lng;\r\n\t},\r\n\r\n\t// @method getSouth(): Number\r\n\t// Returns the south latitude of the bounds\r\n\tgetSouth: function () {\r\n\t\treturn this._southWest.lat;\r\n\t},\r\n\r\n\t// @method getEast(): Number\r\n\t// Returns the east longitude of the bounds\r\n\tgetEast: function () {\r\n\t\treturn this._northEast.lng;\r\n\t},\r\n\r\n\t// @method getNorth(): Number\r\n\t// Returns the north latitude of the bounds\r\n\tgetNorth: function () {\r\n\t\treturn this._northEast.lat;\r\n\t},\r\n\r\n\t// @method contains(otherBounds: LatLngBounds): Boolean\r\n\t// Returns `true` if the rectangle contains the given one.\r\n\r\n\t// @alternative\r\n\t// @method contains (latlng: LatLng): Boolean\r\n\t// Returns `true` if the rectangle contains the given point.\r\n\tcontains: function (obj) { // (LatLngBounds) or (LatLng) -> Boolean\r\n\t\tif (typeof obj[0] === 'number' || obj instanceof LatLng || 'lat' in obj) {\r\n\t\t\tobj = toLatLng(obj);\r\n\t\t} else {\r\n\t\t\tobj = toLatLngBounds(obj);\r\n\t\t}\r\n\r\n\t\tvar sw = this._southWest,\r\n\t\t ne = this._northEast,\r\n\t\t sw2, ne2;\r\n\r\n\t\tif (obj instanceof LatLngBounds) {\r\n\t\t\tsw2 = obj.getSouthWest();\r\n\t\t\tne2 = obj.getNorthEast();\r\n\t\t} else {\r\n\t\t\tsw2 = ne2 = obj;\r\n\t\t}\r\n\r\n\t\treturn (sw2.lat >= sw.lat) && (ne2.lat <= ne.lat) &&\r\n\t\t (sw2.lng >= sw.lng) && (ne2.lng <= ne.lng);\r\n\t},\r\n\r\n\t// @method intersects(otherBounds: LatLngBounds): Boolean\r\n\t// Returns `true` if the rectangle intersects the given bounds. Two bounds intersect if they have at least one point in common.\r\n\tintersects: function (bounds) {\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\r\n\t\tvar sw = this._southWest,\r\n\t\t ne = this._northEast,\r\n\t\t sw2 = bounds.getSouthWest(),\r\n\t\t ne2 = bounds.getNorthEast(),\r\n\r\n\t\t latIntersects = (ne2.lat >= sw.lat) && (sw2.lat <= ne.lat),\r\n\t\t lngIntersects = (ne2.lng >= sw.lng) && (sw2.lng <= ne.lng);\r\n\r\n\t\treturn latIntersects && lngIntersects;\r\n\t},\r\n\r\n\t// @method overlaps(otherBounds: Bounds): Boolean\r\n\t// Returns `true` if the rectangle overlaps the given bounds. Two bounds overlap if their intersection is an area.\r\n\toverlaps: function (bounds) {\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\r\n\t\tvar sw = this._southWest,\r\n\t\t ne = this._northEast,\r\n\t\t sw2 = bounds.getSouthWest(),\r\n\t\t ne2 = bounds.getNorthEast(),\r\n\r\n\t\t latOverlaps = (ne2.lat > sw.lat) && (sw2.lat < ne.lat),\r\n\t\t lngOverlaps = (ne2.lng > sw.lng) && (sw2.lng < ne.lng);\r\n\r\n\t\treturn latOverlaps && lngOverlaps;\r\n\t},\r\n\r\n\t// @method toBBoxString(): String\r\n\t// Returns a string with bounding box coordinates in a 'southwest_lng,southwest_lat,northeast_lng,northeast_lat' format. Useful for sending requests to web services that return geo data.\r\n\ttoBBoxString: function () {\r\n\t\treturn [this.getWest(), this.getSouth(), this.getEast(), this.getNorth()].join(',');\r\n\t},\r\n\r\n\t// @method equals(otherBounds: LatLngBounds, maxMargin?: Number): Boolean\r\n\t// Returns `true` if the rectangle is equivalent (within a small margin of error) to the given bounds. The margin of error can be overridden by setting `maxMargin` to a small number.\r\n\tequals: function (bounds, maxMargin) {\r\n\t\tif (!bounds) { return false; }\r\n\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\r\n\t\treturn this._southWest.equals(bounds.getSouthWest(), maxMargin) &&\r\n\t\t this._northEast.equals(bounds.getNorthEast(), maxMargin);\r\n\t},\r\n\r\n\t// @method isValid(): Boolean\r\n\t// Returns `true` if the bounds are properly initialized.\r\n\tisValid: function () {\r\n\t\treturn !!(this._southWest && this._northEast);\r\n\t}\r\n};\r\n\r\n// TODO International date line?\r\n\r\n// @factory L.latLngBounds(corner1: LatLng, corner2: LatLng)\r\n// Creates a `LatLngBounds` object by defining two diagonally opposite corners of the rectangle.\r\n\r\n// @alternative\r\n// @factory L.latLngBounds(latlngs: LatLng[])\r\n// Creates a `LatLngBounds` object defined by the geographical points it contains. Very useful for zooming the map to fit a particular set of locations with [`fitBounds`](#map-fitbounds).\r\nfunction toLatLngBounds(a, b) {\r\n\tif (a instanceof LatLngBounds) {\r\n\t\treturn a;\r\n\t}\r\n\treturn new LatLngBounds(a, b);\r\n}\n\n/* @class LatLng\r\n * @aka L.LatLng\r\n *\r\n * Represents a geographical point with a certain latitude and longitude.\r\n *\r\n * @example\r\n *\r\n * ```\r\n * var latlng = L.latLng(50.5, 30.5);\r\n * ```\r\n *\r\n * All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent:\r\n *\r\n * ```\r\n * map.panTo([50, 30]);\r\n * map.panTo({lon: 30, lat: 50});\r\n * map.panTo({lat: 50, lng: 30});\r\n * map.panTo(L.latLng(50, 30));\r\n * ```\r\n *\r\n * Note that `LatLng` does not inherit from Leaflet's `Class` object,\r\n * which means new classes can't inherit from it, and new methods\r\n * can't be added to it with the `include` function.\r\n */\r\n\r\nfunction LatLng(lat, lng, alt) {\r\n\tif (isNaN(lat) || isNaN(lng)) {\r\n\t\tthrow new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');\r\n\t}\r\n\r\n\t// @property lat: Number\r\n\t// Latitude in degrees\r\n\tthis.lat = +lat;\r\n\r\n\t// @property lng: Number\r\n\t// Longitude in degrees\r\n\tthis.lng = +lng;\r\n\r\n\t// @property alt: Number\r\n\t// Altitude in meters (optional)\r\n\tif (alt !== undefined) {\r\n\t\tthis.alt = +alt;\r\n\t}\r\n}\r\n\r\nLatLng.prototype = {\r\n\t// @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean\r\n\t// Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number.\r\n\tequals: function (obj, maxMargin) {\r\n\t\tif (!obj) { return false; }\r\n\r\n\t\tobj = toLatLng(obj);\r\n\r\n\t\tvar margin = Math.max(\r\n\t\t Math.abs(this.lat - obj.lat),\r\n\t\t Math.abs(this.lng - obj.lng));\r\n\r\n\t\treturn margin <= (maxMargin === undefined ? 1.0E-9 : maxMargin);\r\n\t},\r\n\r\n\t// @method toString(): String\r\n\t// Returns a string representation of the point (for debugging purposes).\r\n\ttoString: function (precision) {\r\n\t\treturn 'LatLng(' +\r\n\t\t formatNum(this.lat, precision) + ', ' +\r\n\t\t formatNum(this.lng, precision) + ')';\r\n\t},\r\n\r\n\t// @method distanceTo(otherLatLng: LatLng): Number\r\n\t// Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines).\r\n\tdistanceTo: function (other) {\r\n\t\treturn Earth.distance(this, toLatLng(other));\r\n\t},\r\n\r\n\t// @method wrap(): LatLng\r\n\t// Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees.\r\n\twrap: function () {\r\n\t\treturn Earth.wrapLatLng(this);\r\n\t},\r\n\r\n\t// @method toBounds(sizeInMeters: Number): LatLngBounds\r\n\t// Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`.\r\n\ttoBounds: function (sizeInMeters) {\r\n\t\tvar latAccuracy = 180 * sizeInMeters / 40075017,\r\n\t\t lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat);\r\n\r\n\t\treturn toLatLngBounds(\r\n\t\t [this.lat - latAccuracy, this.lng - lngAccuracy],\r\n\t\t [this.lat + latAccuracy, this.lng + lngAccuracy]);\r\n\t},\r\n\r\n\tclone: function () {\r\n\t\treturn new LatLng(this.lat, this.lng, this.alt);\r\n\t}\r\n};\r\n\r\n\r\n\r\n// @factory L.latLng(latitude: Number, longitude: Number, altitude?: Number): LatLng\r\n// Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude).\r\n\r\n// @alternative\r\n// @factory L.latLng(coords: Array): LatLng\r\n// Expects an array of the form `[Number, Number]` or `[Number, Number, Number]` instead.\r\n\r\n// @alternative\r\n// @factory L.latLng(coords: Object): LatLng\r\n// Expects an plain object of the form `{lat: Number, lng: Number}` or `{lat: Number, lng: Number, alt: Number}` instead.\r\n\r\nfunction toLatLng(a, b, c) {\r\n\tif (a instanceof LatLng) {\r\n\t\treturn a;\r\n\t}\r\n\tif (isArray(a) && typeof a[0] !== 'object') {\r\n\t\tif (a.length === 3) {\r\n\t\t\treturn new LatLng(a[0], a[1], a[2]);\r\n\t\t}\r\n\t\tif (a.length === 2) {\r\n\t\t\treturn new LatLng(a[0], a[1]);\r\n\t\t}\r\n\t\treturn null;\r\n\t}\r\n\tif (a === undefined || a === null) {\r\n\t\treturn a;\r\n\t}\r\n\tif (typeof a === 'object' && 'lat' in a) {\r\n\t\treturn new LatLng(a.lat, 'lng' in a ? a.lng : a.lon, a.alt);\r\n\t}\r\n\tif (b === undefined) {\r\n\t\treturn null;\r\n\t}\r\n\treturn new LatLng(a, b, c);\r\n}\n\n/*\r\n * @namespace CRS\r\n * @crs L.CRS.Base\r\n * Object that defines coordinate reference systems for projecting\r\n * geographical points into pixel (screen) coordinates and back (and to\r\n * coordinates in other units for [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services). See\r\n * [spatial reference system](http://en.wikipedia.org/wiki/Coordinate_reference_system).\r\n *\r\n * Leaflet defines the most usual CRSs by default. If you want to use a\r\n * CRS not defined by default, take a look at the\r\n * [Proj4Leaflet](https://github.com/kartena/Proj4Leaflet) plugin.\r\n *\r\n * Note that the CRS instances do not inherit from Leafet's `Class` object,\r\n * and can't be instantiated. Also, new classes can't inherit from them,\r\n * and methods can't be added to them with the `include` function.\r\n */\r\n\r\nvar CRS = {\r\n\t// @method latLngToPoint(latlng: LatLng, zoom: Number): Point\r\n\t// Projects geographical coordinates into pixel coordinates for a given zoom.\r\n\tlatLngToPoint: function (latlng, zoom) {\r\n\t\tvar projectedPoint = this.projection.project(latlng),\r\n\t\t scale = this.scale(zoom);\r\n\r\n\t\treturn this.transformation._transform(projectedPoint, scale);\r\n\t},\r\n\r\n\t// @method pointToLatLng(point: Point, zoom: Number): LatLng\r\n\t// The inverse of `latLngToPoint`. Projects pixel coordinates on a given\r\n\t// zoom into geographical coordinates.\r\n\tpointToLatLng: function (point, zoom) {\r\n\t\tvar scale = this.scale(zoom),\r\n\t\t untransformedPoint = this.transformation.untransform(point, scale);\r\n\r\n\t\treturn this.projection.unproject(untransformedPoint);\r\n\t},\r\n\r\n\t// @method project(latlng: LatLng): Point\r\n\t// Projects geographical coordinates into coordinates in units accepted for\r\n\t// this CRS (e.g. meters for EPSG:3857, for passing it to WMS services).\r\n\tproject: function (latlng) {\r\n\t\treturn this.projection.project(latlng);\r\n\t},\r\n\r\n\t// @method unproject(point: Point): LatLng\r\n\t// Given a projected coordinate returns the corresponding LatLng.\r\n\t// The inverse of `project`.\r\n\tunproject: function (point) {\r\n\t\treturn this.projection.unproject(point);\r\n\t},\r\n\r\n\t// @method scale(zoom: Number): Number\r\n\t// Returns the scale used when transforming projected coordinates into\r\n\t// pixel coordinates for a particular zoom. For example, it returns\r\n\t// `256 * 2^zoom` for Mercator-based CRS.\r\n\tscale: function (zoom) {\r\n\t\treturn 256 * Math.pow(2, zoom);\r\n\t},\r\n\r\n\t// @method zoom(scale: Number): Number\r\n\t// Inverse of `scale()`, returns the zoom level corresponding to a scale\r\n\t// factor of `scale`.\r\n\tzoom: function (scale) {\r\n\t\treturn Math.log(scale / 256) / Math.LN2;\r\n\t},\r\n\r\n\t// @method getProjectedBounds(zoom: Number): Bounds\r\n\t// Returns the projection's bounds scaled and transformed for the provided `zoom`.\r\n\tgetProjectedBounds: function (zoom) {\r\n\t\tif (this.infinite) { return null; }\r\n\r\n\t\tvar b = this.projection.bounds,\r\n\t\t s = this.scale(zoom),\r\n\t\t min = this.transformation.transform(b.min, s),\r\n\t\t max = this.transformation.transform(b.max, s);\r\n\r\n\t\treturn new Bounds(min, max);\r\n\t},\r\n\r\n\t// @method distance(latlng1: LatLng, latlng2: LatLng): Number\r\n\t// Returns the distance between two geographical coordinates.\r\n\r\n\t// @property code: String\r\n\t// Standard code name of the CRS passed into WMS services (e.g. `'EPSG:3857'`)\r\n\t//\r\n\t// @property wrapLng: Number[]\r\n\t// An array of two numbers defining whether the longitude (horizontal) coordinate\r\n\t// axis wraps around a given range and how. Defaults to `[-180, 180]` in most\r\n\t// geographical CRSs. If `undefined`, the longitude axis does not wrap around.\r\n\t//\r\n\t// @property wrapLat: Number[]\r\n\t// Like `wrapLng`, but for the latitude (vertical) axis.\r\n\r\n\t// wrapLng: [min, max],\r\n\t// wrapLat: [min, max],\r\n\r\n\t// @property infinite: Boolean\r\n\t// If true, the coordinate space will be unbounded (infinite in both axes)\r\n\tinfinite: false,\r\n\r\n\t// @method wrapLatLng(latlng: LatLng): LatLng\r\n\t// Returns a `LatLng` where lat and lng has been wrapped according to the\r\n\t// CRS's `wrapLat` and `wrapLng` properties, if they are outside the CRS's bounds.\r\n\twrapLatLng: function (latlng) {\r\n\t\tvar lng = this.wrapLng ? wrapNum(latlng.lng, this.wrapLng, true) : latlng.lng,\r\n\t\t lat = this.wrapLat ? wrapNum(latlng.lat, this.wrapLat, true) : latlng.lat,\r\n\t\t alt = latlng.alt;\r\n\r\n\t\treturn new LatLng(lat, lng, alt);\r\n\t},\r\n\r\n\t// @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds\r\n\t// Returns a `LatLngBounds` with the same size as the given one, ensuring\r\n\t// that its center is within the CRS's bounds.\r\n\t// Only accepts actual `L.LatLngBounds` instances, not arrays.\r\n\twrapLatLngBounds: function (bounds) {\r\n\t\tvar center = bounds.getCenter(),\r\n\t\t newCenter = this.wrapLatLng(center),\r\n\t\t latShift = center.lat - newCenter.lat,\r\n\t\t lngShift = center.lng - newCenter.lng;\r\n\r\n\t\tif (latShift === 0 && lngShift === 0) {\r\n\t\t\treturn bounds;\r\n\t\t}\r\n\r\n\t\tvar sw = bounds.getSouthWest(),\r\n\t\t ne = bounds.getNorthEast(),\r\n\t\t newSw = new LatLng(sw.lat - latShift, sw.lng - lngShift),\r\n\t\t newNe = new LatLng(ne.lat - latShift, ne.lng - lngShift);\r\n\r\n\t\treturn new LatLngBounds(newSw, newNe);\r\n\t}\r\n};\n\n/*\n * @namespace CRS\n * @crs L.CRS.Earth\n *\n * Serves as the base for CRS that are global such that they cover the earth.\n * Can only be used as the base for other CRS and cannot be used directly,\n * since it does not have a `code`, `projection` or `transformation`. `distance()` returns\n * meters.\n */\n\nvar Earth = extend({}, CRS, {\n\twrapLng: [-180, 180],\n\n\t// Mean Earth Radius, as recommended for use by\n\t// the International Union of Geodesy and Geophysics,\n\t// see http://rosettacode.org/wiki/Haversine_formula\n\tR: 6371000,\n\n\t// distance between two geographical points using spherical law of cosines approximation\n\tdistance: function (latlng1, latlng2) {\n\t\tvar rad = Math.PI / 180,\n\t\t lat1 = latlng1.lat * rad,\n\t\t lat2 = latlng2.lat * rad,\n\t\t sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2),\n\t\t sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2),\n\t\t a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon,\n\t\t c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\t\treturn this.R * c;\n\t}\n});\n\n/*\r\n * @namespace Projection\r\n * @projection L.Projection.SphericalMercator\r\n *\r\n * Spherical Mercator projection — the most common projection for online maps,\r\n * used by almost all free and commercial tile providers. Assumes that Earth is\r\n * a sphere. Used by the `EPSG:3857` CRS.\r\n */\r\n\r\nvar earthRadius = 6378137;\r\n\r\nvar SphericalMercator = {\r\n\r\n\tR: earthRadius,\r\n\tMAX_LATITUDE: 85.0511287798,\r\n\r\n\tproject: function (latlng) {\r\n\t\tvar d = Math.PI / 180,\r\n\t\t max = this.MAX_LATITUDE,\r\n\t\t lat = Math.max(Math.min(max, latlng.lat), -max),\r\n\t\t sin = Math.sin(lat * d);\r\n\r\n\t\treturn new Point(\r\n\t\t\tthis.R * latlng.lng * d,\r\n\t\t\tthis.R * Math.log((1 + sin) / (1 - sin)) / 2);\r\n\t},\r\n\r\n\tunproject: function (point) {\r\n\t\tvar d = 180 / Math.PI;\r\n\r\n\t\treturn new LatLng(\r\n\t\t\t(2 * Math.atan(Math.exp(point.y / this.R)) - (Math.PI / 2)) * d,\r\n\t\t\tpoint.x * d / this.R);\r\n\t},\r\n\r\n\tbounds: (function () {\r\n\t\tvar d = earthRadius * Math.PI;\r\n\t\treturn new Bounds([-d, -d], [d, d]);\r\n\t})()\r\n};\n\n/*\r\n * @class Transformation\r\n * @aka L.Transformation\r\n *\r\n * Represents an affine transformation: a set of coefficients `a`, `b`, `c`, `d`\r\n * for transforming a point of a form `(x, y)` into `(a*x + b, c*y + d)` and doing\r\n * the reverse. Used by Leaflet in its projections code.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var transformation = L.transformation(2, 5, -1, 10),\r\n * \tp = L.point(1, 2),\r\n * \tp2 = transformation.transform(p), // L.point(7, 8)\r\n * \tp3 = transformation.untransform(p2); // L.point(1, 2)\r\n * ```\r\n */\r\n\r\n\r\n// factory new L.Transformation(a: Number, b: Number, c: Number, d: Number)\r\n// Creates a `Transformation` object with the given coefficients.\r\nfunction Transformation(a, b, c, d) {\r\n\tif (isArray(a)) {\r\n\t\t// use array properties\r\n\t\tthis._a = a[0];\r\n\t\tthis._b = a[1];\r\n\t\tthis._c = a[2];\r\n\t\tthis._d = a[3];\r\n\t\treturn;\r\n\t}\r\n\tthis._a = a;\r\n\tthis._b = b;\r\n\tthis._c = c;\r\n\tthis._d = d;\r\n}\r\n\r\nTransformation.prototype = {\r\n\t// @method transform(point: Point, scale?: Number): Point\r\n\t// Returns a transformed point, optionally multiplied by the given scale.\r\n\t// Only accepts actual `L.Point` instances, not arrays.\r\n\ttransform: function (point, scale) { // (Point, Number) -> Point\r\n\t\treturn this._transform(point.clone(), scale);\r\n\t},\r\n\r\n\t// destructive transform (faster)\r\n\t_transform: function (point, scale) {\r\n\t\tscale = scale || 1;\r\n\t\tpoint.x = scale * (this._a * point.x + this._b);\r\n\t\tpoint.y = scale * (this._c * point.y + this._d);\r\n\t\treturn point;\r\n\t},\r\n\r\n\t// @method untransform(point: Point, scale?: Number): Point\r\n\t// Returns the reverse transformation of the given point, optionally divided\r\n\t// by the given scale. Only accepts actual `L.Point` instances, not arrays.\r\n\tuntransform: function (point, scale) {\r\n\t\tscale = scale || 1;\r\n\t\treturn new Point(\r\n\t\t (point.x / scale - this._b) / this._a,\r\n\t\t (point.y / scale - this._d) / this._c);\r\n\t}\r\n};\r\n\r\n// factory L.transformation(a: Number, b: Number, c: Number, d: Number)\r\n\r\n// @factory L.transformation(a: Number, b: Number, c: Number, d: Number)\r\n// Instantiates a Transformation object with the given coefficients.\r\n\r\n// @alternative\r\n// @factory L.transformation(coefficients: Array): Transformation\r\n// Expects an coefficients array of the form\r\n// `[a: Number, b: Number, c: Number, d: Number]`.\r\n\r\nfunction toTransformation(a, b, c, d) {\r\n\treturn new Transformation(a, b, c, d);\r\n}\n\n/*\r\n * @namespace CRS\r\n * @crs L.CRS.EPSG3857\r\n *\r\n * The most common CRS for online maps, used by almost all free and commercial\r\n * tile providers. Uses Spherical Mercator projection. Set in by default in\r\n * Map's `crs` option.\r\n */\r\n\r\nvar EPSG3857 = extend({}, Earth, {\r\n\tcode: 'EPSG:3857',\r\n\tprojection: SphericalMercator,\r\n\r\n\ttransformation: (function () {\r\n\t\tvar scale = 0.5 / (Math.PI * SphericalMercator.R);\r\n\t\treturn toTransformation(scale, 0.5, -scale, 0.5);\r\n\t}())\r\n});\r\n\r\nvar EPSG900913 = extend({}, EPSG3857, {\r\n\tcode: 'EPSG:900913'\r\n});\n\n// @namespace SVG; @section\n// There are several static functions which can be called without instantiating L.SVG:\n\n// @function create(name: String): SVGElement\n// Returns a instance of [SVGElement](https://developer.mozilla.org/docs/Web/API/SVGElement),\n// corresponding to the class name passed. For example, using 'line' will return\n// an instance of [SVGLineElement](https://developer.mozilla.org/docs/Web/API/SVGLineElement).\nfunction svgCreate(name) {\n\treturn document.createElementNS('http://www.w3.org/2000/svg', name);\n}\n\n// @function pointsToPath(rings: Point[], closed: Boolean): String\n// Generates a SVG path string for multiple rings, with each ring turning\n// into \"M..L..L..\" instructions\nfunction pointsToPath(rings, closed) {\n\tvar str = '',\n\ti, j, len, len2, points, p;\n\n\tfor (i = 0, len = rings.length; i < len; i++) {\n\t\tpoints = rings[i];\n\n\t\tfor (j = 0, len2 = points.length; j < len2; j++) {\n\t\t\tp = points[j];\n\t\t\tstr += (j ? 'L' : 'M') + p.x + ' ' + p.y;\n\t\t}\n\n\t\t// closes the ring for polygons; \"x\" is VML syntax\n\t\tstr += closed ? (svg ? 'z' : 'x') : '';\n\t}\n\n\t// SVG complains about empty path strings\n\treturn str || 'M0 0';\n}\n\n/*\r\n * @namespace Browser\r\n * @aka L.Browser\r\n *\r\n * A namespace with static properties for browser/feature detection used by Leaflet internally.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * if (L.Browser.ielt9) {\r\n * alert('Upgrade your browser, dude!');\r\n * }\r\n * ```\r\n */\r\n\r\nvar style$1 = document.documentElement.style;\r\n\r\n// @property ie: Boolean; `true` for all Internet Explorer versions (not Edge).\r\nvar ie = 'ActiveXObject' in window;\r\n\r\n// @property ielt9: Boolean; `true` for Internet Explorer versions less than 9.\r\nvar ielt9 = ie && !document.addEventListener;\r\n\r\n// @property edge: Boolean; `true` for the Edge web browser.\r\nvar edge = 'msLaunchUri' in navigator && !('documentMode' in document);\r\n\r\n// @property webkit: Boolean;\r\n// `true` for webkit-based browsers like Chrome and Safari (including mobile versions).\r\nvar webkit = userAgentContains('webkit');\r\n\r\n// @property android: Boolean\r\n// `true` for any browser running on an Android platform.\r\nvar android = userAgentContains('android');\r\n\r\n// @property android23: Boolean; `true` for browsers running on Android 2 or Android 3.\r\nvar android23 = userAgentContains('android 2') || userAgentContains('android 3');\r\n\r\n/* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */\r\nvar webkitVer = parseInt(/WebKit\\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit\r\n// @property androidStock: Boolean; `true` for the Android stock browser (i.e. not Chrome)\r\nvar androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window);\r\n\r\n// @property opera: Boolean; `true` for the Opera browser\r\nvar opera = !!window.opera;\r\n\r\n// @property chrome: Boolean; `true` for the Chrome browser.\r\nvar chrome = userAgentContains('chrome');\r\n\r\n// @property gecko: Boolean; `true` for gecko-based browsers like Firefox.\r\nvar gecko = userAgentContains('gecko') && !webkit && !opera && !ie;\r\n\r\n// @property safari: Boolean; `true` for the Safari browser.\r\nvar safari = !chrome && userAgentContains('safari');\r\n\r\nvar phantom = userAgentContains('phantom');\r\n\r\n// @property opera12: Boolean\r\n// `true` for the Opera browser supporting CSS transforms (version 12 or later).\r\nvar opera12 = 'OTransition' in style$1;\r\n\r\n// @property win: Boolean; `true` when the browser is running in a Windows platform\r\nvar win = navigator.platform.indexOf('Win') === 0;\r\n\r\n// @property ie3d: Boolean; `true` for all Internet Explorer versions supporting CSS transforms.\r\nvar ie3d = ie && ('transition' in style$1);\r\n\r\n// @property webkit3d: Boolean; `true` for webkit-based browsers supporting CSS transforms.\r\nvar webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23;\r\n\r\n// @property gecko3d: Boolean; `true` for gecko-based browsers supporting CSS transforms.\r\nvar gecko3d = 'MozPerspective' in style$1;\r\n\r\n// @property any3d: Boolean\r\n// `true` for all browsers supporting CSS transforms.\r\nvar any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom;\r\n\r\n// @property mobile: Boolean; `true` for all browsers running in a mobile device.\r\nvar mobile = typeof orientation !== 'undefined' || userAgentContains('mobile');\r\n\r\n// @property mobileWebkit: Boolean; `true` for all webkit-based browsers in a mobile device.\r\nvar mobileWebkit = mobile && webkit;\r\n\r\n// @property mobileWebkit3d: Boolean\r\n// `true` for all webkit-based browsers in a mobile device supporting CSS transforms.\r\nvar mobileWebkit3d = mobile && webkit3d;\r\n\r\n// @property msPointer: Boolean\r\n// `true` for browsers implementing the Microsoft touch events model (notably IE10).\r\nvar msPointer = !window.PointerEvent && window.MSPointerEvent;\r\n\r\n// @property pointer: Boolean\r\n// `true` for all browsers supporting [pointer events](https://msdn.microsoft.com/en-us/library/dn433244%28v=vs.85%29.aspx).\r\nvar pointer = !!(window.PointerEvent || msPointer);\r\n\r\n// @property touch: Boolean\r\n// `true` for all browsers supporting [touch events](https://developer.mozilla.org/docs/Web/API/Touch_events).\r\n// This does not necessarily mean that the browser is running in a computer with\r\n// a touchscreen, it only means that the browser is capable of understanding\r\n// touch events.\r\nvar touch = !window.L_NO_TOUCH && (pointer || 'ontouchstart' in window ||\r\n\t\t(window.DocumentTouch && document instanceof window.DocumentTouch));\r\n\r\n// @property mobileOpera: Boolean; `true` for the Opera browser in a mobile device.\r\nvar mobileOpera = mobile && opera;\r\n\r\n// @property mobileGecko: Boolean\r\n// `true` for gecko-based browsers running in a mobile device.\r\nvar mobileGecko = mobile && gecko;\r\n\r\n// @property retina: Boolean\r\n// `true` for browsers on a high-resolution \"retina\" screen or on any screen when browser's display zoom is more than 100%.\r\nvar retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1;\r\n\r\n\r\n// @property canvas: Boolean\r\n// `true` when the browser supports [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API).\r\nvar canvas = (function () {\r\n\treturn !!document.createElement('canvas').getContext;\r\n}());\r\n\r\n// @property svg: Boolean\r\n// `true` when the browser supports [SVG](https://developer.mozilla.org/docs/Web/SVG).\r\nvar svg = !!(document.createElementNS && svgCreate('svg').createSVGRect);\r\n\r\n// @property vml: Boolean\r\n// `true` if the browser supports [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language).\r\nvar vml = !svg && (function () {\r\n\ttry {\r\n\t\tvar div = document.createElement('div');\r\n\t\tdiv.innerHTML = '<v:shape adj=\"1\"/>';\r\n\r\n\t\tvar shape = div.firstChild;\r\n\t\tshape.style.behavior = 'url(#default#VML)';\r\n\r\n\t\treturn shape && (typeof shape.adj === 'object');\r\n\r\n\t} catch (e) {\r\n\t\treturn false;\r\n\t}\r\n}());\r\n\r\n\r\nfunction userAgentContains(str) {\r\n\treturn navigator.userAgent.toLowerCase().indexOf(str) >= 0;\r\n}\r\n\n\nvar Browser = (Object.freeze || Object)({\n\tie: ie,\n\tielt9: ielt9,\n\tedge: edge,\n\twebkit: webkit,\n\tandroid: android,\n\tandroid23: android23,\n\tandroidStock: androidStock,\n\topera: opera,\n\tchrome: chrome,\n\tgecko: gecko,\n\tsafari: safari,\n\tphantom: phantom,\n\topera12: opera12,\n\twin: win,\n\tie3d: ie3d,\n\twebkit3d: webkit3d,\n\tgecko3d: gecko3d,\n\tany3d: any3d,\n\tmobile: mobile,\n\tmobileWebkit: mobileWebkit,\n\tmobileWebkit3d: mobileWebkit3d,\n\tmsPointer: msPointer,\n\tpointer: pointer,\n\ttouch: touch,\n\tmobileOpera: mobileOpera,\n\tmobileGecko: mobileGecko,\n\tretina: retina,\n\tcanvas: canvas,\n\tsvg: svg,\n\tvml: vml\n});\n\n/*\n * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices.\n */\n\n\nvar POINTER_DOWN = msPointer ? 'MSPointerDown' : 'pointerdown';\nvar POINTER_MOVE = msPointer ? 'MSPointerMove' : 'pointermove';\nvar POINTER_UP = msPointer ? 'MSPointerUp' : 'pointerup';\nvar POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel';\nvar TAG_WHITE_LIST = ['INPUT', 'SELECT', 'OPTION'];\n\nvar _pointers = {};\nvar _pointerDocListener = false;\n\n// DomEvent.DoubleTap needs to know about this\nvar _pointersCount = 0;\n\n// Provides a touch events wrapper for (ms)pointer events.\n// ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890\n\nfunction addPointerListener(obj, type, handler, id) {\n\tif (type === 'touchstart') {\n\t\t_addPointerStart(obj, handler, id);\n\n\t} else if (type === 'touchmove') {\n\t\t_addPointerMove(obj, handler, id);\n\n\t} else if (type === 'touchend') {\n\t\t_addPointerEnd(obj, handler, id);\n\t}\n\n\treturn this;\n}\n\nfunction removePointerListener(obj, type, id) {\n\tvar handler = obj['_leaflet_' + type + id];\n\n\tif (type === 'touchstart') {\n\t\tobj.removeEventListener(POINTER_DOWN, handler, false);\n\n\t} else if (type === 'touchmove') {\n\t\tobj.removeEventListener(POINTER_MOVE, handler, false);\n\n\t} else if (type === 'touchend') {\n\t\tobj.removeEventListener(POINTER_UP, handler, false);\n\t\tobj.removeEventListener(POINTER_CANCEL, handler, false);\n\t}\n\n\treturn this;\n}\n\nfunction _addPointerStart(obj, handler, id) {\n\tvar onDown = bind(function (e) {\n\t\tif (e.pointerType !== 'mouse' && e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {\n\t\t\t// In IE11, some touch events needs to fire for form controls, or\n\t\t\t// the controls will stop working. We keep a whitelist of tag names that\n\t\t\t// need these events. For other target tags, we prevent default on the event.\n\t\t\tif (TAG_WHITE_LIST.indexOf(e.target.tagName) < 0) {\n\t\t\t\tpreventDefault(e);\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t_handlePointer(e, handler);\n\t});\n\n\tobj['_leaflet_touchstart' + id] = onDown;\n\tobj.addEventListener(POINTER_DOWN, onDown, false);\n\n\t// need to keep track of what pointers and how many are active to provide e.touches emulation\n\tif (!_pointerDocListener) {\n\t\t// we listen documentElement as any drags that end by moving the touch off the screen get fired there\n\t\tdocument.documentElement.addEventListener(POINTER_DOWN, _globalPointerDown, true);\n\t\tdocument.documentElement.addEventListener(POINTER_MOVE, _globalPointerMove, true);\n\t\tdocument.documentElement.addEventListener(POINTER_UP, _globalPointerUp, true);\n\t\tdocument.documentElement.addEventListener(POINTER_CANCEL, _globalPointerUp, true);\n\n\t\t_pointerDocListener = true;\n\t}\n}\n\nfunction _globalPointerDown(e) {\n\t_pointers[e.pointerId] = e;\n\t_pointersCount++;\n}\n\nfunction _globalPointerMove(e) {\n\tif (_pointers[e.pointerId]) {\n\t\t_pointers[e.pointerId] = e;\n\t}\n}\n\nfunction _globalPointerUp(e) {\n\tdelete _pointers[e.pointerId];\n\t_pointersCount--;\n}\n\nfunction _handlePointer(e, handler) {\n\te.touches = [];\n\tfor (var i in _pointers) {\n\t\te.touches.push(_pointers[i]);\n\t}\n\te.changedTouches = [e];\n\n\thandler(e);\n}\n\nfunction _addPointerMove(obj, handler, id) {\n\tvar onMove = function (e) {\n\t\t// don't fire touch moves when mouse isn't down\n\t\tif ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; }\n\n\t\t_handlePointer(e, handler);\n\t};\n\n\tobj['_leaflet_touchmove' + id] = onMove;\n\tobj.addEventListener(POINTER_MOVE, onMove, false);\n}\n\nfunction _addPointerEnd(obj, handler, id) {\n\tvar onUp = function (e) {\n\t\t_handlePointer(e, handler);\n\t};\n\n\tobj['_leaflet_touchend' + id] = onUp;\n\tobj.addEventListener(POINTER_UP, onUp, false);\n\tobj.addEventListener(POINTER_CANCEL, onUp, false);\n}\n\n/*\r\n * Extends the event handling code with double tap support for mobile browsers.\r\n */\r\n\r\nvar _touchstart = msPointer ? 'MSPointerDown' : pointer ? 'pointerdown' : 'touchstart';\r\nvar _touchend = msPointer ? 'MSPointerUp' : pointer ? 'pointerup' : 'touchend';\r\nvar _pre = '_leaflet_';\r\n\r\n// inspired by Zepto touch code by Thomas Fuchs\r\nfunction addDoubleTapListener(obj, handler, id) {\r\n\tvar last, touch$$1,\r\n\t doubleTap = false,\r\n\t delay = 250;\r\n\r\n\tfunction onTouchStart(e) {\r\n\t\tvar count;\r\n\r\n\t\tif (pointer) {\r\n\t\t\tif ((!edge) || e.pointerType === 'mouse') { return; }\r\n\t\t\tcount = _pointersCount;\r\n\t\t} else {\r\n\t\t\tcount = e.touches.length;\r\n\t\t}\r\n\r\n\t\tif (count > 1) { return; }\r\n\r\n\t\tvar now = Date.now(),\r\n\t\t delta = now - (last || now);\r\n\r\n\t\ttouch$$1 = e.touches ? e.touches[0] : e;\r\n\t\tdoubleTap = (delta > 0 && delta <= delay);\r\n\t\tlast = now;\r\n\t}\r\n\r\n\tfunction onTouchEnd(e) {\r\n\t\tif (doubleTap && !touch$$1.cancelBubble) {\r\n\t\t\tif (pointer) {\r\n\t\t\t\tif ((!edge) || e.pointerType === 'mouse') { return; }\r\n\t\t\t\t// work around .type being readonly with MSPointer* events\r\n\t\t\t\tvar newTouch = {},\r\n\t\t\t\t prop, i;\r\n\r\n\t\t\t\tfor (i in touch$$1) {\r\n\t\t\t\t\tprop = touch$$1[i];\r\n\t\t\t\t\tnewTouch[i] = prop && prop.bind ? prop.bind(touch$$1) : prop;\r\n\t\t\t\t}\r\n\t\t\t\ttouch$$1 = newTouch;\r\n\t\t\t}\r\n\t\t\ttouch$$1.type = 'dblclick';\r\n\t\t\ttouch$$1.button = 0;\r\n\t\t\thandler(touch$$1);\r\n\t\t\tlast = null;\r\n\t\t}\r\n\t}\r\n\r\n\tobj[_pre + _touchstart + id] = onTouchStart;\r\n\tobj[_pre + _touchend + id] = onTouchEnd;\r\n\tobj[_pre + 'dblclick' + id] = handler;\r\n\r\n\tobj.addEventListener(_touchstart, onTouchStart, false);\r\n\tobj.addEventListener(_touchend, onTouchEnd, false);\r\n\r\n\t// On some platforms (notably, chrome<55 on win10 + touchscreen + mouse),\r\n\t// the browser doesn't fire touchend/pointerup events but does fire\r\n\t// native dblclicks. See #4127.\r\n\t// Edge 14 also fires native dblclicks, but only for pointerType mouse, see #5180.\r\n\tobj.addEventListener('dblclick', handler, false);\r\n\r\n\treturn this;\r\n}\r\n\r\nfunction removeDoubleTapListener(obj, id) {\r\n\tvar touchstart = obj[_pre + _touchstart + id],\r\n\t touchend = obj[_pre + _touchend + id],\r\n\t dblclick = obj[_pre + 'dblclick' + id];\r\n\r\n\tobj.removeEventListener(_touchstart, touchstart, false);\r\n\tobj.removeEventListener(_touchend, touchend, false);\r\n\tif (!edge) {\r\n\t\tobj.removeEventListener('dblclick', dblclick, false);\r\n\t}\r\n\r\n\treturn this;\r\n}\n\n/*\r\n * @namespace DomUtil\r\n *\r\n * Utility functions to work with the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model)\r\n * tree, used by Leaflet internally.\r\n *\r\n * Most functions expecting or returning a `HTMLElement` also work for\r\n * SVG elements. The only difference is that classes refer to CSS classes\r\n * in HTML and SVG classes in SVG.\r\n */\r\n\r\n\r\n// @property TRANSFORM: String\r\n// Vendor-prefixed transform style name (e.g. `'webkitTransform'` for WebKit).\r\nvar TRANSFORM = testProp(\r\n\t['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform']);\r\n\r\n// webkitTransition comes first because some browser versions that drop vendor prefix don't do\r\n// the same for the transitionend event, in particular the Android 4.1 stock browser\r\n\r\n// @property TRANSITION: String\r\n// Vendor-prefixed transition style name.\r\nvar TRANSITION = testProp(\r\n\t['webkitTransition', 'transition', 'OTransition', 'MozTransition', 'msTransition']);\r\n\r\n// @property TRANSITION_END: String\r\n// Vendor-prefixed transitionend event name.\r\nvar TRANSITION_END =\r\n\tTRANSITION === 'webkitTransition' || TRANSITION === 'OTransition' ? TRANSITION + 'End' : 'transitionend';\r\n\r\n\r\n// @function get(id: String|HTMLElement): HTMLElement\r\n// Returns an element given its DOM id, or returns the element itself\r\n// if it was passed directly.\r\nfunction get(id) {\r\n\treturn typeof id === 'string' ? document.getElementById(id) : id;\r\n}\r\n\r\n// @function getStyle(el: HTMLElement, styleAttrib: String): String\r\n// Returns the value for a certain style attribute on an element,\r\n// including computed values or values set through CSS.\r\nfunction getStyle(el, style) {\r\n\tvar value = el.style[style] || (el.currentStyle && el.currentStyle[style]);\r\n\r\n\tif ((!value || value === 'auto') && document.defaultView) {\r\n\t\tvar css = document.defaultView.getComputedStyle(el, null);\r\n\t\tvalue = css ? css[style] : null;\r\n\t}\r\n\treturn value === 'auto' ? null : value;\r\n}\r\n\r\n// @function create(tagName: String, className?: String, container?: HTMLElement): HTMLElement\r\n// Creates an HTML element with `tagName`, sets its class to `className`, and optionally appends it to `container` element.\r\nfunction create$1(tagName, className, container) {\r\n\tvar el = document.createElement(tagName);\r\n\tel.className = className || '';\r\n\r\n\tif (container) {\r\n\t\tcontainer.appendChild(el);\r\n\t}\r\n\treturn el;\r\n}\r\n\r\n// @function remove(el: HTMLElement)\r\n// Removes `el` from its parent element\r\nfunction remove(el) {\r\n\tvar parent = el.parentNode;\r\n\tif (parent) {\r\n\t\tparent.removeChild(el);\r\n\t}\r\n}\r\n\r\n// @function empty(el: HTMLElement)\r\n// Removes all of `el`'s children elements from `el`\r\nfunction empty(el) {\r\n\twhile (el.firstChild) {\r\n\t\tel.removeChild(el.firstChild);\r\n\t}\r\n}\r\n\r\n// @function toFront(el: HTMLElement)\r\n// Makes `el` the last child of its parent, so it renders in front of the other children.\r\nfunction toFront(el) {\r\n\tvar parent = el.parentNode;\r\n\tif (parent && parent.lastChild !== el) {\r\n\t\tparent.appendChild(el);\r\n\t}\r\n}\r\n\r\n// @function toBack(el: HTMLElement)\r\n// Makes `el` the first child of its parent, so it renders behind the other children.\r\nfunction toBack(el) {\r\n\tvar parent = el.parentNode;\r\n\tif (parent && parent.firstChild !== el) {\r\n\t\tparent.insertBefore(el, parent.firstChild);\r\n\t}\r\n}\r\n\r\n// @function hasClass(el: HTMLElement, name: String): Boolean\r\n// Returns `true` if the element's class attribute contains `name`.\r\nfunction hasClass(el, name) {\r\n\tif (el.classList !== undefined) {\r\n\t\treturn el.classList.contains(name);\r\n\t}\r\n\tvar className = getClass(el);\r\n\treturn className.length > 0 && new RegExp('(^|\\\\s)' + name + '(\\\\s|$)').test(className);\r\n}\r\n\r\n// @function addClass(el: HTMLElement, name: String)\r\n// Adds `name` to the element's class attribute.\r\nfunction addClass(el, name) {\r\n\tif (el.classList !== undefined) {\r\n\t\tvar classes = splitWords(name);\r\n\t\tfor (var i = 0, len = classes.length; i < len; i++) {\r\n\t\t\tel.classList.add(classes[i]);\r\n\t\t}\r\n\t} else if (!hasClass(el, name)) {\r\n\t\tvar className = getClass(el);\r\n\t\tsetClass(el, (className ? className + ' ' : '') + name);\r\n\t}\r\n}\r\n\r\n// @function removeClass(el: HTMLElement, name: String)\r\n// Removes `name` from the element's class attribute.\r\nfunction removeClass(el, name) {\r\n\tif (el.classList !== undefined) {\r\n\t\tel.classList.remove(name);\r\n\t} else {\r\n\t\tsetClass(el, trim((' ' + getClass(el) + ' ').replace(' ' + name + ' ', ' ')));\r\n\t}\r\n}\r\n\r\n// @function setClass(el: HTMLElement, name: String)\r\n// Sets the element's class.\r\nfunction setClass(el, name) {\r\n\tif (el.className.baseVal === undefined) {\r\n\t\tel.className = name;\r\n\t} else {\r\n\t\t// in case of SVG element\r\n\t\tel.className.baseVal = name;\r\n\t}\r\n}\r\n\r\n// @function getClass(el: HTMLElement): String\r\n// Returns the element's class.\r\nfunction getClass(el) {\r\n\t// Check if the element is an SVGElementInstance and use the correspondingElement instead\r\n\t// (Required for linked SVG elements in IE11.)\r\n\tif (el.correspondingElement) {\r\n\t\tel = el.correspondingElement;\r\n\t}\r\n\treturn el.className.baseVal === undefined ? el.className : el.className.baseVal;\r\n}\r\n\r\n// @function setOpacity(el: HTMLElement, opacity: Number)\r\n// Set the opacity of an element (including old IE support).\r\n// `opacity` must be a number from `0` to `1`.\r\nfunction setOpacity(el, value) {\r\n\tif ('opacity' in el.style) {\r\n\t\tel.style.opacity = value;\r\n\t} else if ('filter' in el.style) {\r\n\t\t_setOpacityIE(el, value);\r\n\t}\r\n}\r\n\r\nfunction _setOpacityIE(el, value) {\r\n\tvar filter = false,\r\n\t filterName = 'DXImageTransform.Microsoft.Alpha';\r\n\r\n\t// filters collection throws an error if we try to retrieve a filter that doesn't exist\r\n\ttry {\r\n\t\tfilter = el.filters.item(filterName);\r\n\t} catch (e) {\r\n\t\t// don't set opacity to 1 if we haven't already set an opacity,\r\n\t\t// it isn't needed and breaks transparent pngs.\r\n\t\tif (value === 1) { return; }\r\n\t}\r\n\r\n\tvalue = Math.round(value * 100);\r\n\r\n\tif (filter) {\r\n\t\tfilter.Enabled = (value !== 100);\r\n\t\tfilter.Opacity = value;\r\n\t} else {\r\n\t\tel.style.filter += ' progid:' + filterName + '(opacity=' + value + ')';\r\n\t}\r\n}\r\n\r\n// @function testProp(props: String[]): String|false\r\n// Goes through the array of style names and returns the first name\r\n// that is a valid style name for an element. If no such name is found,\r\n// it returns false. Useful for vendor-prefixed styles like `transform`.\r\nfunction testProp(props) {\r\n\tvar style = document.documentElement.style;\r\n\r\n\tfor (var i = 0; i < props.length; i++) {\r\n\t\tif (props[i] in style) {\r\n\t\t\treturn props[i];\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n\r\n// @function setTransform(el: HTMLElement, offset: Point, scale?: Number)\r\n// Resets the 3D CSS transform of `el` so it is translated by `offset` pixels\r\n// and optionally scaled by `scale`. Does not have an effect if the\r\n// browser doesn't support 3D CSS transforms.\r\nfunction setTransform(el, offset, scale) {\r\n\tvar pos = offset || new Point(0, 0);\r\n\r\n\tel.style[TRANSFORM] =\r\n\t\t(ie3d ?\r\n\t\t\t'translate(' + pos.x + 'px,' + pos.y + 'px)' :\r\n\t\t\t'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +\r\n\t\t(scale ? ' scale(' + scale + ')' : '');\r\n}\r\n\r\n// @function setPosition(el: HTMLElement, position: Point)\r\n// Sets the position of `el` to coordinates specified by `position`,\r\n// using CSS translate or top/left positioning depending on the browser\r\n// (used by Leaflet internally to position its layers).\r\nfunction setPosition(el, point) {\r\n\r\n\t/*eslint-disable */\r\n\tel._leaflet_pos = point;\r\n\t/* eslint-enable */\r\n\r\n\tif (any3d) {\r\n\t\tsetTransform(el, point);\r\n\t} else {\r\n\t\tel.style.left = point.x + 'px';\r\n\t\tel.style.top = point.y + 'px';\r\n\t}\r\n}\r\n\r\n// @function getPosition(el: HTMLElement): Point\r\n// Returns the coordinates of an element previously positioned with setPosition.\r\nfunction getPosition(el) {\r\n\t// this method is only used for elements previously positioned using setPosition,\r\n\t// so it's safe to cache the position for performance\r\n\r\n\treturn el._leaflet_pos || new Point(0, 0);\r\n}\r\n\r\n// @function disableTextSelection()\r\n// Prevents the user from generating `selectstart` DOM events, usually generated\r\n// when the user drags the mouse through a page with text. Used internally\r\n// by Leaflet to override the behaviour of any click-and-drag interaction on\r\n// the map. Affects drag interactions on the whole document.\r\n\r\n// @function enableTextSelection()\r\n// Cancels the effects of a previous [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection).\r\nvar disableTextSelection;\r\nvar enableTextSelection;\r\nvar _userSelect;\r\nif ('onselectstart' in document) {\r\n\tdisableTextSelection = function () {\r\n\t\ton(window, 'selectstart', preventDefault);\r\n\t};\r\n\tenableTextSelection = function () {\r\n\t\toff(window, 'selectstart', preventDefault);\r\n\t};\r\n} else {\r\n\tvar userSelectProperty = testProp(\r\n\t\t['userSelect', 'WebkitUserSelect', 'OUserSelect', 'MozUserSelect', 'msUserSelect']);\r\n\r\n\tdisableTextSelection = function () {\r\n\t\tif (userSelectProperty) {\r\n\t\t\tvar style = document.documentElement.style;\r\n\t\t\t_userSelect = style[userSelectProperty];\r\n\t\t\tstyle[userSelectProperty] = 'none';\r\n\t\t}\r\n\t};\r\n\tenableTextSelection = function () {\r\n\t\tif (userSelectProperty) {\r\n\t\t\tdocument.documentElement.style[userSelectProperty] = _userSelect;\r\n\t\t\t_userSelect = undefined;\r\n\t\t}\r\n\t};\r\n}\r\n\r\n// @function disableImageDrag()\r\n// As [`L.DomUtil.disableTextSelection`](#domutil-disabletextselection), but\r\n// for `dragstart` DOM events, usually generated when the user drags an image.\r\nfunction disableImageDrag() {\r\n\ton(window, 'dragstart', preventDefault);\r\n}\r\n\r\n// @function enableImageDrag()\r\n// Cancels the effects of a previous [`L.DomUtil.disableImageDrag`](#domutil-disabletextselection).\r\nfunction enableImageDrag() {\r\n\toff(window, 'dragstart', preventDefault);\r\n}\r\n\r\nvar _outlineElement;\nvar _outlineStyle;\r\n// @function preventOutline(el: HTMLElement)\r\n// Makes the [outline](https://developer.mozilla.org/docs/Web/CSS/outline)\r\n// of the element `el` invisible. Used internally by Leaflet to prevent\r\n// focusable elements from displaying an outline when the user performs a\r\n// drag interaction on them.\r\nfunction preventOutline(element) {\r\n\twhile (element.tabIndex === -1) {\r\n\t\telement = element.parentNode;\r\n\t}\r\n\tif (!element.style) { return; }\r\n\trestoreOutline();\r\n\t_outlineElement = element;\r\n\t_outlineStyle = element.style.outline;\r\n\telement.style.outline = 'none';\r\n\ton(window, 'keydown', restoreOutline);\r\n}\r\n\r\n// @function restoreOutline()\r\n// Cancels the effects of a previous [`L.DomUtil.preventOutline`]().\r\nfunction restoreOutline() {\r\n\tif (!_outlineElement) { return; }\r\n\t_outlineElement.style.outline = _outlineStyle;\r\n\t_outlineElement = undefined;\r\n\t_outlineStyle = undefined;\r\n\toff(window, 'keydown', restoreOutline);\r\n}\r\n\r\n// @function getSizedParentNode(el: HTMLElement): HTMLElement\r\n// Finds the closest parent node which size (width and height) is not null.\r\nfunction getSizedParentNode(element) {\r\n\tdo {\r\n\t\telement = element.parentNode;\r\n\t} while ((!element.offsetWidth || !element.offsetHeight) && element !== document.body);\r\n\treturn element;\r\n}\r\n\r\n// @function getScale(el: HTMLElement): Object\r\n// Computes the CSS scale currently applied on the element.\r\n// Returns an object with `x` and `y` members as horizontal and vertical scales respectively,\r\n// and `boundingClientRect` as the result of [`getBoundingClientRect()`](https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect).\r\nfunction getScale(element) {\r\n\tvar rect = element.getBoundingClientRect(); // Read-only in old browsers.\r\n\r\n\treturn {\r\n\t\tx: rect.width / element.offsetWidth || 1,\r\n\t\ty: rect.height / element.offsetHeight || 1,\r\n\t\tboundingClientRect: rect\r\n\t};\r\n}\r\n\n\nvar DomUtil = (Object.freeze || Object)({\n\tTRANSFORM: TRANSFORM,\n\tTRANSITION: TRANSITION,\n\tTRANSITION_END: TRANSITION_END,\n\tget: get,\n\tgetStyle: getStyle,\n\tcreate: create$1,\n\tremove: remove,\n\tempty: empty,\n\ttoFront: toFront,\n\ttoBack: toBack,\n\thasClass: hasClass,\n\taddClass: addClass,\n\tremoveClass: removeClass,\n\tsetClass: setClass,\n\tgetClass: getClass,\n\tsetOpacity: setOpacity,\n\ttestProp: testProp,\n\tsetTransform: setTransform,\n\tsetPosition: setPosition,\n\tgetPosition: getPosition,\n\tdisableTextSelection: disableTextSelection,\n\tenableTextSelection: enableTextSelection,\n\tdisableImageDrag: disableImageDrag,\n\tenableImageDrag: enableImageDrag,\n\tpreventOutline: preventOutline,\n\trestoreOutline: restoreOutline,\n\tgetSizedParentNode: getSizedParentNode,\n\tgetScale: getScale\n});\n\n/*\r\n * @namespace DomEvent\r\n * Utility functions to work with the [DOM events](https://developer.mozilla.org/docs/Web/API/Event), used by Leaflet internally.\r\n */\r\n\r\n// Inspired by John Resig, Dean Edwards and YUI addEvent implementations.\r\n\r\n// @function on(el: HTMLElement, types: String, fn: Function, context?: Object): this\r\n// Adds a listener function (`fn`) to a particular DOM event type of the\r\n// element `el`. You can optionally specify the context of the listener\r\n// (object the `this` keyword will point to). You can also pass several\r\n// space-separated types (e.g. `'click dblclick'`).\r\n\r\n// @alternative\r\n// @function on(el: HTMLElement, eventMap: Object, context?: Object): this\r\n// Adds a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`\r\nfunction on(obj, types, fn, context) {\r\n\r\n\tif (typeof types === 'object') {\r\n\t\tfor (var type in types) {\r\n\t\t\taddOne(obj, type, types[type], fn);\r\n\t\t}\r\n\t} else {\r\n\t\ttypes = splitWords(types);\r\n\r\n\t\tfor (var i = 0, len = types.length; i < len; i++) {\r\n\t\t\taddOne(obj, types[i], fn, context);\r\n\t\t}\r\n\t}\r\n\r\n\treturn this;\r\n}\r\n\r\nvar eventsKey = '_leaflet_events';\r\n\r\n// @function off(el: HTMLElement, types: String, fn: Function, context?: Object): this\r\n// Removes a previously added listener function.\r\n// Note that if you passed a custom context to on, you must pass the same\r\n// context to `off` in order to remove the listener.\r\n\r\n// @alternative\r\n// @function off(el: HTMLElement, eventMap: Object, context?: Object): this\r\n// Removes a set of type/listener pairs, e.g. `{click: onClick, mousemove: onMouseMove}`\r\nfunction off(obj, types, fn, context) {\r\n\r\n\tif (typeof types === 'object') {\r\n\t\tfor (var type in types) {\r\n\t\t\tremoveOne(obj, type, types[type], fn);\r\n\t\t}\r\n\t} else if (types) {\r\n\t\ttypes = splitWords(types);\r\n\r\n\t\tfor (var i = 0, len = types.length; i < len; i++) {\r\n\t\t\tremoveOne(obj, types[i], fn, context);\r\n\t\t}\r\n\t} else {\r\n\t\tfor (var j in obj[eventsKey]) {\r\n\t\t\tremoveOne(obj, j, obj[eventsKey][j]);\r\n\t\t}\r\n\t\tdelete obj[eventsKey];\r\n\t}\r\n\r\n\treturn this;\r\n}\r\n\r\nfunction addOne(obj, type, fn, context) {\r\n\tvar id = type + stamp(fn) + (context ? '_' + stamp(context) : '');\r\n\r\n\tif (obj[eventsKey] && obj[eventsKey][id]) { return this; }\r\n\r\n\tvar handler = function (e) {\r\n\t\treturn fn.call(context || obj, e || window.event);\r\n\t};\r\n\r\n\tvar originalHandler = handler;\r\n\r\n\tif (pointer && type.indexOf('touch') === 0) {\r\n\t\t// Needs DomEvent.Pointer.js\r\n\t\taddPointerListener(obj, type, handler, id);\r\n\r\n\t} else if (touch && (type === 'dblclick') && addDoubleTapListener &&\r\n\t !(pointer && chrome)) {\r\n\t\t// Chrome >55 does not need the synthetic dblclicks from addDoubleTapListener\r\n\t\t// See #5180\r\n\t\taddDoubleTapListener(obj, handler, id);\r\n\r\n\t} else if ('addEventListener' in obj) {\r\n\r\n\t\tif (type === 'mousewheel') {\r\n\t\t\tobj.addEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false);\r\n\r\n\t\t} else if ((type === 'mouseenter') || (type === 'mouseleave')) {\r\n\t\t\thandler = function (e) {\r\n\t\t\t\te = e || window.event;\r\n\t\t\t\tif (isExternalTarget(obj, e)) {\r\n\t\t\t\t\toriginalHandler(e);\r\n\t\t\t\t}\r\n\t\t\t};\r\n\t\t\tobj.addEventListener(type === 'mouseenter' ? 'mouseover' : 'mouseout', handler, false);\r\n\r\n\t\t} else {\r\n\t\t\tif (type === 'click' && android) {\r\n\t\t\t\thandler = function (e) {\r\n\t\t\t\t\tfilterClick(e, originalHandler);\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t\tobj.addEventListener(type, handler, false);\r\n\t\t}\r\n\r\n\t} else if ('attachEvent' in obj) {\r\n\t\tobj.attachEvent('on' + type, handler);\r\n\t}\r\n\r\n\tobj[eventsKey] = obj[eventsKey] || {};\r\n\tobj[eventsKey][id] = handler;\r\n}\r\n\r\nfunction removeOne(obj, type, fn, context) {\r\n\r\n\tvar id = type + stamp(fn) + (context ? '_' + stamp(context) : ''),\r\n\t handler = obj[eventsKey] && obj[eventsKey][id];\r\n\r\n\tif (!handler) { return this; }\r\n\r\n\tif (pointer && type.indexOf('touch') === 0) {\r\n\t\tremovePointerListener(obj, type, id);\r\n\r\n\t} else if (touch && (type === 'dblclick') && removeDoubleTapListener &&\r\n\t !(pointer && chrome)) {\r\n\t\tremoveDoubleTapListener(obj, id);\r\n\r\n\t} else if ('removeEventListener' in obj) {\r\n\r\n\t\tif (type === 'mousewheel') {\r\n\t\t\tobj.removeEventListener('onwheel' in obj ? 'wheel' : 'mousewheel', handler, false);\r\n\r\n\t\t} else {\r\n\t\t\tobj.removeEventListener(\r\n\t\t\t\ttype === 'mouseenter' ? 'mouseover' :\r\n\t\t\t\ttype === 'mouseleave' ? 'mouseout' : type, handler, false);\r\n\t\t}\r\n\r\n\t} else if ('detachEvent' in obj) {\r\n\t\tobj.detachEvent('on' + type, handler);\r\n\t}\r\n\r\n\tobj[eventsKey][id] = null;\r\n}\r\n\r\n// @function stopPropagation(ev: DOMEvent): this\r\n// Stop the given event from propagation to parent elements. Used inside the listener functions:\r\n// ```js\r\n// L.DomEvent.on(div, 'click', function (ev) {\r\n// \tL.DomEvent.stopPropagation(ev);\r\n// });\r\n// ```\r\nfunction stopPropagation(e) {\r\n\r\n\tif (e.stopPropagation) {\r\n\t\te.stopPropagation();\r\n\t} else if (e.originalEvent) { // In case of Leaflet event.\r\n\t\te.originalEvent._stopped = true;\r\n\t} else {\r\n\t\te.cancelBubble = true;\r\n\t}\r\n\tskipped(e);\r\n\r\n\treturn this;\r\n}\r\n\r\n// @function disableScrollPropagation(el: HTMLElement): this\r\n// Adds `stopPropagation` to the element's `'mousewheel'` events (plus browser variants).\r\nfunction disableScrollPropagation(el) {\r\n\taddOne(el, 'mousewheel', stopPropagation);\r\n\treturn this;\r\n}\r\n\r\n// @function disableClickPropagation(el: HTMLElement): this\r\n// Adds `stopPropagation` to the element's `'click'`, `'doubleclick'`,\r\n// `'mousedown'` and `'touchstart'` events (plus browser variants).\r\nfunction disableClickPropagation(el) {\r\n\ton(el, 'mousedown touchstart dblclick', stopPropagation);\r\n\taddOne(el, 'click', fakeStop);\r\n\treturn this;\r\n}\r\n\r\n// @function preventDefault(ev: DOMEvent): this\r\n// Prevents the default action of the DOM Event `ev` from happening (such as\r\n// following a link in the href of the a element, or doing a POST request\r\n// with page reload when a `<form>` is submitted).\r\n// Use it inside listener functions.\r\nfunction preventDefault(e) {\r\n\tif (e.preventDefault) {\r\n\t\te.preventDefault();\r\n\t} else {\r\n\t\te.returnValue = false;\r\n\t}\r\n\treturn this;\r\n}\r\n\r\n// @function stop(ev: DOMEvent): this\r\n// Does `stopPropagation` and `preventDefault` at the same time.\r\nfunction stop(e) {\r\n\tpreventDefault(e);\r\n\tstopPropagation(e);\r\n\treturn this;\r\n}\r\n\r\n// @function getMousePosition(ev: DOMEvent, container?: HTMLElement): Point\r\n// Gets normalized mouse position from a DOM event relative to the\r\n// `container` (border excluded) or to the whole page if not specified.\r\nfunction getMousePosition(e, container) {\r\n\tif (!container) {\r\n\t\treturn new Point(e.clientX, e.clientY);\r\n\t}\r\n\r\n\tvar scale = getScale(container),\r\n\t offset = scale.boundingClientRect; // left and top values are in page scale (like the event clientX/Y)\r\n\r\n\treturn new Point(\r\n\t\t// offset.left/top values are in page scale (like clientX/Y),\r\n\t\t// whereas clientLeft/Top (border width) values are the original values (before CSS scale applies).\r\n\t\t(e.clientX - offset.left) / scale.x - container.clientLeft,\r\n\t\t(e.clientY - offset.top) / scale.y - container.clientTop\r\n\t);\r\n}\r\n\r\n// Chrome on Win scrolls double the pixels as in other platforms (see #4538),\r\n// and Firefox scrolls device pixels, not CSS pixels\r\nvar wheelPxFactor =\r\n\t(win && chrome) ? 2 * window.devicePixelRatio :\r\n\tgecko ? window.devicePixelRatio : 1;\r\n\r\n// @function getWheelDelta(ev: DOMEvent): Number\r\n// Gets normalized wheel delta from a mousewheel DOM event, in vertical\r\n// pixels scrolled (negative if scrolling down).\r\n// Events from pointing devices without precise scrolling are mapped to\r\n// a best guess of 60 pixels.\r\nfunction getWheelDelta(e) {\r\n\treturn (edge) ? e.wheelDeltaY / 2 : // Don't trust window-geometry-based delta\r\n\t (e.deltaY && e.deltaMode === 0) ? -e.deltaY / wheelPxFactor : // Pixels\r\n\t (e.deltaY && e.deltaMode === 1) ? -e.deltaY * 20 : // Lines\r\n\t (e.deltaY && e.deltaMode === 2) ? -e.deltaY * 60 : // Pages\r\n\t (e.deltaX || e.deltaZ) ? 0 :\t// Skip horizontal/depth wheel events\r\n\t e.wheelDelta ? (e.wheelDeltaY || e.wheelDelta) / 2 : // Legacy IE pixels\r\n\t (e.detail && Math.abs(e.detail) < 32765) ? -e.detail * 20 : // Legacy Moz lines\r\n\t e.detail ? e.detail / -32765 * 60 : // Legacy Moz pages\r\n\t 0;\r\n}\r\n\r\nvar skipEvents = {};\r\n\r\nfunction fakeStop(e) {\r\n\t// fakes stopPropagation by setting a special event flag, checked/reset with skipped(e)\r\n\tskipEvents[e.type] = true;\r\n}\r\n\r\nfunction skipped(e) {\r\n\tvar events = skipEvents[e.type];\r\n\t// reset when checking, as it's only used in map container and propagates outside of the map\r\n\tskipEvents[e.type] = false;\r\n\treturn events;\r\n}\r\n\r\n// check if element really left/entered the event target (for mouseenter/mouseleave)\r\nfunction isExternalTarget(el, e) {\r\n\r\n\tvar related = e.relatedTarget;\r\n\r\n\tif (!related) { return true; }\r\n\r\n\ttry {\r\n\t\twhile (related && (related !== el)) {\r\n\t\t\trelated = related.parentNode;\r\n\t\t}\r\n\t} catch (err) {\r\n\t\treturn false;\r\n\t}\r\n\treturn (related !== el);\r\n}\r\n\r\nvar lastClick;\r\n\r\n// this is a horrible workaround for a bug in Android where a single touch triggers two click events\r\nfunction filterClick(e, handler) {\r\n\tvar timeStamp = (e.timeStamp || (e.originalEvent && e.originalEvent.timeStamp)),\r\n\t elapsed = lastClick && (timeStamp - lastClick);\r\n\r\n\t// are they closer together than 500ms yet more than 100ms?\r\n\t// Android typically triggers them ~300ms apart while multiple listeners\r\n\t// on the same event should be triggered far faster;\r\n\t// or check if click is simulated on the element, and if it is, reject any non-simulated events\r\n\r\n\tif ((elapsed && elapsed > 100 && elapsed < 500) || (e.target._simulatedClick && !e._simulated)) {\r\n\t\tstop(e);\r\n\t\treturn;\r\n\t}\r\n\tlastClick = timeStamp;\r\n\r\n\thandler(e);\r\n}\r\n\r\n\r\n\n\nvar DomEvent = (Object.freeze || Object)({\n\ton: on,\n\toff: off,\n\tstopPropagation: stopPropagation,\n\tdisableScrollPropagation: disableScrollPropagation,\n\tdisableClickPropagation: disableClickPropagation,\n\tpreventDefault: preventDefault,\n\tstop: stop,\n\tgetMousePosition: getMousePosition,\n\tgetWheelDelta: getWheelDelta,\n\tfakeStop: fakeStop,\n\tskipped: skipped,\n\tisExternalTarget: isExternalTarget,\n\taddListener: on,\n\tremoveListener: off\n});\n\n/*\n * @class PosAnimation\n * @aka L.PosAnimation\n * @inherits Evented\n * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.\n *\n * @example\n * ```js\n * var fx = new L.PosAnimation();\n * fx.run(el, [300, 500], 0.5);\n * ```\n *\n * @constructor L.PosAnimation()\n * Creates a `PosAnimation` object.\n *\n */\n\nvar PosAnimation = Evented.extend({\n\n\t// @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number)\n\t// Run an animation of a given element to a new position, optionally setting\n\t// duration in seconds (`0.25` by default) and easing linearity factor (3rd\n\t// argument of the [cubic bezier curve](http://cubic-bezier.com/#0,0,.5,1),\n\t// `0.5` by default).\n\trun: function (el, newPos, duration, easeLinearity) {\n\t\tthis.stop();\n\n\t\tthis._el = el;\n\t\tthis._inProgress = true;\n\t\tthis._duration = duration || 0.25;\n\t\tthis._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);\n\n\t\tthis._startPos = getPosition(el);\n\t\tthis._offset = newPos.subtract(this._startPos);\n\t\tthis._startTime = +new Date();\n\n\t\t// @event start: Event\n\t\t// Fired when the animation starts\n\t\tthis.fire('start');\n\n\t\tthis._animate();\n\t},\n\n\t// @method stop()\n\t// Stops the animation (if currently running).\n\tstop: function () {\n\t\tif (!this._inProgress) { return; }\n\n\t\tthis._step(true);\n\t\tthis._complete();\n\t},\n\n\t_animate: function () {\n\t\t// animation loop\n\t\tthis._animId = requestAnimFrame(this._animate, this);\n\t\tthis._step();\n\t},\n\n\t_step: function (round) {\n\t\tvar elapsed = (+new Date()) - this._startTime,\n\t\t duration = this._duration * 1000;\n\n\t\tif (elapsed < duration) {\n\t\t\tthis._runFrame(this._easeOut(elapsed / duration), round);\n\t\t} else {\n\t\t\tthis._runFrame(1);\n\t\t\tthis._complete();\n\t\t}\n\t},\n\n\t_runFrame: function (progress, round) {\n\t\tvar pos = this._startPos.add(this._offset.multiplyBy(progress));\n\t\tif (round) {\n\t\t\tpos._round();\n\t\t}\n\t\tsetPosition(this._el, pos);\n\n\t\t// @event step: Event\n\t\t// Fired continuously during the animation.\n\t\tthis.fire('step');\n\t},\n\n\t_complete: function () {\n\t\tcancelAnimFrame(this._animId);\n\n\t\tthis._inProgress = false;\n\t\t// @event end: Event\n\t\t// Fired when the animation ends.\n\t\tthis.fire('end');\n\t},\n\n\t_easeOut: function (t) {\n\t\treturn 1 - Math.pow(1 - t, this._easeOutPower);\n\t}\n});\n\n/*\r\n * @class Map\r\n * @aka L.Map\r\n * @inherits Evented\r\n *\r\n * The central class of the API — it is used to create a map on a page and manipulate it.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * // initialize the map on the \"map\" div with a given center and zoom\r\n * var map = L.map('map', {\r\n * \tcenter: [51.505, -0.09],\r\n * \tzoom: 13\r\n * });\r\n * ```\r\n *\r\n */\r\n\r\nvar Map = Evented.extend({\r\n\r\n\toptions: {\r\n\t\t// @section Map State Options\r\n\t\t// @option crs: CRS = L.CRS.EPSG3857\r\n\t\t// The [Coordinate Reference System](#crs) to use. Don't change this if you're not\r\n\t\t// sure what it means.\r\n\t\tcrs: EPSG3857,\r\n\r\n\t\t// @option center: LatLng = undefined\r\n\t\t// Initial geographic center of the map\r\n\t\tcenter: undefined,\r\n\r\n\t\t// @option zoom: Number = undefined\r\n\t\t// Initial map zoom level\r\n\t\tzoom: undefined,\r\n\r\n\t\t// @option minZoom: Number = *\r\n\t\t// Minimum zoom level of the map.\r\n\t\t// If not specified and at least one `GridLayer` or `TileLayer` is in the map,\r\n\t\t// the lowest of their `minZoom` options will be used instead.\r\n\t\tminZoom: undefined,\r\n\r\n\t\t// @option maxZoom: Number = *\r\n\t\t// Maximum zoom level of the map.\r\n\t\t// If not specified and at least one `GridLayer` or `TileLayer` is in the map,\r\n\t\t// the highest of their `maxZoom` options will be used instead.\r\n\t\tmaxZoom: undefined,\r\n\r\n\t\t// @option layers: Layer[] = []\r\n\t\t// Array of layers that will be added to the map initially\r\n\t\tlayers: [],\r\n\r\n\t\t// @option maxBounds: LatLngBounds = null\r\n\t\t// When this option is set, the map restricts the view to the given\r\n\t\t// geographical bounds, bouncing the user back if the user tries to pan\r\n\t\t// outside the view. To set the restriction dynamically, use\r\n\t\t// [`setMaxBounds`](#map-setmaxbounds) method.\r\n\t\tmaxBounds: undefined,\r\n\r\n\t\t// @option renderer: Renderer = *\r\n\t\t// The default method for drawing vector layers on the map. `L.SVG`\r\n\t\t// or `L.Canvas` by default depending on browser support.\r\n\t\trenderer: undefined,\r\n\r\n\r\n\t\t// @section Animation Options\r\n\t\t// @option zoomAnimation: Boolean = true\r\n\t\t// Whether the map zoom animation is enabled. By default it's enabled\r\n\t\t// in all browsers that support CSS3 Transitions except Android.\r\n\t\tzoomAnimation: true,\r\n\r\n\t\t// @option zoomAnimationThreshold: Number = 4\r\n\t\t// Won't animate zoom if the zoom difference exceeds this value.\r\n\t\tzoomAnimationThreshold: 4,\r\n\r\n\t\t// @option fadeAnimation: Boolean = true\r\n\t\t// Whether the tile fade animation is enabled. By default it's enabled\r\n\t\t// in all browsers that support CSS3 Transitions except Android.\r\n\t\tfadeAnimation: true,\r\n\r\n\t\t// @option markerZoomAnimation: Boolean = true\r\n\t\t// Whether markers animate their zoom with the zoom animation, if disabled\r\n\t\t// they will disappear for the length of the animation. By default it's\r\n\t\t// enabled in all browsers that support CSS3 Transitions except Android.\r\n\t\tmarkerZoomAnimation: true,\r\n\r\n\t\t// @option transform3DLimit: Number = 2^23\r\n\t\t// Defines the maximum size of a CSS translation transform. The default\r\n\t\t// value should not be changed unless a web browser positions layers in\r\n\t\t// the wrong place after doing a large `panBy`.\r\n\t\ttransform3DLimit: 8388608, // Precision limit of a 32-bit float\r\n\r\n\t\t// @section Interaction Options\r\n\t\t// @option zoomSnap: Number = 1\r\n\t\t// Forces the map's zoom level to always be a multiple of this, particularly\r\n\t\t// right after a [`fitBounds()`](#map-fitbounds) or a pinch-zoom.\r\n\t\t// By default, the zoom level snaps to the nearest integer; lower values\r\n\t\t// (e.g. `0.5` or `0.1`) allow for greater granularity. A value of `0`\r\n\t\t// means the zoom level will not be snapped after `fitBounds` or a pinch-zoom.\r\n\t\tzoomSnap: 1,\r\n\r\n\t\t// @option zoomDelta: Number = 1\r\n\t\t// Controls how much the map's zoom level will change after a\r\n\t\t// [`zoomIn()`](#map-zoomin), [`zoomOut()`](#map-zoomout), pressing `+`\r\n\t\t// or `-` on the keyboard, or using the [zoom controls](#control-zoom).\r\n\t\t// Values smaller than `1` (e.g. `0.5`) allow for greater granularity.\r\n\t\tzoomDelta: 1,\r\n\r\n\t\t// @option trackResize: Boolean = true\r\n\t\t// Whether the map automatically handles browser window resize to update itself.\r\n\t\ttrackResize: true\r\n\t},\r\n\r\n\tinitialize: function (id, options) { // (HTMLElement or String, Object)\r\n\t\toptions = setOptions(this, options);\r\n\r\n\t\t// Make sure to assign internal flags at the beginning,\r\n\t\t// to avoid inconsistent state in some edge cases.\r\n\t\tthis._handlers = [];\r\n\t\tthis._layers = {};\r\n\t\tthis._zoomBoundLayers = {};\r\n\t\tthis._sizeChanged = true;\r\n\r\n\t\tthis._initContainer(id);\r\n\t\tthis._initLayout();\r\n\r\n\t\t// hack for https://github.com/Leaflet/Leaflet/issues/1980\r\n\t\tthis._onResize = bind(this._onResize, this);\r\n\r\n\t\tthis._initEvents();\r\n\r\n\t\tif (options.maxBounds) {\r\n\t\t\tthis.setMaxBounds(options.maxBounds);\r\n\t\t}\r\n\r\n\t\tif (options.zoom !== undefined) {\r\n\t\t\tthis._zoom = this._limitZoom(options.zoom);\r\n\t\t}\r\n\r\n\t\tif (options.center && options.zoom !== undefined) {\r\n\t\t\tthis.setView(toLatLng(options.center), options.zoom, {reset: true});\r\n\t\t}\r\n\r\n\t\tthis.callInitHooks();\r\n\r\n\t\t// don't animate on browsers without hardware-accelerated transitions or old Android/Opera\r\n\t\tthis._zoomAnimated = TRANSITION && any3d && !mobileOpera &&\r\n\t\t\t\tthis.options.zoomAnimation;\r\n\r\n\t\t// zoom transitions run with the same duration for all layers, so if one of transitionend events\r\n\t\t// happens after starting zoom animation (propagating to the map pane), we know that it ended globally\r\n\t\tif (this._zoomAnimated) {\r\n\t\t\tthis._createAnimProxy();\r\n\t\t\ton(this._proxy, TRANSITION_END, this._catchTransitionEnd, this);\r\n\t\t}\r\n\r\n\t\tthis._addLayers(this.options.layers);\r\n\t},\r\n\r\n\r\n\t// @section Methods for modifying map state\r\n\r\n\t// @method setView(center: LatLng, zoom: Number, options?: Zoom/pan options): this\r\n\t// Sets the view of the map (geographical center and zoom) with the given\r\n\t// animation options.\r\n\tsetView: function (center, zoom, options) {\r\n\r\n\t\tzoom = zoom === undefined ? this._zoom : this._limitZoom(zoom);\r\n\t\tcenter = this._limitCenter(toLatLng(center), zoom, this.options.maxBounds);\r\n\t\toptions = options || {};\r\n\r\n\t\tthis._stop();\r\n\r\n\t\tif (this._loaded && !options.reset && options !== true) {\r\n\r\n\t\t\tif (options.animate !== undefined) {\r\n\t\t\t\toptions.zoom = extend({animate: options.animate}, options.zoom);\r\n\t\t\t\toptions.pan = extend({animate: options.animate, duration: options.duration}, options.pan);\r\n\t\t\t}\r\n\r\n\t\t\t// try animating pan or zoom\r\n\t\t\tvar moved = (this._zoom !== zoom) ?\r\n\t\t\t\tthis._tryAnimatedZoom && this._tryAnimatedZoom(center, zoom, options.zoom) :\r\n\t\t\t\tthis._tryAnimatedPan(center, options.pan);\r\n\r\n\t\t\tif (moved) {\r\n\t\t\t\t// prevent resize handler call, the view will refresh after animation anyway\r\n\t\t\t\tclearTimeout(this._sizeTimer);\r\n\t\t\t\treturn this;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// animation didn't start, just reset the map view\r\n\t\tthis._resetView(center, zoom);\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method setZoom(zoom: Number, options?: Zoom/pan options): this\r\n\t// Sets the zoom of the map.\r\n\tsetZoom: function (zoom, options) {\r\n\t\tif (!this._loaded) {\r\n\t\t\tthis._zoom = zoom;\r\n\t\t\treturn this;\r\n\t\t}\r\n\t\treturn this.setView(this.getCenter(), zoom, {zoom: options});\r\n\t},\r\n\r\n\t// @method zoomIn(delta?: Number, options?: Zoom options): this\r\n\t// Increases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).\r\n\tzoomIn: function (delta, options) {\r\n\t\tdelta = delta || (any3d ? this.options.zoomDelta : 1);\r\n\t\treturn this.setZoom(this._zoom + delta, options);\r\n\t},\r\n\r\n\t// @method zoomOut(delta?: Number, options?: Zoom options): this\r\n\t// Decreases the zoom of the map by `delta` ([`zoomDelta`](#map-zoomdelta) by default).\r\n\tzoomOut: function (delta, options) {\r\n\t\tdelta = delta || (any3d ? this.options.zoomDelta : 1);\r\n\t\treturn this.setZoom(this._zoom - delta, options);\r\n\t},\r\n\r\n\t// @method setZoomAround(latlng: LatLng, zoom: Number, options: Zoom options): this\r\n\t// Zooms the map while keeping a specified geographical point on the map\r\n\t// stationary (e.g. used internally for scroll zoom and double-click zoom).\r\n\t// @alternative\r\n\t// @method setZoomAround(offset: Point, zoom: Number, options: Zoom options): this\r\n\t// Zooms the map while keeping a specified pixel on the map (relative to the top-left corner) stationary.\r\n\tsetZoomAround: function (latlng, zoom, options) {\r\n\t\tvar scale = this.getZoomScale(zoom),\r\n\t\t viewHalf = this.getSize().divideBy(2),\r\n\t\t containerPoint = latlng instanceof Point ? latlng : this.latLngToContainerPoint(latlng),\r\n\r\n\t\t centerOffset = containerPoint.subtract(viewHalf).multiplyBy(1 - 1 / scale),\r\n\t\t newCenter = this.containerPointToLatLng(viewHalf.add(centerOffset));\r\n\r\n\t\treturn this.setView(newCenter, zoom, {zoom: options});\r\n\t},\r\n\r\n\t_getBoundsCenterZoom: function (bounds, options) {\r\n\r\n\t\toptions = options || {};\r\n\t\tbounds = bounds.getBounds ? bounds.getBounds() : toLatLngBounds(bounds);\r\n\r\n\t\tvar paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),\r\n\t\t paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),\r\n\r\n\t\t zoom = this.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));\r\n\r\n\t\tzoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom;\r\n\r\n\t\tif (zoom === Infinity) {\r\n\t\t\treturn {\r\n\t\t\t\tcenter: bounds.getCenter(),\r\n\t\t\t\tzoom: zoom\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tvar paddingOffset = paddingBR.subtract(paddingTL).divideBy(2),\r\n\r\n\t\t swPoint = this.project(bounds.getSouthWest(), zoom),\r\n\t\t nePoint = this.project(bounds.getNorthEast(), zoom),\r\n\t\t center = this.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom);\r\n\r\n\t\treturn {\r\n\t\t\tcenter: center,\r\n\t\t\tzoom: zoom\r\n\t\t};\r\n\t},\r\n\r\n\t// @method fitBounds(bounds: LatLngBounds, options?: fitBounds options): this\r\n\t// Sets a map view that contains the given geographical bounds with the\r\n\t// maximum zoom level possible.\r\n\tfitBounds: function (bounds, options) {\r\n\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\r\n\t\tif (!bounds.isValid()) {\r\n\t\t\tthrow new Error('Bounds are not valid.');\r\n\t\t}\r\n\r\n\t\tvar target = this._getBoundsCenterZoom(bounds, options);\r\n\t\treturn this.setView(target.center, target.zoom, options);\r\n\t},\r\n\r\n\t// @method fitWorld(options?: fitBounds options): this\r\n\t// Sets a map view that mostly contains the whole world with the maximum\r\n\t// zoom level possible.\r\n\tfitWorld: function (options) {\r\n\t\treturn this.fitBounds([[-90, -180], [90, 180]], options);\r\n\t},\r\n\r\n\t// @method panTo(latlng: LatLng, options?: Pan options): this\r\n\t// Pans the map to a given center.\r\n\tpanTo: function (center, options) { // (LatLng)\r\n\t\treturn this.setView(center, this._zoom, {pan: options});\r\n\t},\r\n\r\n\t// @method panBy(offset: Point, options?: Pan options): this\r\n\t// Pans the map by a given number of pixels (animated).\r\n\tpanBy: function (offset, options) {\r\n\t\toffset = toPoint(offset).round();\r\n\t\toptions = options || {};\r\n\r\n\t\tif (!offset.x && !offset.y) {\r\n\t\t\treturn this.fire('moveend');\r\n\t\t}\r\n\t\t// If we pan too far, Chrome gets issues with tiles\r\n\t\t// and makes them disappear or appear in the wrong place (slightly offset) #2602\r\n\t\tif (options.animate !== true && !this.getSize().contains(offset)) {\r\n\t\t\tthis._resetView(this.unproject(this.project(this.getCenter()).add(offset)), this.getZoom());\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tif (!this._panAnim) {\r\n\t\t\tthis._panAnim = new PosAnimation();\r\n\r\n\t\t\tthis._panAnim.on({\r\n\t\t\t\t'step': this._onPanTransitionStep,\r\n\t\t\t\t'end': this._onPanTransitionEnd\r\n\t\t\t}, this);\r\n\t\t}\r\n\r\n\t\t// don't fire movestart if animating inertia\r\n\t\tif (!options.noMoveStart) {\r\n\t\t\tthis.fire('movestart');\r\n\t\t}\r\n\r\n\t\t// animate pan unless animate: false specified\r\n\t\tif (options.animate !== false) {\r\n\t\t\taddClass(this._mapPane, 'leaflet-pan-anim');\r\n\r\n\t\t\tvar newPos = this._getMapPanePos().subtract(offset).round();\r\n\t\t\tthis._panAnim.run(this._mapPane, newPos, options.duration || 0.25, options.easeLinearity);\r\n\t\t} else {\r\n\t\t\tthis._rawPanBy(offset);\r\n\t\t\tthis.fire('move').fire('moveend');\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method flyTo(latlng: LatLng, zoom?: Number, options?: Zoom/pan options): this\r\n\t// Sets the view of the map (geographical center and zoom) performing a smooth\r\n\t// pan-zoom animation.\r\n\tflyTo: function (targetCenter, targetZoom, options) {\r\n\r\n\t\toptions = options || {};\r\n\t\tif (options.animate === false || !any3d) {\r\n\t\t\treturn this.setView(targetCenter, targetZoom, options);\r\n\t\t}\r\n\r\n\t\tthis._stop();\r\n\r\n\t\tvar from = this.project(this.getCenter()),\r\n\t\t to = this.project(targetCenter),\r\n\t\t size = this.getSize(),\r\n\t\t startZoom = this._zoom;\r\n\r\n\t\ttargetCenter = toLatLng(targetCenter);\r\n\t\ttargetZoom = targetZoom === undefined ? startZoom : targetZoom;\r\n\r\n\t\tvar w0 = Math.max(size.x, size.y),\r\n\t\t w1 = w0 * this.getZoomScale(startZoom, targetZoom),\r\n\t\t u1 = (to.distanceTo(from)) || 1,\r\n\t\t rho = 1.42,\r\n\t\t rho2 = rho * rho;\r\n\r\n\t\tfunction r(i) {\r\n\t\t\tvar s1 = i ? -1 : 1,\r\n\t\t\t s2 = i ? w1 : w0,\r\n\t\t\t t1 = w1 * w1 - w0 * w0 + s1 * rho2 * rho2 * u1 * u1,\r\n\t\t\t b1 = 2 * s2 * rho2 * u1,\r\n\t\t\t b = t1 / b1,\r\n\t\t\t sq = Math.sqrt(b * b + 1) - b;\r\n\r\n\t\t\t // workaround for floating point precision bug when sq = 0, log = -Infinite,\r\n\t\t\t // thus triggering an infinite loop in flyTo\r\n\t\t\t var log = sq < 0.000000001 ? -18 : Math.log(sq);\r\n\r\n\t\t\treturn log;\r\n\t\t}\r\n\r\n\t\tfunction sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }\r\n\t\tfunction cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }\r\n\t\tfunction tanh(n) { return sinh(n) / cosh(n); }\r\n\r\n\t\tvar r0 = r(0);\r\n\r\n\t\tfunction w(s) { return w0 * (cosh(r0) / cosh(r0 + rho * s)); }\r\n\t\tfunction u(s) { return w0 * (cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2; }\r\n\r\n\t\tfunction easeOut(t) { return 1 - Math.pow(1 - t, 1.5); }\r\n\r\n\t\tvar start = Date.now(),\r\n\t\t S = (r(1) - r0) / rho,\r\n\t\t duration = options.duration ? 1000 * options.duration : 1000 * S * 0.8;\r\n\r\n\t\tfunction frame() {\r\n\t\t\tvar t = (Date.now() - start) / duration,\r\n\t\t\t s = easeOut(t) * S;\r\n\r\n\t\t\tif (t <= 1) {\r\n\t\t\t\tthis._flyToFrame = requestAnimFrame(frame, this);\r\n\r\n\t\t\t\tthis._move(\r\n\t\t\t\t\tthis.unproject(from.add(to.subtract(from).multiplyBy(u(s) / u1)), startZoom),\r\n\t\t\t\t\tthis.getScaleZoom(w0 / w(s), startZoom),\r\n\t\t\t\t\t{flyTo: true});\r\n\r\n\t\t\t} else {\r\n\t\t\t\tthis\r\n\t\t\t\t\t._move(targetCenter, targetZoom)\r\n\t\t\t\t\t._moveEnd(true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis._moveStart(true, options.noMoveStart);\r\n\r\n\t\tframe.call(this);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method flyToBounds(bounds: LatLngBounds, options?: fitBounds options): this\r\n\t// Sets the view of the map with a smooth animation like [`flyTo`](#map-flyto),\r\n\t// but takes a bounds parameter like [`fitBounds`](#map-fitbounds).\r\n\tflyToBounds: function (bounds, options) {\r\n\t\tvar target = this._getBoundsCenterZoom(bounds, options);\r\n\t\treturn this.flyTo(target.center, target.zoom, options);\r\n\t},\r\n\r\n\t// @method setMaxBounds(bounds: Bounds): this\r\n\t// Restricts the map view to the given bounds (see the [maxBounds](#map-maxbounds) option).\r\n\tsetMaxBounds: function (bounds) {\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\r\n\t\tif (!bounds.isValid()) {\r\n\t\t\tthis.options.maxBounds = null;\r\n\t\t\treturn this.off('moveend', this._panInsideMaxBounds);\r\n\t\t} else if (this.options.maxBounds) {\r\n\t\t\tthis.off('moveend', this._panInsideMaxBounds);\r\n\t\t}\r\n\r\n\t\tthis.options.maxBounds = bounds;\r\n\r\n\t\tif (this._loaded) {\r\n\t\t\tthis._panInsideMaxBounds();\r\n\t\t}\r\n\r\n\t\treturn this.on('moveend', this._panInsideMaxBounds);\r\n\t},\r\n\r\n\t// @method setMinZoom(zoom: Number): this\r\n\t// Sets the lower limit for the available zoom levels (see the [minZoom](#map-minzoom) option).\r\n\tsetMinZoom: function (zoom) {\r\n\t\tvar oldZoom = this.options.minZoom;\r\n\t\tthis.options.minZoom = zoom;\r\n\r\n\t\tif (this._loaded && oldZoom !== zoom) {\r\n\t\t\tthis.fire('zoomlevelschange');\r\n\r\n\t\t\tif (this.getZoom() < this.options.minZoom) {\r\n\t\t\t\treturn this.setZoom(zoom);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method setMaxZoom(zoom: Number): this\r\n\t// Sets the upper limit for the available zoom levels (see the [maxZoom](#map-maxzoom) option).\r\n\tsetMaxZoom: function (zoom) {\r\n\t\tvar oldZoom = this.options.maxZoom;\r\n\t\tthis.options.maxZoom = zoom;\r\n\r\n\t\tif (this._loaded && oldZoom !== zoom) {\r\n\t\t\tthis.fire('zoomlevelschange');\r\n\r\n\t\t\tif (this.getZoom() > this.options.maxZoom) {\r\n\t\t\t\treturn this.setZoom(zoom);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method panInsideBounds(bounds: LatLngBounds, options?: Pan options): this\r\n\t// Pans the map to the closest view that would lie inside the given bounds (if it's not already), controlling the animation using the options specific, if any.\r\n\tpanInsideBounds: function (bounds, options) {\r\n\t\tthis._enforcingBounds = true;\r\n\t\tvar center = this.getCenter(),\r\n\t\t newCenter = this._limitCenter(center, this._zoom, toLatLngBounds(bounds));\r\n\r\n\t\tif (!center.equals(newCenter)) {\r\n\t\t\tthis.panTo(newCenter, options);\r\n\t\t}\r\n\r\n\t\tthis._enforcingBounds = false;\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method panInside(latlng: LatLng, options?: options): this\r\n\t// Pans the map the minimum amount to make the `latlng` visible. Use\r\n\t// `padding`, `paddingTopLeft` and `paddingTopRight` options to fit\r\n\t// the display to more restricted bounds, like [`fitBounds`](#map-fitbounds).\r\n\t// If `latlng` is already within the (optionally padded) display bounds,\r\n\t// the map will not be panned.\r\n\tpanInside: function (latlng, options) {\r\n\t\toptions = options || {};\r\n\r\n\t\tvar paddingTL = toPoint(options.paddingTopLeft || options.padding || [0, 0]),\r\n\t\t paddingBR = toPoint(options.paddingBottomRight || options.padding || [0, 0]),\r\n\t\t center = this.getCenter(),\r\n\t\t pixelCenter = this.project(center),\r\n\t\t pixelPoint = this.project(latlng),\r\n\t\t pixelBounds = this.getPixelBounds(),\r\n\t\t halfPixelBounds = pixelBounds.getSize().divideBy(2),\r\n\t\t paddedBounds = toBounds([pixelBounds.min.add(paddingTL), pixelBounds.max.subtract(paddingBR)]);\r\n\r\n\t\tif (!paddedBounds.contains(pixelPoint)) {\r\n\t\t\tthis._enforcingBounds = true;\r\n\t\t\tvar diff = pixelCenter.subtract(pixelPoint),\r\n\t\t\t newCenter = toPoint(pixelPoint.x + diff.x, pixelPoint.y + diff.y);\r\n\r\n\t\t\tif (pixelPoint.x < paddedBounds.min.x || pixelPoint.x > paddedBounds.max.x) {\r\n\t\t\t\tnewCenter.x = pixelCenter.x - diff.x;\r\n\t\t\t\tif (diff.x > 0) {\r\n\t\t\t\t\tnewCenter.x += halfPixelBounds.x - paddingTL.x;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tnewCenter.x -= halfPixelBounds.x - paddingBR.x;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (pixelPoint.y < paddedBounds.min.y || pixelPoint.y > paddedBounds.max.y) {\r\n\t\t\t\tnewCenter.y = pixelCenter.y - diff.y;\r\n\t\t\t\tif (diff.y > 0) {\r\n\t\t\t\t\tnewCenter.y += halfPixelBounds.y - paddingTL.y;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tnewCenter.y -= halfPixelBounds.y - paddingBR.y;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tthis.panTo(this.unproject(newCenter), options);\r\n\t\t\tthis._enforcingBounds = false;\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method invalidateSize(options: Zoom/pan options): this\r\n\t// Checks if the map container size changed and updates the map if so —\r\n\t// call it after you've changed the map size dynamically, also animating\r\n\t// pan by default. If `options.pan` is `false`, panning will not occur.\r\n\t// If `options.debounceMoveend` is `true`, it will delay `moveend` event so\r\n\t// that it doesn't happen often even if the method is called many\r\n\t// times in a row.\r\n\r\n\t// @alternative\r\n\t// @method invalidateSize(animate: Boolean): this\r\n\t// Checks if the map container size changed and updates the map if so —\r\n\t// call it after you've changed the map size dynamically, also animating\r\n\t// pan by default.\r\n\tinvalidateSize: function (options) {\r\n\t\tif (!this._loaded) { return this; }\r\n\r\n\t\toptions = extend({\r\n\t\t\tanimate: false,\r\n\t\t\tpan: true\r\n\t\t}, options === true ? {animate: true} : options);\r\n\r\n\t\tvar oldSize = this.getSize();\r\n\t\tthis._sizeChanged = true;\r\n\t\tthis._lastCenter = null;\r\n\r\n\t\tvar newSize = this.getSize(),\r\n\t\t oldCenter = oldSize.divideBy(2).round(),\r\n\t\t newCenter = newSize.divideBy(2).round(),\r\n\t\t offset = oldCenter.subtract(newCenter);\r\n\r\n\t\tif (!offset.x && !offset.y) { return this; }\r\n\r\n\t\tif (options.animate && options.pan) {\r\n\t\t\tthis.panBy(offset);\r\n\r\n\t\t} else {\r\n\t\t\tif (options.pan) {\r\n\t\t\t\tthis._rawPanBy(offset);\r\n\t\t\t}\r\n\r\n\t\t\tthis.fire('move');\r\n\r\n\t\t\tif (options.debounceMoveend) {\r\n\t\t\t\tclearTimeout(this._sizeTimer);\r\n\t\t\t\tthis._sizeTimer = setTimeout(bind(this.fire, this, 'moveend'), 200);\r\n\t\t\t} else {\r\n\t\t\t\tthis.fire('moveend');\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// @section Map state change events\r\n\t\t// @event resize: ResizeEvent\r\n\t\t// Fired when the map is resized.\r\n\t\treturn this.fire('resize', {\r\n\t\t\toldSize: oldSize,\r\n\t\t\tnewSize: newSize\r\n\t\t});\r\n\t},\r\n\r\n\t// @section Methods for modifying map state\r\n\t// @method stop(): this\r\n\t// Stops the currently running `panTo` or `flyTo` animation, if any.\r\n\tstop: function () {\r\n\t\tthis.setZoom(this._limitZoom(this._zoom));\r\n\t\tif (!this.options.zoomSnap) {\r\n\t\t\tthis.fire('viewreset');\r\n\t\t}\r\n\t\treturn this._stop();\r\n\t},\r\n\r\n\t// @section Geolocation methods\r\n\t// @method locate(options?: Locate options): this\r\n\t// Tries to locate the user using the Geolocation API, firing a [`locationfound`](#map-locationfound)\r\n\t// event with location data on success or a [`locationerror`](#map-locationerror) event on failure,\r\n\t// and optionally sets the map view to the user's location with respect to\r\n\t// detection accuracy (or to the world view if geolocation failed).\r\n\t// Note that, if your page doesn't use HTTPS, this method will fail in\r\n\t// modern browsers ([Chrome 50 and newer](https://sites.google.com/a/chromium.org/dev/Home/chromium-security/deprecating-powerful-features-on-insecure-origins))\r\n\t// See `Locate options` for more details.\r\n\tlocate: function (options) {\r\n\r\n\t\toptions = this._locateOptions = extend({\r\n\t\t\ttimeout: 10000,\r\n\t\t\twatch: false\r\n\t\t\t// setView: false\r\n\t\t\t// maxZoom: <Number>\r\n\t\t\t// maximumAge: 0\r\n\t\t\t// enableHighAccuracy: false\r\n\t\t}, options);\r\n\r\n\t\tif (!('geolocation' in navigator)) {\r\n\t\t\tthis._handleGeolocationError({\r\n\t\t\t\tcode: 0,\r\n\t\t\t\tmessage: 'Geolocation not supported.'\r\n\t\t\t});\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tvar onResponse = bind(this._handleGeolocationResponse, this),\r\n\t\t onError = bind(this._handleGeolocationError, this);\r\n\r\n\t\tif (options.watch) {\r\n\t\t\tthis._locationWatchId =\r\n\t\t\t navigator.geolocation.watchPosition(onResponse, onError, options);\r\n\t\t} else {\r\n\t\t\tnavigator.geolocation.getCurrentPosition(onResponse, onError, options);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method stopLocate(): this\r\n\t// Stops watching location previously initiated by `map.locate({watch: true})`\r\n\t// and aborts resetting the map view if map.locate was called with\r\n\t// `{setView: true}`.\r\n\tstopLocate: function () {\r\n\t\tif (navigator.geolocation && navigator.geolocation.clearWatch) {\r\n\t\t\tnavigator.geolocation.clearWatch(this._locationWatchId);\r\n\t\t}\r\n\t\tif (this._locateOptions) {\r\n\t\t\tthis._locateOptions.setView = false;\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_handleGeolocationError: function (error) {\r\n\t\tvar c = error.code,\r\n\t\t message = error.message ||\r\n\t\t (c === 1 ? 'permission denied' :\r\n\t\t (c === 2 ? 'position unavailable' : 'timeout'));\r\n\r\n\t\tif (this._locateOptions.setView && !this._loaded) {\r\n\t\t\tthis.fitWorld();\r\n\t\t}\r\n\r\n\t\t// @section Location events\r\n\t\t// @event locationerror: ErrorEvent\r\n\t\t// Fired when geolocation (using the [`locate`](#map-locate) method) failed.\r\n\t\tthis.fire('locationerror', {\r\n\t\t\tcode: c,\r\n\t\t\tmessage: 'Geolocation error: ' + message + '.'\r\n\t\t});\r\n\t},\r\n\r\n\t_handleGeolocationResponse: function (pos) {\r\n\t\tvar lat = pos.coords.latitude,\r\n\t\t lng = pos.coords.longitude,\r\n\t\t latlng = new LatLng(lat, lng),\r\n\t\t bounds = latlng.toBounds(pos.coords.accuracy * 2),\r\n\t\t options = this._locateOptions;\r\n\r\n\t\tif (options.setView) {\r\n\t\t\tvar zoom = this.getBoundsZoom(bounds);\r\n\t\t\tthis.setView(latlng, options.maxZoom ? Math.min(zoom, options.maxZoom) : zoom);\r\n\t\t}\r\n\r\n\t\tvar data = {\r\n\t\t\tlatlng: latlng,\r\n\t\t\tbounds: bounds,\r\n\t\t\ttimestamp: pos.timestamp\r\n\t\t};\r\n\r\n\t\tfor (var i in pos.coords) {\r\n\t\t\tif (typeof pos.coords[i] === 'number') {\r\n\t\t\t\tdata[i] = pos.coords[i];\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// @event locationfound: LocationEvent\r\n\t\t// Fired when geolocation (using the [`locate`](#map-locate) method)\r\n\t\t// went successfully.\r\n\t\tthis.fire('locationfound', data);\r\n\t},\r\n\r\n\t// TODO Appropriate docs section?\r\n\t// @section Other Methods\r\n\t// @method addHandler(name: String, HandlerClass: Function): this\r\n\t// Adds a new `Handler` to the map, given its name and constructor function.\r\n\taddHandler: function (name, HandlerClass) {\r\n\t\tif (!HandlerClass) { return this; }\r\n\r\n\t\tvar handler = this[name] = new HandlerClass(this);\r\n\r\n\t\tthis._handlers.push(handler);\r\n\r\n\t\tif (this.options[name]) {\r\n\t\t\thandler.enable();\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method remove(): this\r\n\t// Destroys the map and clears all related event listeners.\r\n\tremove: function () {\r\n\r\n\t\tthis._initEvents(true);\r\n\r\n\t\tif (this._containerId !== this._container._leaflet_id) {\r\n\t\t\tthrow new Error('Map container is being reused by another instance');\r\n\t\t}\r\n\r\n\t\ttry {\r\n\t\t\t// throws error in IE6-8\r\n\t\t\tdelete this._container._leaflet_id;\r\n\t\t\tdelete this._containerId;\r\n\t\t} catch (e) {\r\n\t\t\t/*eslint-disable */\r\n\t\t\tthis._container._leaflet_id = undefined;\r\n\t\t\t/* eslint-enable */\r\n\t\t\tthis._containerId = undefined;\r\n\t\t}\r\n\r\n\t\tif (this._locationWatchId !== undefined) {\r\n\t\t\tthis.stopLocate();\r\n\t\t}\r\n\r\n\t\tthis._stop();\r\n\r\n\t\tremove(this._mapPane);\r\n\r\n\t\tif (this._clearControlPos) {\r\n\t\t\tthis._clearControlPos();\r\n\t\t}\r\n\t\tif (this._resizeRequest) {\r\n\t\t\tcancelAnimFrame(this._resizeRequest);\r\n\t\t\tthis._resizeRequest = null;\r\n\t\t}\r\n\r\n\t\tthis._clearHandlers();\r\n\r\n\t\tif (this._loaded) {\r\n\t\t\t// @section Map state change events\r\n\t\t\t// @event unload: Event\r\n\t\t\t// Fired when the map is destroyed with [remove](#map-remove) method.\r\n\t\t\tthis.fire('unload');\r\n\t\t}\r\n\r\n\t\tvar i;\r\n\t\tfor (i in this._layers) {\r\n\t\t\tthis._layers[i].remove();\r\n\t\t}\r\n\t\tfor (i in this._panes) {\r\n\t\t\tremove(this._panes[i]);\r\n\t\t}\r\n\r\n\t\tthis._layers = [];\r\n\t\tthis._panes = [];\r\n\t\tdelete this._mapPane;\r\n\t\tdelete this._renderer;\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @section Other Methods\r\n\t// @method createPane(name: String, container?: HTMLElement): HTMLElement\r\n\t// Creates a new [map pane](#map-pane) with the given name if it doesn't exist already,\r\n\t// then returns it. The pane is created as a child of `container`, or\r\n\t// as a child of the main map pane if not set.\r\n\tcreatePane: function (name, container) {\r\n\t\tvar className = 'leaflet-pane' + (name ? ' leaflet-' + name.replace('Pane', '') + '-pane' : ''),\r\n\t\t pane = create$1('div', className, container || this._mapPane);\r\n\r\n\t\tif (name) {\r\n\t\t\tthis._panes[name] = pane;\r\n\t\t}\r\n\t\treturn pane;\r\n\t},\r\n\r\n\t// @section Methods for Getting Map State\r\n\r\n\t// @method getCenter(): LatLng\r\n\t// Returns the geographical center of the map view\r\n\tgetCenter: function () {\r\n\t\tthis._checkIfLoaded();\r\n\r\n\t\tif (this._lastCenter && !this._moved()) {\r\n\t\t\treturn this._lastCenter;\r\n\t\t}\r\n\t\treturn this.layerPointToLatLng(this._getCenterLayerPoint());\r\n\t},\r\n\r\n\t// @method getZoom(): Number\r\n\t// Returns the current zoom level of the map view\r\n\tgetZoom: function () {\r\n\t\treturn this._zoom;\r\n\t},\r\n\r\n\t// @method getBounds(): LatLngBounds\r\n\t// Returns the geographical bounds visible in the current map view\r\n\tgetBounds: function () {\r\n\t\tvar bounds = this.getPixelBounds(),\r\n\t\t sw = this.unproject(bounds.getBottomLeft()),\r\n\t\t ne = this.unproject(bounds.getTopRight());\r\n\r\n\t\treturn new LatLngBounds(sw, ne);\r\n\t},\r\n\r\n\t// @method getMinZoom(): Number\r\n\t// Returns the minimum zoom level of the map (if set in the `minZoom` option of the map or of any layers), or `0` by default.\r\n\tgetMinZoom: function () {\r\n\t\treturn this.options.minZoom === undefined ? this._layersMinZoom || 0 : this.options.minZoom;\r\n\t},\r\n\r\n\t// @method getMaxZoom(): Number\r\n\t// Returns the maximum zoom level of the map (if set in the `maxZoom` option of the map or of any layers).\r\n\tgetMaxZoom: function () {\r\n\t\treturn this.options.maxZoom === undefined ?\r\n\t\t\t(this._layersMaxZoom === undefined ? Infinity : this._layersMaxZoom) :\r\n\t\t\tthis.options.maxZoom;\r\n\t},\r\n\r\n\t// @method getBoundsZoom(bounds: LatLngBounds, inside?: Boolean, padding?: Point): Number\r\n\t// Returns the maximum zoom level on which the given bounds fit to the map\r\n\t// view in its entirety. If `inside` (optional) is set to `true`, the method\r\n\t// instead returns the minimum zoom level on which the map view fits into\r\n\t// the given bounds in its entirety.\r\n\tgetBoundsZoom: function (bounds, inside, padding) { // (LatLngBounds[, Boolean, Point]) -> Number\r\n\t\tbounds = toLatLngBounds(bounds);\r\n\t\tpadding = toPoint(padding || [0, 0]);\r\n\r\n\t\tvar zoom = this.getZoom() || 0,\r\n\t\t min = this.getMinZoom(),\r\n\t\t max = this.getMaxZoom(),\r\n\t\t nw = bounds.getNorthWest(),\r\n\t\t se = bounds.getSouthEast(),\r\n\t\t size = this.getSize().subtract(padding),\r\n\t\t boundsSize = toBounds(this.project(se, zoom), this.project(nw, zoom)).getSize(),\r\n\t\t snap = any3d ? this.options.zoomSnap : 1,\r\n\t\t scalex = size.x / boundsSize.x,\r\n\t\t scaley = size.y / boundsSize.y,\r\n\t\t scale = inside ? Math.max(scalex, scaley) : Math.min(scalex, scaley);\r\n\r\n\t\tzoom = this.getScaleZoom(scale, zoom);\r\n\r\n\t\tif (snap) {\r\n\t\t\tzoom = Math.round(zoom / (snap / 100)) * (snap / 100); // don't jump if within 1% of a snap level\r\n\t\t\tzoom = inside ? Math.ceil(zoom / snap) * snap : Math.floor(zoom / snap) * snap;\r\n\t\t}\r\n\r\n\t\treturn Math.max(min, Math.min(max, zoom));\r\n\t},\r\n\r\n\t// @method getSize(): Point\r\n\t// Returns the current size of the map container (in pixels).\r\n\tgetSize: function () {\r\n\t\tif (!this._size || this._sizeChanged) {\r\n\t\t\tthis._size = new Point(\r\n\t\t\t\tthis._container.clientWidth || 0,\r\n\t\t\t\tthis._container.clientHeight || 0);\r\n\r\n\t\t\tthis._sizeChanged = false;\r\n\t\t}\r\n\t\treturn this._size.clone();\r\n\t},\r\n\r\n\t// @method getPixelBounds(): Bounds\r\n\t// Returns the bounds of the current map view in projected pixel\r\n\t// coordinates (sometimes useful in layer and overlay implementations).\r\n\tgetPixelBounds: function (center, zoom) {\r\n\t\tvar topLeftPoint = this._getTopLeftPoint(center, zoom);\r\n\t\treturn new Bounds(topLeftPoint, topLeftPoint.add(this.getSize()));\r\n\t},\r\n\r\n\t// TODO: Check semantics - isn't the pixel origin the 0,0 coord relative to\r\n\t// the map pane? \"left point of the map layer\" can be confusing, specially\r\n\t// since there can be negative offsets.\r\n\t// @method getPixelOrigin(): Point\r\n\t// Returns the projected pixel coordinates of the top left point of\r\n\t// the map layer (useful in custom layer and overlay implementations).\r\n\tgetPixelOrigin: function () {\r\n\t\tthis._checkIfLoaded();\r\n\t\treturn this._pixelOrigin;\r\n\t},\r\n\r\n\t// @method getPixelWorldBounds(zoom?: Number): Bounds\r\n\t// Returns the world's bounds in pixel coordinates for zoom level `zoom`.\r\n\t// If `zoom` is omitted, the map's current zoom level is used.\r\n\tgetPixelWorldBounds: function (zoom) {\r\n\t\treturn this.options.crs.getProjectedBounds(zoom === undefined ? this.getZoom() : zoom);\r\n\t},\r\n\r\n\t// @section Other Methods\r\n\r\n\t// @method getPane(pane: String|HTMLElement): HTMLElement\r\n\t// Returns a [map pane](#map-pane), given its name or its HTML element (its identity).\r\n\tgetPane: function (pane) {\r\n\t\treturn typeof pane === 'string' ? this._panes[pane] : pane;\r\n\t},\r\n\r\n\t// @method getPanes(): Object\r\n\t// Returns a plain object containing the names of all [panes](#map-pane) as keys and\r\n\t// the panes as values.\r\n\tgetPanes: function () {\r\n\t\treturn this._panes;\r\n\t},\r\n\r\n\t// @method getContainer: HTMLElement\r\n\t// Returns the HTML element that contains the map.\r\n\tgetContainer: function () {\r\n\t\treturn this._container;\r\n\t},\r\n\r\n\r\n\t// @section Conversion Methods\r\n\r\n\t// @method getZoomScale(toZoom: Number, fromZoom: Number): Number\r\n\t// Returns the scale factor to be applied to a map transition from zoom level\r\n\t// `fromZoom` to `toZoom`. Used internally to help with zoom animations.\r\n\tgetZoomScale: function (toZoom, fromZoom) {\r\n\t\t// TODO replace with universal implementation after refactoring projections\r\n\t\tvar crs = this.options.crs;\r\n\t\tfromZoom = fromZoom === undefined ? this._zoom : fromZoom;\r\n\t\treturn crs.scale(toZoom) / crs.scale(fromZoom);\r\n\t},\r\n\r\n\t// @method getScaleZoom(scale: Number, fromZoom: Number): Number\r\n\t// Returns the zoom level that the map would end up at, if it is at `fromZoom`\r\n\t// level and everything is scaled by a factor of `scale`. Inverse of\r\n\t// [`getZoomScale`](#map-getZoomScale).\r\n\tgetScaleZoom: function (scale, fromZoom) {\r\n\t\tvar crs = this.options.crs;\r\n\t\tfromZoom = fromZoom === undefined ? this._zoom : fromZoom;\r\n\t\tvar zoom = crs.zoom(scale * crs.scale(fromZoom));\r\n\t\treturn isNaN(zoom) ? Infinity : zoom;\r\n\t},\r\n\r\n\t// @method project(latlng: LatLng, zoom: Number): Point\r\n\t// Projects a geographical coordinate `LatLng` according to the projection\r\n\t// of the map's CRS, then scales it according to `zoom` and the CRS's\r\n\t// `Transformation`. The result is pixel coordinate relative to\r\n\t// the CRS origin.\r\n\tproject: function (latlng, zoom) {\r\n\t\tzoom = zoom === undefined ? this._zoom : zoom;\r\n\t\treturn this.options.crs.latLngToPoint(toLatLng(latlng), zoom);\r\n\t},\r\n\r\n\t// @method unproject(point: Point, zoom: Number): LatLng\r\n\t// Inverse of [`project`](#map-project).\r\n\tunproject: function (point, zoom) {\r\n\t\tzoom = zoom === undefined ? this._zoom : zoom;\r\n\t\treturn this.options.crs.pointToLatLng(toPoint(point), zoom);\r\n\t},\r\n\r\n\t// @method layerPointToLatLng(point: Point): LatLng\r\n\t// Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),\r\n\t// returns the corresponding geographical coordinate (for the current zoom level).\r\n\tlayerPointToLatLng: function (point) {\r\n\t\tvar projectedPoint = toPoint(point).add(this.getPixelOrigin());\r\n\t\treturn this.unproject(projectedPoint);\r\n\t},\r\n\r\n\t// @method latLngToLayerPoint(latlng: LatLng): Point\r\n\t// Given a geographical coordinate, returns the corresponding pixel coordinate\r\n\t// relative to the [origin pixel](#map-getpixelorigin).\r\n\tlatLngToLayerPoint: function (latlng) {\r\n\t\tvar projectedPoint = this.project(toLatLng(latlng))._round();\r\n\t\treturn projectedPoint._subtract(this.getPixelOrigin());\r\n\t},\r\n\r\n\t// @method wrapLatLng(latlng: LatLng): LatLng\r\n\t// Returns a `LatLng` where `lat` and `lng` has been wrapped according to the\r\n\t// map's CRS's `wrapLat` and `wrapLng` properties, if they are outside the\r\n\t// CRS's bounds.\r\n\t// By default this means longitude is wrapped around the dateline so its\r\n\t// value is between -180 and +180 degrees.\r\n\twrapLatLng: function (latlng) {\r\n\t\treturn this.options.crs.wrapLatLng(toLatLng(latlng));\r\n\t},\r\n\r\n\t// @method wrapLatLngBounds(bounds: LatLngBounds): LatLngBounds\r\n\t// Returns a `LatLngBounds` with the same size as the given one, ensuring that\r\n\t// its center is within the CRS's bounds.\r\n\t// By default this means the center longitude is wrapped around the dateline so its\r\n\t// value is between -180 and +180 degrees, and the majority of the bounds\r\n\t// overlaps the CRS's bounds.\r\n\twrapLatLngBounds: function (latlng) {\r\n\t\treturn this.options.crs.wrapLatLngBounds(toLatLngBounds(latlng));\r\n\t},\r\n\r\n\t// @method distance(latlng1: LatLng, latlng2: LatLng): Number\r\n\t// Returns the distance between two geographical coordinates according to\r\n\t// the map's CRS. By default this measures distance in meters.\r\n\tdistance: function (latlng1, latlng2) {\r\n\t\treturn this.options.crs.distance(toLatLng(latlng1), toLatLng(latlng2));\r\n\t},\r\n\r\n\t// @method containerPointToLayerPoint(point: Point): Point\r\n\t// Given a pixel coordinate relative to the map container, returns the corresponding\r\n\t// pixel coordinate relative to the [origin pixel](#map-getpixelorigin).\r\n\tcontainerPointToLayerPoint: function (point) { // (Point)\r\n\t\treturn toPoint(point).subtract(this._getMapPanePos());\r\n\t},\r\n\r\n\t// @method layerPointToContainerPoint(point: Point): Point\r\n\t// Given a pixel coordinate relative to the [origin pixel](#map-getpixelorigin),\r\n\t// returns the corresponding pixel coordinate relative to the map container.\r\n\tlayerPointToContainerPoint: function (point) { // (Point)\r\n\t\treturn toPoint(point).add(this._getMapPanePos());\r\n\t},\r\n\r\n\t// @method containerPointToLatLng(point: Point): LatLng\r\n\t// Given a pixel coordinate relative to the map container, returns\r\n\t// the corresponding geographical coordinate (for the current zoom level).\r\n\tcontainerPointToLatLng: function (point) {\r\n\t\tvar layerPoint = this.containerPointToLayerPoint(toPoint(point));\r\n\t\treturn this.layerPointToLatLng(layerPoint);\r\n\t},\r\n\r\n\t// @method latLngToContainerPoint(latlng: LatLng): Point\r\n\t// Given a geographical coordinate, returns the corresponding pixel coordinate\r\n\t// relative to the map container.\r\n\tlatLngToContainerPoint: function (latlng) {\r\n\t\treturn this.layerPointToContainerPoint(this.latLngToLayerPoint(toLatLng(latlng)));\r\n\t},\r\n\r\n\t// @method mouseEventToContainerPoint(ev: MouseEvent): Point\r\n\t// Given a MouseEvent object, returns the pixel coordinate relative to the\r\n\t// map container where the event took place.\r\n\tmouseEventToContainerPoint: function (e) {\r\n\t\treturn getMousePosition(e, this._container);\r\n\t},\r\n\r\n\t// @method mouseEventToLayerPoint(ev: MouseEvent): Point\r\n\t// Given a MouseEvent object, returns the pixel coordinate relative to\r\n\t// the [origin pixel](#map-getpixelorigin) where the event took place.\r\n\tmouseEventToLayerPoint: function (e) {\r\n\t\treturn this.containerPointToLayerPoint(this.mouseEventToContainerPoint(e));\r\n\t},\r\n\r\n\t// @method mouseEventToLatLng(ev: MouseEvent): LatLng\r\n\t// Given a MouseEvent object, returns geographical coordinate where the\r\n\t// event took place.\r\n\tmouseEventToLatLng: function (e) { // (MouseEvent)\r\n\t\treturn this.layerPointToLatLng(this.mouseEventToLayerPoint(e));\r\n\t},\r\n\r\n\r\n\t// map initialization methods\r\n\r\n\t_initContainer: function (id) {\r\n\t\tvar container = this._container = get(id);\r\n\r\n\t\tif (!container) {\r\n\t\t\tthrow new Error('Map container not found.');\r\n\t\t} else if (container._leaflet_id) {\r\n\t\t\tthrow new Error('Map container is already initialized.');\r\n\t\t}\r\n\r\n\t\ton(container, 'scroll', this._onScroll, this);\r\n\t\tthis._containerId = stamp(container);\r\n\t},\r\n\r\n\t_initLayout: function () {\r\n\t\tvar container = this._container;\r\n\r\n\t\tthis._fadeAnimated = this.options.fadeAnimation && any3d;\r\n\r\n\t\taddClass(container, 'leaflet-container' +\r\n\t\t\t(touch ? ' leaflet-touch' : '') +\r\n\t\t\t(retina ? ' leaflet-retina' : '') +\r\n\t\t\t(ielt9 ? ' leaflet-oldie' : '') +\r\n\t\t\t(safari ? ' leaflet-safari' : '') +\r\n\t\t\t(this._fadeAnimated ? ' leaflet-fade-anim' : ''));\r\n\r\n\t\tvar position = getStyle(container, 'position');\r\n\r\n\t\tif (position !== 'absolute' && position !== 'relative' && position !== 'fixed') {\r\n\t\t\tcontainer.style.position = 'relative';\r\n\t\t}\r\n\r\n\t\tthis._initPanes();\r\n\r\n\t\tif (this._initControlPos) {\r\n\t\t\tthis._initControlPos();\r\n\t\t}\r\n\t},\r\n\r\n\t_initPanes: function () {\r\n\t\tvar panes = this._panes = {};\r\n\t\tthis._paneRenderers = {};\r\n\r\n\t\t// @section\r\n\t\t//\r\n\t\t// Panes are DOM elements used to control the ordering of layers on the map. You\r\n\t\t// can access panes with [`map.getPane`](#map-getpane) or\r\n\t\t// [`map.getPanes`](#map-getpanes) methods. New panes can be created with the\r\n\t\t// [`map.createPane`](#map-createpane) method.\r\n\t\t//\r\n\t\t// Every map has the following default panes that differ only in zIndex.\r\n\t\t//\r\n\t\t// @pane mapPane: HTMLElement = 'auto'\r\n\t\t// Pane that contains all other map panes\r\n\r\n\t\tthis._mapPane = this.createPane('mapPane', this._container);\r\n\t\tsetPosition(this._mapPane, new Point(0, 0));\r\n\r\n\t\t// @pane tilePane: HTMLElement = 200\r\n\t\t// Pane for `GridLayer`s and `TileLayer`s\r\n\t\tthis.createPane('tilePane');\r\n\t\t// @pane overlayPane: HTMLElement = 400\r\n\t\t// Pane for vectors (`Path`s, like `Polyline`s and `Polygon`s), `ImageOverlay`s and `VideoOverlay`s\r\n\t\tthis.createPane('shadowPane');\r\n\t\t// @pane shadowPane: HTMLElement = 500\r\n\t\t// Pane for overlay shadows (e.g. `Marker` shadows)\r\n\t\tthis.createPane('overlayPane');\r\n\t\t// @pane markerPane: HTMLElement = 600\r\n\t\t// Pane for `Icon`s of `Marker`s\r\n\t\tthis.createPane('markerPane');\r\n\t\t// @pane tooltipPane: HTMLElement = 650\r\n\t\t// Pane for `Tooltip`s.\r\n\t\tthis.createPane('tooltipPane');\r\n\t\t// @pane popupPane: HTMLElement = 700\r\n\t\t// Pane for `Popup`s.\r\n\t\tthis.createPane('popupPane');\r\n\r\n\t\tif (!this.options.markerZoomAnimation) {\r\n\t\t\taddClass(panes.markerPane, 'leaflet-zoom-hide');\r\n\t\t\taddClass(panes.shadowPane, 'leaflet-zoom-hide');\r\n\t\t}\r\n\t},\r\n\r\n\r\n\t// private methods that modify map state\r\n\r\n\t// @section Map state change events\r\n\t_resetView: function (center, zoom) {\r\n\t\tsetPosition(this._mapPane, new Point(0, 0));\r\n\r\n\t\tvar loading = !this._loaded;\r\n\t\tthis._loaded = true;\r\n\t\tzoom = this._limitZoom(zoom);\r\n\r\n\t\tthis.fire('viewprereset');\r\n\r\n\t\tvar zoomChanged = this._zoom !== zoom;\r\n\t\tthis\r\n\t\t\t._moveStart(zoomChanged, false)\r\n\t\t\t._move(center, zoom)\r\n\t\t\t._moveEnd(zoomChanged);\r\n\r\n\t\t// @event viewreset: Event\r\n\t\t// Fired when the map needs to redraw its content (this usually happens\r\n\t\t// on map zoom or load). Very useful for creating custom overlays.\r\n\t\tthis.fire('viewreset');\r\n\r\n\t\t// @event load: Event\r\n\t\t// Fired when the map is initialized (when its center and zoom are set\r\n\t\t// for the first time).\r\n\t\tif (loading) {\r\n\t\t\tthis.fire('load');\r\n\t\t}\r\n\t},\r\n\r\n\t_moveStart: function (zoomChanged, noMoveStart) {\r\n\t\t// @event zoomstart: Event\r\n\t\t// Fired when the map zoom is about to change (e.g. before zoom animation).\r\n\t\t// @event movestart: Event\r\n\t\t// Fired when the view of the map starts changing (e.g. user starts dragging the map).\r\n\t\tif (zoomChanged) {\r\n\t\t\tthis.fire('zoomstart');\r\n\t\t}\r\n\t\tif (!noMoveStart) {\r\n\t\t\tthis.fire('movestart');\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_move: function (center, zoom, data) {\r\n\t\tif (zoom === undefined) {\r\n\t\t\tzoom = this._zoom;\r\n\t\t}\r\n\t\tvar zoomChanged = this._zoom !== zoom;\r\n\r\n\t\tthis._zoom = zoom;\r\n\t\tthis._lastCenter = center;\r\n\t\tthis._pixelOrigin = this._getNewPixelOrigin(center);\r\n\r\n\t\t// @event zoom: Event\r\n\t\t// Fired repeatedly during any change in zoom level, including zoom\r\n\t\t// and fly animations.\r\n\t\tif (zoomChanged || (data && data.pinch)) {\t// Always fire 'zoom' if pinching because #3530\r\n\t\t\tthis.fire('zoom', data);\r\n\t\t}\r\n\r\n\t\t// @event move: Event\r\n\t\t// Fired repeatedly during any movement of the map, including pan and\r\n\t\t// fly animations.\r\n\t\treturn this.fire('move', data);\r\n\t},\r\n\r\n\t_moveEnd: function (zoomChanged) {\r\n\t\t// @event zoomend: Event\r\n\t\t// Fired when the map has changed, after any animations.\r\n\t\tif (zoomChanged) {\r\n\t\t\tthis.fire('zoomend');\r\n\t\t}\r\n\r\n\t\t// @event moveend: Event\r\n\t\t// Fired when the center of the map stops changing (e.g. user stopped\r\n\t\t// dragging the map).\r\n\t\treturn this.fire('moveend');\r\n\t},\r\n\r\n\t_stop: function () {\r\n\t\tcancelAnimFrame(this._flyToFrame);\r\n\t\tif (this._panAnim) {\r\n\t\t\tthis._panAnim.stop();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_rawPanBy: function (offset) {\r\n\t\tsetPosition(this._mapPane, this._getMapPanePos().subtract(offset));\r\n\t},\r\n\r\n\t_getZoomSpan: function () {\r\n\t\treturn this.getMaxZoom() - this.getMinZoom();\r\n\t},\r\n\r\n\t_panInsideMaxBounds: function () {\r\n\t\tif (!this._enforcingBounds) {\r\n\t\t\tthis.panInsideBounds(this.options.maxBounds);\r\n\t\t}\r\n\t},\r\n\r\n\t_checkIfLoaded: function () {\r\n\t\tif (!this._loaded) {\r\n\t\t\tthrow new Error('Set map center and zoom first.');\r\n\t\t}\r\n\t},\r\n\r\n\t// DOM event handling\r\n\r\n\t// @section Interaction events\r\n\t_initEvents: function (remove$$1) {\r\n\t\tthis._targets = {};\r\n\t\tthis._targets[stamp(this._container)] = this;\r\n\r\n\t\tvar onOff = remove$$1 ? off : on;\r\n\r\n\t\t// @event click: MouseEvent\r\n\t\t// Fired when the user clicks (or taps) the map.\r\n\t\t// @event dblclick: MouseEvent\r\n\t\t// Fired when the user double-clicks (or double-taps) the map.\r\n\t\t// @event mousedown: MouseEvent\r\n\t\t// Fired when the user pushes the mouse button on the map.\r\n\t\t// @event mouseup: MouseEvent\r\n\t\t// Fired when the user releases the mouse button on the map.\r\n\t\t// @event mouseover: MouseEvent\r\n\t\t// Fired when the mouse enters the map.\r\n\t\t// @event mouseout: MouseEvent\r\n\t\t// Fired when the mouse leaves the map.\r\n\t\t// @event mousemove: MouseEvent\r\n\t\t// Fired while the mouse moves over the map.\r\n\t\t// @event contextmenu: MouseEvent\r\n\t\t// Fired when the user pushes the right mouse button on the map, prevents\r\n\t\t// default browser context menu from showing if there are listeners on\r\n\t\t// this event. Also fired on mobile when the user holds a single touch\r\n\t\t// for a second (also called long press).\r\n\t\t// @event keypress: KeyboardEvent\r\n\t\t// Fired when the user presses a key from the keyboard that produces a character value while the map is focused.\r\n\t\t// @event keydown: KeyboardEvent\r\n\t\t// Fired when the user presses a key from the keyboard while the map is focused. Unlike the `keypress` event,\r\n\t\t// the `keydown` event is fired for keys that produce a character value and for keys\r\n\t\t// that do not produce a character value.\r\n\t\t// @event keyup: KeyboardEvent\r\n\t\t// Fired when the user releases a key from the keyboard while the map is focused.\r\n\t\tonOff(this._container, 'click dblclick mousedown mouseup ' +\r\n\t\t\t'mouseover mouseout mousemove contextmenu keypress keydown keyup', this._handleDOMEvent, this);\r\n\r\n\t\tif (this.options.trackResize) {\r\n\t\t\tonOff(window, 'resize', this._onResize, this);\r\n\t\t}\r\n\r\n\t\tif (any3d && this.options.transform3DLimit) {\r\n\t\t\t(remove$$1 ? this.off : this.on).call(this, 'moveend', this._onMoveEnd);\r\n\t\t}\r\n\t},\r\n\r\n\t_onResize: function () {\r\n\t\tcancelAnimFrame(this._resizeRequest);\r\n\t\tthis._resizeRequest = requestAnimFrame(\r\n\t\t function () { this.invalidateSize({debounceMoveend: true}); }, this);\r\n\t},\r\n\r\n\t_onScroll: function () {\r\n\t\tthis._container.scrollTop = 0;\r\n\t\tthis._container.scrollLeft = 0;\r\n\t},\r\n\r\n\t_onMoveEnd: function () {\r\n\t\tvar pos = this._getMapPanePos();\r\n\t\tif (Math.max(Math.abs(pos.x), Math.abs(pos.y)) >= this.options.transform3DLimit) {\r\n\t\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=1203873 but Webkit also have\r\n\t\t\t// a pixel offset on very high values, see: http://jsfiddle.net/dg6r5hhb/\r\n\t\t\tthis._resetView(this.getCenter(), this.getZoom());\r\n\t\t}\r\n\t},\r\n\r\n\t_findEventTargets: function (e, type) {\r\n\t\tvar targets = [],\r\n\t\t target,\r\n\t\t isHover = type === 'mouseout' || type === 'mouseover',\r\n\t\t src = e.target || e.srcElement,\r\n\t\t dragging = false;\r\n\r\n\t\twhile (src) {\r\n\t\t\ttarget = this._targets[stamp(src)];\r\n\t\t\tif (target && (type === 'click' || type === 'preclick') && !e._simulated && this._draggableMoved(target)) {\r\n\t\t\t\t// Prevent firing click after you just dragged an object.\r\n\t\t\t\tdragging = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\tif (target && target.listens(type, true)) {\r\n\t\t\t\tif (isHover && !isExternalTarget(src, e)) { break; }\r\n\t\t\t\ttargets.push(target);\r\n\t\t\t\tif (isHover) { break; }\r\n\t\t\t}\r\n\t\t\tif (src === this._container) { break; }\r\n\t\t\tsrc = src.parentNode;\r\n\t\t}\r\n\t\tif (!targets.length && !dragging && !isHover && isExternalTarget(src, e)) {\r\n\t\t\ttargets = [this];\r\n\t\t}\r\n\t\treturn targets;\r\n\t},\r\n\r\n\t_handleDOMEvent: function (e) {\r\n\t\tif (!this._loaded || skipped(e)) { return; }\r\n\r\n\t\tvar type = e.type;\r\n\r\n\t\tif (type === 'mousedown' || type === 'keypress' || type === 'keyup' || type === 'keydown') {\r\n\t\t\t// prevents outline when clicking on keyboard-focusable element\r\n\t\t\tpreventOutline(e.target || e.srcElement);\r\n\t\t}\r\n\r\n\t\tthis._fireDOMEvent(e, type);\r\n\t},\r\n\r\n\t_mouseEvents: ['click', 'dblclick', 'mouseover', 'mouseout', 'contextmenu'],\r\n\r\n\t_fireDOMEvent: function (e, type, targets) {\r\n\r\n\t\tif (e.type === 'click') {\r\n\t\t\t// Fire a synthetic 'preclick' event which propagates up (mainly for closing popups).\r\n\t\t\t// @event preclick: MouseEvent\r\n\t\t\t// Fired before mouse click on the map (sometimes useful when you\r\n\t\t\t// want something to happen on click before any existing click\r\n\t\t\t// handlers start running).\r\n\t\t\tvar synth = extend({}, e);\r\n\t\t\tsynth.type = 'preclick';\r\n\t\t\tthis._fireDOMEvent(synth, synth.type, targets);\r\n\t\t}\r\n\r\n\t\tif (e._stopped) { return; }\r\n\r\n\t\t// Find the layer the event is propagating from and its parents.\r\n\t\ttargets = (targets || []).concat(this._findEventTargets(e, type));\r\n\r\n\t\tif (!targets.length) { return; }\r\n\r\n\t\tvar target = targets[0];\r\n\t\tif (type === 'contextmenu' && target.listens(type, true)) {\r\n\t\t\tpreventDefault(e);\r\n\t\t}\r\n\r\n\t\tvar data = {\r\n\t\t\toriginalEvent: e\r\n\t\t};\r\n\r\n\t\tif (e.type !== 'keypress' && e.type !== 'keydown' && e.type !== 'keyup') {\r\n\t\t\tvar isMarker = target.getLatLng && (!target._radius || target._radius <= 10);\r\n\t\t\tdata.containerPoint = isMarker ?\r\n\t\t\t\tthis.latLngToContainerPoint(target.getLatLng()) : this.mouseEventToContainerPoint(e);\r\n\t\t\tdata.layerPoint = this.containerPointToLayerPoint(data.containerPoint);\r\n\t\t\tdata.latlng = isMarker ? target.getLatLng() : this.layerPointToLatLng(data.layerPoint);\r\n\t\t}\r\n\r\n\t\tfor (var i = 0; i < targets.length; i++) {\r\n\t\t\ttargets[i].fire(type, data, true);\r\n\t\t\tif (data.originalEvent._stopped ||\r\n\t\t\t\t(targets[i].options.bubblingMouseEvents === false && indexOf(this._mouseEvents, type) !== -1)) { return; }\r\n\t\t}\r\n\t},\r\n\r\n\t_draggableMoved: function (obj) {\r\n\t\tobj = obj.dragging && obj.dragging.enabled() ? obj : this;\r\n\t\treturn (obj.dragging && obj.dragging.moved()) || (this.boxZoom && this.boxZoom.moved());\r\n\t},\r\n\r\n\t_clearHandlers: function () {\r\n\t\tfor (var i = 0, len = this._handlers.length; i < len; i++) {\r\n\t\t\tthis._handlers[i].disable();\r\n\t\t}\r\n\t},\r\n\r\n\t// @section Other Methods\r\n\r\n\t// @method whenReady(fn: Function, context?: Object): this\r\n\t// Runs the given function `fn` when the map gets initialized with\r\n\t// a view (center and zoom) and at least one layer, or immediately\r\n\t// if it's already initialized, optionally passing a function context.\r\n\twhenReady: function (callback, context) {\r\n\t\tif (this._loaded) {\r\n\t\t\tcallback.call(context || this, {target: this});\r\n\t\t} else {\r\n\t\t\tthis.on('load', callback, context);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\r\n\t// private methods for getting map state\r\n\r\n\t_getMapPanePos: function () {\r\n\t\treturn getPosition(this._mapPane) || new Point(0, 0);\r\n\t},\r\n\r\n\t_moved: function () {\r\n\t\tvar pos = this._getMapPanePos();\r\n\t\treturn pos && !pos.equals([0, 0]);\r\n\t},\r\n\r\n\t_getTopLeftPoint: function (center, zoom) {\r\n\t\tvar pixelOrigin = center && zoom !== undefined ?\r\n\t\t\tthis._getNewPixelOrigin(center, zoom) :\r\n\t\t\tthis.getPixelOrigin();\r\n\t\treturn pixelOrigin.subtract(this._getMapPanePos());\r\n\t},\r\n\r\n\t_getNewPixelOrigin: function (center, zoom) {\r\n\t\tvar viewHalf = this.getSize()._divideBy(2);\r\n\t\treturn this.project(center, zoom)._subtract(viewHalf)._add(this._getMapPanePos())._round();\r\n\t},\r\n\r\n\t_latLngToNewLayerPoint: function (latlng, zoom, center) {\r\n\t\tvar topLeft = this._getNewPixelOrigin(center, zoom);\r\n\t\treturn this.project(latlng, zoom)._subtract(topLeft);\r\n\t},\r\n\r\n\t_latLngBoundsToNewLayerBounds: function (latLngBounds, zoom, center) {\r\n\t\tvar topLeft = this._getNewPixelOrigin(center, zoom);\r\n\t\treturn toBounds([\r\n\t\t\tthis.project(latLngBounds.getSouthWest(), zoom)._subtract(topLeft),\r\n\t\t\tthis.project(latLngBounds.getNorthWest(), zoom)._subtract(topLeft),\r\n\t\t\tthis.project(latLngBounds.getSouthEast(), zoom)._subtract(topLeft),\r\n\t\t\tthis.project(latLngBounds.getNorthEast(), zoom)._subtract(topLeft)\r\n\t\t]);\r\n\t},\r\n\r\n\t// layer point of the current center\r\n\t_getCenterLayerPoint: function () {\r\n\t\treturn this.containerPointToLayerPoint(this.getSize()._divideBy(2));\r\n\t},\r\n\r\n\t// offset of the specified place to the current center in pixels\r\n\t_getCenterOffset: function (latlng) {\r\n\t\treturn this.latLngToLayerPoint(latlng).subtract(this._getCenterLayerPoint());\r\n\t},\r\n\r\n\t// adjust center for view to get inside bounds\r\n\t_limitCenter: function (center, zoom, bounds) {\r\n\r\n\t\tif (!bounds) { return center; }\r\n\r\n\t\tvar centerPoint = this.project(center, zoom),\r\n\t\t viewHalf = this.getSize().divideBy(2),\r\n\t\t viewBounds = new Bounds(centerPoint.subtract(viewHalf), centerPoint.add(viewHalf)),\r\n\t\t offset = this._getBoundsOffset(viewBounds, bounds, zoom);\r\n\r\n\t\t// If offset is less than a pixel, ignore.\r\n\t\t// This prevents unstable projections from getting into\r\n\t\t// an infinite loop of tiny offsets.\r\n\t\tif (offset.round().equals([0, 0])) {\r\n\t\t\treturn center;\r\n\t\t}\r\n\r\n\t\treturn this.unproject(centerPoint.add(offset), zoom);\r\n\t},\r\n\r\n\t// adjust offset for view to get inside bounds\r\n\t_limitOffset: function (offset, bounds) {\r\n\t\tif (!bounds) { return offset; }\r\n\r\n\t\tvar viewBounds = this.getPixelBounds(),\r\n\t\t newBounds = new Bounds(viewBounds.min.add(offset), viewBounds.max.add(offset));\r\n\r\n\t\treturn offset.add(this._getBoundsOffset(newBounds, bounds));\r\n\t},\r\n\r\n\t// returns offset needed for pxBounds to get inside maxBounds at a specified zoom\r\n\t_getBoundsOffset: function (pxBounds, maxBounds, zoom) {\r\n\t\tvar projectedMaxBounds = toBounds(\r\n\t\t this.project(maxBounds.getNorthEast(), zoom),\r\n\t\t this.project(maxBounds.getSouthWest(), zoom)\r\n\t\t ),\r\n\t\t minOffset = projectedMaxBounds.min.subtract(pxBounds.min),\r\n\t\t maxOffset = projectedMaxBounds.max.subtract(pxBounds.max),\r\n\r\n\t\t dx = this._rebound(minOffset.x, -maxOffset.x),\r\n\t\t dy = this._rebound(minOffset.y, -maxOffset.y);\r\n\r\n\t\treturn new Point(dx, dy);\r\n\t},\r\n\r\n\t_rebound: function (left, right) {\r\n\t\treturn left + right > 0 ?\r\n\t\t\tMath.round(left - right) / 2 :\r\n\t\t\tMath.max(0, Math.ceil(left)) - Math.max(0, Math.floor(right));\r\n\t},\r\n\r\n\t_limitZoom: function (zoom) {\r\n\t\tvar min = this.getMinZoom(),\r\n\t\t max = this.getMaxZoom(),\r\n\t\t snap = any3d ? this.options.zoomSnap : 1;\r\n\t\tif (snap) {\r\n\t\t\tzoom = Math.round(zoom / snap) * snap;\r\n\t\t}\r\n\t\treturn Math.max(min, Math.min(max, zoom));\r\n\t},\r\n\r\n\t_onPanTransitionStep: function () {\r\n\t\tthis.fire('move');\r\n\t},\r\n\r\n\t_onPanTransitionEnd: function () {\r\n\t\tremoveClass(this._mapPane, 'leaflet-pan-anim');\r\n\t\tthis.fire('moveend');\r\n\t},\r\n\r\n\t_tryAnimatedPan: function (center, options) {\r\n\t\t// difference between the new and current centers in pixels\r\n\t\tvar offset = this._getCenterOffset(center)._trunc();\r\n\r\n\t\t// don't animate too far unless animate: true specified in options\r\n\t\tif ((options && options.animate) !== true && !this.getSize().contains(offset)) { return false; }\r\n\r\n\t\tthis.panBy(offset, options);\r\n\r\n\t\treturn true;\r\n\t},\r\n\r\n\t_createAnimProxy: function () {\r\n\r\n\t\tvar proxy = this._proxy = create$1('div', 'leaflet-proxy leaflet-zoom-animated');\r\n\t\tthis._panes.mapPane.appendChild(proxy);\r\n\r\n\t\tthis.on('zoomanim', function (e) {\r\n\t\t\tvar prop = TRANSFORM,\r\n\t\t\t transform = this._proxy.style[prop];\r\n\r\n\t\t\tsetTransform(this._proxy, this.project(e.center, e.zoom), this.getZoomScale(e.zoom, 1));\r\n\r\n\t\t\t// workaround for case when transform is the same and so transitionend event is not fired\r\n\t\t\tif (transform === this._proxy.style[prop] && this._animatingZoom) {\r\n\t\t\t\tthis._onZoomTransitionEnd();\r\n\t\t\t}\r\n\t\t}, this);\r\n\r\n\t\tthis.on('load moveend', function () {\r\n\t\t\tvar c = this.getCenter(),\r\n\t\t\t z = this.getZoom();\r\n\t\t\tsetTransform(this._proxy, this.project(c, z), this.getZoomScale(z, 1));\r\n\t\t}, this);\r\n\r\n\t\tthis._on('unload', this._destroyAnimProxy, this);\r\n\t},\r\n\r\n\t_destroyAnimProxy: function () {\r\n\t\tremove(this._proxy);\r\n\t\tdelete this._proxy;\r\n\t},\r\n\r\n\t_catchTransitionEnd: function (e) {\r\n\t\tif (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) {\r\n\t\t\tthis._onZoomTransitionEnd();\r\n\t\t}\r\n\t},\r\n\r\n\t_nothingToAnimate: function () {\r\n\t\treturn !this._container.getElementsByClassName('leaflet-zoom-animated').length;\r\n\t},\r\n\r\n\t_tryAnimatedZoom: function (center, zoom, options) {\r\n\r\n\t\tif (this._animatingZoom) { return true; }\r\n\r\n\t\toptions = options || {};\r\n\r\n\t\t// don't animate if disabled, not supported or zoom difference is too large\r\n\t\tif (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() ||\r\n\t\t Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; }\r\n\r\n\t\t// offset is the pixel coords of the zoom origin relative to the current center\r\n\t\tvar scale = this.getZoomScale(zoom),\r\n\t\t offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale);\r\n\r\n\t\t// don't animate if the zoom origin isn't within one screen from the current center, unless forced\r\n\t\tif (options.animate !== true && !this.getSize().contains(offset)) { return false; }\r\n\r\n\t\trequestAnimFrame(function () {\r\n\t\t\tthis\r\n\t\t\t ._moveStart(true, false)\r\n\t\t\t ._animateZoom(center, zoom, true);\r\n\t\t}, this);\r\n\r\n\t\treturn true;\r\n\t},\r\n\r\n\t_animateZoom: function (center, zoom, startAnim, noUpdate) {\r\n\t\tif (!this._mapPane) { return; }\r\n\r\n\t\tif (startAnim) {\r\n\t\t\tthis._animatingZoom = true;\r\n\r\n\t\t\t// remember what center/zoom to set after animation\r\n\t\t\tthis._animateToCenter = center;\r\n\t\t\tthis._animateToZoom = zoom;\r\n\r\n\t\t\taddClass(this._mapPane, 'leaflet-zoom-anim');\r\n\t\t}\r\n\r\n\t\t// @event zoomanim: ZoomAnimEvent\r\n\t\t// Fired at least once per zoom animation. For continuous zoom, like pinch zooming, fired once per frame during zoom.\r\n\t\tthis.fire('zoomanim', {\r\n\t\t\tcenter: center,\r\n\t\t\tzoom: zoom,\r\n\t\t\tnoUpdate: noUpdate\r\n\t\t});\r\n\r\n\t\t// Work around webkit not firing 'transitionend', see https://github.com/Leaflet/Leaflet/issues/3689, 2693\r\n\t\tsetTimeout(bind(this._onZoomTransitionEnd, this), 250);\r\n\t},\r\n\r\n\t_onZoomTransitionEnd: function () {\r\n\t\tif (!this._animatingZoom) { return; }\r\n\r\n\t\tif (this._mapPane) {\r\n\t\t\tremoveClass(this._mapPane, 'leaflet-zoom-anim');\r\n\t\t}\r\n\r\n\t\tthis._animatingZoom = false;\r\n\r\n\t\tthis._move(this._animateToCenter, this._animateToZoom);\r\n\r\n\t\t// This anim frame should prevent an obscure iOS webkit tile loading race condition.\r\n\t\trequestAnimFrame(function () {\r\n\t\t\tthis._moveEnd(true);\r\n\t\t}, this);\r\n\t}\r\n});\r\n\r\n// @section\r\n\r\n// @factory L.map(id: String, options?: Map options)\r\n// Instantiates a map object given the DOM ID of a `<div>` element\r\n// and optionally an object literal with `Map options`.\r\n//\r\n// @alternative\r\n// @factory L.map(el: HTMLElement, options?: Map options)\r\n// Instantiates a map object given an instance of a `<div>` HTML element\r\n// and optionally an object literal with `Map options`.\r\nfunction createMap(id, options) {\r\n\treturn new Map(id, options);\r\n}\n\n/*\r\n * @class Control\r\n * @aka L.Control\r\n * @inherits Class\r\n *\r\n * L.Control is a base class for implementing map controls. Handles positioning.\r\n * All other controls extend from this class.\r\n */\r\n\r\nvar Control = Class.extend({\r\n\t// @section\r\n\t// @aka Control options\r\n\toptions: {\r\n\t\t// @option position: String = 'topright'\r\n\t\t// The position of the control (one of the map corners). Possible values are `'topleft'`,\r\n\t\t// `'topright'`, `'bottomleft'` or `'bottomright'`\r\n\t\tposition: 'topright'\r\n\t},\r\n\r\n\tinitialize: function (options) {\r\n\t\tsetOptions(this, options);\r\n\t},\r\n\r\n\t/* @section\r\n\t * Classes extending L.Control will inherit the following methods:\r\n\t *\r\n\t * @method getPosition: string\r\n\t * Returns the position of the control.\r\n\t */\r\n\tgetPosition: function () {\r\n\t\treturn this.options.position;\r\n\t},\r\n\r\n\t// @method setPosition(position: string): this\r\n\t// Sets the position of the control.\r\n\tsetPosition: function (position) {\r\n\t\tvar map = this._map;\r\n\r\n\t\tif (map) {\r\n\t\t\tmap.removeControl(this);\r\n\t\t}\r\n\r\n\t\tthis.options.position = position;\r\n\r\n\t\tif (map) {\r\n\t\t\tmap.addControl(this);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getContainer: HTMLElement\r\n\t// Returns the HTMLElement that contains the control.\r\n\tgetContainer: function () {\r\n\t\treturn this._container;\r\n\t},\r\n\r\n\t// @method addTo(map: Map): this\r\n\t// Adds the control to the given map.\r\n\taddTo: function (map) {\r\n\t\tthis.remove();\r\n\t\tthis._map = map;\r\n\r\n\t\tvar container = this._container = this.onAdd(map),\r\n\t\t pos = this.getPosition(),\r\n\t\t corner = map._controlCorners[pos];\r\n\r\n\t\taddClass(container, 'leaflet-control');\r\n\r\n\t\tif (pos.indexOf('bottom') !== -1) {\r\n\t\t\tcorner.insertBefore(container, corner.firstChild);\r\n\t\t} else {\r\n\t\t\tcorner.appendChild(container);\r\n\t\t}\r\n\r\n\t\tthis._map.on('unload', this.remove, this);\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method remove: this\r\n\t// Removes the control from the map it is currently active on.\r\n\tremove: function () {\r\n\t\tif (!this._map) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tremove(this._container);\r\n\r\n\t\tif (this.onRemove) {\r\n\t\t\tthis.onRemove(this._map);\r\n\t\t}\r\n\r\n\t\tthis._map.off('unload', this.remove, this);\r\n\t\tthis._map = null;\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_refocusOnMap: function (e) {\r\n\t\t// if map exists and event is not a keyboard event\r\n\t\tif (this._map && e && e.screenX > 0 && e.screenY > 0) {\r\n\t\t\tthis._map.getContainer().focus();\r\n\t\t}\r\n\t}\r\n});\r\n\r\nvar control = function (options) {\r\n\treturn new Control(options);\r\n};\r\n\r\n/* @section Extension methods\r\n * @uninheritable\r\n *\r\n * Every control should extend from `L.Control` and (re-)implement the following methods.\r\n *\r\n * @method onAdd(map: Map): HTMLElement\r\n * Should return the container DOM element for the control and add listeners on relevant map events. Called on [`control.addTo(map)`](#control-addTo).\r\n *\r\n * @method onRemove(map: Map)\r\n * Optional method. Should contain all clean up code that removes the listeners previously added in [`onAdd`](#control-onadd). Called on [`control.remove()`](#control-remove).\r\n */\r\n\r\n/* @namespace Map\r\n * @section Methods for Layers and Controls\r\n */\r\nMap.include({\r\n\t// @method addControl(control: Control): this\r\n\t// Adds the given control to the map\r\n\taddControl: function (control) {\r\n\t\tcontrol.addTo(this);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method removeControl(control: Control): this\r\n\t// Removes the given control from the map\r\n\tremoveControl: function (control) {\r\n\t\tcontrol.remove();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_initControlPos: function () {\r\n\t\tvar corners = this._controlCorners = {},\r\n\t\t l = 'leaflet-',\r\n\t\t container = this._controlContainer =\r\n\t\t create$1('div', l + 'control-container', this._container);\r\n\r\n\t\tfunction createCorner(vSide, hSide) {\r\n\t\t\tvar className = l + vSide + ' ' + l + hSide;\r\n\r\n\t\t\tcorners[vSide + hSide] = create$1('div', className, container);\r\n\t\t}\r\n\r\n\t\tcreateCorner('top', 'left');\r\n\t\tcreateCorner('top', 'right');\r\n\t\tcreateCorner('bottom', 'left');\r\n\t\tcreateCorner('bottom', 'right');\r\n\t},\r\n\r\n\t_clearControlPos: function () {\r\n\t\tfor (var i in this._controlCorners) {\r\n\t\t\tremove(this._controlCorners[i]);\r\n\t\t}\r\n\t\tremove(this._controlContainer);\r\n\t\tdelete this._controlCorners;\r\n\t\tdelete this._controlContainer;\r\n\t}\r\n});\n\n/*\r\n * @class Control.Layers\r\n * @aka L.Control.Layers\r\n * @inherits Control\r\n *\r\n * The layers control gives users the ability to switch between different base layers and switch overlays on/off (check out the [detailed example](http://leafletjs.com/examples/layers-control/)). Extends `Control`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var baseLayers = {\r\n * \t\"Mapbox\": mapbox,\r\n * \t\"OpenStreetMap\": osm\r\n * };\r\n *\r\n * var overlays = {\r\n * \t\"Marker\": marker,\r\n * \t\"Roads\": roadsLayer\r\n * };\r\n *\r\n * L.control.layers(baseLayers, overlays).addTo(map);\r\n * ```\r\n *\r\n * The `baseLayers` and `overlays` parameters are object literals with layer names as keys and `Layer` objects as values:\r\n *\r\n * ```js\r\n * {\r\n * \"<someName1>\": layer1,\r\n * \"<someName2>\": layer2\r\n * }\r\n * ```\r\n *\r\n * The layer names can contain HTML, which allows you to add additional styling to the items:\r\n *\r\n * ```js\r\n * {\"<img src='my-layer-icon' /> <span class='my-layer-item'>My Layer</span>\": myLayer}\r\n * ```\r\n */\r\n\r\nvar Layers = Control.extend({\r\n\t// @section\r\n\t// @aka Control.Layers options\r\n\toptions: {\r\n\t\t// @option collapsed: Boolean = true\r\n\t\t// If `true`, the control will be collapsed into an icon and expanded on mouse hover or touch.\r\n\t\tcollapsed: true,\r\n\t\tposition: 'topright',\r\n\r\n\t\t// @option autoZIndex: Boolean = true\r\n\t\t// If `true`, the control will assign zIndexes in increasing order to all of its layers so that the order is preserved when switching them on/off.\r\n\t\tautoZIndex: true,\r\n\r\n\t\t// @option hideSingleBase: Boolean = false\r\n\t\t// If `true`, the base layers in the control will be hidden when there is only one.\r\n\t\thideSingleBase: false,\r\n\r\n\t\t// @option sortLayers: Boolean = false\r\n\t\t// Whether to sort the layers. When `false`, layers will keep the order\r\n\t\t// in which they were added to the control.\r\n\t\tsortLayers: false,\r\n\r\n\t\t// @option sortFunction: Function = *\r\n\t\t// A [compare function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)\r\n\t\t// that will be used for sorting the layers, when `sortLayers` is `true`.\r\n\t\t// The function receives both the `L.Layer` instances and their names, as in\r\n\t\t// `sortFunction(layerA, layerB, nameA, nameB)`.\r\n\t\t// By default, it sorts layers alphabetically by their name.\r\n\t\tsortFunction: function (layerA, layerB, nameA, nameB) {\r\n\t\t\treturn nameA < nameB ? -1 : (nameB < nameA ? 1 : 0);\r\n\t\t}\r\n\t},\r\n\r\n\tinitialize: function (baseLayers, overlays, options) {\r\n\t\tsetOptions(this, options);\r\n\r\n\t\tthis._layerControlInputs = [];\r\n\t\tthis._layers = [];\r\n\t\tthis._lastZIndex = 0;\r\n\t\tthis._handlingClick = false;\r\n\r\n\t\tfor (var i in baseLayers) {\r\n\t\t\tthis._addLayer(baseLayers[i], i);\r\n\t\t}\r\n\r\n\t\tfor (i in overlays) {\r\n\t\t\tthis._addLayer(overlays[i], i, true);\r\n\t\t}\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tthis._initLayout();\r\n\t\tthis._update();\r\n\r\n\t\tthis._map = map;\r\n\t\tmap.on('zoomend', this._checkDisabledLayers, this);\r\n\r\n\t\tfor (var i = 0; i < this._layers.length; i++) {\r\n\t\t\tthis._layers[i].layer.on('add remove', this._onLayerChange, this);\r\n\t\t}\r\n\r\n\t\treturn this._container;\r\n\t},\r\n\r\n\taddTo: function (map) {\r\n\t\tControl.prototype.addTo.call(this, map);\r\n\t\t// Trigger expand after Layers Control has been inserted into DOM so that is now has an actual height.\r\n\t\treturn this._expandIfNotCollapsed();\r\n\t},\r\n\r\n\tonRemove: function () {\r\n\t\tthis._map.off('zoomend', this._checkDisabledLayers, this);\r\n\r\n\t\tfor (var i = 0; i < this._layers.length; i++) {\r\n\t\t\tthis._layers[i].layer.off('add remove', this._onLayerChange, this);\r\n\t\t}\r\n\t},\r\n\r\n\t// @method addBaseLayer(layer: Layer, name: String): this\r\n\t// Adds a base layer (radio button entry) with the given name to the control.\r\n\taddBaseLayer: function (layer, name) {\r\n\t\tthis._addLayer(layer, name);\r\n\t\treturn (this._map) ? this._update() : this;\r\n\t},\r\n\r\n\t// @method addOverlay(layer: Layer, name: String): this\r\n\t// Adds an overlay (checkbox entry) with the given name to the control.\r\n\taddOverlay: function (layer, name) {\r\n\t\tthis._addLayer(layer, name, true);\r\n\t\treturn (this._map) ? this._update() : this;\r\n\t},\r\n\r\n\t// @method removeLayer(layer: Layer): this\r\n\t// Remove the given layer from the control.\r\n\tremoveLayer: function (layer) {\r\n\t\tlayer.off('add remove', this._onLayerChange, this);\r\n\r\n\t\tvar obj = this._getLayer(stamp(layer));\r\n\t\tif (obj) {\r\n\t\t\tthis._layers.splice(this._layers.indexOf(obj), 1);\r\n\t\t}\r\n\t\treturn (this._map) ? this._update() : this;\r\n\t},\r\n\r\n\t// @method expand(): this\r\n\t// Expand the control container if collapsed.\r\n\texpand: function () {\r\n\t\taddClass(this._container, 'leaflet-control-layers-expanded');\r\n\t\tthis._section.style.height = null;\r\n\t\tvar acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50);\r\n\t\tif (acceptableHeight < this._section.clientHeight) {\r\n\t\t\taddClass(this._section, 'leaflet-control-layers-scrollbar');\r\n\t\t\tthis._section.style.height = acceptableHeight + 'px';\r\n\t\t} else {\r\n\t\t\tremoveClass(this._section, 'leaflet-control-layers-scrollbar');\r\n\t\t}\r\n\t\tthis._checkDisabledLayers();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method collapse(): this\r\n\t// Collapse the control container if expanded.\r\n\tcollapse: function () {\r\n\t\tremoveClass(this._container, 'leaflet-control-layers-expanded');\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_initLayout: function () {\r\n\t\tvar className = 'leaflet-control-layers',\r\n\t\t container = this._container = create$1('div', className),\r\n\t\t collapsed = this.options.collapsed;\r\n\r\n\t\t// makes this work on IE touch devices by stopping it from firing a mouseout event when the touch is released\r\n\t\tcontainer.setAttribute('aria-haspopup', true);\r\n\r\n\t\tdisableClickPropagation(container);\r\n\t\tdisableScrollPropagation(container);\r\n\r\n\t\tvar section = this._section = create$1('section', className + '-list');\r\n\r\n\t\tif (collapsed) {\r\n\t\t\tthis._map.on('click', this.collapse, this);\r\n\r\n\t\t\tif (!android) {\r\n\t\t\t\ton(container, {\r\n\t\t\t\t\tmouseenter: this.expand,\r\n\t\t\t\t\tmouseleave: this.collapse\r\n\t\t\t\t}, this);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tvar link = this._layersLink = create$1('a', className + '-toggle', container);\r\n\t\tlink.href = '#';\r\n\t\tlink.title = 'Layers';\r\n\r\n\t\tif (touch) {\r\n\t\t\ton(link, 'click', stop);\r\n\t\t\ton(link, 'click', this.expand, this);\r\n\t\t} else {\r\n\t\t\ton(link, 'focus', this.expand, this);\r\n\t\t}\r\n\r\n\t\tif (!collapsed) {\r\n\t\t\tthis.expand();\r\n\t\t}\r\n\r\n\t\tthis._baseLayersList = create$1('div', className + '-base', section);\r\n\t\tthis._separator = create$1('div', className + '-separator', section);\r\n\t\tthis._overlaysList = create$1('div', className + '-overlays', section);\r\n\r\n\t\tcontainer.appendChild(section);\r\n\t},\r\n\r\n\t_getLayer: function (id) {\r\n\t\tfor (var i = 0; i < this._layers.length; i++) {\r\n\r\n\t\t\tif (this._layers[i] && stamp(this._layers[i].layer) === id) {\r\n\t\t\t\treturn this._layers[i];\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t_addLayer: function (layer, name, overlay) {\r\n\t\tif (this._map) {\r\n\t\t\tlayer.on('add remove', this._onLayerChange, this);\r\n\t\t}\r\n\r\n\t\tthis._layers.push({\r\n\t\t\tlayer: layer,\r\n\t\t\tname: name,\r\n\t\t\toverlay: overlay\r\n\t\t});\r\n\r\n\t\tif (this.options.sortLayers) {\r\n\t\t\tthis._layers.sort(bind(function (a, b) {\r\n\t\t\t\treturn this.options.sortFunction(a.layer, b.layer, a.name, b.name);\r\n\t\t\t}, this));\r\n\t\t}\r\n\r\n\t\tif (this.options.autoZIndex && layer.setZIndex) {\r\n\t\t\tthis._lastZIndex++;\r\n\t\t\tlayer.setZIndex(this._lastZIndex);\r\n\t\t}\r\n\r\n\t\tthis._expandIfNotCollapsed();\r\n\t},\r\n\r\n\t_update: function () {\r\n\t\tif (!this._container) { return this; }\r\n\r\n\t\tempty(this._baseLayersList);\r\n\t\tempty(this._overlaysList);\r\n\r\n\t\tthis._layerControlInputs = [];\r\n\t\tvar baseLayersPresent, overlaysPresent, i, obj, baseLayersCount = 0;\r\n\r\n\t\tfor (i = 0; i < this._layers.length; i++) {\r\n\t\t\tobj = this._layers[i];\r\n\t\t\tthis._addItem(obj);\r\n\t\t\toverlaysPresent = overlaysPresent || obj.overlay;\r\n\t\t\tbaseLayersPresent = baseLayersPresent || !obj.overlay;\r\n\t\t\tbaseLayersCount += !obj.overlay ? 1 : 0;\r\n\t\t}\r\n\r\n\t\t// Hide base layers section if there's only one layer.\r\n\t\tif (this.options.hideSingleBase) {\r\n\t\t\tbaseLayersPresent = baseLayersPresent && baseLayersCount > 1;\r\n\t\t\tthis._baseLayersList.style.display = baseLayersPresent ? '' : 'none';\r\n\t\t}\r\n\r\n\t\tthis._separator.style.display = overlaysPresent && baseLayersPresent ? '' : 'none';\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_onLayerChange: function (e) {\r\n\t\tif (!this._handlingClick) {\r\n\t\t\tthis._update();\r\n\t\t}\r\n\r\n\t\tvar obj = this._getLayer(stamp(e.target));\r\n\r\n\t\t// @namespace Map\r\n\t\t// @section Layer events\r\n\t\t// @event baselayerchange: LayersControlEvent\r\n\t\t// Fired when the base layer is changed through the [layer control](#control-layers).\r\n\t\t// @event overlayadd: LayersControlEvent\r\n\t\t// Fired when an overlay is selected through the [layer control](#control-layers).\r\n\t\t// @event overlayremove: LayersControlEvent\r\n\t\t// Fired when an overlay is deselected through the [layer control](#control-layers).\r\n\t\t// @namespace Control.Layers\r\n\t\tvar type = obj.overlay ?\r\n\t\t\t(e.type === 'add' ? 'overlayadd' : 'overlayremove') :\r\n\t\t\t(e.type === 'add' ? 'baselayerchange' : null);\r\n\r\n\t\tif (type) {\r\n\t\t\tthis._map.fire(type, obj);\r\n\t\t}\r\n\t},\r\n\r\n\t// IE7 bugs out if you create a radio dynamically, so you have to do it this hacky way (see http://bit.ly/PqYLBe)\r\n\t_createRadioElement: function (name, checked) {\r\n\r\n\t\tvar radioHtml = '<input type=\"radio\" class=\"leaflet-control-layers-selector\" name=\"' +\r\n\t\t\t\tname + '\"' + (checked ? ' checked=\"checked\"' : '') + '/>';\r\n\r\n\t\tvar radioFragment = document.createElement('div');\r\n\t\tradioFragment.innerHTML = radioHtml;\r\n\r\n\t\treturn radioFragment.firstChild;\r\n\t},\r\n\r\n\t_addItem: function (obj) {\r\n\t\tvar label = document.createElement('label'),\r\n\t\t checked = this._map.hasLayer(obj.layer),\r\n\t\t input;\r\n\r\n\t\tif (obj.overlay) {\r\n\t\t\tinput = document.createElement('input');\r\n\t\t\tinput.type = 'checkbox';\r\n\t\t\tinput.className = 'leaflet-control-layers-selector';\r\n\t\t\tinput.defaultChecked = checked;\r\n\t\t} else {\r\n\t\t\tinput = this._createRadioElement('leaflet-base-layers_' + stamp(this), checked);\r\n\t\t}\r\n\r\n\t\tthis._layerControlInputs.push(input);\r\n\t\tinput.layerId = stamp(obj.layer);\r\n\r\n\t\ton(input, 'click', this._onInputClick, this);\r\n\r\n\t\tvar name = document.createElement('span');\r\n\t\tname.innerHTML = ' ' + obj.name;\r\n\r\n\t\t// Helps from preventing layer control flicker when checkboxes are disabled\r\n\t\t// https://github.com/Leaflet/Leaflet/issues/2771\r\n\t\tvar holder = document.createElement('div');\r\n\r\n\t\tlabel.appendChild(holder);\r\n\t\tholder.appendChild(input);\r\n\t\tholder.appendChild(name);\r\n\r\n\t\tvar container = obj.overlay ? this._overlaysList : this._baseLayersList;\r\n\t\tcontainer.appendChild(label);\r\n\r\n\t\tthis._checkDisabledLayers();\r\n\t\treturn label;\r\n\t},\r\n\r\n\t_onInputClick: function () {\r\n\t\tvar inputs = this._layerControlInputs,\r\n\t\t input, layer;\r\n\t\tvar addedLayers = [],\r\n\t\t removedLayers = [];\r\n\r\n\t\tthis._handlingClick = true;\r\n\r\n\t\tfor (var i = inputs.length - 1; i >= 0; i--) {\r\n\t\t\tinput = inputs[i];\r\n\t\t\tlayer = this._getLayer(input.layerId).layer;\r\n\r\n\t\t\tif (input.checked) {\r\n\t\t\t\taddedLayers.push(layer);\r\n\t\t\t} else if (!input.checked) {\r\n\t\t\t\tremovedLayers.push(layer);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Bugfix issue 2318: Should remove all old layers before readding new ones\r\n\t\tfor (i = 0; i < removedLayers.length; i++) {\r\n\t\t\tif (this._map.hasLayer(removedLayers[i])) {\r\n\t\t\t\tthis._map.removeLayer(removedLayers[i]);\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (i = 0; i < addedLayers.length; i++) {\r\n\t\t\tif (!this._map.hasLayer(addedLayers[i])) {\r\n\t\t\t\tthis._map.addLayer(addedLayers[i]);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis._handlingClick = false;\r\n\r\n\t\tthis._refocusOnMap();\r\n\t},\r\n\r\n\t_checkDisabledLayers: function () {\r\n\t\tvar inputs = this._layerControlInputs,\r\n\t\t input,\r\n\t\t layer,\r\n\t\t zoom = this._map.getZoom();\r\n\r\n\t\tfor (var i = inputs.length - 1; i >= 0; i--) {\r\n\t\t\tinput = inputs[i];\r\n\t\t\tlayer = this._getLayer(input.layerId).layer;\r\n\t\t\tinput.disabled = (layer.options.minZoom !== undefined && zoom < layer.options.minZoom) ||\r\n\t\t\t (layer.options.maxZoom !== undefined && zoom > layer.options.maxZoom);\r\n\r\n\t\t}\r\n\t},\r\n\r\n\t_expandIfNotCollapsed: function () {\r\n\t\tif (this._map && !this.options.collapsed) {\r\n\t\t\tthis.expand();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_expand: function () {\r\n\t\t// Backward compatibility, remove me in 1.1.\r\n\t\treturn this.expand();\r\n\t},\r\n\r\n\t_collapse: function () {\r\n\t\t// Backward compatibility, remove me in 1.1.\r\n\t\treturn this.collapse();\r\n\t}\r\n\r\n});\r\n\r\n\r\n// @factory L.control.layers(baselayers?: Object, overlays?: Object, options?: Control.Layers options)\r\n// Creates an attribution control with the given layers. Base layers will be switched with radio buttons, while overlays will be switched with checkboxes. Note that all base layers should be passed in the base layers object, but only one should be added to the map during map instantiation.\r\nvar layers = function (baseLayers, overlays, options) {\r\n\treturn new Layers(baseLayers, overlays, options);\r\n};\n\n/*\r\n * @class Control.Zoom\r\n * @aka L.Control.Zoom\r\n * @inherits Control\r\n *\r\n * A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its [`zoomControl` option](#map-zoomcontrol) to `false`. Extends `Control`.\r\n */\r\n\r\nvar Zoom = Control.extend({\r\n\t// @section\r\n\t// @aka Control.Zoom options\r\n\toptions: {\r\n\t\tposition: 'topleft',\r\n\r\n\t\t// @option zoomInText: String = '+'\r\n\t\t// The text set on the 'zoom in' button.\r\n\t\tzoomInText: '+',\r\n\r\n\t\t// @option zoomInTitle: String = 'Zoom in'\r\n\t\t// The title set on the 'zoom in' button.\r\n\t\tzoomInTitle: 'Zoom in',\r\n\r\n\t\t// @option zoomOutText: String = '&#x2212;'\r\n\t\t// The text set on the 'zoom out' button.\r\n\t\tzoomOutText: '&#x2212;',\r\n\r\n\t\t// @option zoomOutTitle: String = 'Zoom out'\r\n\t\t// The title set on the 'zoom out' button.\r\n\t\tzoomOutTitle: 'Zoom out'\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tvar zoomName = 'leaflet-control-zoom',\r\n\t\t container = create$1('div', zoomName + ' leaflet-bar'),\r\n\t\t options = this.options;\r\n\r\n\t\tthis._zoomInButton = this._createButton(options.zoomInText, options.zoomInTitle,\r\n\t\t zoomName + '-in', container, this._zoomIn);\r\n\t\tthis._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle,\r\n\t\t zoomName + '-out', container, this._zoomOut);\r\n\r\n\t\tthis._updateDisabled();\r\n\t\tmap.on('zoomend zoomlevelschange', this._updateDisabled, this);\r\n\r\n\t\treturn container;\r\n\t},\r\n\r\n\tonRemove: function (map) {\r\n\t\tmap.off('zoomend zoomlevelschange', this._updateDisabled, this);\r\n\t},\r\n\r\n\tdisable: function () {\r\n\t\tthis._disabled = true;\r\n\t\tthis._updateDisabled();\r\n\t\treturn this;\r\n\t},\r\n\r\n\tenable: function () {\r\n\t\tthis._disabled = false;\r\n\t\tthis._updateDisabled();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_zoomIn: function (e) {\r\n\t\tif (!this._disabled && this._map._zoom < this._map.getMaxZoom()) {\r\n\t\t\tthis._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));\r\n\t\t}\r\n\t},\r\n\r\n\t_zoomOut: function (e) {\r\n\t\tif (!this._disabled && this._map._zoom > this._map.getMinZoom()) {\r\n\t\t\tthis._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1));\r\n\t\t}\r\n\t},\r\n\r\n\t_createButton: function (html, title, className, container, fn) {\r\n\t\tvar link = create$1('a', className, container);\r\n\t\tlink.innerHTML = html;\r\n\t\tlink.href = '#';\r\n\t\tlink.title = title;\r\n\r\n\t\t/*\r\n\t\t * Will force screen readers like VoiceOver to read this as \"Zoom in - button\"\r\n\t\t */\r\n\t\tlink.setAttribute('role', 'button');\r\n\t\tlink.setAttribute('aria-label', title);\r\n\r\n\t\tdisableClickPropagation(link);\r\n\t\ton(link, 'click', stop);\r\n\t\ton(link, 'click', fn, this);\r\n\t\ton(link, 'click', this._refocusOnMap, this);\r\n\r\n\t\treturn link;\r\n\t},\r\n\r\n\t_updateDisabled: function () {\r\n\t\tvar map = this._map,\r\n\t\t className = 'leaflet-disabled';\r\n\r\n\t\tremoveClass(this._zoomInButton, className);\r\n\t\tremoveClass(this._zoomOutButton, className);\r\n\r\n\t\tif (this._disabled || map._zoom === map.getMinZoom()) {\r\n\t\t\taddClass(this._zoomOutButton, className);\r\n\t\t}\r\n\t\tif (this._disabled || map._zoom === map.getMaxZoom()) {\r\n\t\t\taddClass(this._zoomInButton, className);\r\n\t\t}\r\n\t}\r\n});\r\n\r\n// @namespace Map\r\n// @section Control options\r\n// @option zoomControl: Boolean = true\r\n// Whether a [zoom control](#control-zoom) is added to the map by default.\r\nMap.mergeOptions({\r\n\tzoomControl: true\r\n});\r\n\r\nMap.addInitHook(function () {\r\n\tif (this.options.zoomControl) {\r\n\t\t// @section Controls\r\n\t\t// @property zoomControl: Control.Zoom\r\n\t\t// The default zoom control (only available if the\r\n\t\t// [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map).\r\n\t\tthis.zoomControl = new Zoom();\r\n\t\tthis.addControl(this.zoomControl);\r\n\t}\r\n});\r\n\r\n// @namespace Control.Zoom\r\n// @factory L.control.zoom(options: Control.Zoom options)\r\n// Creates a zoom control\r\nvar zoom = function (options) {\r\n\treturn new Zoom(options);\r\n};\n\n/*\n * @class Control.Scale\n * @aka L.Control.Scale\n * @inherits Control\n *\n * A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends `Control`.\n *\n * @example\n *\n * ```js\n * L.control.scale().addTo(map);\n * ```\n */\n\nvar Scale = Control.extend({\n\t// @section\n\t// @aka Control.Scale options\n\toptions: {\n\t\tposition: 'bottomleft',\n\n\t\t// @option maxWidth: Number = 100\n\t\t// Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500).\n\t\tmaxWidth: 100,\n\n\t\t// @option metric: Boolean = True\n\t\t// Whether to show the metric scale line (m/km).\n\t\tmetric: true,\n\n\t\t// @option imperial: Boolean = True\n\t\t// Whether to show the imperial scale line (mi/ft).\n\t\timperial: true\n\n\t\t// @option updateWhenIdle: Boolean = false\n\t\t// If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)).\n\t},\n\n\tonAdd: function (map) {\n\t\tvar className = 'leaflet-control-scale',\n\t\t container = create$1('div', className),\n\t\t options = this.options;\n\n\t\tthis._addScales(options, className + '-line', container);\n\n\t\tmap.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this);\n\t\tmap.whenReady(this._update, this);\n\n\t\treturn container;\n\t},\n\n\tonRemove: function (map) {\n\t\tmap.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this);\n\t},\n\n\t_addScales: function (options, className, container) {\n\t\tif (options.metric) {\n\t\t\tthis._mScale = create$1('div', className, container);\n\t\t}\n\t\tif (options.imperial) {\n\t\t\tthis._iScale = create$1('div', className, container);\n\t\t}\n\t},\n\n\t_update: function () {\n\t\tvar map = this._map,\n\t\t y = map.getSize().y / 2;\n\n\t\tvar maxMeters = map.distance(\n\t\t\tmap.containerPointToLatLng([0, y]),\n\t\t\tmap.containerPointToLatLng([this.options.maxWidth, y]));\n\n\t\tthis._updateScales(maxMeters);\n\t},\n\n\t_updateScales: function (maxMeters) {\n\t\tif (this.options.metric && maxMeters) {\n\t\t\tthis._updateMetric(maxMeters);\n\t\t}\n\t\tif (this.options.imperial && maxMeters) {\n\t\t\tthis._updateImperial(maxMeters);\n\t\t}\n\t},\n\n\t_updateMetric: function (maxMeters) {\n\t\tvar meters = this._getRoundNum(maxMeters),\n\t\t label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';\n\n\t\tthis._updateScale(this._mScale, label, meters / maxMeters);\n\t},\n\n\t_updateImperial: function (maxMeters) {\n\t\tvar maxFeet = maxMeters * 3.2808399,\n\t\t maxMiles, miles, feet;\n\n\t\tif (maxFeet > 5280) {\n\t\t\tmaxMiles = maxFeet / 5280;\n\t\t\tmiles = this._getRoundNum(maxMiles);\n\t\t\tthis._updateScale(this._iScale, miles + ' mi', miles / maxMiles);\n\n\t\t} else {\n\t\t\tfeet = this._getRoundNum(maxFeet);\n\t\t\tthis._updateScale(this._iScale, feet + ' ft', feet / maxFeet);\n\t\t}\n\t},\n\n\t_updateScale: function (scale, text, ratio) {\n\t\tscale.style.width = Math.round(this.options.maxWidth * ratio) + 'px';\n\t\tscale.innerHTML = text;\n\t},\n\n\t_getRoundNum: function (num) {\n\t\tvar pow10 = Math.pow(10, (Math.floor(num) + '').length - 1),\n\t\t d = num / pow10;\n\n\t\td = d >= 10 ? 10 :\n\t\t d >= 5 ? 5 :\n\t\t d >= 3 ? 3 :\n\t\t d >= 2 ? 2 : 1;\n\n\t\treturn pow10 * d;\n\t}\n});\n\n\n// @factory L.control.scale(options?: Control.Scale options)\n// Creates an scale control with the given options.\nvar scale = function (options) {\n\treturn new Scale(options);\n};\n\n/*\r\n * @class Control.Attribution\r\n * @aka L.Control.Attribution\r\n * @inherits Control\r\n *\r\n * The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its [`attributionControl` option](#map-attributioncontrol) to `false`, and it fetches attribution texts from layers with the [`getAttribution` method](#layer-getattribution) automatically. Extends Control.\r\n */\r\n\r\nvar Attribution = Control.extend({\r\n\t// @section\r\n\t// @aka Control.Attribution options\r\n\toptions: {\r\n\t\tposition: 'bottomright',\r\n\r\n\t\t// @option prefix: String = 'Leaflet'\r\n\t\t// The HTML text shown before the attributions. Pass `false` to disable.\r\n\t\tprefix: '<a href=\"https://leafletjs.com\" title=\"A JS library for interactive maps\">Leaflet</a>'\r\n\t},\r\n\r\n\tinitialize: function (options) {\r\n\t\tsetOptions(this, options);\r\n\r\n\t\tthis._attributions = {};\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tmap.attributionControl = this;\r\n\t\tthis._container = create$1('div', 'leaflet-control-attribution');\r\n\t\tdisableClickPropagation(this._container);\r\n\r\n\t\t// TODO ugly, refactor\r\n\t\tfor (var i in map._layers) {\r\n\t\t\tif (map._layers[i].getAttribution) {\r\n\t\t\t\tthis.addAttribution(map._layers[i].getAttribution());\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis._update();\r\n\r\n\t\treturn this._container;\r\n\t},\r\n\r\n\t// @method setPrefix(prefix: String): this\r\n\t// Sets the text before the attributions.\r\n\tsetPrefix: function (prefix) {\r\n\t\tthis.options.prefix = prefix;\r\n\t\tthis._update();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method addAttribution(text: String): this\r\n\t// Adds an attribution text (e.g. `'Vector data &copy; Mapbox'`).\r\n\taddAttribution: function (text) {\r\n\t\tif (!text) { return this; }\r\n\r\n\t\tif (!this._attributions[text]) {\r\n\t\t\tthis._attributions[text] = 0;\r\n\t\t}\r\n\t\tthis._attributions[text]++;\r\n\r\n\t\tthis._update();\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method removeAttribution(text: String): this\r\n\t// Removes an attribution text.\r\n\tremoveAttribution: function (text) {\r\n\t\tif (!text) { return this; }\r\n\r\n\t\tif (this._attributions[text]) {\r\n\t\t\tthis._attributions[text]--;\r\n\t\t\tthis._update();\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_update: function () {\r\n\t\tif (!this._map) { return; }\r\n\r\n\t\tvar attribs = [];\r\n\r\n\t\tfor (var i in this._attributions) {\r\n\t\t\tif (this._attributions[i]) {\r\n\t\t\t\tattribs.push(i);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tvar prefixAndAttribs = [];\r\n\r\n\t\tif (this.options.prefix) {\r\n\t\t\tprefixAndAttribs.push(this.options.prefix);\r\n\t\t}\r\n\t\tif (attribs.length) {\r\n\t\t\tprefixAndAttribs.push(attribs.join(', '));\r\n\t\t}\r\n\r\n\t\tthis._container.innerHTML = prefixAndAttribs.join(' | ');\r\n\t}\r\n});\r\n\r\n// @namespace Map\r\n// @section Control options\r\n// @option attributionControl: Boolean = true\r\n// Whether a [attribution control](#control-attribution) is added to the map by default.\r\nMap.mergeOptions({\r\n\tattributionControl: true\r\n});\r\n\r\nMap.addInitHook(function () {\r\n\tif (this.options.attributionControl) {\r\n\t\tnew Attribution().addTo(this);\r\n\t}\r\n});\r\n\r\n// @namespace Control.Attribution\r\n// @factory L.control.attribution(options: Control.Attribution options)\r\n// Creates an attribution control.\r\nvar attribution = function (options) {\r\n\treturn new Attribution(options);\r\n};\n\nControl.Layers = Layers;\nControl.Zoom = Zoom;\nControl.Scale = Scale;\nControl.Attribution = Attribution;\n\ncontrol.layers = layers;\ncontrol.zoom = zoom;\ncontrol.scale = scale;\ncontrol.attribution = attribution;\n\n/*\n\tL.Handler is a base class for handler classes that are used internally to inject\n\tinteraction features like dragging to classes like Map and Marker.\n*/\n\n// @class Handler\n// @aka L.Handler\n// Abstract class for map interaction handlers\n\nvar Handler = Class.extend({\n\tinitialize: function (map) {\n\t\tthis._map = map;\n\t},\n\n\t// @method enable(): this\n\t// Enables the handler\n\tenable: function () {\n\t\tif (this._enabled) { return this; }\n\n\t\tthis._enabled = true;\n\t\tthis.addHooks();\n\t\treturn this;\n\t},\n\n\t// @method disable(): this\n\t// Disables the handler\n\tdisable: function () {\n\t\tif (!this._enabled) { return this; }\n\n\t\tthis._enabled = false;\n\t\tthis.removeHooks();\n\t\treturn this;\n\t},\n\n\t// @method enabled(): Boolean\n\t// Returns `true` if the handler is enabled\n\tenabled: function () {\n\t\treturn !!this._enabled;\n\t}\n\n\t// @section Extension methods\n\t// Classes inheriting from `Handler` must implement the two following methods:\n\t// @method addHooks()\n\t// Called when the handler is enabled, should add event hooks.\n\t// @method removeHooks()\n\t// Called when the handler is disabled, should remove the event hooks added previously.\n});\n\n// @section There is static function which can be called without instantiating L.Handler:\n// @function addTo(map: Map, name: String): this\n// Adds a new Handler to the given map with the given name.\nHandler.addTo = function (map, name) {\n\tmap.addHandler(name, this);\n\treturn this;\n};\n\nvar Mixin = {Events: Events};\n\n/*\r\n * @class Draggable\r\n * @aka L.Draggable\r\n * @inherits Evented\r\n *\r\n * A class for making DOM elements draggable (including touch support).\r\n * Used internally for map and marker dragging. Only works for elements\r\n * that were positioned with [`L.DomUtil.setPosition`](#domutil-setposition).\r\n *\r\n * @example\r\n * ```js\r\n * var draggable = new L.Draggable(elementToDrag);\r\n * draggable.enable();\r\n * ```\r\n */\r\n\r\nvar START = touch ? 'touchstart mousedown' : 'mousedown';\r\nvar END = {\r\n\tmousedown: 'mouseup',\r\n\ttouchstart: 'touchend',\r\n\tpointerdown: 'touchend',\r\n\tMSPointerDown: 'touchend'\r\n};\r\nvar MOVE = {\r\n\tmousedown: 'mousemove',\r\n\ttouchstart: 'touchmove',\r\n\tpointerdown: 'touchmove',\r\n\tMSPointerDown: 'touchmove'\r\n};\r\n\r\n\r\nvar Draggable = Evented.extend({\r\n\r\n\toptions: {\r\n\t\t// @section\r\n\t\t// @aka Draggable options\r\n\t\t// @option clickTolerance: Number = 3\r\n\t\t// The max number of pixels a user can shift the mouse pointer during a click\r\n\t\t// for it to be considered a valid click (as opposed to a mouse drag).\r\n\t\tclickTolerance: 3\r\n\t},\r\n\r\n\t// @constructor L.Draggable(el: HTMLElement, dragHandle?: HTMLElement, preventOutline?: Boolean, options?: Draggable options)\r\n\t// Creates a `Draggable` object for moving `el` when you start dragging the `dragHandle` element (equals `el` itself by default).\r\n\tinitialize: function (element, dragStartTarget, preventOutline$$1, options) {\r\n\t\tsetOptions(this, options);\r\n\r\n\t\tthis._element = element;\r\n\t\tthis._dragStartTarget = dragStartTarget || element;\r\n\t\tthis._preventOutline = preventOutline$$1;\r\n\t},\r\n\r\n\t// @method enable()\r\n\t// Enables the dragging ability\r\n\tenable: function () {\r\n\t\tif (this._enabled) { return; }\r\n\r\n\t\ton(this._dragStartTarget, START, this._onDown, this);\r\n\r\n\t\tthis._enabled = true;\r\n\t},\r\n\r\n\t// @method disable()\r\n\t// Disables the dragging ability\r\n\tdisable: function () {\r\n\t\tif (!this._enabled) { return; }\r\n\r\n\t\t// If we're currently dragging this draggable,\r\n\t\t// disabling it counts as first ending the drag.\r\n\t\tif (Draggable._dragging === this) {\r\n\t\t\tthis.finishDrag();\r\n\t\t}\r\n\r\n\t\toff(this._dragStartTarget, START, this._onDown, this);\r\n\r\n\t\tthis._enabled = false;\r\n\t\tthis._moved = false;\r\n\t},\r\n\r\n\t_onDown: function (e) {\r\n\t\t// Ignore simulated events, since we handle both touch and\r\n\t\t// mouse explicitly; otherwise we risk getting duplicates of\r\n\t\t// touch events, see #4315.\r\n\t\t// Also ignore the event if disabled; this happens in IE11\r\n\t\t// under some circumstances, see #3666.\r\n\t\tif (e._simulated || !this._enabled) { return; }\r\n\r\n\t\tthis._moved = false;\r\n\r\n\t\tif (hasClass(this._element, 'leaflet-zoom-anim')) { return; }\r\n\r\n\t\tif (Draggable._dragging || e.shiftKey || ((e.which !== 1) && (e.button !== 1) && !e.touches)) { return; }\r\n\t\tDraggable._dragging = this; // Prevent dragging multiple objects at once.\r\n\r\n\t\tif (this._preventOutline) {\r\n\t\t\tpreventOutline(this._element);\r\n\t\t}\r\n\r\n\t\tdisableImageDrag();\r\n\t\tdisableTextSelection();\r\n\r\n\t\tif (this._moving) { return; }\r\n\r\n\t\t// @event down: Event\r\n\t\t// Fired when a drag is about to start.\r\n\t\tthis.fire('down');\r\n\r\n\t\tvar first = e.touches ? e.touches[0] : e,\r\n\t\t sizedParent = getSizedParentNode(this._element);\r\n\r\n\t\tthis._startPoint = new Point(first.clientX, first.clientY);\r\n\r\n\t\t// Cache the scale, so that we can continuously compensate for it during drag (_onMove).\r\n\t\tthis._parentScale = getScale(sizedParent);\r\n\r\n\t\ton(document, MOVE[e.type], this._onMove, this);\r\n\t\ton(document, END[e.type], this._onUp, this);\r\n\t},\r\n\r\n\t_onMove: function (e) {\r\n\t\t// Ignore simulated events, since we handle both touch and\r\n\t\t// mouse explicitly; otherwise we risk getting duplicates of\r\n\t\t// touch events, see #4315.\r\n\t\t// Also ignore the event if disabled; this happens in IE11\r\n\t\t// under some circumstances, see #3666.\r\n\t\tif (e._simulated || !this._enabled) { return; }\r\n\r\n\t\tif (e.touches && e.touches.length > 1) {\r\n\t\t\tthis._moved = true;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tvar first = (e.touches && e.touches.length === 1 ? e.touches[0] : e),\r\n\t\t offset = new Point(first.clientX, first.clientY)._subtract(this._startPoint);\r\n\r\n\t\tif (!offset.x && !offset.y) { return; }\r\n\t\tif (Math.abs(offset.x) + Math.abs(offset.y) < this.options.clickTolerance) { return; }\r\n\r\n\t\t// We assume that the parent container's position, border and scale do not change for the duration of the drag.\r\n\t\t// Therefore there is no need to account for the position and border (they are eliminated by the subtraction)\r\n\t\t// and we can use the cached value for the scale.\r\n\t\toffset.x /= this._parentScale.x;\r\n\t\toffset.y /= this._parentScale.y;\r\n\r\n\t\tpreventDefault(e);\r\n\r\n\t\tif (!this._moved) {\r\n\t\t\t// @event dragstart: Event\r\n\t\t\t// Fired when a drag starts\r\n\t\t\tthis.fire('dragstart');\r\n\r\n\t\t\tthis._moved = true;\r\n\t\t\tthis._startPos = getPosition(this._element).subtract(offset);\r\n\r\n\t\t\taddClass(document.body, 'leaflet-dragging');\r\n\r\n\t\t\tthis._lastTarget = e.target || e.srcElement;\r\n\t\t\t// IE and Edge do not give the <use> element, so fetch it\r\n\t\t\t// if necessary\r\n\t\t\tif ((window.SVGElementInstance) && (this._lastTarget instanceof SVGElementInstance)) {\r\n\t\t\t\tthis._lastTarget = this._lastTarget.correspondingUseElement;\r\n\t\t\t}\r\n\t\t\taddClass(this._lastTarget, 'leaflet-drag-target');\r\n\t\t}\r\n\r\n\t\tthis._newPos = this._startPos.add(offset);\r\n\t\tthis._moving = true;\r\n\r\n\t\tcancelAnimFrame(this._animRequest);\r\n\t\tthis._lastEvent = e;\r\n\t\tthis._animRequest = requestAnimFrame(this._updatePosition, this, true);\r\n\t},\r\n\r\n\t_updatePosition: function () {\r\n\t\tvar e = {originalEvent: this._lastEvent};\r\n\r\n\t\t// @event predrag: Event\r\n\t\t// Fired continuously during dragging *before* each corresponding\r\n\t\t// update of the element's position.\r\n\t\tthis.fire('predrag', e);\r\n\t\tsetPosition(this._element, this._newPos);\r\n\r\n\t\t// @event drag: Event\r\n\t\t// Fired continuously during dragging.\r\n\t\tthis.fire('drag', e);\r\n\t},\r\n\r\n\t_onUp: function (e) {\r\n\t\t// Ignore simulated events, since we handle both touch and\r\n\t\t// mouse explicitly; otherwise we risk getting duplicates of\r\n\t\t// touch events, see #4315.\r\n\t\t// Also ignore the event if disabled; this happens in IE11\r\n\t\t// under some circumstances, see #3666.\r\n\t\tif (e._simulated || !this._enabled) { return; }\r\n\t\tthis.finishDrag();\r\n\t},\r\n\r\n\tfinishDrag: function () {\r\n\t\tremoveClass(document.body, 'leaflet-dragging');\r\n\r\n\t\tif (this._lastTarget) {\r\n\t\t\tremoveClass(this._lastTarget, 'leaflet-drag-target');\r\n\t\t\tthis._lastTarget = null;\r\n\t\t}\r\n\r\n\t\tfor (var i in MOVE) {\r\n\t\t\toff(document, MOVE[i], this._onMove, this);\r\n\t\t\toff(document, END[i], this._onUp, this);\r\n\t\t}\r\n\r\n\t\tenableImageDrag();\r\n\t\tenableTextSelection();\r\n\r\n\t\tif (this._moved && this._moving) {\r\n\t\t\t// ensure drag is not fired after dragend\r\n\t\t\tcancelAnimFrame(this._animRequest);\r\n\r\n\t\t\t// @event dragend: DragEndEvent\r\n\t\t\t// Fired when the drag ends.\r\n\t\t\tthis.fire('dragend', {\r\n\t\t\t\tdistance: this._newPos.distanceTo(this._startPos)\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tthis._moving = false;\r\n\t\tDraggable._dragging = false;\r\n\t}\r\n\r\n});\n\n/*\r\n * @namespace LineUtil\r\n *\r\n * Various utility functions for polyline points processing, used by Leaflet internally to make polylines lightning-fast.\r\n */\r\n\r\n// Simplify polyline with vertex reduction and Douglas-Peucker simplification.\r\n// Improves rendering performance dramatically by lessening the number of points to draw.\r\n\r\n// @function simplify(points: Point[], tolerance: Number): Point[]\r\n// Dramatically reduces the number of points in a polyline while retaining\r\n// its shape and returns a new array of simplified points, using the\r\n// [Douglas-Peucker algorithm](http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm).\r\n// Used for a huge performance boost when processing/displaying Leaflet polylines for\r\n// each zoom level and also reducing visual noise. tolerance affects the amount of\r\n// simplification (lesser value means higher quality but slower and with more points).\r\n// Also released as a separated micro-library [Simplify.js](http://mourner.github.com/simplify-js/).\r\nfunction simplify(points, tolerance) {\r\n\tif (!tolerance || !points.length) {\r\n\t\treturn points.slice();\r\n\t}\r\n\r\n\tvar sqTolerance = tolerance * tolerance;\r\n\r\n\t // stage 1: vertex reduction\r\n\t points = _reducePoints(points, sqTolerance);\r\n\r\n\t // stage 2: Douglas-Peucker simplification\r\n\t points = _simplifyDP(points, sqTolerance);\r\n\r\n\treturn points;\r\n}\r\n\r\n// @function pointToSegmentDistance(p: Point, p1: Point, p2: Point): Number\r\n// Returns the distance between point `p` and segment `p1` to `p2`.\r\nfunction pointToSegmentDistance(p, p1, p2) {\r\n\treturn Math.sqrt(_sqClosestPointOnSegment(p, p1, p2, true));\r\n}\r\n\r\n// @function closestPointOnSegment(p: Point, p1: Point, p2: Point): Number\r\n// Returns the closest point from a point `p` on a segment `p1` to `p2`.\r\nfunction closestPointOnSegment(p, p1, p2) {\r\n\treturn _sqClosestPointOnSegment(p, p1, p2);\r\n}\r\n\r\n// Douglas-Peucker simplification, see http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm\r\nfunction _simplifyDP(points, sqTolerance) {\r\n\r\n\tvar len = points.length,\r\n\t ArrayConstructor = typeof Uint8Array !== undefined + '' ? Uint8Array : Array,\r\n\t markers = new ArrayConstructor(len);\r\n\r\n\t markers[0] = markers[len - 1] = 1;\r\n\r\n\t_simplifyDPStep(points, markers, sqTolerance, 0, len - 1);\r\n\r\n\tvar i,\r\n\t newPoints = [];\r\n\r\n\tfor (i = 0; i < len; i++) {\r\n\t\tif (markers[i]) {\r\n\t\t\tnewPoints.push(points[i]);\r\n\t\t}\r\n\t}\r\n\r\n\treturn newPoints;\r\n}\r\n\r\nfunction _simplifyDPStep(points, markers, sqTolerance, first, last) {\r\n\r\n\tvar maxSqDist = 0,\r\n\tindex, i, sqDist;\r\n\r\n\tfor (i = first + 1; i <= last - 1; i++) {\r\n\t\tsqDist = _sqClosestPointOnSegment(points[i], points[first], points[last], true);\r\n\r\n\t\tif (sqDist > maxSqDist) {\r\n\t\t\tindex = i;\r\n\t\t\tmaxSqDist = sqDist;\r\n\t\t}\r\n\t}\r\n\r\n\tif (maxSqDist > sqTolerance) {\r\n\t\tmarkers[index] = 1;\r\n\r\n\t\t_simplifyDPStep(points, markers, sqTolerance, first, index);\r\n\t\t_simplifyDPStep(points, markers, sqTolerance, index, last);\r\n\t}\r\n}\r\n\r\n// reduce points that are too close to each other to a single point\r\nfunction _reducePoints(points, sqTolerance) {\r\n\tvar reducedPoints = [points[0]];\r\n\r\n\tfor (var i = 1, prev = 0, len = points.length; i < len; i++) {\r\n\t\tif (_sqDist(points[i], points[prev]) > sqTolerance) {\r\n\t\t\treducedPoints.push(points[i]);\r\n\t\t\tprev = i;\r\n\t\t}\r\n\t}\r\n\tif (prev < len - 1) {\r\n\t\treducedPoints.push(points[len - 1]);\r\n\t}\r\n\treturn reducedPoints;\r\n}\r\n\r\nvar _lastCode;\r\n\r\n// @function clipSegment(a: Point, b: Point, bounds: Bounds, useLastCode?: Boolean, round?: Boolean): Point[]|Boolean\r\n// Clips the segment a to b by rectangular bounds with the\r\n// [Cohen-Sutherland algorithm](https://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland_algorithm)\r\n// (modifying the segment points directly!). Used by Leaflet to only show polyline\r\n// points that are on the screen or near, increasing performance.\r\nfunction clipSegment(a, b, bounds, useLastCode, round) {\r\n\tvar codeA = useLastCode ? _lastCode : _getBitCode(a, bounds),\r\n\t codeB = _getBitCode(b, bounds),\r\n\r\n\t codeOut, p, newCode;\r\n\r\n\t // save 2nd code to avoid calculating it on the next segment\r\n\t _lastCode = codeB;\r\n\r\n\twhile (true) {\r\n\t\t// if a,b is inside the clip window (trivial accept)\r\n\t\tif (!(codeA | codeB)) {\r\n\t\t\treturn [a, b];\r\n\t\t}\r\n\r\n\t\t// if a,b is outside the clip window (trivial reject)\r\n\t\tif (codeA & codeB) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\t// other cases\r\n\t\tcodeOut = codeA || codeB;\r\n\t\tp = _getEdgeIntersection(a, b, codeOut, bounds, round);\r\n\t\tnewCode = _getBitCode(p, bounds);\r\n\r\n\t\tif (codeOut === codeA) {\r\n\t\t\ta = p;\r\n\t\t\tcodeA = newCode;\r\n\t\t} else {\r\n\t\t\tb = p;\r\n\t\t\tcodeB = newCode;\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction _getEdgeIntersection(a, b, code, bounds, round) {\r\n\tvar dx = b.x - a.x,\r\n\t dy = b.y - a.y,\r\n\t min = bounds.min,\r\n\t max = bounds.max,\r\n\t x, y;\r\n\r\n\tif (code & 8) { // top\r\n\t\tx = a.x + dx * (max.y - a.y) / dy;\r\n\t\ty = max.y;\r\n\r\n\t} else if (code & 4) { // bottom\r\n\t\tx = a.x + dx * (min.y - a.y) / dy;\r\n\t\ty = min.y;\r\n\r\n\t} else if (code & 2) { // right\r\n\t\tx = max.x;\r\n\t\ty = a.y + dy * (max.x - a.x) / dx;\r\n\r\n\t} else if (code & 1) { // left\r\n\t\tx = min.x;\r\n\t\ty = a.y + dy * (min.x - a.x) / dx;\r\n\t}\r\n\r\n\treturn new Point(x, y, round);\r\n}\r\n\r\nfunction _getBitCode(p, bounds) {\r\n\tvar code = 0;\r\n\r\n\tif (p.x < bounds.min.x) { // left\r\n\t\tcode |= 1;\r\n\t} else if (p.x > bounds.max.x) { // right\r\n\t\tcode |= 2;\r\n\t}\r\n\r\n\tif (p.y < bounds.min.y) { // bottom\r\n\t\tcode |= 4;\r\n\t} else if (p.y > bounds.max.y) { // top\r\n\t\tcode |= 8;\r\n\t}\r\n\r\n\treturn code;\r\n}\r\n\r\n// square distance (to avoid unnecessary Math.sqrt calls)\r\nfunction _sqDist(p1, p2) {\r\n\tvar dx = p2.x - p1.x,\r\n\t dy = p2.y - p1.y;\r\n\treturn dx * dx + dy * dy;\r\n}\r\n\r\n// return closest point on segment or distance to that point\r\nfunction _sqClosestPointOnSegment(p, p1, p2, sqDist) {\r\n\tvar x = p1.x,\r\n\t y = p1.y,\r\n\t dx = p2.x - x,\r\n\t dy = p2.y - y,\r\n\t dot = dx * dx + dy * dy,\r\n\t t;\r\n\r\n\tif (dot > 0) {\r\n\t\tt = ((p.x - x) * dx + (p.y - y) * dy) / dot;\r\n\r\n\t\tif (t > 1) {\r\n\t\t\tx = p2.x;\r\n\t\t\ty = p2.y;\r\n\t\t} else if (t > 0) {\r\n\t\t\tx += dx * t;\r\n\t\t\ty += dy * t;\r\n\t\t}\r\n\t}\r\n\r\n\tdx = p.x - x;\r\n\tdy = p.y - y;\r\n\r\n\treturn sqDist ? dx * dx + dy * dy : new Point(x, y);\r\n}\r\n\r\n\r\n// @function isFlat(latlngs: LatLng[]): Boolean\r\n// Returns true if `latlngs` is a flat array, false is nested.\r\nfunction isFlat(latlngs) {\r\n\treturn !isArray(latlngs[0]) || (typeof latlngs[0][0] !== 'object' && typeof latlngs[0][0] !== 'undefined');\r\n}\r\n\r\nfunction _flat(latlngs) {\r\n\tconsole.warn('Deprecated use of _flat, please use L.LineUtil.isFlat instead.');\r\n\treturn isFlat(latlngs);\r\n}\r\n\n\nvar LineUtil = (Object.freeze || Object)({\n\tsimplify: simplify,\n\tpointToSegmentDistance: pointToSegmentDistance,\n\tclosestPointOnSegment: closestPointOnSegment,\n\tclipSegment: clipSegment,\n\t_getEdgeIntersection: _getEdgeIntersection,\n\t_getBitCode: _getBitCode,\n\t_sqClosestPointOnSegment: _sqClosestPointOnSegment,\n\tisFlat: isFlat,\n\t_flat: _flat\n});\n\n/*\r\n * @namespace PolyUtil\r\n * Various utility functions for polygon geometries.\r\n */\r\n\r\n/* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[]\r\n * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)).\r\n * Used by Leaflet to only show polygon points that are on the screen or near, increasing\r\n * performance. Note that polygon points needs different algorithm for clipping\r\n * than polyline, so there's a separate method for it.\r\n */\r\nfunction clipPolygon(points, bounds, round) {\r\n\tvar clippedPoints,\r\n\t edges = [1, 4, 2, 8],\r\n\t i, j, k,\r\n\t a, b,\r\n\t len, edge, p;\r\n\r\n\tfor (i = 0, len = points.length; i < len; i++) {\r\n\t\tpoints[i]._code = _getBitCode(points[i], bounds);\r\n\t}\r\n\r\n\t// for each edge (left, bottom, right, top)\r\n\tfor (k = 0; k < 4; k++) {\r\n\t\tedge = edges[k];\r\n\t\tclippedPoints = [];\r\n\r\n\t\tfor (i = 0, len = points.length, j = len - 1; i < len; j = i++) {\r\n\t\t\ta = points[i];\r\n\t\t\tb = points[j];\r\n\r\n\t\t\t// if a is inside the clip window\r\n\t\t\tif (!(a._code & edge)) {\r\n\t\t\t\t// if b is outside the clip window (a->b goes out of screen)\r\n\t\t\t\tif (b._code & edge) {\r\n\t\t\t\t\tp = _getEdgeIntersection(b, a, edge, bounds, round);\r\n\t\t\t\t\tp._code = _getBitCode(p, bounds);\r\n\t\t\t\t\tclippedPoints.push(p);\r\n\t\t\t\t}\r\n\t\t\t\tclippedPoints.push(a);\r\n\r\n\t\t\t// else if b is inside the clip window (a->b enters the screen)\r\n\t\t\t} else if (!(b._code & edge)) {\r\n\t\t\t\tp = _getEdgeIntersection(b, a, edge, bounds, round);\r\n\t\t\t\tp._code = _getBitCode(p, bounds);\r\n\t\t\t\tclippedPoints.push(p);\r\n\t\t\t}\r\n\t\t}\r\n\t\tpoints = clippedPoints;\r\n\t}\r\n\r\n\treturn points;\r\n}\r\n\n\nvar PolyUtil = (Object.freeze || Object)({\n\tclipPolygon: clipPolygon\n});\n\n/*\r\n * @namespace Projection\r\n * @section\r\n * Leaflet comes with a set of already defined Projections out of the box:\r\n *\r\n * @projection L.Projection.LonLat\r\n *\r\n * Equirectangular, or Plate Carree projection — the most simple projection,\r\n * mostly used by GIS enthusiasts. Directly maps `x` as longitude, and `y` as\r\n * latitude. Also suitable for flat worlds, e.g. game maps. Used by the\r\n * `EPSG:4326` and `Simple` CRS.\r\n */\r\n\r\nvar LonLat = {\r\n\tproject: function (latlng) {\r\n\t\treturn new Point(latlng.lng, latlng.lat);\r\n\t},\r\n\r\n\tunproject: function (point) {\r\n\t\treturn new LatLng(point.y, point.x);\r\n\t},\r\n\r\n\tbounds: new Bounds([-180, -90], [180, 90])\r\n};\n\n/*\r\n * @namespace Projection\r\n * @projection L.Projection.Mercator\r\n *\r\n * Elliptical Mercator projection — more complex than Spherical Mercator. Assumes that Earth is an ellipsoid. Used by the EPSG:3395 CRS.\r\n */\r\n\r\nvar Mercator = {\r\n\tR: 6378137,\r\n\tR_MINOR: 6356752.314245179,\r\n\r\n\tbounds: new Bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]),\r\n\r\n\tproject: function (latlng) {\r\n\t\tvar d = Math.PI / 180,\r\n\t\t r = this.R,\r\n\t\t y = latlng.lat * d,\r\n\t\t tmp = this.R_MINOR / r,\r\n\t\t e = Math.sqrt(1 - tmp * tmp),\r\n\t\t con = e * Math.sin(y);\r\n\r\n\t\tvar ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2);\r\n\t\ty = -r * Math.log(Math.max(ts, 1E-10));\r\n\r\n\t\treturn new Point(latlng.lng * d * r, y);\r\n\t},\r\n\r\n\tunproject: function (point) {\r\n\t\tvar d = 180 / Math.PI,\r\n\t\t r = this.R,\r\n\t\t tmp = this.R_MINOR / r,\r\n\t\t e = Math.sqrt(1 - tmp * tmp),\r\n\t\t ts = Math.exp(-point.y / r),\r\n\t\t phi = Math.PI / 2 - 2 * Math.atan(ts);\r\n\r\n\t\tfor (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) {\r\n\t\t\tcon = e * Math.sin(phi);\r\n\t\t\tcon = Math.pow((1 - con) / (1 + con), e / 2);\r\n\t\t\tdphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi;\r\n\t\t\tphi += dphi;\r\n\t\t}\r\n\r\n\t\treturn new LatLng(phi * d, point.x * d / r);\r\n\t}\r\n};\n\n/*\n * @class Projection\n\n * An object with methods for projecting geographical coordinates of the world onto\n * a flat surface (and back). See [Map projection](http://en.wikipedia.org/wiki/Map_projection).\n\n * @property bounds: Bounds\n * The bounds (specified in CRS units) where the projection is valid\n\n * @method project(latlng: LatLng): Point\n * Projects geographical coordinates into a 2D point.\n * Only accepts actual `L.LatLng` instances, not arrays.\n\n * @method unproject(point: Point): LatLng\n * The inverse of `project`. Projects a 2D point into a geographical location.\n * Only accepts actual `L.Point` instances, not arrays.\n\n * Note that the projection instances do not inherit from Leafet's `Class` object,\n * and can't be instantiated. Also, new classes can't inherit from them,\n * and methods can't be added to them with the `include` function.\n\n */\n\n\n\n\nvar index = (Object.freeze || Object)({\n\tLonLat: LonLat,\n\tMercator: Mercator,\n\tSphericalMercator: SphericalMercator\n});\n\n/*\r\n * @namespace CRS\r\n * @crs L.CRS.EPSG3395\r\n *\r\n * Rarely used by some commercial tile providers. Uses Elliptical Mercator projection.\r\n */\r\nvar EPSG3395 = extend({}, Earth, {\r\n\tcode: 'EPSG:3395',\r\n\tprojection: Mercator,\r\n\r\n\ttransformation: (function () {\r\n\t\tvar scale = 0.5 / (Math.PI * Mercator.R);\r\n\t\treturn toTransformation(scale, 0.5, -scale, 0.5);\r\n\t}())\r\n});\n\n/*\r\n * @namespace CRS\r\n * @crs L.CRS.EPSG4326\r\n *\r\n * A common CRS among GIS enthusiasts. Uses simple Equirectangular projection.\r\n *\r\n * Leaflet 1.0.x complies with the [TMS coordinate scheme for EPSG:4326](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic),\r\n * which is a breaking change from 0.7.x behaviour. If you are using a `TileLayer`\r\n * with this CRS, ensure that there are two 256x256 pixel tiles covering the\r\n * whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90),\r\n * or (-180,-90) for `TileLayer`s with [the `tms` option](#tilelayer-tms) set.\r\n */\r\n\r\nvar EPSG4326 = extend({}, Earth, {\r\n\tcode: 'EPSG:4326',\r\n\tprojection: LonLat,\r\n\ttransformation: toTransformation(1 / 180, 1, -1 / 180, 0.5)\r\n});\n\n/*\n * @namespace CRS\n * @crs L.CRS.Simple\n *\n * A simple CRS that maps longitude and latitude into `x` and `y` directly.\n * May be used for maps of flat surfaces (e.g. game maps). Note that the `y`\n * axis should still be inverted (going from bottom to top). `distance()` returns\n * simple euclidean distance.\n */\n\nvar Simple = extend({}, CRS, {\n\tprojection: LonLat,\n\ttransformation: toTransformation(1, 0, -1, 0),\n\n\tscale: function (zoom) {\n\t\treturn Math.pow(2, zoom);\n\t},\n\n\tzoom: function (scale) {\n\t\treturn Math.log(scale) / Math.LN2;\n\t},\n\n\tdistance: function (latlng1, latlng2) {\n\t\tvar dx = latlng2.lng - latlng1.lng,\n\t\t dy = latlng2.lat - latlng1.lat;\n\n\t\treturn Math.sqrt(dx * dx + dy * dy);\n\t},\n\n\tinfinite: true\n});\n\nCRS.Earth = Earth;\nCRS.EPSG3395 = EPSG3395;\nCRS.EPSG3857 = EPSG3857;\nCRS.EPSG900913 = EPSG900913;\nCRS.EPSG4326 = EPSG4326;\nCRS.Simple = Simple;\n\n/*\n * @class Layer\n * @inherits Evented\n * @aka L.Layer\n * @aka ILayer\n *\n * A set of methods from the Layer base class that all Leaflet layers use.\n * Inherits all methods, options and events from `L.Evented`.\n *\n * @example\n *\n * ```js\n * var layer = L.marker(latlng).addTo(map);\n * layer.addTo(map);\n * layer.remove();\n * ```\n *\n * @event add: Event\n * Fired after the layer is added to a map\n *\n * @event remove: Event\n * Fired after the layer is removed from a map\n */\n\n\nvar Layer = Evented.extend({\n\n\t// Classes extending `L.Layer` will inherit the following options:\n\toptions: {\n\t\t// @option pane: String = 'overlayPane'\n\t\t// By default the layer will be added to the map's [overlay pane](#map-overlaypane). Overriding this option will cause the layer to be placed on another pane by default.\n\t\tpane: 'overlayPane',\n\n\t\t// @option attribution: String = null\n\t\t// String to be shown in the attribution control, e.g. \"© OpenStreetMap contributors\". It describes the layer data and is often a legal obligation towards copyright holders and tile providers.\n\t\tattribution: null,\n\n\t\tbubblingMouseEvents: true\n\t},\n\n\t/* @section\n\t * Classes extending `L.Layer` will inherit the following methods:\n\t *\n\t * @method addTo(map: Map|LayerGroup): this\n\t * Adds the layer to the given map or layer group.\n\t */\n\taddTo: function (map) {\n\t\tmap.addLayer(this);\n\t\treturn this;\n\t},\n\n\t// @method remove: this\n\t// Removes the layer from the map it is currently active on.\n\tremove: function () {\n\t\treturn this.removeFrom(this._map || this._mapToAdd);\n\t},\n\n\t// @method removeFrom(map: Map): this\n\t// Removes the layer from the given map\n\tremoveFrom: function (obj) {\n\t\tif (obj) {\n\t\t\tobj.removeLayer(this);\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method getPane(name? : String): HTMLElement\n\t// Returns the `HTMLElement` representing the named pane on the map. If `name` is omitted, returns the pane for this layer.\n\tgetPane: function (name) {\n\t\treturn this._map.getPane(name ? (this.options[name] || name) : this.options.pane);\n\t},\n\n\taddInteractiveTarget: function (targetEl) {\n\t\tthis._map._targets[stamp(targetEl)] = this;\n\t\treturn this;\n\t},\n\n\tremoveInteractiveTarget: function (targetEl) {\n\t\tdelete this._map._targets[stamp(targetEl)];\n\t\treturn this;\n\t},\n\n\t// @method getAttribution: String\n\t// Used by the `attribution control`, returns the [attribution option](#gridlayer-attribution).\n\tgetAttribution: function () {\n\t\treturn this.options.attribution;\n\t},\n\n\t_layerAdd: function (e) {\n\t\tvar map = e.target;\n\n\t\t// check in case layer gets added and then removed before the map is ready\n\t\tif (!map.hasLayer(this)) { return; }\n\n\t\tthis._map = map;\n\t\tthis._zoomAnimated = map._zoomAnimated;\n\n\t\tif (this.getEvents) {\n\t\t\tvar events = this.getEvents();\n\t\t\tmap.on(events, this);\n\t\t\tthis.once('remove', function () {\n\t\t\t\tmap.off(events, this);\n\t\t\t}, this);\n\t\t}\n\n\t\tthis.onAdd(map);\n\n\t\tif (this.getAttribution && map.attributionControl) {\n\t\t\tmap.attributionControl.addAttribution(this.getAttribution());\n\t\t}\n\n\t\tthis.fire('add');\n\t\tmap.fire('layeradd', {layer: this});\n\t}\n});\n\n/* @section Extension methods\n * @uninheritable\n *\n * Every layer should extend from `L.Layer` and (re-)implement the following methods.\n *\n * @method onAdd(map: Map): this\n * Should contain code that creates DOM elements for the layer, adds them to `map panes` where they should belong and puts listeners on relevant map events. Called on [`map.addLayer(layer)`](#map-addlayer).\n *\n * @method onRemove(map: Map): this\n * Should contain all clean up code that removes the layer's elements from the DOM and removes listeners previously added in [`onAdd`](#layer-onadd). Called on [`map.removeLayer(layer)`](#map-removelayer).\n *\n * @method getEvents(): Object\n * This optional method should return an object like `{ viewreset: this._reset }` for [`addEventListener`](#evented-addeventlistener). The event handlers in this object will be automatically added and removed from the map with your layer.\n *\n * @method getAttribution(): String\n * This optional method should return a string containing HTML to be shown on the `Attribution control` whenever the layer is visible.\n *\n * @method beforeAdd(map: Map): this\n * Optional method. Called on [`map.addLayer(layer)`](#map-addlayer), before the layer is added to the map, before events are initialized, without waiting until the map is in a usable state. Use for early initialization only.\n */\n\n\n/* @namespace Map\n * @section Layer events\n *\n * @event layeradd: LayerEvent\n * Fired when a new layer is added to the map.\n *\n * @event layerremove: LayerEvent\n * Fired when some layer is removed from the map\n *\n * @section Methods for Layers and Controls\n */\nMap.include({\n\t// @method addLayer(layer: Layer): this\n\t// Adds the given layer to the map\n\taddLayer: function (layer) {\n\t\tif (!layer._layerAdd) {\n\t\t\tthrow new Error('The provided object is not a Layer.');\n\t\t}\n\n\t\tvar id = stamp(layer);\n\t\tif (this._layers[id]) { return this; }\n\t\tthis._layers[id] = layer;\n\n\t\tlayer._mapToAdd = this;\n\n\t\tif (layer.beforeAdd) {\n\t\t\tlayer.beforeAdd(this);\n\t\t}\n\n\t\tthis.whenReady(layer._layerAdd, layer);\n\n\t\treturn this;\n\t},\n\n\t// @method removeLayer(layer: Layer): this\n\t// Removes the given layer from the map.\n\tremoveLayer: function (layer) {\n\t\tvar id = stamp(layer);\n\n\t\tif (!this._layers[id]) { return this; }\n\n\t\tif (this._loaded) {\n\t\t\tlayer.onRemove(this);\n\t\t}\n\n\t\tif (layer.getAttribution && this.attributionControl) {\n\t\t\tthis.attributionControl.removeAttribution(layer.getAttribution());\n\t\t}\n\n\t\tdelete this._layers[id];\n\n\t\tif (this._loaded) {\n\t\t\tthis.fire('layerremove', {layer: layer});\n\t\t\tlayer.fire('remove');\n\t\t}\n\n\t\tlayer._map = layer._mapToAdd = null;\n\n\t\treturn this;\n\t},\n\n\t// @method hasLayer(layer: Layer): Boolean\n\t// Returns `true` if the given layer is currently added to the map\n\thasLayer: function (layer) {\n\t\treturn !!layer && (stamp(layer) in this._layers);\n\t},\n\n\t/* @method eachLayer(fn: Function, context?: Object): this\n\t * Iterates over the layers of the map, optionally specifying context of the iterator function.\n\t * ```\n\t * map.eachLayer(function(layer){\n\t * layer.bindPopup('Hello');\n\t * });\n\t * ```\n\t */\n\teachLayer: function (method, context) {\n\t\tfor (var i in this._layers) {\n\t\t\tmethod.call(context, this._layers[i]);\n\t\t}\n\t\treturn this;\n\t},\n\n\t_addLayers: function (layers) {\n\t\tlayers = layers ? (isArray(layers) ? layers : [layers]) : [];\n\n\t\tfor (var i = 0, len = layers.length; i < len; i++) {\n\t\t\tthis.addLayer(layers[i]);\n\t\t}\n\t},\n\n\t_addZoomLimit: function (layer) {\n\t\tif (isNaN(layer.options.maxZoom) || !isNaN(layer.options.minZoom)) {\n\t\t\tthis._zoomBoundLayers[stamp(layer)] = layer;\n\t\t\tthis._updateZoomLevels();\n\t\t}\n\t},\n\n\t_removeZoomLimit: function (layer) {\n\t\tvar id = stamp(layer);\n\n\t\tif (this._zoomBoundLayers[id]) {\n\t\t\tdelete this._zoomBoundLayers[id];\n\t\t\tthis._updateZoomLevels();\n\t\t}\n\t},\n\n\t_updateZoomLevels: function () {\n\t\tvar minZoom = Infinity,\n\t\t maxZoom = -Infinity,\n\t\t oldZoomSpan = this._getZoomSpan();\n\n\t\tfor (var i in this._zoomBoundLayers) {\n\t\t\tvar options = this._zoomBoundLayers[i].options;\n\n\t\t\tminZoom = options.minZoom === undefined ? minZoom : Math.min(minZoom, options.minZoom);\n\t\t\tmaxZoom = options.maxZoom === undefined ? maxZoom : Math.max(maxZoom, options.maxZoom);\n\t\t}\n\n\t\tthis._layersMaxZoom = maxZoom === -Infinity ? undefined : maxZoom;\n\t\tthis._layersMinZoom = minZoom === Infinity ? undefined : minZoom;\n\n\t\t// @section Map state change events\n\t\t// @event zoomlevelschange: Event\n\t\t// Fired when the number of zoomlevels on the map is changed due\n\t\t// to adding or removing a layer.\n\t\tif (oldZoomSpan !== this._getZoomSpan()) {\n\t\t\tthis.fire('zoomlevelschange');\n\t\t}\n\n\t\tif (this.options.maxZoom === undefined && this._layersMaxZoom && this.getZoom() > this._layersMaxZoom) {\n\t\t\tthis.setZoom(this._layersMaxZoom);\n\t\t}\n\t\tif (this.options.minZoom === undefined && this._layersMinZoom && this.getZoom() < this._layersMinZoom) {\n\t\t\tthis.setZoom(this._layersMinZoom);\n\t\t}\n\t}\n});\n\n/*\r\n * @class LayerGroup\r\n * @aka L.LayerGroup\r\n * @inherits Layer\r\n *\r\n * Used to group several layers and handle them as one. If you add it to the map,\r\n * any layers added or removed from the group will be added/removed on the map as\r\n * well. Extends `Layer`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * L.layerGroup([marker1, marker2])\r\n * \t.addLayer(polyline)\r\n * \t.addTo(map);\r\n * ```\r\n */\r\n\r\nvar LayerGroup = Layer.extend({\r\n\r\n\tinitialize: function (layers, options) {\r\n\t\tsetOptions(this, options);\r\n\r\n\t\tthis._layers = {};\r\n\r\n\t\tvar i, len;\r\n\r\n\t\tif (layers) {\r\n\t\t\tfor (i = 0, len = layers.length; i < len; i++) {\r\n\t\t\t\tthis.addLayer(layers[i]);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t// @method addLayer(layer: Layer): this\r\n\t// Adds the given layer to the group.\r\n\taddLayer: function (layer) {\r\n\t\tvar id = this.getLayerId(layer);\r\n\r\n\t\tthis._layers[id] = layer;\r\n\r\n\t\tif (this._map) {\r\n\t\t\tthis._map.addLayer(layer);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method removeLayer(layer: Layer): this\r\n\t// Removes the given layer from the group.\r\n\t// @alternative\r\n\t// @method removeLayer(id: Number): this\r\n\t// Removes the layer with the given internal ID from the group.\r\n\tremoveLayer: function (layer) {\r\n\t\tvar id = layer in this._layers ? layer : this.getLayerId(layer);\r\n\r\n\t\tif (this._map && this._layers[id]) {\r\n\t\t\tthis._map.removeLayer(this._layers[id]);\r\n\t\t}\r\n\r\n\t\tdelete this._layers[id];\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method hasLayer(layer: Layer): Boolean\r\n\t// Returns `true` if the given layer is currently added to the group.\r\n\t// @alternative\r\n\t// @method hasLayer(id: Number): Boolean\r\n\t// Returns `true` if the given internal ID is currently added to the group.\r\n\thasLayer: function (layer) {\r\n\t\treturn !!layer && (layer in this._layers || this.getLayerId(layer) in this._layers);\r\n\t},\r\n\r\n\t// @method clearLayers(): this\r\n\t// Removes all the layers from the group.\r\n\tclearLayers: function () {\r\n\t\treturn this.eachLayer(this.removeLayer, this);\r\n\t},\r\n\r\n\t// @method invoke(methodName: String, …): this\r\n\t// Calls `methodName` on every layer contained in this group, passing any\r\n\t// additional parameters. Has no effect if the layers contained do not\r\n\t// implement `methodName`.\r\n\tinvoke: function (methodName) {\r\n\t\tvar args = Array.prototype.slice.call(arguments, 1),\r\n\t\t i, layer;\r\n\r\n\t\tfor (i in this._layers) {\r\n\t\t\tlayer = this._layers[i];\r\n\r\n\t\t\tif (layer[methodName]) {\r\n\t\t\t\tlayer[methodName].apply(layer, args);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tthis.eachLayer(map.addLayer, map);\r\n\t},\r\n\r\n\tonRemove: function (map) {\r\n\t\tthis.eachLayer(map.removeLayer, map);\r\n\t},\r\n\r\n\t// @method eachLayer(fn: Function, context?: Object): this\r\n\t// Iterates over the layers of the group, optionally specifying context of the iterator function.\r\n\t// ```js\r\n\t// group.eachLayer(function (layer) {\r\n\t// \tlayer.bindPopup('Hello');\r\n\t// });\r\n\t// ```\r\n\teachLayer: function (method, context) {\r\n\t\tfor (var i in this._layers) {\r\n\t\t\tmethod.call(context, this._layers[i]);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getLayer(id: Number): Layer\r\n\t// Returns the layer with the given internal ID.\r\n\tgetLayer: function (id) {\r\n\t\treturn this._layers[id];\r\n\t},\r\n\r\n\t// @method getLayers(): Layer[]\r\n\t// Returns an array of all the layers added to the group.\r\n\tgetLayers: function () {\r\n\t\tvar layers = [];\r\n\t\tthis.eachLayer(layers.push, layers);\r\n\t\treturn layers;\r\n\t},\r\n\r\n\t// @method setZIndex(zIndex: Number): this\r\n\t// Calls `setZIndex` on every layer contained in this group, passing the z-index.\r\n\tsetZIndex: function (zIndex) {\r\n\t\treturn this.invoke('setZIndex', zIndex);\r\n\t},\r\n\r\n\t// @method getLayerId(layer: Layer): Number\r\n\t// Returns the internal ID for a layer\r\n\tgetLayerId: function (layer) {\r\n\t\treturn stamp(layer);\r\n\t}\r\n});\r\n\r\n\r\n// @factory L.layerGroup(layers?: Layer[], options?: Object)\r\n// Create a layer group, optionally given an initial set of layers and an `options` object.\r\nvar layerGroup = function (layers, options) {\r\n\treturn new LayerGroup(layers, options);\r\n};\n\n/*\r\n * @class FeatureGroup\r\n * @aka L.FeatureGroup\r\n * @inherits LayerGroup\r\n *\r\n * Extended `LayerGroup` that makes it easier to do the same thing to all its member layers:\r\n * * [`bindPopup`](#layer-bindpopup) binds a popup to all of the layers at once (likewise with [`bindTooltip`](#layer-bindtooltip))\r\n * * Events are propagated to the `FeatureGroup`, so if the group has an event\r\n * handler, it will handle events from any of the layers. This includes mouse events\r\n * and custom events.\r\n * * Has `layeradd` and `layerremove` events\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * L.featureGroup([marker1, marker2, polyline])\r\n * \t.bindPopup('Hello world!')\r\n * \t.on('click', function() { alert('Clicked on a member of the group!'); })\r\n * \t.addTo(map);\r\n * ```\r\n */\r\n\r\nvar FeatureGroup = LayerGroup.extend({\r\n\r\n\taddLayer: function (layer) {\r\n\t\tif (this.hasLayer(layer)) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tlayer.addEventParent(this);\r\n\r\n\t\tLayerGroup.prototype.addLayer.call(this, layer);\r\n\r\n\t\t// @event layeradd: LayerEvent\r\n\t\t// Fired when a layer is added to this `FeatureGroup`\r\n\t\treturn this.fire('layeradd', {layer: layer});\r\n\t},\r\n\r\n\tremoveLayer: function (layer) {\r\n\t\tif (!this.hasLayer(layer)) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\t\tif (layer in this._layers) {\r\n\t\t\tlayer = this._layers[layer];\r\n\t\t}\r\n\r\n\t\tlayer.removeEventParent(this);\r\n\r\n\t\tLayerGroup.prototype.removeLayer.call(this, layer);\r\n\r\n\t\t// @event layerremove: LayerEvent\r\n\t\t// Fired when a layer is removed from this `FeatureGroup`\r\n\t\treturn this.fire('layerremove', {layer: layer});\r\n\t},\r\n\r\n\t// @method setStyle(style: Path options): this\r\n\t// Sets the given path options to each layer of the group that has a `setStyle` method.\r\n\tsetStyle: function (style) {\r\n\t\treturn this.invoke('setStyle', style);\r\n\t},\r\n\r\n\t// @method bringToFront(): this\r\n\t// Brings the layer group to the top of all other layers\r\n\tbringToFront: function () {\r\n\t\treturn this.invoke('bringToFront');\r\n\t},\r\n\r\n\t// @method bringToBack(): this\r\n\t// Brings the layer group to the back of all other layers\r\n\tbringToBack: function () {\r\n\t\treturn this.invoke('bringToBack');\r\n\t},\r\n\r\n\t// @method getBounds(): LatLngBounds\r\n\t// Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children).\r\n\tgetBounds: function () {\r\n\t\tvar bounds = new LatLngBounds();\r\n\r\n\t\tfor (var id in this._layers) {\r\n\t\t\tvar layer = this._layers[id];\r\n\t\t\tbounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng());\r\n\t\t}\r\n\t\treturn bounds;\r\n\t}\r\n});\r\n\r\n// @factory L.featureGroup(layers: Layer[])\r\n// Create a feature group, optionally given an initial set of layers.\r\nvar featureGroup = function (layers) {\r\n\treturn new FeatureGroup(layers);\r\n};\n\n/*\r\n * @class Icon\r\n * @aka L.Icon\r\n *\r\n * Represents an icon to provide when creating a marker.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var myIcon = L.icon({\r\n * iconUrl: 'my-icon.png',\r\n * iconRetinaUrl: 'my-icon@2x.png',\r\n * iconSize: [38, 95],\r\n * iconAnchor: [22, 94],\r\n * popupAnchor: [-3, -76],\r\n * shadowUrl: 'my-icon-shadow.png',\r\n * shadowRetinaUrl: 'my-icon-shadow@2x.png',\r\n * shadowSize: [68, 95],\r\n * shadowAnchor: [22, 94]\r\n * });\r\n *\r\n * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);\r\n * ```\r\n *\r\n * `L.Icon.Default` extends `L.Icon` and is the blue icon Leaflet uses for markers by default.\r\n *\r\n */\r\n\r\nvar Icon = Class.extend({\r\n\r\n\t/* @section\r\n\t * @aka Icon options\r\n\t *\r\n\t * @option iconUrl: String = null\r\n\t * **(required)** The URL to the icon image (absolute or relative to your script path).\r\n\t *\r\n\t * @option iconRetinaUrl: String = null\r\n\t * The URL to a retina sized version of the icon image (absolute or relative to your\r\n\t * script path). Used for Retina screen devices.\r\n\t *\r\n\t * @option iconSize: Point = null\r\n\t * Size of the icon image in pixels.\r\n\t *\r\n\t * @option iconAnchor: Point = null\r\n\t * The coordinates of the \"tip\" of the icon (relative to its top left corner). The icon\r\n\t * will be aligned so that this point is at the marker's geographical location. Centered\r\n\t * by default if size is specified, also can be set in CSS with negative margins.\r\n\t *\r\n\t * @option popupAnchor: Point = [0, 0]\r\n\t * The coordinates of the point from which popups will \"open\", relative to the icon anchor.\r\n\t *\r\n\t * @option tooltipAnchor: Point = [0, 0]\r\n\t * The coordinates of the point from which tooltips will \"open\", relative to the icon anchor.\r\n\t *\r\n\t * @option shadowUrl: String = null\r\n\t * The URL to the icon shadow image. If not specified, no shadow image will be created.\r\n\t *\r\n\t * @option shadowRetinaUrl: String = null\r\n\t *\r\n\t * @option shadowSize: Point = null\r\n\t * Size of the shadow image in pixels.\r\n\t *\r\n\t * @option shadowAnchor: Point = null\r\n\t * The coordinates of the \"tip\" of the shadow (relative to its top left corner) (the same\r\n\t * as iconAnchor if not specified).\r\n\t *\r\n\t * @option className: String = ''\r\n\t * A custom class name to assign to both icon and shadow images. Empty by default.\r\n\t */\r\n\r\n\toptions: {\r\n\t\tpopupAnchor: [0, 0],\r\n\t\ttooltipAnchor: [0, 0]\r\n\t},\r\n\r\n\tinitialize: function (options) {\r\n\t\tsetOptions(this, options);\r\n\t},\r\n\r\n\t// @method createIcon(oldIcon?: HTMLElement): HTMLElement\r\n\t// Called internally when the icon has to be shown, returns a `<img>` HTML element\r\n\t// styled according to the options.\r\n\tcreateIcon: function (oldIcon) {\r\n\t\treturn this._createIcon('icon', oldIcon);\r\n\t},\r\n\r\n\t// @method createShadow(oldIcon?: HTMLElement): HTMLElement\r\n\t// As `createIcon`, but for the shadow beneath it.\r\n\tcreateShadow: function (oldIcon) {\r\n\t\treturn this._createIcon('shadow', oldIcon);\r\n\t},\r\n\r\n\t_createIcon: function (name, oldIcon) {\r\n\t\tvar src = this._getIconUrl(name);\r\n\r\n\t\tif (!src) {\r\n\t\t\tif (name === 'icon') {\r\n\t\t\t\tthrow new Error('iconUrl not set in Icon options (see the docs).');\r\n\t\t\t}\r\n\t\t\treturn null;\r\n\t\t}\r\n\r\n\t\tvar img = this._createImg(src, oldIcon && oldIcon.tagName === 'IMG' ? oldIcon : null);\r\n\t\tthis._setIconStyles(img, name);\r\n\r\n\t\treturn img;\r\n\t},\r\n\r\n\t_setIconStyles: function (img, name) {\r\n\t\tvar options = this.options;\r\n\t\tvar sizeOption = options[name + 'Size'];\r\n\r\n\t\tif (typeof sizeOption === 'number') {\r\n\t\t\tsizeOption = [sizeOption, sizeOption];\r\n\t\t}\r\n\r\n\t\tvar size = toPoint(sizeOption),\r\n\t\t anchor = toPoint(name === 'shadow' && options.shadowAnchor || options.iconAnchor ||\r\n\t\t size && size.divideBy(2, true));\r\n\r\n\t\timg.className = 'leaflet-marker-' + name + ' ' + (options.className || '');\r\n\r\n\t\tif (anchor) {\r\n\t\t\timg.style.marginLeft = (-anchor.x) + 'px';\r\n\t\t\timg.style.marginTop = (-anchor.y) + 'px';\r\n\t\t}\r\n\r\n\t\tif (size) {\r\n\t\t\timg.style.width = size.x + 'px';\r\n\t\t\timg.style.height = size.y + 'px';\r\n\t\t}\r\n\t},\r\n\r\n\t_createImg: function (src, el) {\r\n\t\tel = el || document.createElement('img');\r\n\t\tel.src = src;\r\n\t\treturn el;\r\n\t},\r\n\r\n\t_getIconUrl: function (name) {\r\n\t\treturn retina && this.options[name + 'RetinaUrl'] || this.options[name + 'Url'];\r\n\t}\r\n});\r\n\r\n\r\n// @factory L.icon(options: Icon options)\r\n// Creates an icon instance with the given options.\r\nfunction icon(options) {\r\n\treturn new Icon(options);\r\n}\n\n/*\n * @miniclass Icon.Default (Icon)\n * @aka L.Icon.Default\n * @section\n *\n * A trivial subclass of `Icon`, represents the icon to use in `Marker`s when\n * no icon is specified. Points to the blue marker image distributed with Leaflet\n * releases.\n *\n * In order to customize the default icon, just change the properties of `L.Icon.Default.prototype.options`\n * (which is a set of `Icon options`).\n *\n * If you want to _completely_ replace the default icon, override the\n * `L.Marker.prototype.options.icon` with your own icon instead.\n */\n\nvar IconDefault = Icon.extend({\n\n\toptions: {\n\t\ticonUrl: 'marker-icon.png',\n\t\ticonRetinaUrl: 'marker-icon-2x.png',\n\t\tshadowUrl: 'marker-shadow.png',\n\t\ticonSize: [25, 41],\n\t\ticonAnchor: [12, 41],\n\t\tpopupAnchor: [1, -34],\n\t\ttooltipAnchor: [16, -28],\n\t\tshadowSize: [41, 41]\n\t},\n\n\t_getIconUrl: function (name) {\n\t\tif (!IconDefault.imagePath) {\t// Deprecated, backwards-compatibility only\n\t\t\tIconDefault.imagePath = this._detectIconPath();\n\t\t}\n\n\t\t// @option imagePath: String\n\t\t// `Icon.Default` will try to auto-detect the location of the\n\t\t// blue icon images. If you are placing these images in a non-standard\n\t\t// way, set this option to point to the right path.\n\t\treturn (this.options.imagePath || IconDefault.imagePath) + Icon.prototype._getIconUrl.call(this, name);\n\t},\n\n\t_detectIconPath: function () {\n\t\tvar el = create$1('div', 'leaflet-default-icon-path', document.body);\n\t\tvar path = getStyle(el, 'background-image') ||\n\t\t getStyle(el, 'backgroundImage');\t// IE8\n\n\t\tdocument.body.removeChild(el);\n\n\t\tif (path === null || path.indexOf('url') !== 0) {\n\t\t\tpath = '';\n\t\t} else {\n\t\t\tpath = path.replace(/^url\\([\"']?/, '').replace(/marker-icon\\.png[\"']?\\)$/, '');\n\t\t}\n\n\t\treturn path;\n\t}\n});\n\n/*\n * L.Handler.MarkerDrag is used internally by L.Marker to make the markers draggable.\n */\n\n\n/* @namespace Marker\n * @section Interaction handlers\n *\n * Interaction handlers are properties of a marker instance that allow you to control interaction behavior in runtime, enabling or disabling certain features such as dragging (see `Handler` methods). Example:\n *\n * ```js\n * marker.dragging.disable();\n * ```\n *\n * @property dragging: Handler\n * Marker dragging handler (by both mouse and touch). Only valid when the marker is on the map (Otherwise set [`marker.options.draggable`](#marker-draggable)).\n */\n\nvar MarkerDrag = Handler.extend({\n\tinitialize: function (marker) {\n\t\tthis._marker = marker;\n\t},\n\n\taddHooks: function () {\n\t\tvar icon = this._marker._icon;\n\n\t\tif (!this._draggable) {\n\t\t\tthis._draggable = new Draggable(icon, icon, true);\n\t\t}\n\n\t\tthis._draggable.on({\n\t\t\tdragstart: this._onDragStart,\n\t\t\tpredrag: this._onPreDrag,\n\t\t\tdrag: this._onDrag,\n\t\t\tdragend: this._onDragEnd\n\t\t}, this).enable();\n\n\t\taddClass(icon, 'leaflet-marker-draggable');\n\t},\n\n\tremoveHooks: function () {\n\t\tthis._draggable.off({\n\t\t\tdragstart: this._onDragStart,\n\t\t\tpredrag: this._onPreDrag,\n\t\t\tdrag: this._onDrag,\n\t\t\tdragend: this._onDragEnd\n\t\t}, this).disable();\n\n\t\tif (this._marker._icon) {\n\t\t\tremoveClass(this._marker._icon, 'leaflet-marker-draggable');\n\t\t}\n\t},\n\n\tmoved: function () {\n\t\treturn this._draggable && this._draggable._moved;\n\t},\n\n\t_adjustPan: function (e) {\n\t\tvar marker = this._marker,\n\t\t map = marker._map,\n\t\t speed = this._marker.options.autoPanSpeed,\n\t\t padding = this._marker.options.autoPanPadding,\n\t\t iconPos = getPosition(marker._icon),\n\t\t bounds = map.getPixelBounds(),\n\t\t origin = map.getPixelOrigin();\n\n\t\tvar panBounds = toBounds(\n\t\t\tbounds.min._subtract(origin).add(padding),\n\t\t\tbounds.max._subtract(origin).subtract(padding)\n\t\t);\n\n\t\tif (!panBounds.contains(iconPos)) {\n\t\t\t// Compute incremental movement\n\t\t\tvar movement = toPoint(\n\t\t\t\t(Math.max(panBounds.max.x, iconPos.x) - panBounds.max.x) / (bounds.max.x - panBounds.max.x) -\n\t\t\t\t(Math.min(panBounds.min.x, iconPos.x) - panBounds.min.x) / (bounds.min.x - panBounds.min.x),\n\n\t\t\t\t(Math.max(panBounds.max.y, iconPos.y) - panBounds.max.y) / (bounds.max.y - panBounds.max.y) -\n\t\t\t\t(Math.min(panBounds.min.y, iconPos.y) - panBounds.min.y) / (bounds.min.y - panBounds.min.y)\n\t\t\t).multiplyBy(speed);\n\n\t\t\tmap.panBy(movement, {animate: false});\n\n\t\t\tthis._draggable._newPos._add(movement);\n\t\t\tthis._draggable._startPos._add(movement);\n\n\t\t\tsetPosition(marker._icon, this._draggable._newPos);\n\t\t\tthis._onDrag(e);\n\n\t\t\tthis._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));\n\t\t}\n\t},\n\n\t_onDragStart: function () {\n\t\t// @section Dragging events\n\t\t// @event dragstart: Event\n\t\t// Fired when the user starts dragging the marker.\n\n\t\t// @event movestart: Event\n\t\t// Fired when the marker starts moving (because of dragging).\n\n\t\tthis._oldLatLng = this._marker.getLatLng();\n\t\tthis._marker\n\t\t .closePopup()\n\t\t .fire('movestart')\n\t\t .fire('dragstart');\n\t},\n\n\t_onPreDrag: function (e) {\n\t\tif (this._marker.options.autoPan) {\n\t\t\tcancelAnimFrame(this._panRequest);\n\t\t\tthis._panRequest = requestAnimFrame(this._adjustPan.bind(this, e));\n\t\t}\n\t},\n\n\t_onDrag: function (e) {\n\t\tvar marker = this._marker,\n\t\t shadow = marker._shadow,\n\t\t iconPos = getPosition(marker._icon),\n\t\t latlng = marker._map.layerPointToLatLng(iconPos);\n\n\t\t// update shadow position\n\t\tif (shadow) {\n\t\t\tsetPosition(shadow, iconPos);\n\t\t}\n\n\t\tmarker._latlng = latlng;\n\t\te.latlng = latlng;\n\t\te.oldLatLng = this._oldLatLng;\n\n\t\t// @event drag: Event\n\t\t// Fired repeatedly while the user drags the marker.\n\t\tmarker\n\t\t .fire('move', e)\n\t\t .fire('drag', e);\n\t},\n\n\t_onDragEnd: function (e) {\n\t\t// @event dragend: DragEndEvent\n\t\t// Fired when the user stops dragging the marker.\n\n\t\t cancelAnimFrame(this._panRequest);\n\n\t\t// @event moveend: Event\n\t\t// Fired when the marker stops moving (because of dragging).\n\t\tdelete this._oldLatLng;\n\t\tthis._marker\n\t\t .fire('moveend')\n\t\t .fire('dragend', e);\n\t}\n});\n\n/*\r\n * @class Marker\r\n * @inherits Interactive layer\r\n * @aka L.Marker\r\n * L.Marker is used to display clickable/draggable icons on the map. Extends `Layer`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * L.marker([50.5, 30.5]).addTo(map);\r\n * ```\r\n */\r\n\r\nvar Marker = Layer.extend({\r\n\r\n\t// @section\r\n\t// @aka Marker options\r\n\toptions: {\r\n\t\t// @option icon: Icon = *\r\n\t\t// Icon instance to use for rendering the marker.\r\n\t\t// See [Icon documentation](#L.Icon) for details on how to customize the marker icon.\r\n\t\t// If not specified, a common instance of `L.Icon.Default` is used.\r\n\t\ticon: new IconDefault(),\r\n\r\n\t\t// Option inherited from \"Interactive layer\" abstract class\r\n\t\tinteractive: true,\r\n\r\n\t\t// @option keyboard: Boolean = true\r\n\t\t// Whether the marker can be tabbed to with a keyboard and clicked by pressing enter.\r\n\t\tkeyboard: true,\r\n\r\n\t\t// @option title: String = ''\r\n\t\t// Text for the browser tooltip that appear on marker hover (no tooltip by default).\r\n\t\ttitle: '',\r\n\r\n\t\t// @option alt: String = ''\r\n\t\t// Text for the `alt` attribute of the icon image (useful for accessibility).\r\n\t\talt: '',\r\n\r\n\t\t// @option zIndexOffset: Number = 0\r\n\t\t// By default, marker images zIndex is set automatically based on its latitude. Use this option if you want to put the marker on top of all others (or below), specifying a high value like `1000` (or high negative value, respectively).\r\n\t\tzIndexOffset: 0,\r\n\r\n\t\t// @option opacity: Number = 1.0\r\n\t\t// The opacity of the marker.\r\n\t\topacity: 1,\r\n\r\n\t\t// @option riseOnHover: Boolean = false\r\n\t\t// If `true`, the marker will get on top of others when you hover the mouse over it.\r\n\t\triseOnHover: false,\r\n\r\n\t\t// @option riseOffset: Number = 250\r\n\t\t// The z-index offset used for the `riseOnHover` feature.\r\n\t\triseOffset: 250,\r\n\r\n\t\t// @option pane: String = 'markerPane'\r\n\t\t// `Map pane` where the markers icon will be added.\r\n\t\tpane: 'markerPane',\r\n\r\n\t\t// @option pane: String = 'shadowPane'\r\n\t\t// `Map pane` where the markers shadow will be added.\r\n\t\tshadowPane: 'shadowPane',\r\n\r\n\t\t// @option bubblingMouseEvents: Boolean = false\r\n\t\t// When `true`, a mouse event on this marker will trigger the same event on the map\r\n\t\t// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).\r\n\t\tbubblingMouseEvents: false,\r\n\r\n\t\t// @section Draggable marker options\r\n\t\t// @option draggable: Boolean = false\r\n\t\t// Whether the marker is draggable with mouse/touch or not.\r\n\t\tdraggable: false,\r\n\r\n\t\t// @option autoPan: Boolean = false\r\n\t\t// Whether to pan the map when dragging this marker near its edge or not.\r\n\t\tautoPan: false,\r\n\r\n\t\t// @option autoPanPadding: Point = Point(50, 50)\r\n\t\t// Distance (in pixels to the left/right and to the top/bottom) of the\r\n\t\t// map edge to start panning the map.\r\n\t\tautoPanPadding: [50, 50],\r\n\r\n\t\t// @option autoPanSpeed: Number = 10\r\n\t\t// Number of pixels the map should pan by.\r\n\t\tautoPanSpeed: 10\r\n\t},\r\n\r\n\t/* @section\r\n\t *\r\n\t * In addition to [shared layer methods](#Layer) like `addTo()` and `remove()` and [popup methods](#Popup) like bindPopup() you can also use the following methods:\r\n\t */\r\n\r\n\tinitialize: function (latlng, options) {\r\n\t\tsetOptions(this, options);\r\n\t\tthis._latlng = toLatLng(latlng);\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tthis._zoomAnimated = this._zoomAnimated && map.options.markerZoomAnimation;\r\n\r\n\t\tif (this._zoomAnimated) {\r\n\t\t\tmap.on('zoomanim', this._animateZoom, this);\r\n\t\t}\r\n\r\n\t\tthis._initIcon();\r\n\t\tthis.update();\r\n\t},\r\n\r\n\tonRemove: function (map) {\r\n\t\tif (this.dragging && this.dragging.enabled()) {\r\n\t\t\tthis.options.draggable = true;\r\n\t\t\tthis.dragging.removeHooks();\r\n\t\t}\r\n\t\tdelete this.dragging;\r\n\r\n\t\tif (this._zoomAnimated) {\r\n\t\t\tmap.off('zoomanim', this._animateZoom, this);\r\n\t\t}\r\n\r\n\t\tthis._removeIcon();\r\n\t\tthis._removeShadow();\r\n\t},\r\n\r\n\tgetEvents: function () {\r\n\t\treturn {\r\n\t\t\tzoom: this.update,\r\n\t\t\tviewreset: this.update\r\n\t\t};\r\n\t},\r\n\r\n\t// @method getLatLng: LatLng\r\n\t// Returns the current geographical position of the marker.\r\n\tgetLatLng: function () {\r\n\t\treturn this._latlng;\r\n\t},\r\n\r\n\t// @method setLatLng(latlng: LatLng): this\r\n\t// Changes the marker position to the given point.\r\n\tsetLatLng: function (latlng) {\r\n\t\tvar oldLatLng = this._latlng;\r\n\t\tthis._latlng = toLatLng(latlng);\r\n\t\tthis.update();\r\n\r\n\t\t// @event move: Event\r\n\t\t// Fired when the marker is moved via [`setLatLng`](#marker-setlatlng) or by [dragging](#marker-dragging). Old and new coordinates are included in event arguments as `oldLatLng`, `latlng`.\r\n\t\treturn this.fire('move', {oldLatLng: oldLatLng, latlng: this._latlng});\r\n\t},\r\n\r\n\t// @method setZIndexOffset(offset: Number): this\r\n\t// Changes the [zIndex offset](#marker-zindexoffset) of the marker.\r\n\tsetZIndexOffset: function (offset) {\r\n\t\tthis.options.zIndexOffset = offset;\r\n\t\treturn this.update();\r\n\t},\r\n\r\n\t// @method getIcon: Icon\r\n\t// Returns the current icon used by the marker\r\n\tgetIcon: function () {\r\n\t\treturn this.options.icon;\r\n\t},\r\n\r\n\t// @method setIcon(icon: Icon): this\r\n\t// Changes the marker icon.\r\n\tsetIcon: function (icon) {\r\n\r\n\t\tthis.options.icon = icon;\r\n\r\n\t\tif (this._map) {\r\n\t\t\tthis._initIcon();\r\n\t\t\tthis.update();\r\n\t\t}\r\n\r\n\t\tif (this._popup) {\r\n\t\t\tthis.bindPopup(this._popup, this._popup.options);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\tgetElement: function () {\r\n\t\treturn this._icon;\r\n\t},\r\n\r\n\tupdate: function () {\r\n\r\n\t\tif (this._icon && this._map) {\r\n\t\t\tvar pos = this._map.latLngToLayerPoint(this._latlng).round();\r\n\t\t\tthis._setPos(pos);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_initIcon: function () {\r\n\t\tvar options = this.options,\r\n\t\t classToAdd = 'leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');\r\n\r\n\t\tvar icon = options.icon.createIcon(this._icon),\r\n\t\t addIcon = false;\r\n\r\n\t\t// if we're not reusing the icon, remove the old one and init new one\r\n\t\tif (icon !== this._icon) {\r\n\t\t\tif (this._icon) {\r\n\t\t\t\tthis._removeIcon();\r\n\t\t\t}\r\n\t\t\taddIcon = true;\r\n\r\n\t\t\tif (options.title) {\r\n\t\t\t\ticon.title = options.title;\r\n\t\t\t}\r\n\r\n\t\t\tif (icon.tagName === 'IMG') {\r\n\t\t\t\ticon.alt = options.alt || '';\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\taddClass(icon, classToAdd);\r\n\r\n\t\tif (options.keyboard) {\r\n\t\t\ticon.tabIndex = '0';\r\n\t\t}\r\n\r\n\t\tthis._icon = icon;\r\n\r\n\t\tif (options.riseOnHover) {\r\n\t\t\tthis.on({\r\n\t\t\t\tmouseover: this._bringToFront,\r\n\t\t\t\tmouseout: this._resetZIndex\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tvar newShadow = options.icon.createShadow(this._shadow),\r\n\t\t addShadow = false;\r\n\r\n\t\tif (newShadow !== this._shadow) {\r\n\t\t\tthis._removeShadow();\r\n\t\t\taddShadow = true;\r\n\t\t}\r\n\r\n\t\tif (newShadow) {\r\n\t\t\taddClass(newShadow, classToAdd);\r\n\t\t\tnewShadow.alt = '';\r\n\t\t}\r\n\t\tthis._shadow = newShadow;\r\n\r\n\r\n\t\tif (options.opacity < 1) {\r\n\t\t\tthis._updateOpacity();\r\n\t\t}\r\n\r\n\r\n\t\tif (addIcon) {\r\n\t\t\tthis.getPane().appendChild(this._icon);\r\n\t\t}\r\n\t\tthis._initInteraction();\r\n\t\tif (newShadow && addShadow) {\r\n\t\t\tthis.getPane(options.shadowPane).appendChild(this._shadow);\r\n\t\t}\r\n\t},\r\n\r\n\t_removeIcon: function () {\r\n\t\tif (this.options.riseOnHover) {\r\n\t\t\tthis.off({\r\n\t\t\t\tmouseover: this._bringToFront,\r\n\t\t\t\tmouseout: this._resetZIndex\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tremove(this._icon);\r\n\t\tthis.removeInteractiveTarget(this._icon);\r\n\r\n\t\tthis._icon = null;\r\n\t},\r\n\r\n\t_removeShadow: function () {\r\n\t\tif (this._shadow) {\r\n\t\t\tremove(this._shadow);\r\n\t\t}\r\n\t\tthis._shadow = null;\r\n\t},\r\n\r\n\t_setPos: function (pos) {\r\n\t\tsetPosition(this._icon, pos);\r\n\r\n\t\tif (this._shadow) {\r\n\t\t\tsetPosition(this._shadow, pos);\r\n\t\t}\r\n\r\n\t\tthis._zIndex = pos.y + this.options.zIndexOffset;\r\n\r\n\t\tthis._resetZIndex();\r\n\t},\r\n\r\n\t_updateZIndex: function (offset) {\r\n\t\tthis._icon.style.zIndex = this._zIndex + offset;\r\n\t},\r\n\r\n\t_animateZoom: function (opt) {\r\n\t\tvar pos = this._map._latLngToNewLayerPoint(this._latlng, opt.zoom, opt.center).round();\r\n\r\n\t\tthis._setPos(pos);\r\n\t},\r\n\r\n\t_initInteraction: function () {\r\n\r\n\t\tif (!this.options.interactive) { return; }\r\n\r\n\t\taddClass(this._icon, 'leaflet-interactive');\r\n\r\n\t\tthis.addInteractiveTarget(this._icon);\r\n\r\n\t\tif (MarkerDrag) {\r\n\t\t\tvar draggable = this.options.draggable;\r\n\t\t\tif (this.dragging) {\r\n\t\t\t\tdraggable = this.dragging.enabled();\r\n\t\t\t\tthis.dragging.disable();\r\n\t\t\t}\r\n\r\n\t\t\tthis.dragging = new MarkerDrag(this);\r\n\r\n\t\t\tif (draggable) {\r\n\t\t\t\tthis.dragging.enable();\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t// @method setOpacity(opacity: Number): this\r\n\t// Changes the opacity of the marker.\r\n\tsetOpacity: function (opacity) {\r\n\t\tthis.options.opacity = opacity;\r\n\t\tif (this._map) {\r\n\t\t\tthis._updateOpacity();\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_updateOpacity: function () {\r\n\t\tvar opacity = this.options.opacity;\r\n\r\n\t\tif (this._icon) {\r\n\t\t\tsetOpacity(this._icon, opacity);\r\n\t\t}\r\n\r\n\t\tif (this._shadow) {\r\n\t\t\tsetOpacity(this._shadow, opacity);\r\n\t\t}\r\n\t},\r\n\r\n\t_bringToFront: function () {\r\n\t\tthis._updateZIndex(this.options.riseOffset);\r\n\t},\r\n\r\n\t_resetZIndex: function () {\r\n\t\tthis._updateZIndex(0);\r\n\t},\r\n\r\n\t_getPopupAnchor: function () {\r\n\t\treturn this.options.icon.options.popupAnchor;\r\n\t},\r\n\r\n\t_getTooltipAnchor: function () {\r\n\t\treturn this.options.icon.options.tooltipAnchor;\r\n\t}\r\n});\r\n\r\n\r\n// factory L.marker(latlng: LatLng, options? : Marker options)\r\n\r\n// @factory L.marker(latlng: LatLng, options? : Marker options)\r\n// Instantiates a Marker object given a geographical point and optionally an options object.\r\nfunction marker(latlng, options) {\r\n\treturn new Marker(latlng, options);\r\n}\n\n/*\n * @class Path\n * @aka L.Path\n * @inherits Interactive layer\n *\n * An abstract class that contains options and constants shared between vector\n * overlays (Polygon, Polyline, Circle). Do not use it directly. Extends `Layer`.\n */\n\nvar Path = Layer.extend({\n\n\t// @section\n\t// @aka Path options\n\toptions: {\n\t\t// @option stroke: Boolean = true\n\t\t// Whether to draw stroke along the path. Set it to `false` to disable borders on polygons or circles.\n\t\tstroke: true,\n\n\t\t// @option color: String = '#3388ff'\n\t\t// Stroke color\n\t\tcolor: '#3388ff',\n\n\t\t// @option weight: Number = 3\n\t\t// Stroke width in pixels\n\t\tweight: 3,\n\n\t\t// @option opacity: Number = 1.0\n\t\t// Stroke opacity\n\t\topacity: 1,\n\n\t\t// @option lineCap: String= 'round'\n\t\t// A string that defines [shape to be used at the end](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linecap) of the stroke.\n\t\tlineCap: 'round',\n\n\t\t// @option lineJoin: String = 'round'\n\t\t// A string that defines [shape to be used at the corners](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-linejoin) of the stroke.\n\t\tlineJoin: 'round',\n\n\t\t// @option dashArray: String = null\n\t\t// A string that defines the stroke [dash pattern](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dasharray). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).\n\t\tdashArray: null,\n\n\t\t// @option dashOffset: String = null\n\t\t// A string that defines the [distance into the dash pattern to start the dash](https://developer.mozilla.org/docs/Web/SVG/Attribute/stroke-dashoffset). Doesn't work on `Canvas`-powered layers in [some old browsers](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/setLineDash#Browser_compatibility).\n\t\tdashOffset: null,\n\n\t\t// @option fill: Boolean = depends\n\t\t// Whether to fill the path with color. Set it to `false` to disable filling on polygons or circles.\n\t\tfill: false,\n\n\t\t// @option fillColor: String = *\n\t\t// Fill color. Defaults to the value of the [`color`](#path-color) option\n\t\tfillColor: null,\n\n\t\t// @option fillOpacity: Number = 0.2\n\t\t// Fill opacity.\n\t\tfillOpacity: 0.2,\n\n\t\t// @option fillRule: String = 'evenodd'\n\t\t// A string that defines [how the inside of a shape](https://developer.mozilla.org/docs/Web/SVG/Attribute/fill-rule) is determined.\n\t\tfillRule: 'evenodd',\n\n\t\t// className: '',\n\n\t\t// Option inherited from \"Interactive layer\" abstract class\n\t\tinteractive: true,\n\n\t\t// @option bubblingMouseEvents: Boolean = true\n\t\t// When `true`, a mouse event on this path will trigger the same event on the map\n\t\t// (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used).\n\t\tbubblingMouseEvents: true\n\t},\n\n\tbeforeAdd: function (map) {\n\t\t// Renderer is set here because we need to call renderer.getEvents\n\t\t// before this.getEvents.\n\t\tthis._renderer = map.getRenderer(this);\n\t},\n\n\tonAdd: function () {\n\t\tthis._renderer._initPath(this);\n\t\tthis._reset();\n\t\tthis._renderer._addPath(this);\n\t},\n\n\tonRemove: function () {\n\t\tthis._renderer._removePath(this);\n\t},\n\n\t// @method redraw(): this\n\t// Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.\n\tredraw: function () {\n\t\tif (this._map) {\n\t\t\tthis._renderer._updatePath(this);\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method setStyle(style: Path options): this\n\t// Changes the appearance of a Path based on the options in the `Path options` object.\n\tsetStyle: function (style) {\n\t\tsetOptions(this, style);\n\t\tif (this._renderer) {\n\t\t\tthis._renderer._updateStyle(this);\n\t\t\tif (this.options.stroke && style.hasOwnProperty('weight')) {\n\t\t\t\tthis._updateBounds();\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method bringToFront(): this\n\t// Brings the layer to the top of all path layers.\n\tbringToFront: function () {\n\t\tif (this._renderer) {\n\t\t\tthis._renderer._bringToFront(this);\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method bringToBack(): this\n\t// Brings the layer to the bottom of all path layers.\n\tbringToBack: function () {\n\t\tif (this._renderer) {\n\t\t\tthis._renderer._bringToBack(this);\n\t\t}\n\t\treturn this;\n\t},\n\n\tgetElement: function () {\n\t\treturn this._path;\n\t},\n\n\t_reset: function () {\n\t\t// defined in child classes\n\t\tthis._project();\n\t\tthis._update();\n\t},\n\n\t_clickTolerance: function () {\n\t\t// used when doing hit detection for Canvas layers\n\t\treturn (this.options.stroke ? this.options.weight / 2 : 0) + this._renderer.options.tolerance;\n\t}\n});\n\n/*\n * @class CircleMarker\n * @aka L.CircleMarker\n * @inherits Path\n *\n * A circle of a fixed size with radius specified in pixels. Extends `Path`.\n */\n\nvar CircleMarker = Path.extend({\n\n\t// @section\n\t// @aka CircleMarker options\n\toptions: {\n\t\tfill: true,\n\n\t\t// @option radius: Number = 10\n\t\t// Radius of the circle marker, in pixels\n\t\tradius: 10\n\t},\n\n\tinitialize: function (latlng, options) {\n\t\tsetOptions(this, options);\n\t\tthis._latlng = toLatLng(latlng);\n\t\tthis._radius = this.options.radius;\n\t},\n\n\t// @method setLatLng(latLng: LatLng): this\n\t// Sets the position of a circle marker to a new location.\n\tsetLatLng: function (latlng) {\n\t\tthis._latlng = toLatLng(latlng);\n\t\tthis.redraw();\n\t\treturn this.fire('move', {latlng: this._latlng});\n\t},\n\n\t// @method getLatLng(): LatLng\n\t// Returns the current geographical position of the circle marker\n\tgetLatLng: function () {\n\t\treturn this._latlng;\n\t},\n\n\t// @method setRadius(radius: Number): this\n\t// Sets the radius of a circle marker. Units are in pixels.\n\tsetRadius: function (radius) {\n\t\tthis.options.radius = this._radius = radius;\n\t\treturn this.redraw();\n\t},\n\n\t// @method getRadius(): Number\n\t// Returns the current radius of the circle\n\tgetRadius: function () {\n\t\treturn this._radius;\n\t},\n\n\tsetStyle : function (options) {\n\t\tvar radius = options && options.radius || this._radius;\n\t\tPath.prototype.setStyle.call(this, options);\n\t\tthis.setRadius(radius);\n\t\treturn this;\n\t},\n\n\t_project: function () {\n\t\tthis._point = this._map.latLngToLayerPoint(this._latlng);\n\t\tthis._updateBounds();\n\t},\n\n\t_updateBounds: function () {\n\t\tvar r = this._radius,\n\t\t r2 = this._radiusY || r,\n\t\t w = this._clickTolerance(),\n\t\t p = [r + w, r2 + w];\n\t\tthis._pxBounds = new Bounds(this._point.subtract(p), this._point.add(p));\n\t},\n\n\t_update: function () {\n\t\tif (this._map) {\n\t\t\tthis._updatePath();\n\t\t}\n\t},\n\n\t_updatePath: function () {\n\t\tthis._renderer._updateCircle(this);\n\t},\n\n\t_empty: function () {\n\t\treturn this._radius && !this._renderer._bounds.intersects(this._pxBounds);\n\t},\n\n\t// Needed by the `Canvas` renderer for interactivity\n\t_containsPoint: function (p) {\n\t\treturn p.distanceTo(this._point) <= this._radius + this._clickTolerance();\n\t}\n});\n\n\n// @factory L.circleMarker(latlng: LatLng, options?: CircleMarker options)\n// Instantiates a circle marker object given a geographical point, and an optional options object.\nfunction circleMarker(latlng, options) {\n\treturn new CircleMarker(latlng, options);\n}\n\n/*\n * @class Circle\n * @aka L.Circle\n * @inherits CircleMarker\n *\n * A class for drawing circle overlays on a map. Extends `CircleMarker`.\n *\n * It's an approximation and starts to diverge from a real circle closer to poles (due to projection distortion).\n *\n * @example\n *\n * ```js\n * L.circle([50.5, 30.5], {radius: 200}).addTo(map);\n * ```\n */\n\nvar Circle = CircleMarker.extend({\n\n\tinitialize: function (latlng, options, legacyOptions) {\n\t\tif (typeof options === 'number') {\n\t\t\t// Backwards compatibility with 0.7.x factory (latlng, radius, options?)\n\t\t\toptions = extend({}, legacyOptions, {radius: options});\n\t\t}\n\t\tsetOptions(this, options);\n\t\tthis._latlng = toLatLng(latlng);\n\n\t\tif (isNaN(this.options.radius)) { throw new Error('Circle radius cannot be NaN'); }\n\n\t\t// @section\n\t\t// @aka Circle options\n\t\t// @option radius: Number; Radius of the circle, in meters.\n\t\tthis._mRadius = this.options.radius;\n\t},\n\n\t// @method setRadius(radius: Number): this\n\t// Sets the radius of a circle. Units are in meters.\n\tsetRadius: function (radius) {\n\t\tthis._mRadius = radius;\n\t\treturn this.redraw();\n\t},\n\n\t// @method getRadius(): Number\n\t// Returns the current radius of a circle. Units are in meters.\n\tgetRadius: function () {\n\t\treturn this._mRadius;\n\t},\n\n\t// @method getBounds(): LatLngBounds\n\t// Returns the `LatLngBounds` of the path.\n\tgetBounds: function () {\n\t\tvar half = [this._radius, this._radiusY || this._radius];\n\n\t\treturn new LatLngBounds(\n\t\t\tthis._map.layerPointToLatLng(this._point.subtract(half)),\n\t\t\tthis._map.layerPointToLatLng(this._point.add(half)));\n\t},\n\n\tsetStyle: Path.prototype.setStyle,\n\n\t_project: function () {\n\n\t\tvar lng = this._latlng.lng,\n\t\t lat = this._latlng.lat,\n\t\t map = this._map,\n\t\t crs = map.options.crs;\n\n\t\tif (crs.distance === Earth.distance) {\n\t\t\tvar d = Math.PI / 180,\n\t\t\t latR = (this._mRadius / Earth.R) / d,\n\t\t\t top = map.project([lat + latR, lng]),\n\t\t\t bottom = map.project([lat - latR, lng]),\n\t\t\t p = top.add(bottom).divideBy(2),\n\t\t\t lat2 = map.unproject(p).lat,\n\t\t\t lngR = Math.acos((Math.cos(latR * d) - Math.sin(lat * d) * Math.sin(lat2 * d)) /\n\t\t\t (Math.cos(lat * d) * Math.cos(lat2 * d))) / d;\n\n\t\t\tif (isNaN(lngR) || lngR === 0) {\n\t\t\t\tlngR = latR / Math.cos(Math.PI / 180 * lat); // Fallback for edge case, #2425\n\t\t\t}\n\n\t\t\tthis._point = p.subtract(map.getPixelOrigin());\n\t\t\tthis._radius = isNaN(lngR) ? 0 : p.x - map.project([lat2, lng - lngR]).x;\n\t\t\tthis._radiusY = p.y - top.y;\n\n\t\t} else {\n\t\t\tvar latlng2 = crs.unproject(crs.project(this._latlng).subtract([this._mRadius, 0]));\n\n\t\t\tthis._point = map.latLngToLayerPoint(this._latlng);\n\t\t\tthis._radius = this._point.x - map.latLngToLayerPoint(latlng2).x;\n\t\t}\n\n\t\tthis._updateBounds();\n\t}\n});\n\n// @factory L.circle(latlng: LatLng, options?: Circle options)\n// Instantiates a circle object given a geographical point, and an options object\n// which contains the circle radius.\n// @alternative\n// @factory L.circle(latlng: LatLng, radius: Number, options?: Circle options)\n// Obsolete way of instantiating a circle, for compatibility with 0.7.x code.\n// Do not use in new applications or plugins.\nfunction circle(latlng, options, legacyOptions) {\n\treturn new Circle(latlng, options, legacyOptions);\n}\n\n/*\n * @class Polyline\n * @aka L.Polyline\n * @inherits Path\n *\n * A class for drawing polyline overlays on a map. Extends `Path`.\n *\n * @example\n *\n * ```js\n * // create a red polyline from an array of LatLng points\n * var latlngs = [\n * \t[45.51, -122.68],\n * \t[37.77, -122.43],\n * \t[34.04, -118.2]\n * ];\n *\n * var polyline = L.polyline(latlngs, {color: 'red'}).addTo(map);\n *\n * // zoom the map to the polyline\n * map.fitBounds(polyline.getBounds());\n * ```\n *\n * You can also pass a multi-dimensional array to represent a `MultiPolyline` shape:\n *\n * ```js\n * // create a red polyline from an array of arrays of LatLng points\n * var latlngs = [\n * \t[[45.51, -122.68],\n * \t [37.77, -122.43],\n * \t [34.04, -118.2]],\n * \t[[40.78, -73.91],\n * \t [41.83, -87.62],\n * \t [32.76, -96.72]]\n * ];\n * ```\n */\n\n\nvar Polyline = Path.extend({\n\n\t// @section\n\t// @aka Polyline options\n\toptions: {\n\t\t// @option smoothFactor: Number = 1.0\n\t\t// How much to simplify the polyline on each zoom level. More means\n\t\t// better performance and smoother look, and less means more accurate representation.\n\t\tsmoothFactor: 1.0,\n\n\t\t// @option noClip: Boolean = false\n\t\t// Disable polyline clipping.\n\t\tnoClip: false\n\t},\n\n\tinitialize: function (latlngs, options) {\n\t\tsetOptions(this, options);\n\t\tthis._setLatLngs(latlngs);\n\t},\n\n\t// @method getLatLngs(): LatLng[]\n\t// Returns an array of the points in the path, or nested arrays of points in case of multi-polyline.\n\tgetLatLngs: function () {\n\t\treturn this._latlngs;\n\t},\n\n\t// @method setLatLngs(latlngs: LatLng[]): this\n\t// Replaces all the points in the polyline with the given array of geographical points.\n\tsetLatLngs: function (latlngs) {\n\t\tthis._setLatLngs(latlngs);\n\t\treturn this.redraw();\n\t},\n\n\t// @method isEmpty(): Boolean\n\t// Returns `true` if the Polyline has no LatLngs.\n\tisEmpty: function () {\n\t\treturn !this._latlngs.length;\n\t},\n\n\t// @method closestLayerPoint(p: Point): Point\n\t// Returns the point closest to `p` on the Polyline.\n\tclosestLayerPoint: function (p) {\n\t\tvar minDistance = Infinity,\n\t\t minPoint = null,\n\t\t closest = _sqClosestPointOnSegment,\n\t\t p1, p2;\n\n\t\tfor (var j = 0, jLen = this._parts.length; j < jLen; j++) {\n\t\t\tvar points = this._parts[j];\n\n\t\t\tfor (var i = 1, len = points.length; i < len; i++) {\n\t\t\t\tp1 = points[i - 1];\n\t\t\t\tp2 = points[i];\n\n\t\t\t\tvar sqDist = closest(p, p1, p2, true);\n\n\t\t\t\tif (sqDist < minDistance) {\n\t\t\t\t\tminDistance = sqDist;\n\t\t\t\t\tminPoint = closest(p, p1, p2);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (minPoint) {\n\t\t\tminPoint.distance = Math.sqrt(minDistance);\n\t\t}\n\t\treturn minPoint;\n\t},\n\n\t// @method getCenter(): LatLng\n\t// Returns the center ([centroid](http://en.wikipedia.org/wiki/Centroid)) of the polyline.\n\tgetCenter: function () {\n\t\t// throws error when not yet added to map as this center calculation requires projected coordinates\n\t\tif (!this._map) {\n\t\t\tthrow new Error('Must add layer to map before using getCenter()');\n\t\t}\n\n\t\tvar i, halfDist, segDist, dist, p1, p2, ratio,\n\t\t points = this._rings[0],\n\t\t len = points.length;\n\n\t\tif (!len) { return null; }\n\n\t\t// polyline centroid algorithm; only uses the first ring if there are multiple\n\n\t\tfor (i = 0, halfDist = 0; i < len - 1; i++) {\n\t\t\thalfDist += points[i].distanceTo(points[i + 1]) / 2;\n\t\t}\n\n\t\t// The line is so small in the current view that all points are on the same pixel.\n\t\tif (halfDist === 0) {\n\t\t\treturn this._map.layerPointToLatLng(points[0]);\n\t\t}\n\n\t\tfor (i = 0, dist = 0; i < len - 1; i++) {\n\t\t\tp1 = points[i];\n\t\t\tp2 = points[i + 1];\n\t\t\tsegDist = p1.distanceTo(p2);\n\t\t\tdist += segDist;\n\n\t\t\tif (dist > halfDist) {\n\t\t\t\tratio = (dist - halfDist) / segDist;\n\t\t\t\treturn this._map.layerPointToLatLng([\n\t\t\t\t\tp2.x - ratio * (p2.x - p1.x),\n\t\t\t\t\tp2.y - ratio * (p2.y - p1.y)\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\t},\n\n\t// @method getBounds(): LatLngBounds\n\t// Returns the `LatLngBounds` of the path.\n\tgetBounds: function () {\n\t\treturn this._bounds;\n\t},\n\n\t// @method addLatLng(latlng: LatLng, latlngs? LatLng[]): this\n\t// Adds a given point to the polyline. By default, adds to the first ring of\n\t// the polyline in case of a multi-polyline, but can be overridden by passing\n\t// a specific ring as a LatLng array (that you can earlier access with [`getLatLngs`](#polyline-getlatlngs)).\n\taddLatLng: function (latlng, latlngs) {\n\t\tlatlngs = latlngs || this._defaultShape();\n\t\tlatlng = toLatLng(latlng);\n\t\tlatlngs.push(latlng);\n\t\tthis._bounds.extend(latlng);\n\t\treturn this.redraw();\n\t},\n\n\t_setLatLngs: function (latlngs) {\n\t\tthis._bounds = new LatLngBounds();\n\t\tthis._latlngs = this._convertLatLngs(latlngs);\n\t},\n\n\t_defaultShape: function () {\n\t\treturn isFlat(this._latlngs) ? this._latlngs : this._latlngs[0];\n\t},\n\n\t// recursively convert latlngs input into actual LatLng instances; calculate bounds along the way\n\t_convertLatLngs: function (latlngs) {\n\t\tvar result = [],\n\t\t flat = isFlat(latlngs);\n\n\t\tfor (var i = 0, len = latlngs.length; i < len; i++) {\n\t\t\tif (flat) {\n\t\t\t\tresult[i] = toLatLng(latlngs[i]);\n\t\t\t\tthis._bounds.extend(result[i]);\n\t\t\t} else {\n\t\t\t\tresult[i] = this._convertLatLngs(latlngs[i]);\n\t\t\t}\n\t\t}\n\n\t\treturn result;\n\t},\n\n\t_project: function () {\n\t\tvar pxBounds = new Bounds();\n\t\tthis._rings = [];\n\t\tthis._projectLatlngs(this._latlngs, this._rings, pxBounds);\n\n\t\tif (this._bounds.isValid() && pxBounds.isValid()) {\n\t\t\tthis._rawPxBounds = pxBounds;\n\t\t\tthis._updateBounds();\n\t\t}\n\t},\n\n\t_updateBounds: function () {\n\t\tvar w = this._clickTolerance(),\n\t\t p = new Point(w, w);\n\t\tthis._pxBounds = new Bounds([\n\t\t\tthis._rawPxBounds.min.subtract(p),\n\t\t\tthis._rawPxBounds.max.add(p)\n\t\t]);\n\t},\n\n\t// recursively turns latlngs into a set of rings with projected coordinates\n\t_projectLatlngs: function (latlngs, result, projectedBounds) {\n\t\tvar flat = latlngs[0] instanceof LatLng,\n\t\t len = latlngs.length,\n\t\t i, ring;\n\n\t\tif (flat) {\n\t\t\tring = [];\n\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\tring[i] = this._map.latLngToLayerPoint(latlngs[i]);\n\t\t\t\tprojectedBounds.extend(ring[i]);\n\t\t\t}\n\t\t\tresult.push(ring);\n\t\t} else {\n\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\tthis._projectLatlngs(latlngs[i], result, projectedBounds);\n\t\t\t}\n\t\t}\n\t},\n\n\t// clip polyline by renderer bounds so that we have less to render for performance\n\t_clipPoints: function () {\n\t\tvar bounds = this._renderer._bounds;\n\n\t\tthis._parts = [];\n\t\tif (!this._pxBounds || !this._pxBounds.intersects(bounds)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.options.noClip) {\n\t\t\tthis._parts = this._rings;\n\t\t\treturn;\n\t\t}\n\n\t\tvar parts = this._parts,\n\t\t i, j, k, len, len2, segment, points;\n\n\t\tfor (i = 0, k = 0, len = this._rings.length; i < len; i++) {\n\t\t\tpoints = this._rings[i];\n\n\t\t\tfor (j = 0, len2 = points.length; j < len2 - 1; j++) {\n\t\t\t\tsegment = clipSegment(points[j], points[j + 1], bounds, j, true);\n\n\t\t\t\tif (!segment) { continue; }\n\n\t\t\t\tparts[k] = parts[k] || [];\n\t\t\t\tparts[k].push(segment[0]);\n\n\t\t\t\t// if segment goes out of screen, or it's the last one, it's the end of the line part\n\t\t\t\tif ((segment[1] !== points[j + 1]) || (j === len2 - 2)) {\n\t\t\t\t\tparts[k].push(segment[1]);\n\t\t\t\t\tk++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// simplify each clipped part of the polyline for performance\n\t_simplifyPoints: function () {\n\t\tvar parts = this._parts,\n\t\t tolerance = this.options.smoothFactor;\n\n\t\tfor (var i = 0, len = parts.length; i < len; i++) {\n\t\t\tparts[i] = simplify(parts[i], tolerance);\n\t\t}\n\t},\n\n\t_update: function () {\n\t\tif (!this._map) { return; }\n\n\t\tthis._clipPoints();\n\t\tthis._simplifyPoints();\n\t\tthis._updatePath();\n\t},\n\n\t_updatePath: function () {\n\t\tthis._renderer._updatePoly(this);\n\t},\n\n\t// Needed by the `Canvas` renderer for interactivity\n\t_containsPoint: function (p, closed) {\n\t\tvar i, j, k, len, len2, part,\n\t\t w = this._clickTolerance();\n\n\t\tif (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }\n\n\t\t// hit detection for polylines\n\t\tfor (i = 0, len = this._parts.length; i < len; i++) {\n\t\t\tpart = this._parts[i];\n\n\t\t\tfor (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {\n\t\t\t\tif (!closed && (j === 0)) { continue; }\n\n\t\t\t\tif (pointToSegmentDistance(p, part[k], part[j]) <= w) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n});\n\n// @factory L.polyline(latlngs: LatLng[], options?: Polyline options)\n// Instantiates a polyline object given an array of geographical points and\n// optionally an options object. You can create a `Polyline` object with\n// multiple separate lines (`MultiPolyline`) by passing an array of arrays\n// of geographic points.\nfunction polyline(latlngs, options) {\n\treturn new Polyline(latlngs, options);\n}\n\n// Retrocompat. Allow plugins to support Leaflet versions before and after 1.1.\nPolyline._flat = _flat;\n\n/*\n * @class Polygon\n * @aka L.Polygon\n * @inherits Polyline\n *\n * A class for drawing polygon overlays on a map. Extends `Polyline`.\n *\n * Note that points you pass when creating a polygon shouldn't have an additional last point equal to the first one — it's better to filter out such points.\n *\n *\n * @example\n *\n * ```js\n * // create a red polygon from an array of LatLng points\n * var latlngs = [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];\n *\n * var polygon = L.polygon(latlngs, {color: 'red'}).addTo(map);\n *\n * // zoom the map to the polygon\n * map.fitBounds(polygon.getBounds());\n * ```\n *\n * You can also pass an array of arrays of latlngs, with the first array representing the outer shape and the other arrays representing holes in the outer shape:\n *\n * ```js\n * var latlngs = [\n * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring\n * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole\n * ];\n * ```\n *\n * Additionally, you can pass a multi-dimensional array to represent a MultiPolygon shape.\n *\n * ```js\n * var latlngs = [\n * [ // first polygon\n * [[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]], // outer ring\n * [[37.29, -108.58],[40.71, -108.58],[40.71, -102.50],[37.29, -102.50]] // hole\n * ],\n * [ // second polygon\n * [[41, -111.03],[45, -111.04],[45, -104.05],[41, -104.05]]\n * ]\n * ];\n * ```\n */\n\nvar Polygon = Polyline.extend({\n\n\toptions: {\n\t\tfill: true\n\t},\n\n\tisEmpty: function () {\n\t\treturn !this._latlngs.length || !this._latlngs[0].length;\n\t},\n\n\tgetCenter: function () {\n\t\t// throws error when not yet added to map as this center calculation requires projected coordinates\n\t\tif (!this._map) {\n\t\t\tthrow new Error('Must add layer to map before using getCenter()');\n\t\t}\n\n\t\tvar i, j, p1, p2, f, area, x, y, center,\n\t\t points = this._rings[0],\n\t\t len = points.length;\n\n\t\tif (!len) { return null; }\n\n\t\t// polygon centroid algorithm; only uses the first ring if there are multiple\n\n\t\tarea = x = y = 0;\n\n\t\tfor (i = 0, j = len - 1; i < len; j = i++) {\n\t\t\tp1 = points[i];\n\t\t\tp2 = points[j];\n\n\t\t\tf = p1.y * p2.x - p2.y * p1.x;\n\t\t\tx += (p1.x + p2.x) * f;\n\t\t\ty += (p1.y + p2.y) * f;\n\t\t\tarea += f * 3;\n\t\t}\n\n\t\tif (area === 0) {\n\t\t\t// Polygon is so small that all points are on same pixel.\n\t\t\tcenter = points[0];\n\t\t} else {\n\t\t\tcenter = [x / area, y / area];\n\t\t}\n\t\treturn this._map.layerPointToLatLng(center);\n\t},\n\n\t_convertLatLngs: function (latlngs) {\n\t\tvar result = Polyline.prototype._convertLatLngs.call(this, latlngs),\n\t\t len = result.length;\n\n\t\t// remove last point if it equals first one\n\t\tif (len >= 2 && result[0] instanceof LatLng && result[0].equals(result[len - 1])) {\n\t\t\tresult.pop();\n\t\t}\n\t\treturn result;\n\t},\n\n\t_setLatLngs: function (latlngs) {\n\t\tPolyline.prototype._setLatLngs.call(this, latlngs);\n\t\tif (isFlat(this._latlngs)) {\n\t\t\tthis._latlngs = [this._latlngs];\n\t\t}\n\t},\n\n\t_defaultShape: function () {\n\t\treturn isFlat(this._latlngs[0]) ? this._latlngs[0] : this._latlngs[0][0];\n\t},\n\n\t_clipPoints: function () {\n\t\t// polygons need a different clipping algorithm so we redefine that\n\n\t\tvar bounds = this._renderer._bounds,\n\t\t w = this.options.weight,\n\t\t p = new Point(w, w);\n\n\t\t// increase clip padding by stroke width to avoid stroke on clip edges\n\t\tbounds = new Bounds(bounds.min.subtract(p), bounds.max.add(p));\n\n\t\tthis._parts = [];\n\t\tif (!this._pxBounds || !this._pxBounds.intersects(bounds)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.options.noClip) {\n\t\t\tthis._parts = this._rings;\n\t\t\treturn;\n\t\t}\n\n\t\tfor (var i = 0, len = this._rings.length, clipped; i < len; i++) {\n\t\t\tclipped = clipPolygon(this._rings[i], bounds, true);\n\t\t\tif (clipped.length) {\n\t\t\t\tthis._parts.push(clipped);\n\t\t\t}\n\t\t}\n\t},\n\n\t_updatePath: function () {\n\t\tthis._renderer._updatePoly(this, true);\n\t},\n\n\t// Needed by the `Canvas` renderer for interactivity\n\t_containsPoint: function (p) {\n\t\tvar inside = false,\n\t\t part, p1, p2, i, j, k, len, len2;\n\n\t\tif (!this._pxBounds || !this._pxBounds.contains(p)) { return false; }\n\n\t\t// ray casting algorithm for detecting if point is in polygon\n\t\tfor (i = 0, len = this._parts.length; i < len; i++) {\n\t\t\tpart = this._parts[i];\n\n\t\t\tfor (j = 0, len2 = part.length, k = len2 - 1; j < len2; k = j++) {\n\t\t\t\tp1 = part[j];\n\t\t\t\tp2 = part[k];\n\n\t\t\t\tif (((p1.y > p.y) !== (p2.y > p.y)) && (p.x < (p2.x - p1.x) * (p.y - p1.y) / (p2.y - p1.y) + p1.x)) {\n\t\t\t\t\tinside = !inside;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// also check if it's on polygon stroke\n\t\treturn inside || Polyline.prototype._containsPoint.call(this, p, true);\n\t}\n\n});\n\n\n// @factory L.polygon(latlngs: LatLng[], options?: Polyline options)\nfunction polygon(latlngs, options) {\n\treturn new Polygon(latlngs, options);\n}\n\n/*\r\n * @class GeoJSON\r\n * @aka L.GeoJSON\r\n * @inherits FeatureGroup\r\n *\r\n * Represents a GeoJSON object or an array of GeoJSON objects. Allows you to parse\r\n * GeoJSON data and display it on the map. Extends `FeatureGroup`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * L.geoJSON(data, {\r\n * \tstyle: function (feature) {\r\n * \t\treturn {color: feature.properties.color};\r\n * \t}\r\n * }).bindPopup(function (layer) {\r\n * \treturn layer.feature.properties.description;\r\n * }).addTo(map);\r\n * ```\r\n */\r\n\r\nvar GeoJSON = FeatureGroup.extend({\r\n\r\n\t/* @section\r\n\t * @aka GeoJSON options\r\n\t *\r\n\t * @option pointToLayer: Function = *\r\n\t * A `Function` defining how GeoJSON points spawn Leaflet layers. It is internally\r\n\t * called when data is added, passing the GeoJSON point feature and its `LatLng`.\r\n\t * The default is to spawn a default `Marker`:\r\n\t * ```js\r\n\t * function(geoJsonPoint, latlng) {\r\n\t * \treturn L.marker(latlng);\r\n\t * }\r\n\t * ```\r\n\t *\r\n\t * @option style: Function = *\r\n\t * A `Function` defining the `Path options` for styling GeoJSON lines and polygons,\r\n\t * called internally when data is added.\r\n\t * The default value is to not override any defaults:\r\n\t * ```js\r\n\t * function (geoJsonFeature) {\r\n\t * \treturn {}\r\n\t * }\r\n\t * ```\r\n\t *\r\n\t * @option onEachFeature: Function = *\r\n\t * A `Function` that will be called once for each created `Feature`, after it has\r\n\t * been created and styled. Useful for attaching events and popups to features.\r\n\t * The default is to do nothing with the newly created layers:\r\n\t * ```js\r\n\t * function (feature, layer) {}\r\n\t * ```\r\n\t *\r\n\t * @option filter: Function = *\r\n\t * A `Function` that will be used to decide whether to include a feature or not.\r\n\t * The default is to include all features:\r\n\t * ```js\r\n\t * function (geoJsonFeature) {\r\n\t * \treturn true;\r\n\t * }\r\n\t * ```\r\n\t * Note: dynamically changing the `filter` option will have effect only on newly\r\n\t * added data. It will _not_ re-evaluate already included features.\r\n\t *\r\n\t * @option coordsToLatLng: Function = *\r\n\t * A `Function` that will be used for converting GeoJSON coordinates to `LatLng`s.\r\n\t * The default is the `coordsToLatLng` static method.\r\n\t */\r\n\r\n\tinitialize: function (geojson, options) {\r\n\t\tsetOptions(this, options);\r\n\r\n\t\tthis._layers = {};\r\n\r\n\t\tif (geojson) {\r\n\t\t\tthis.addData(geojson);\r\n\t\t}\r\n\t},\r\n\r\n\t// @method addData( <GeoJSON> data ): this\r\n\t// Adds a GeoJSON object to the layer.\r\n\taddData: function (geojson) {\r\n\t\tvar features = isArray(geojson) ? geojson : geojson.features,\r\n\t\t i, len, feature;\r\n\r\n\t\tif (features) {\r\n\t\t\tfor (i = 0, len = features.length; i < len; i++) {\r\n\t\t\t\t// only add this if geometry or geometries are set and not null\r\n\t\t\t\tfeature = features[i];\r\n\t\t\t\tif (feature.geometries || feature.geometry || feature.features || feature.coordinates) {\r\n\t\t\t\t\tthis.addData(feature);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tvar options = this.options;\r\n\r\n\t\tif (options.filter && !options.filter(geojson)) { return this; }\r\n\r\n\t\tvar layer = geometryToLayer(geojson, options);\r\n\t\tif (!layer) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\t\tlayer.feature = asFeature(geojson);\r\n\r\n\t\tlayer.defaultOptions = layer.options;\r\n\t\tthis.resetStyle(layer);\r\n\r\n\t\tif (options.onEachFeature) {\r\n\t\t\toptions.onEachFeature(geojson, layer);\r\n\t\t}\r\n\r\n\t\treturn this.addLayer(layer);\r\n\t},\r\n\r\n\t// @method resetStyle( <Path> layer ): this\r\n\t// Resets the given vector layer's style to the original GeoJSON style, useful for resetting style after hover events.\r\n\tresetStyle: function (layer) {\r\n\t\t// reset any custom styles\r\n\t\tlayer.options = extend({}, layer.defaultOptions);\r\n\t\tthis._setLayerStyle(layer, this.options.style);\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method setStyle( <Function> style ): this\r\n\t// Changes styles of GeoJSON vector layers with the given style function.\r\n\tsetStyle: function (style) {\r\n\t\treturn this.eachLayer(function (layer) {\r\n\t\t\tthis._setLayerStyle(layer, style);\r\n\t\t}, this);\r\n\t},\r\n\r\n\t_setLayerStyle: function (layer, style) {\r\n\t\tif (layer.setStyle) {\r\n\t\t\tif (typeof style === 'function') {\r\n\t\t\t\tstyle = style(layer.feature);\r\n\t\t\t}\r\n\t\t\tlayer.setStyle(style);\r\n\t\t}\r\n\t}\r\n});\r\n\r\n// @section\r\n// There are several static functions which can be called without instantiating L.GeoJSON:\r\n\r\n// @function geometryToLayer(featureData: Object, options?: GeoJSON options): Layer\r\n// Creates a `Layer` from a given GeoJSON feature. Can use a custom\r\n// [`pointToLayer`](#geojson-pointtolayer) and/or [`coordsToLatLng`](#geojson-coordstolatlng)\r\n// functions if provided as options.\r\nfunction geometryToLayer(geojson, options) {\r\n\r\n\tvar geometry = geojson.type === 'Feature' ? geojson.geometry : geojson,\r\n\t coords = geometry ? geometry.coordinates : null,\r\n\t layers = [],\r\n\t pointToLayer = options && options.pointToLayer,\r\n\t _coordsToLatLng = options && options.coordsToLatLng || coordsToLatLng,\r\n\t latlng, latlngs, i, len;\r\n\r\n\tif (!coords && !geometry) {\r\n\t\treturn null;\r\n\t}\r\n\r\n\tswitch (geometry.type) {\r\n\tcase 'Point':\r\n\t\tlatlng = _coordsToLatLng(coords);\r\n\t\treturn pointToLayer ? pointToLayer(geojson, latlng) : new Marker(latlng);\r\n\r\n\tcase 'MultiPoint':\r\n\t\tfor (i = 0, len = coords.length; i < len; i++) {\r\n\t\t\tlatlng = _coordsToLatLng(coords[i]);\r\n\t\t\tlayers.push(pointToLayer ? pointToLayer(geojson, latlng) : new Marker(latlng));\r\n\t\t}\r\n\t\treturn new FeatureGroup(layers);\r\n\r\n\tcase 'LineString':\r\n\tcase 'MultiLineString':\r\n\t\tlatlngs = coordsToLatLngs(coords, geometry.type === 'LineString' ? 0 : 1, _coordsToLatLng);\r\n\t\treturn new Polyline(latlngs, options);\r\n\r\n\tcase 'Polygon':\r\n\tcase 'MultiPolygon':\r\n\t\tlatlngs = coordsToLatLngs(coords, geometry.type === 'Polygon' ? 1 : 2, _coordsToLatLng);\r\n\t\treturn new Polygon(latlngs, options);\r\n\r\n\tcase 'GeometryCollection':\r\n\t\tfor (i = 0, len = geometry.geometries.length; i < len; i++) {\r\n\t\t\tvar layer = geometryToLayer({\r\n\t\t\t\tgeometry: geometry.geometries[i],\r\n\t\t\t\ttype: 'Feature',\r\n\t\t\t\tproperties: geojson.properties\r\n\t\t\t}, options);\r\n\r\n\t\t\tif (layer) {\r\n\t\t\t\tlayers.push(layer);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn new FeatureGroup(layers);\r\n\r\n\tdefault:\r\n\t\tthrow new Error('Invalid GeoJSON object.');\r\n\t}\r\n}\r\n\r\n// @function coordsToLatLng(coords: Array): LatLng\r\n// Creates a `LatLng` object from an array of 2 numbers (longitude, latitude)\r\n// or 3 numbers (longitude, latitude, altitude) used in GeoJSON for points.\r\nfunction coordsToLatLng(coords) {\r\n\treturn new LatLng(coords[1], coords[0], coords[2]);\r\n}\r\n\r\n// @function coordsToLatLngs(coords: Array, levelsDeep?: Number, coordsToLatLng?: Function): Array\r\n// Creates a multidimensional array of `LatLng`s from a GeoJSON coordinates array.\r\n// `levelsDeep` specifies the nesting level (0 is for an array of points, 1 for an array of arrays of points, etc., 0 by default).\r\n// Can use a custom [`coordsToLatLng`](#geojson-coordstolatlng) function.\r\nfunction coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {\r\n\tvar latlngs = [];\r\n\r\n\tfor (var i = 0, len = coords.length, latlng; i < len; i++) {\r\n\t\tlatlng = levelsDeep ?\r\n\t\t\tcoordsToLatLngs(coords[i], levelsDeep - 1, _coordsToLatLng) :\r\n\t\t\t(_coordsToLatLng || coordsToLatLng)(coords[i]);\r\n\r\n\t\tlatlngs.push(latlng);\r\n\t}\r\n\r\n\treturn latlngs;\r\n}\r\n\r\n// @function latLngToCoords(latlng: LatLng, precision?: Number): Array\r\n// Reverse of [`coordsToLatLng`](#geojson-coordstolatlng)\r\nfunction latLngToCoords(latlng, precision) {\r\n\tprecision = typeof precision === 'number' ? precision : 6;\r\n\treturn latlng.alt !== undefined ?\r\n\t\t[formatNum(latlng.lng, precision), formatNum(latlng.lat, precision), formatNum(latlng.alt, precision)] :\r\n\t\t[formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)];\r\n}\r\n\r\n// @function latLngsToCoords(latlngs: Array, levelsDeep?: Number, closed?: Boolean): Array\r\n// Reverse of [`coordsToLatLngs`](#geojson-coordstolatlngs)\r\n// `closed` determines whether the first point should be appended to the end of the array to close the feature, only used when `levelsDeep` is 0. False by default.\r\nfunction latLngsToCoords(latlngs, levelsDeep, closed, precision) {\r\n\tvar coords = [];\r\n\r\n\tfor (var i = 0, len = latlngs.length; i < len; i++) {\r\n\t\tcoords.push(levelsDeep ?\r\n\t\t\tlatLngsToCoords(latlngs[i], levelsDeep - 1, closed, precision) :\r\n\t\t\tlatLngToCoords(latlngs[i], precision));\r\n\t}\r\n\r\n\tif (!levelsDeep && closed) {\r\n\t\tcoords.push(coords[0]);\r\n\t}\r\n\r\n\treturn coords;\r\n}\r\n\r\nfunction getFeature(layer, newGeometry) {\r\n\treturn layer.feature ?\r\n\t\textend({}, layer.feature, {geometry: newGeometry}) :\r\n\t\tasFeature(newGeometry);\r\n}\r\n\r\n// @function asFeature(geojson: Object): Object\r\n// Normalize GeoJSON geometries/features into GeoJSON features.\r\nfunction asFeature(geojson) {\r\n\tif (geojson.type === 'Feature' || geojson.type === 'FeatureCollection') {\r\n\t\treturn geojson;\r\n\t}\r\n\r\n\treturn {\r\n\t\ttype: 'Feature',\r\n\t\tproperties: {},\r\n\t\tgeometry: geojson\r\n\t};\r\n}\r\n\r\nvar PointToGeoJSON = {\r\n\ttoGeoJSON: function (precision) {\r\n\t\treturn getFeature(this, {\r\n\t\t\ttype: 'Point',\r\n\t\t\tcoordinates: latLngToCoords(this.getLatLng(), precision)\r\n\t\t});\r\n\t}\r\n};\r\n\r\n// @namespace Marker\r\n// @method toGeoJSON(precision?: Number): Object\r\n// `precision` is the number of decimal places for coordinates.\r\n// The default value is 6 places.\r\n// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the marker (as a GeoJSON `Point` Feature).\r\nMarker.include(PointToGeoJSON);\r\n\r\n// @namespace CircleMarker\r\n// @method toGeoJSON(precision?: Number): Object\r\n// `precision` is the number of decimal places for coordinates.\r\n// The default value is 6 places.\r\n// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the circle marker (as a GeoJSON `Point` Feature).\r\nCircle.include(PointToGeoJSON);\r\nCircleMarker.include(PointToGeoJSON);\r\n\r\n\r\n// @namespace Polyline\r\n// @method toGeoJSON(precision?: Number): Object\r\n// `precision` is the number of decimal places for coordinates.\r\n// The default value is 6 places.\r\n// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polyline (as a GeoJSON `LineString` or `MultiLineString` Feature).\r\nPolyline.include({\r\n\ttoGeoJSON: function (precision) {\r\n\t\tvar multi = !isFlat(this._latlngs);\r\n\r\n\t\tvar coords = latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision);\r\n\r\n\t\treturn getFeature(this, {\r\n\t\t\ttype: (multi ? 'Multi' : '') + 'LineString',\r\n\t\t\tcoordinates: coords\r\n\t\t});\r\n\t}\r\n});\r\n\r\n// @namespace Polygon\r\n// @method toGeoJSON(precision?: Number): Object\r\n// `precision` is the number of decimal places for coordinates.\r\n// The default value is 6 places.\r\n// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the polygon (as a GeoJSON `Polygon` or `MultiPolygon` Feature).\r\nPolygon.include({\r\n\ttoGeoJSON: function (precision) {\r\n\t\tvar holes = !isFlat(this._latlngs),\r\n\t\t multi = holes && !isFlat(this._latlngs[0]);\r\n\r\n\t\tvar coords = latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision);\r\n\r\n\t\tif (!holes) {\r\n\t\t\tcoords = [coords];\r\n\t\t}\r\n\r\n\t\treturn getFeature(this, {\r\n\t\t\ttype: (multi ? 'Multi' : '') + 'Polygon',\r\n\t\t\tcoordinates: coords\r\n\t\t});\r\n\t}\r\n});\r\n\r\n\r\n// @namespace LayerGroup\r\nLayerGroup.include({\r\n\ttoMultiPoint: function (precision) {\r\n\t\tvar coords = [];\r\n\r\n\t\tthis.eachLayer(function (layer) {\r\n\t\t\tcoords.push(layer.toGeoJSON(precision).geometry.coordinates);\r\n\t\t});\r\n\r\n\t\treturn getFeature(this, {\r\n\t\t\ttype: 'MultiPoint',\r\n\t\t\tcoordinates: coords\r\n\t\t});\r\n\t},\r\n\r\n\t// @method toGeoJSON(precision?: Number): Object\r\n\t// `precision` is the number of decimal places for coordinates.\r\n\t// The default value is 6 places.\r\n\t// Returns a [`GeoJSON`](http://en.wikipedia.org/wiki/GeoJSON) representation of the layer group (as a GeoJSON `FeatureCollection`, `GeometryCollection`, or `MultiPoint`).\r\n\ttoGeoJSON: function (precision) {\r\n\r\n\t\tvar type = this.feature && this.feature.geometry && this.feature.geometry.type;\r\n\r\n\t\tif (type === 'MultiPoint') {\r\n\t\t\treturn this.toMultiPoint(precision);\r\n\t\t}\r\n\r\n\t\tvar isGeometryCollection = type === 'GeometryCollection',\r\n\t\t jsons = [];\r\n\r\n\t\tthis.eachLayer(function (layer) {\r\n\t\t\tif (layer.toGeoJSON) {\r\n\t\t\t\tvar json = layer.toGeoJSON(precision);\r\n\t\t\t\tif (isGeometryCollection) {\r\n\t\t\t\t\tjsons.push(json.geometry);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvar feature = asFeature(json);\r\n\t\t\t\t\t// Squash nested feature collections\r\n\t\t\t\t\tif (feature.type === 'FeatureCollection') {\r\n\t\t\t\t\t\tjsons.push.apply(jsons, feature.features);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tjsons.push(feature);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tif (isGeometryCollection) {\r\n\t\t\treturn getFeature(this, {\r\n\t\t\t\tgeometries: jsons,\r\n\t\t\t\ttype: 'GeometryCollection'\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\ttype: 'FeatureCollection',\r\n\t\t\tfeatures: jsons\r\n\t\t};\r\n\t}\r\n});\r\n\r\n// @namespace GeoJSON\r\n// @factory L.geoJSON(geojson?: Object, options?: GeoJSON options)\r\n// Creates a GeoJSON layer. Optionally accepts an object in\r\n// [GeoJSON format](https://tools.ietf.org/html/rfc7946) to display on the map\r\n// (you can alternatively add it later with `addData` method) and an `options` object.\r\nfunction geoJSON(geojson, options) {\r\n\treturn new GeoJSON(geojson, options);\r\n}\r\n\r\n// Backward compatibility.\r\nvar geoJson = geoJSON;\n\n/*\r\n * @class ImageOverlay\r\n * @aka L.ImageOverlay\r\n * @inherits Interactive layer\r\n *\r\n * Used to load and display a single image over specific bounds of the map. Extends `Layer`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var imageUrl = 'http://www.lib.utexas.edu/maps/historical/newark_nj_1922.jpg',\r\n * \timageBounds = [[40.712216, -74.22655], [40.773941, -74.12544]];\r\n * L.imageOverlay(imageUrl, imageBounds).addTo(map);\r\n * ```\r\n */\r\n\r\nvar ImageOverlay = Layer.extend({\r\n\r\n\t// @section\r\n\t// @aka ImageOverlay options\r\n\toptions: {\r\n\t\t// @option opacity: Number = 1.0\r\n\t\t// The opacity of the image overlay.\r\n\t\topacity: 1,\r\n\r\n\t\t// @option alt: String = ''\r\n\t\t// Text for the `alt` attribute of the image (useful for accessibility).\r\n\t\talt: '',\r\n\r\n\t\t// @option interactive: Boolean = false\r\n\t\t// If `true`, the image overlay will emit [mouse events](#interactive-layer) when clicked or hovered.\r\n\t\tinteractive: false,\r\n\r\n\t\t// @option crossOrigin: Boolean|String = false\r\n\t\t// Whether the crossOrigin attribute will be added to the image.\r\n\t\t// If a String is provided, the image will have its crossOrigin attribute set to the String provided. This is needed if you want to access image pixel data.\r\n\t\t// Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.\r\n\t\tcrossOrigin: false,\r\n\r\n\t\t// @option errorOverlayUrl: String = ''\r\n\t\t// URL to the overlay image to show in place of the overlay that failed to load.\r\n\t\terrorOverlayUrl: '',\r\n\r\n\t\t// @option zIndex: Number = 1\r\n\t\t// The explicit [zIndex](https://developer.mozilla.org/docs/Web/CSS/CSS_Positioning/Understanding_z_index) of the overlay layer.\r\n\t\tzIndex: 1,\r\n\r\n\t\t// @option className: String = ''\r\n\t\t// A custom class name to assign to the image. Empty by default.\r\n\t\tclassName: ''\r\n\t},\r\n\r\n\tinitialize: function (url, bounds, options) { // (String, LatLngBounds, Object)\r\n\t\tthis._url = url;\r\n\t\tthis._bounds = toLatLngBounds(bounds);\r\n\r\n\t\tsetOptions(this, options);\r\n\t},\r\n\r\n\tonAdd: function () {\r\n\t\tif (!this._image) {\r\n\t\t\tthis._initImage();\r\n\r\n\t\t\tif (this.options.opacity < 1) {\r\n\t\t\t\tthis._updateOpacity();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (this.options.interactive) {\r\n\t\t\taddClass(this._image, 'leaflet-interactive');\r\n\t\t\tthis.addInteractiveTarget(this._image);\r\n\t\t}\r\n\r\n\t\tthis.getPane().appendChild(this._image);\r\n\t\tthis._reset();\r\n\t},\r\n\r\n\tonRemove: function () {\r\n\t\tremove(this._image);\r\n\t\tif (this.options.interactive) {\r\n\t\t\tthis.removeInteractiveTarget(this._image);\r\n\t\t}\r\n\t},\r\n\r\n\t// @method setOpacity(opacity: Number): this\r\n\t// Sets the opacity of the overlay.\r\n\tsetOpacity: function (opacity) {\r\n\t\tthis.options.opacity = opacity;\r\n\r\n\t\tif (this._image) {\r\n\t\t\tthis._updateOpacity();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\tsetStyle: function (styleOpts) {\r\n\t\tif (styleOpts.opacity) {\r\n\t\t\tthis.setOpacity(styleOpts.opacity);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method bringToFront(): this\r\n\t// Brings the layer to the top of all overlays.\r\n\tbringToFront: function () {\r\n\t\tif (this._map) {\r\n\t\t\ttoFront(this._image);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method bringToBack(): this\r\n\t// Brings the layer to the bottom of all overlays.\r\n\tbringToBack: function () {\r\n\t\tif (this._map) {\r\n\t\t\ttoBack(this._image);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method setUrl(url: String): this\r\n\t// Changes the URL of the image.\r\n\tsetUrl: function (url) {\r\n\t\tthis._url = url;\r\n\r\n\t\tif (this._image) {\r\n\t\t\tthis._image.src = url;\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method setBounds(bounds: LatLngBounds): this\r\n\t// Update the bounds that this ImageOverlay covers\r\n\tsetBounds: function (bounds) {\r\n\t\tthis._bounds = toLatLngBounds(bounds);\r\n\r\n\t\tif (this._map) {\r\n\t\t\tthis._reset();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\tgetEvents: function () {\r\n\t\tvar events = {\r\n\t\t\tzoom: this._reset,\r\n\t\t\tviewreset: this._reset\r\n\t\t};\r\n\r\n\t\tif (this._zoomAnimated) {\r\n\t\t\tevents.zoomanim = this._animateZoom;\r\n\t\t}\r\n\r\n\t\treturn events;\r\n\t},\r\n\r\n\t// @method setZIndex(value: Number): this\r\n\t// Changes the [zIndex](#imageoverlay-zindex) of the image overlay.\r\n\tsetZIndex: function (value) {\r\n\t\tthis.options.zIndex = value;\r\n\t\tthis._updateZIndex();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getBounds(): LatLngBounds\r\n\t// Get the bounds that this ImageOverlay covers\r\n\tgetBounds: function () {\r\n\t\treturn this._bounds;\r\n\t},\r\n\r\n\t// @method getElement(): HTMLElement\r\n\t// Returns the instance of [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement)\r\n\t// used by this overlay.\r\n\tgetElement: function () {\r\n\t\treturn this._image;\r\n\t},\r\n\r\n\t_initImage: function () {\r\n\t\tvar wasElementSupplied = this._url.tagName === 'IMG';\r\n\t\tvar img = this._image = wasElementSupplied ? this._url : create$1('img');\r\n\r\n\t\taddClass(img, 'leaflet-image-layer');\r\n\t\tif (this._zoomAnimated) { addClass(img, 'leaflet-zoom-animated'); }\r\n\t\tif (this.options.className) { addClass(img, this.options.className); }\r\n\r\n\t\timg.onselectstart = falseFn;\r\n\t\timg.onmousemove = falseFn;\r\n\r\n\t\t// @event load: Event\r\n\t\t// Fired when the ImageOverlay layer has loaded its image\r\n\t\timg.onload = bind(this.fire, this, 'load');\r\n\t\timg.onerror = bind(this._overlayOnError, this, 'error');\r\n\r\n\t\tif (this.options.crossOrigin || this.options.crossOrigin === '') {\r\n\t\t\timg.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;\r\n\t\t}\r\n\r\n\t\tif (this.options.zIndex) {\r\n\t\t\tthis._updateZIndex();\r\n\t\t}\r\n\r\n\t\tif (wasElementSupplied) {\r\n\t\t\tthis._url = img.src;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\timg.src = this._url;\r\n\t\timg.alt = this.options.alt;\r\n\t},\r\n\r\n\t_animateZoom: function (e) {\r\n\t\tvar scale = this._map.getZoomScale(e.zoom),\r\n\t\t offset = this._map._latLngBoundsToNewLayerBounds(this._bounds, e.zoom, e.center).min;\r\n\r\n\t\tsetTransform(this._image, offset, scale);\r\n\t},\r\n\r\n\t_reset: function () {\r\n\t\tvar image = this._image,\r\n\t\t bounds = new Bounds(\r\n\t\t this._map.latLngToLayerPoint(this._bounds.getNorthWest()),\r\n\t\t this._map.latLngToLayerPoint(this._bounds.getSouthEast())),\r\n\t\t size = bounds.getSize();\r\n\r\n\t\tsetPosition(image, bounds.min);\r\n\r\n\t\timage.style.width = size.x + 'px';\r\n\t\timage.style.height = size.y + 'px';\r\n\t},\r\n\r\n\t_updateOpacity: function () {\r\n\t\tsetOpacity(this._image, this.options.opacity);\r\n\t},\r\n\r\n\t_updateZIndex: function () {\r\n\t\tif (this._image && this.options.zIndex !== undefined && this.options.zIndex !== null) {\r\n\t\t\tthis._image.style.zIndex = this.options.zIndex;\r\n\t\t}\r\n\t},\r\n\r\n\t_overlayOnError: function () {\r\n\t\t// @event error: Event\r\n\t\t// Fired when the ImageOverlay layer fails to load its image\r\n\t\tthis.fire('error');\r\n\r\n\t\tvar errorUrl = this.options.errorOverlayUrl;\r\n\t\tif (errorUrl && this._url !== errorUrl) {\r\n\t\t\tthis._url = errorUrl;\r\n\t\t\tthis._image.src = errorUrl;\r\n\t\t}\r\n\t}\r\n});\r\n\r\n// @factory L.imageOverlay(imageUrl: String, bounds: LatLngBounds, options?: ImageOverlay options)\r\n// Instantiates an image overlay object given the URL of the image and the\r\n// geographical bounds it is tied to.\r\nvar imageOverlay = function (url, bounds, options) {\r\n\treturn new ImageOverlay(url, bounds, options);\r\n};\n\n/*\r\n * @class VideoOverlay\r\n * @aka L.VideoOverlay\r\n * @inherits ImageOverlay\r\n *\r\n * Used to load and display a video player over specific bounds of the map. Extends `ImageOverlay`.\r\n *\r\n * A video overlay uses the [`<video>`](https://developer.mozilla.org/docs/Web/HTML/Element/video)\r\n * HTML5 element.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',\r\n * \tvideoBounds = [[ 32, -130], [ 13, -100]];\r\n * L.videoOverlay(videoUrl, videoBounds ).addTo(map);\r\n * ```\r\n */\r\n\r\nvar VideoOverlay = ImageOverlay.extend({\r\n\r\n\t// @section\r\n\t// @aka VideoOverlay options\r\n\toptions: {\r\n\t\t// @option autoplay: Boolean = true\r\n\t\t// Whether the video starts playing automatically when loaded.\r\n\t\tautoplay: true,\r\n\r\n\t\t// @option loop: Boolean = true\r\n\t\t// Whether the video will loop back to the beginning when played.\r\n\t\tloop: true,\r\n\r\n\t\t// @option keepAspectRatio: Boolean = true\r\n\t\t// Whether the video will save aspect ratio after the projection.\r\n\t\t// Relevant for supported browsers. Browser compatibility- https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit\r\n\t\tkeepAspectRatio: true\r\n\t},\r\n\r\n\t_initImage: function () {\r\n\t\tvar wasElementSupplied = this._url.tagName === 'VIDEO';\r\n\t\tvar vid = this._image = wasElementSupplied ? this._url : create$1('video');\r\n\r\n\t\taddClass(vid, 'leaflet-image-layer');\r\n\t\tif (this._zoomAnimated) { addClass(vid, 'leaflet-zoom-animated'); }\r\n\r\n\t\tvid.onselectstart = falseFn;\r\n\t\tvid.onmousemove = falseFn;\r\n\r\n\t\t// @event load: Event\r\n\t\t// Fired when the video has finished loading the first frame\r\n\t\tvid.onloadeddata = bind(this.fire, this, 'load');\r\n\r\n\t\tif (wasElementSupplied) {\r\n\t\t\tvar sourceElements = vid.getElementsByTagName('source');\r\n\t\t\tvar sources = [];\r\n\t\t\tfor (var j = 0; j < sourceElements.length; j++) {\r\n\t\t\t\tsources.push(sourceElements[j].src);\r\n\t\t\t}\r\n\r\n\t\t\tthis._url = (sourceElements.length > 0) ? sources : [vid.src];\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!isArray(this._url)) { this._url = [this._url]; }\r\n\r\n\t\tif (!this.options.keepAspectRatio && vid.style.hasOwnProperty('objectFit')) { vid.style['objectFit'] = 'fill'; }\r\n\t\tvid.autoplay = !!this.options.autoplay;\r\n\t\tvid.loop = !!this.options.loop;\r\n\t\tfor (var i = 0; i < this._url.length; i++) {\r\n\t\t\tvar source = create$1('source');\r\n\t\t\tsource.src = this._url[i];\r\n\t\t\tvid.appendChild(source);\r\n\t\t}\r\n\t}\r\n\r\n\t// @method getElement(): HTMLVideoElement\r\n\t// Returns the instance of [`HTMLVideoElement`](https://developer.mozilla.org/docs/Web/API/HTMLVideoElement)\r\n\t// used by this overlay.\r\n});\r\n\r\n\r\n// @factory L.videoOverlay(video: String|Array|HTMLVideoElement, bounds: LatLngBounds, options?: VideoOverlay options)\r\n// Instantiates an image overlay object given the URL of the video (or array of URLs, or even a video element) and the\r\n// geographical bounds it is tied to.\r\n\r\nfunction videoOverlay(video, bounds, options) {\r\n\treturn new VideoOverlay(video, bounds, options);\r\n}\n\n/*\n * @class SVGOverlay\n * @aka L.SVGOverlay\n * @inherits ImageOverlay\n *\n * Used to load, display and provide DOM access to an SVG file over specific bounds of the map. Extends `ImageOverlay`.\n *\n * An SVG overlay uses the [`<svg>`](https://developer.mozilla.org/docs/Web/SVG/Element/svg) element.\n *\n * @example\n *\n * ```js\n * var element = '<svg width=\"200\" height=\"200\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><image xlink:href=\"https://mdn.mozillademos.org/files/6457/mdn_logo_only_color.png\" height=\"200\" width=\"200\"/></svg>',\n * \t\t elementBounds = [ [ 32, -130 ], [ 13, -100 ] ];\n * L.svgOverlay(element, elementBounds).addTo(map);\n * ```\n */\n\nvar SVGOverlay = ImageOverlay.extend({\n\t_initImage: function () {\n\t\tvar el = this._image = this._url;\n\n\t\taddClass(el, 'leaflet-image-layer');\n\t\tif (this._zoomAnimated) { addClass(el, 'leaflet-zoom-animated'); }\n\n\t\tel.onselectstart = falseFn;\n\t\tel.onmousemove = falseFn;\n\t}\n\n\t// @method getElement(): SVGElement\n\t// Returns the instance of [`SVGElement`](https://developer.mozilla.org/docs/Web/API/SVGElement)\n\t// used by this overlay.\n});\n\n\n// @factory L.svgOverlay(svg: String|SVGElement, bounds: LatLngBounds, options?: SVGOverlay options)\n// Instantiates an image overlay object given an SVG element and the geographical bounds it is tied to.\n// A viewBox attribute is required on the SVG element to zoom in and out properly.\n\nfunction svgOverlay(el, bounds, options) {\n\treturn new SVGOverlay(el, bounds, options);\n}\n\n/*\r\n * @class DivOverlay\r\n * @inherits Layer\r\n * @aka L.DivOverlay\r\n * Base model for L.Popup and L.Tooltip. Inherit from it for custom popup like plugins.\r\n */\r\n\r\n// @namespace DivOverlay\r\nvar DivOverlay = Layer.extend({\r\n\r\n\t// @section\r\n\t// @aka DivOverlay options\r\n\toptions: {\r\n\t\t// @option offset: Point = Point(0, 7)\r\n\t\t// The offset of the popup position. Useful to control the anchor\r\n\t\t// of the popup when opening it on some overlays.\r\n\t\toffset: [0, 7],\r\n\r\n\t\t// @option className: String = ''\r\n\t\t// A custom CSS class name to assign to the popup.\r\n\t\tclassName: '',\r\n\r\n\t\t// @option pane: String = 'popupPane'\r\n\t\t// `Map pane` where the popup will be added.\r\n\t\tpane: 'popupPane'\r\n\t},\r\n\r\n\tinitialize: function (options, source) {\r\n\t\tsetOptions(this, options);\r\n\r\n\t\tthis._source = source;\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tthis._zoomAnimated = map._zoomAnimated;\r\n\r\n\t\tif (!this._container) {\r\n\t\t\tthis._initLayout();\r\n\t\t}\r\n\r\n\t\tif (map._fadeAnimated) {\r\n\t\t\tsetOpacity(this._container, 0);\r\n\t\t}\r\n\r\n\t\tclearTimeout(this._removeTimeout);\r\n\t\tthis.getPane().appendChild(this._container);\r\n\t\tthis.update();\r\n\r\n\t\tif (map._fadeAnimated) {\r\n\t\t\tsetOpacity(this._container, 1);\r\n\t\t}\r\n\r\n\t\tthis.bringToFront();\r\n\t},\r\n\r\n\tonRemove: function (map) {\r\n\t\tif (map._fadeAnimated) {\r\n\t\t\tsetOpacity(this._container, 0);\r\n\t\t\tthis._removeTimeout = setTimeout(bind(remove, undefined, this._container), 200);\r\n\t\t} else {\r\n\t\t\tremove(this._container);\r\n\t\t}\r\n\t},\r\n\r\n\t// @namespace Popup\r\n\t// @method getLatLng: LatLng\r\n\t// Returns the geographical point of popup.\r\n\tgetLatLng: function () {\r\n\t\treturn this._latlng;\r\n\t},\r\n\r\n\t// @method setLatLng(latlng: LatLng): this\r\n\t// Sets the geographical point where the popup will open.\r\n\tsetLatLng: function (latlng) {\r\n\t\tthis._latlng = toLatLng(latlng);\r\n\t\tif (this._map) {\r\n\t\t\tthis._updatePosition();\r\n\t\t\tthis._adjustPan();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getContent: String|HTMLElement\r\n\t// Returns the content of the popup.\r\n\tgetContent: function () {\r\n\t\treturn this._content;\r\n\t},\r\n\r\n\t// @method setContent(htmlContent: String|HTMLElement|Function): this\r\n\t// Sets the HTML content of the popup. If a function is passed the source layer will be passed to the function. The function should return a `String` or `HTMLElement` to be used in the popup.\r\n\tsetContent: function (content) {\r\n\t\tthis._content = content;\r\n\t\tthis.update();\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getElement: String|HTMLElement\r\n\t// Alias for [getContent()](#popup-getcontent)\r\n\tgetElement: function () {\r\n\t\treturn this._container;\r\n\t},\r\n\r\n\t// @method update: null\r\n\t// Updates the popup content, layout and position. Useful for updating the popup after something inside changed, e.g. image loaded.\r\n\tupdate: function () {\r\n\t\tif (!this._map) { return; }\r\n\r\n\t\tthis._container.style.visibility = 'hidden';\r\n\r\n\t\tthis._updateContent();\r\n\t\tthis._updateLayout();\r\n\t\tthis._updatePosition();\r\n\r\n\t\tthis._container.style.visibility = '';\r\n\r\n\t\tthis._adjustPan();\r\n\t},\r\n\r\n\tgetEvents: function () {\r\n\t\tvar events = {\r\n\t\t\tzoom: this._updatePosition,\r\n\t\t\tviewreset: this._updatePosition\r\n\t\t};\r\n\r\n\t\tif (this._zoomAnimated) {\r\n\t\t\tevents.zoomanim = this._animateZoom;\r\n\t\t}\r\n\t\treturn events;\r\n\t},\r\n\r\n\t// @method isOpen: Boolean\r\n\t// Returns `true` when the popup is visible on the map.\r\n\tisOpen: function () {\r\n\t\treturn !!this._map && this._map.hasLayer(this);\r\n\t},\r\n\r\n\t// @method bringToFront: this\r\n\t// Brings this popup in front of other popups (in the same map pane).\r\n\tbringToFront: function () {\r\n\t\tif (this._map) {\r\n\t\t\ttoFront(this._container);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method bringToBack: this\r\n\t// Brings this popup to the back of other popups (in the same map pane).\r\n\tbringToBack: function () {\r\n\t\tif (this._map) {\r\n\t\t\ttoBack(this._container);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t_prepareOpen: function (parent, layer, latlng) {\r\n\t\tif (!(layer instanceof Layer)) {\r\n\t\t\tlatlng = layer;\r\n\t\t\tlayer = parent;\r\n\t\t}\r\n\r\n\t\tif (layer instanceof FeatureGroup) {\r\n\t\t\tfor (var id in parent._layers) {\r\n\t\t\t\tlayer = parent._layers[id];\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!latlng) {\r\n\t\t\tif (layer.getCenter) {\r\n\t\t\t\tlatlng = layer.getCenter();\r\n\t\t\t} else if (layer.getLatLng) {\r\n\t\t\t\tlatlng = layer.getLatLng();\r\n\t\t\t} else {\r\n\t\t\t\tthrow new Error('Unable to get source layer LatLng.');\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// set overlay source to this layer\r\n\t\tthis._source = layer;\r\n\r\n\t\t// update the overlay (content, layout, ect...)\r\n\t\tthis.update();\r\n\r\n\t\treturn latlng;\r\n\t},\r\n\r\n\t_updateContent: function () {\r\n\t\tif (!this._content) { return; }\r\n\r\n\t\tvar node = this._contentNode;\r\n\t\tvar content = (typeof this._content === 'function') ? this._content(this._source || this) : this._content;\r\n\r\n\t\tif (typeof content === 'string') {\r\n\t\t\tnode.innerHTML = content;\r\n\t\t} else {\r\n\t\t\twhile (node.hasChildNodes()) {\r\n\t\t\t\tnode.removeChild(node.firstChild);\r\n\t\t\t}\r\n\t\t\tnode.appendChild(content);\r\n\t\t}\r\n\t\tthis.fire('contentupdate');\r\n\t},\r\n\r\n\t_updatePosition: function () {\r\n\t\tif (!this._map) { return; }\r\n\r\n\t\tvar pos = this._map.latLngToLayerPoint(this._latlng),\r\n\t\t offset = toPoint(this.options.offset),\r\n\t\t anchor = this._getAnchor();\r\n\r\n\t\tif (this._zoomAnimated) {\r\n\t\t\tsetPosition(this._container, pos.add(anchor));\r\n\t\t} else {\r\n\t\t\toffset = offset.add(pos).add(anchor);\r\n\t\t}\r\n\r\n\t\tvar bottom = this._containerBottom = -offset.y,\r\n\t\t left = this._containerLeft = -Math.round(this._containerWidth / 2) + offset.x;\r\n\r\n\t\t// bottom position the popup in case the height of the popup changes (images loading etc)\r\n\t\tthis._container.style.bottom = bottom + 'px';\r\n\t\tthis._container.style.left = left + 'px';\r\n\t},\r\n\r\n\t_getAnchor: function () {\r\n\t\treturn [0, 0];\r\n\t}\r\n\r\n});\n\n/*\r\n * @class Popup\r\n * @inherits DivOverlay\r\n * @aka L.Popup\r\n * Used to open popups in certain places of the map. Use [Map.openPopup](#map-openpopup) to\r\n * open popups while making sure that only one popup is open at one time\r\n * (recommended for usability), or use [Map.addLayer](#map-addlayer) to open as many as you want.\r\n *\r\n * @example\r\n *\r\n * If you want to just bind a popup to marker click and then open it, it's really easy:\r\n *\r\n * ```js\r\n * marker.bindPopup(popupContent).openPopup();\r\n * ```\r\n * Path overlays like polylines also have a `bindPopup` method.\r\n * Here's a more complicated way to open a popup on a map:\r\n *\r\n * ```js\r\n * var popup = L.popup()\r\n * \t.setLatLng(latlng)\r\n * \t.setContent('<p>Hello world!<br />This is a nice popup.</p>')\r\n * \t.openOn(map);\r\n * ```\r\n */\r\n\r\n\r\n// @namespace Popup\r\nvar Popup = DivOverlay.extend({\r\n\r\n\t// @section\r\n\t// @aka Popup options\r\n\toptions: {\r\n\t\t// @option maxWidth: Number = 300\r\n\t\t// Max width of the popup, in pixels.\r\n\t\tmaxWidth: 300,\r\n\r\n\t\t// @option minWidth: Number = 50\r\n\t\t// Min width of the popup, in pixels.\r\n\t\tminWidth: 50,\r\n\r\n\t\t// @option maxHeight: Number = null\r\n\t\t// If set, creates a scrollable container of the given height\r\n\t\t// inside a popup if its content exceeds it.\r\n\t\tmaxHeight: null,\r\n\r\n\t\t// @option autoPan: Boolean = true\r\n\t\t// Set it to `false` if you don't want the map to do panning animation\r\n\t\t// to fit the opened popup.\r\n\t\tautoPan: true,\r\n\r\n\t\t// @option autoPanPaddingTopLeft: Point = null\r\n\t\t// The margin between the popup and the top left corner of the map\r\n\t\t// view after autopanning was performed.\r\n\t\tautoPanPaddingTopLeft: null,\r\n\r\n\t\t// @option autoPanPaddingBottomRight: Point = null\r\n\t\t// The margin between the popup and the bottom right corner of the map\r\n\t\t// view after autopanning was performed.\r\n\t\tautoPanPaddingBottomRight: null,\r\n\r\n\t\t// @option autoPanPadding: Point = Point(5, 5)\r\n\t\t// Equivalent of setting both top left and bottom right autopan padding to the same value.\r\n\t\tautoPanPadding: [5, 5],\r\n\r\n\t\t// @option keepInView: Boolean = false\r\n\t\t// Set it to `true` if you want to prevent users from panning the popup\r\n\t\t// off of the screen while it is open.\r\n\t\tkeepInView: false,\r\n\r\n\t\t// @option closeButton: Boolean = true\r\n\t\t// Controls the presence of a close button in the popup.\r\n\t\tcloseButton: true,\r\n\r\n\t\t// @option autoClose: Boolean = true\r\n\t\t// Set it to `false` if you want to override the default behavior of\r\n\t\t// the popup closing when another popup is opened.\r\n\t\tautoClose: true,\r\n\r\n\t\t// @option closeOnEscapeKey: Boolean = true\r\n\t\t// Set it to `false` if you want to override the default behavior of\r\n\t\t// the ESC key for closing of the popup.\r\n\t\tcloseOnEscapeKey: true,\r\n\r\n\t\t// @option closeOnClick: Boolean = *\r\n\t\t// Set it if you want to override the default behavior of the popup closing when user clicks\r\n\t\t// on the map. Defaults to the map's [`closePopupOnClick`](#map-closepopuponclick) option.\r\n\r\n\t\t// @option className: String = ''\r\n\t\t// A custom CSS class name to assign to the popup.\r\n\t\tclassName: ''\r\n\t},\r\n\r\n\t// @namespace Popup\r\n\t// @method openOn(map: Map): this\r\n\t// Adds the popup to the map and closes the previous one. The same as `map.openPopup(popup)`.\r\n\topenOn: function (map) {\r\n\t\tmap.openPopup(this);\r\n\t\treturn this;\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\t\tDivOverlay.prototype.onAdd.call(this, map);\r\n\r\n\t\t// @namespace Map\r\n\t\t// @section Popup events\r\n\t\t// @event popupopen: PopupEvent\r\n\t\t// Fired when a popup is opened in the map\r\n\t\tmap.fire('popupopen', {popup: this});\r\n\r\n\t\tif (this._source) {\r\n\t\t\t// @namespace Layer\r\n\t\t\t// @section Popup events\r\n\t\t\t// @event popupopen: PopupEvent\r\n\t\t\t// Fired when a popup bound to this layer is opened\r\n\t\t\tthis._source.fire('popupopen', {popup: this}, true);\r\n\t\t\t// For non-path layers, we toggle the popup when clicking\r\n\t\t\t// again the layer, so prevent the map to reopen it.\r\n\t\t\tif (!(this._source instanceof Path)) {\r\n\t\t\t\tthis._source.on('preclick', stopPropagation);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\tonRemove: function (map) {\r\n\t\tDivOverlay.prototype.onRemove.call(this, map);\r\n\r\n\t\t// @namespace Map\r\n\t\t// @section Popup events\r\n\t\t// @event popupclose: PopupEvent\r\n\t\t// Fired when a popup in the map is closed\r\n\t\tmap.fire('popupclose', {popup: this});\r\n\r\n\t\tif (this._source) {\r\n\t\t\t// @namespace Layer\r\n\t\t\t// @section Popup events\r\n\t\t\t// @event popupclose: PopupEvent\r\n\t\t\t// Fired when a popup bound to this layer is closed\r\n\t\t\tthis._source.fire('popupclose', {popup: this}, true);\r\n\t\t\tif (!(this._source instanceof Path)) {\r\n\t\t\t\tthis._source.off('preclick', stopPropagation);\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\tgetEvents: function () {\r\n\t\tvar events = DivOverlay.prototype.getEvents.call(this);\r\n\r\n\t\tif (this.options.closeOnClick !== undefined ? this.options.closeOnClick : this._map.options.closePopupOnClick) {\r\n\t\t\tevents.preclick = this._close;\r\n\t\t}\r\n\r\n\t\tif (this.options.keepInView) {\r\n\t\t\tevents.moveend = this._adjustPan;\r\n\t\t}\r\n\r\n\t\treturn events;\r\n\t},\r\n\r\n\t_close: function () {\r\n\t\tif (this._map) {\r\n\t\t\tthis._map.closePopup(this);\r\n\t\t}\r\n\t},\r\n\r\n\t_initLayout: function () {\r\n\t\tvar prefix = 'leaflet-popup',\r\n\t\t container = this._container = create$1('div',\r\n\t\t\tprefix + ' ' + (this.options.className || '') +\r\n\t\t\t' leaflet-zoom-animated');\r\n\r\n\t\tvar wrapper = this._wrapper = create$1('div', prefix + '-content-wrapper', container);\r\n\t\tthis._contentNode = create$1('div', prefix + '-content', wrapper);\r\n\r\n\t\tdisableClickPropagation(wrapper);\r\n\t\tdisableScrollPropagation(this._contentNode);\r\n\t\ton(wrapper, 'contextmenu', stopPropagation);\r\n\r\n\t\tthis._tipContainer = create$1('div', prefix + '-tip-container', container);\r\n\t\tthis._tip = create$1('div', prefix + '-tip', this._tipContainer);\r\n\r\n\t\tif (this.options.closeButton) {\r\n\t\t\tvar closeButton = this._closeButton = create$1('a', prefix + '-close-button', container);\r\n\t\t\tcloseButton.href = '#close';\r\n\t\t\tcloseButton.innerHTML = '&#215;';\r\n\r\n\t\t\ton(closeButton, 'click', this._onCloseButtonClick, this);\r\n\t\t}\r\n\t},\r\n\r\n\t_updateLayout: function () {\r\n\t\tvar container = this._contentNode,\r\n\t\t style = container.style;\r\n\r\n\t\tstyle.width = '';\r\n\t\tstyle.whiteSpace = 'nowrap';\r\n\r\n\t\tvar width = container.offsetWidth;\r\n\t\twidth = Math.min(width, this.options.maxWidth);\r\n\t\twidth = Math.max(width, this.options.minWidth);\r\n\r\n\t\tstyle.width = (width + 1) + 'px';\r\n\t\tstyle.whiteSpace = '';\r\n\r\n\t\tstyle.height = '';\r\n\r\n\t\tvar height = container.offsetHeight,\r\n\t\t maxHeight = this.options.maxHeight,\r\n\t\t scrolledClass = 'leaflet-popup-scrolled';\r\n\r\n\t\tif (maxHeight && height > maxHeight) {\r\n\t\t\tstyle.height = maxHeight + 'px';\r\n\t\t\taddClass(container, scrolledClass);\r\n\t\t} else {\r\n\t\t\tremoveClass(container, scrolledClass);\r\n\t\t}\r\n\r\n\t\tthis._containerWidth = this._container.offsetWidth;\r\n\t},\r\n\r\n\t_animateZoom: function (e) {\r\n\t\tvar pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center),\r\n\t\t anchor = this._getAnchor();\r\n\t\tsetPosition(this._container, pos.add(anchor));\r\n\t},\r\n\r\n\t_adjustPan: function () {\r\n\t\tif (!this.options.autoPan) { return; }\r\n\t\tif (this._map._panAnim) { this._map._panAnim.stop(); }\r\n\r\n\t\tvar map = this._map,\r\n\t\t marginBottom = parseInt(getStyle(this._container, 'marginBottom'), 10) || 0,\r\n\t\t containerHeight = this._container.offsetHeight + marginBottom,\r\n\t\t containerWidth = this._containerWidth,\r\n\t\t layerPos = new Point(this._containerLeft, -containerHeight - this._containerBottom);\r\n\r\n\t\tlayerPos._add(getPosition(this._container));\r\n\r\n\t\tvar containerPos = map.layerPointToContainerPoint(layerPos),\r\n\t\t padding = toPoint(this.options.autoPanPadding),\r\n\t\t paddingTL = toPoint(this.options.autoPanPaddingTopLeft || padding),\r\n\t\t paddingBR = toPoint(this.options.autoPanPaddingBottomRight || padding),\r\n\t\t size = map.getSize(),\r\n\t\t dx = 0,\r\n\t\t dy = 0;\r\n\r\n\t\tif (containerPos.x + containerWidth + paddingBR.x > size.x) { // right\r\n\t\t\tdx = containerPos.x + containerWidth - size.x + paddingBR.x;\r\n\t\t}\r\n\t\tif (containerPos.x - dx - paddingTL.x < 0) { // left\r\n\t\t\tdx = containerPos.x - paddingTL.x;\r\n\t\t}\r\n\t\tif (containerPos.y + containerHeight + paddingBR.y > size.y) { // bottom\r\n\t\t\tdy = containerPos.y + containerHeight - size.y + paddingBR.y;\r\n\t\t}\r\n\t\tif (containerPos.y - dy - paddingTL.y < 0) { // top\r\n\t\t\tdy = containerPos.y - paddingTL.y;\r\n\t\t}\r\n\r\n\t\t// @namespace Map\r\n\t\t// @section Popup events\r\n\t\t// @event autopanstart: Event\r\n\t\t// Fired when the map starts autopanning when opening a popup.\r\n\t\tif (dx || dy) {\r\n\t\t\tmap\r\n\t\t\t .fire('autopanstart')\r\n\t\t\t .panBy([dx, dy]);\r\n\t\t}\r\n\t},\r\n\r\n\t_onCloseButtonClick: function (e) {\r\n\t\tthis._close();\r\n\t\tstop(e);\r\n\t},\r\n\r\n\t_getAnchor: function () {\r\n\t\t// Where should we anchor the popup on the source layer?\r\n\t\treturn toPoint(this._source && this._source._getPopupAnchor ? this._source._getPopupAnchor() : [0, 0]);\r\n\t}\r\n\r\n});\r\n\r\n// @namespace Popup\r\n// @factory L.popup(options?: Popup options, source?: Layer)\r\n// Instantiates a `Popup` object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the popup with a reference to the Layer to which it refers.\r\nvar popup = function (options, source) {\r\n\treturn new Popup(options, source);\r\n};\r\n\r\n\r\n/* @namespace Map\r\n * @section Interaction Options\r\n * @option closePopupOnClick: Boolean = true\r\n * Set it to `false` if you don't want popups to close when user clicks the map.\r\n */\r\nMap.mergeOptions({\r\n\tclosePopupOnClick: true\r\n});\r\n\r\n\r\n// @namespace Map\r\n// @section Methods for Layers and Controls\r\nMap.include({\r\n\t// @method openPopup(popup: Popup): this\r\n\t// Opens the specified popup while closing the previously opened (to make sure only one is opened at one time for usability).\r\n\t// @alternative\r\n\t// @method openPopup(content: String|HTMLElement, latlng: LatLng, options?: Popup options): this\r\n\t// Creates a popup with the specified content and options and opens it in the given point on a map.\r\n\topenPopup: function (popup, latlng, options) {\r\n\t\tif (!(popup instanceof Popup)) {\r\n\t\t\tpopup = new Popup(options).setContent(popup);\r\n\t\t}\r\n\r\n\t\tif (latlng) {\r\n\t\t\tpopup.setLatLng(latlng);\r\n\t\t}\r\n\r\n\t\tif (this.hasLayer(popup)) {\r\n\t\t\treturn this;\r\n\t\t}\r\n\r\n\t\tif (this._popup && this._popup.options.autoClose) {\r\n\t\t\tthis.closePopup();\r\n\t\t}\r\n\r\n\t\tthis._popup = popup;\r\n\t\treturn this.addLayer(popup);\r\n\t},\r\n\r\n\t// @method closePopup(popup?: Popup): this\r\n\t// Closes the popup previously opened with [openPopup](#map-openpopup) (or the given one).\r\n\tclosePopup: function (popup) {\r\n\t\tif (!popup || popup === this._popup) {\r\n\t\t\tpopup = this._popup;\r\n\t\t\tthis._popup = null;\r\n\t\t}\r\n\t\tif (popup) {\r\n\t\t\tthis.removeLayer(popup);\r\n\t\t}\r\n\t\treturn this;\r\n\t}\r\n});\r\n\r\n/*\r\n * @namespace Layer\r\n * @section Popup methods example\r\n *\r\n * All layers share a set of methods convenient for binding popups to it.\r\n *\r\n * ```js\r\n * var layer = L.Polygon(latlngs).bindPopup('Hi There!').addTo(map);\r\n * layer.openPopup();\r\n * layer.closePopup();\r\n * ```\r\n *\r\n * Popups will also be automatically opened when the layer is clicked on and closed when the layer is removed from the map or another popup is opened.\r\n */\r\n\r\n// @section Popup methods\r\nLayer.include({\r\n\r\n\t// @method bindPopup(content: String|HTMLElement|Function|Popup, options?: Popup options): this\r\n\t// Binds a popup to the layer with the passed `content` and sets up the\r\n\t// necessary event listeners. If a `Function` is passed it will receive\r\n\t// the layer as the first argument and should return a `String` or `HTMLElement`.\r\n\tbindPopup: function (content, options) {\r\n\r\n\t\tif (content instanceof Popup) {\r\n\t\t\tsetOptions(content, options);\r\n\t\t\tthis._popup = content;\r\n\t\t\tcontent._source = this;\r\n\t\t} else {\r\n\t\t\tif (!this._popup || options) {\r\n\t\t\t\tthis._popup = new Popup(options, this);\r\n\t\t\t}\r\n\t\t\tthis._popup.setContent(content);\r\n\t\t}\r\n\r\n\t\tif (!this._popupHandlersAdded) {\r\n\t\t\tthis.on({\r\n\t\t\t\tclick: this._openPopup,\r\n\t\t\t\tkeypress: this._onKeyPress,\r\n\t\t\t\tremove: this.closePopup,\r\n\t\t\t\tmove: this._movePopup\r\n\t\t\t});\r\n\t\t\tthis._popupHandlersAdded = true;\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method unbindPopup(): this\r\n\t// Removes the popup previously bound with `bindPopup`.\r\n\tunbindPopup: function () {\r\n\t\tif (this._popup) {\r\n\t\t\tthis.off({\r\n\t\t\t\tclick: this._openPopup,\r\n\t\t\t\tkeypress: this._onKeyPress,\r\n\t\t\t\tremove: this.closePopup,\r\n\t\t\t\tmove: this._movePopup\r\n\t\t\t});\r\n\t\t\tthis._popupHandlersAdded = false;\r\n\t\t\tthis._popup = null;\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method openPopup(latlng?: LatLng): this\r\n\t// Opens the bound popup at the specified `latlng` or at the default popup anchor if no `latlng` is passed.\r\n\topenPopup: function (layer, latlng) {\r\n\t\tif (this._popup && this._map) {\r\n\t\t\tlatlng = this._popup._prepareOpen(this, layer, latlng);\r\n\r\n\t\t\t// open the popup on the map\r\n\t\t\tthis._map.openPopup(this._popup, latlng);\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method closePopup(): this\r\n\t// Closes the popup bound to this layer if it is open.\r\n\tclosePopup: function () {\r\n\t\tif (this._popup) {\r\n\t\t\tthis._popup._close();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method togglePopup(): this\r\n\t// Opens or closes the popup bound to this layer depending on its current state.\r\n\ttogglePopup: function (target) {\r\n\t\tif (this._popup) {\r\n\t\t\tif (this._popup._map) {\r\n\t\t\t\tthis.closePopup();\r\n\t\t\t} else {\r\n\t\t\t\tthis.openPopup(target);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method isPopupOpen(): boolean\r\n\t// Returns `true` if the popup bound to this layer is currently open.\r\n\tisPopupOpen: function () {\r\n\t\treturn (this._popup ? this._popup.isOpen() : false);\r\n\t},\r\n\r\n\t// @method setPopupContent(content: String|HTMLElement|Popup): this\r\n\t// Sets the content of the popup bound to this layer.\r\n\tsetPopupContent: function (content) {\r\n\t\tif (this._popup) {\r\n\t\t\tthis._popup.setContent(content);\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method getPopup(): Popup\r\n\t// Returns the popup bound to this layer.\r\n\tgetPopup: function () {\r\n\t\treturn this._popup;\r\n\t},\r\n\r\n\t_openPopup: function (e) {\r\n\t\tvar layer = e.layer || e.target;\r\n\r\n\t\tif (!this._popup) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!this._map) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// prevent map click\r\n\t\tstop(e);\r\n\r\n\t\t// if this inherits from Path its a vector and we can just\r\n\t\t// open the popup at the new location\r\n\t\tif (layer instanceof Path) {\r\n\t\t\tthis.openPopup(e.layer || e.target, e.latlng);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// otherwise treat it like a marker and figure out\r\n\t\t// if we should toggle it open/closed\r\n\t\tif (this._map.hasLayer(this._popup) && this._popup._source === layer) {\r\n\t\t\tthis.closePopup();\r\n\t\t} else {\r\n\t\t\tthis.openPopup(layer, e.latlng);\r\n\t\t}\r\n\t},\r\n\r\n\t_movePopup: function (e) {\r\n\t\tthis._popup.setLatLng(e.latlng);\r\n\t},\r\n\r\n\t_onKeyPress: function (e) {\r\n\t\tif (e.originalEvent.keyCode === 13) {\r\n\t\t\tthis._openPopup(e);\r\n\t\t}\r\n\t}\r\n});\n\n/*\n * @class Tooltip\n * @inherits DivOverlay\n * @aka L.Tooltip\n * Used to display small texts on top of map layers.\n *\n * @example\n *\n * ```js\n * marker.bindTooltip(\"my tooltip text\").openTooltip();\n * ```\n * Note about tooltip offset. Leaflet takes two options in consideration\n * for computing tooltip offsetting:\n * - the `offset` Tooltip option: it defaults to [0, 0], and it's specific to one tooltip.\n * Add a positive x offset to move the tooltip to the right, and a positive y offset to\n * move it to the bottom. Negatives will move to the left and top.\n * - the `tooltipAnchor` Icon option: this will only be considered for Marker. You\n * should adapt this value if you use a custom icon.\n */\n\n\n// @namespace Tooltip\nvar Tooltip = DivOverlay.extend({\n\n\t// @section\n\t// @aka Tooltip options\n\toptions: {\n\t\t// @option pane: String = 'tooltipPane'\n\t\t// `Map pane` where the tooltip will be added.\n\t\tpane: 'tooltipPane',\n\n\t\t// @option offset: Point = Point(0, 0)\n\t\t// Optional offset of the tooltip position.\n\t\toffset: [0, 0],\n\n\t\t// @option direction: String = 'auto'\n\t\t// Direction where to open the tooltip. Possible values are: `right`, `left`,\n\t\t// `top`, `bottom`, `center`, `auto`.\n\t\t// `auto` will dynamically switch between `right` and `left` according to the tooltip\n\t\t// position on the map.\n\t\tdirection: 'auto',\n\n\t\t// @option permanent: Boolean = false\n\t\t// Whether to open the tooltip permanently or only on mouseover.\n\t\tpermanent: false,\n\n\t\t// @option sticky: Boolean = false\n\t\t// If true, the tooltip will follow the mouse instead of being fixed at the feature center.\n\t\tsticky: false,\n\n\t\t// @option interactive: Boolean = false\n\t\t// If true, the tooltip will listen to the feature events.\n\t\tinteractive: false,\n\n\t\t// @option opacity: Number = 0.9\n\t\t// Tooltip container opacity.\n\t\topacity: 0.9\n\t},\n\n\tonAdd: function (map) {\n\t\tDivOverlay.prototype.onAdd.call(this, map);\n\t\tthis.setOpacity(this.options.opacity);\n\n\t\t// @namespace Map\n\t\t// @section Tooltip events\n\t\t// @event tooltipopen: TooltipEvent\n\t\t// Fired when a tooltip is opened in the map.\n\t\tmap.fire('tooltipopen', {tooltip: this});\n\n\t\tif (this._source) {\n\t\t\t// @namespace Layer\n\t\t\t// @section Tooltip events\n\t\t\t// @event tooltipopen: TooltipEvent\n\t\t\t// Fired when a tooltip bound to this layer is opened.\n\t\t\tthis._source.fire('tooltipopen', {tooltip: this}, true);\n\t\t}\n\t},\n\n\tonRemove: function (map) {\n\t\tDivOverlay.prototype.onRemove.call(this, map);\n\n\t\t// @namespace Map\n\t\t// @section Tooltip events\n\t\t// @event tooltipclose: TooltipEvent\n\t\t// Fired when a tooltip in the map is closed.\n\t\tmap.fire('tooltipclose', {tooltip: this});\n\n\t\tif (this._source) {\n\t\t\t// @namespace Layer\n\t\t\t// @section Tooltip events\n\t\t\t// @event tooltipclose: TooltipEvent\n\t\t\t// Fired when a tooltip bound to this layer is closed.\n\t\t\tthis._source.fire('tooltipclose', {tooltip: this}, true);\n\t\t}\n\t},\n\n\tgetEvents: function () {\n\t\tvar events = DivOverlay.prototype.getEvents.call(this);\n\n\t\tif (touch && !this.options.permanent) {\n\t\t\tevents.preclick = this._close;\n\t\t}\n\n\t\treturn events;\n\t},\n\n\t_close: function () {\n\t\tif (this._map) {\n\t\t\tthis._map.closeTooltip(this);\n\t\t}\n\t},\n\n\t_initLayout: function () {\n\t\tvar prefix = 'leaflet-tooltip',\n\t\t className = prefix + ' ' + (this.options.className || '') + ' leaflet-zoom-' + (this._zoomAnimated ? 'animated' : 'hide');\n\n\t\tthis._contentNode = this._container = create$1('div', className);\n\t},\n\n\t_updateLayout: function () {},\n\n\t_adjustPan: function () {},\n\n\t_setPosition: function (pos) {\n\t\tvar map = this._map,\n\t\t container = this._container,\n\t\t centerPoint = map.latLngToContainerPoint(map.getCenter()),\n\t\t tooltipPoint = map.layerPointToContainerPoint(pos),\n\t\t direction = this.options.direction,\n\t\t tooltipWidth = container.offsetWidth,\n\t\t tooltipHeight = container.offsetHeight,\n\t\t offset = toPoint(this.options.offset),\n\t\t anchor = this._getAnchor();\n\n\t\tif (direction === 'top') {\n\t\t\tpos = pos.add(toPoint(-tooltipWidth / 2 + offset.x, -tooltipHeight + offset.y + anchor.y, true));\n\t\t} else if (direction === 'bottom') {\n\t\t\tpos = pos.subtract(toPoint(tooltipWidth / 2 - offset.x, -offset.y, true));\n\t\t} else if (direction === 'center') {\n\t\t\tpos = pos.subtract(toPoint(tooltipWidth / 2 + offset.x, tooltipHeight / 2 - anchor.y + offset.y, true));\n\t\t} else if (direction === 'right' || direction === 'auto' && tooltipPoint.x < centerPoint.x) {\n\t\t\tdirection = 'right';\n\t\t\tpos = pos.add(toPoint(offset.x + anchor.x, anchor.y - tooltipHeight / 2 + offset.y, true));\n\t\t} else {\n\t\t\tdirection = 'left';\n\t\t\tpos = pos.subtract(toPoint(tooltipWidth + anchor.x - offset.x, tooltipHeight / 2 - anchor.y - offset.y, true));\n\t\t}\n\n\t\tremoveClass(container, 'leaflet-tooltip-right');\n\t\tremoveClass(container, 'leaflet-tooltip-left');\n\t\tremoveClass(container, 'leaflet-tooltip-top');\n\t\tremoveClass(container, 'leaflet-tooltip-bottom');\n\t\taddClass(container, 'leaflet-tooltip-' + direction);\n\t\tsetPosition(container, pos);\n\t},\n\n\t_updatePosition: function () {\n\t\tvar pos = this._map.latLngToLayerPoint(this._latlng);\n\t\tthis._setPosition(pos);\n\t},\n\n\tsetOpacity: function (opacity) {\n\t\tthis.options.opacity = opacity;\n\n\t\tif (this._container) {\n\t\t\tsetOpacity(this._container, opacity);\n\t\t}\n\t},\n\n\t_animateZoom: function (e) {\n\t\tvar pos = this._map._latLngToNewLayerPoint(this._latlng, e.zoom, e.center);\n\t\tthis._setPosition(pos);\n\t},\n\n\t_getAnchor: function () {\n\t\t// Where should we anchor the tooltip on the source layer?\n\t\treturn toPoint(this._source && this._source._getTooltipAnchor && !this.options.sticky ? this._source._getTooltipAnchor() : [0, 0]);\n\t}\n\n});\n\n// @namespace Tooltip\n// @factory L.tooltip(options?: Tooltip options, source?: Layer)\n// Instantiates a Tooltip object given an optional `options` object that describes its appearance and location and an optional `source` object that is used to tag the tooltip with a reference to the Layer to which it refers.\nvar tooltip = function (options, source) {\n\treturn new Tooltip(options, source);\n};\n\n// @namespace Map\n// @section Methods for Layers and Controls\nMap.include({\n\n\t// @method openTooltip(tooltip: Tooltip): this\n\t// Opens the specified tooltip.\n\t// @alternative\n\t// @method openTooltip(content: String|HTMLElement, latlng: LatLng, options?: Tooltip options): this\n\t// Creates a tooltip with the specified content and options and open it.\n\topenTooltip: function (tooltip, latlng, options) {\n\t\tif (!(tooltip instanceof Tooltip)) {\n\t\t\ttooltip = new Tooltip(options).setContent(tooltip);\n\t\t}\n\n\t\tif (latlng) {\n\t\t\ttooltip.setLatLng(latlng);\n\t\t}\n\n\t\tif (this.hasLayer(tooltip)) {\n\t\t\treturn this;\n\t\t}\n\n\t\treturn this.addLayer(tooltip);\n\t},\n\n\t// @method closeTooltip(tooltip?: Tooltip): this\n\t// Closes the tooltip given as parameter.\n\tcloseTooltip: function (tooltip) {\n\t\tif (tooltip) {\n\t\t\tthis.removeLayer(tooltip);\n\t\t}\n\t\treturn this;\n\t}\n\n});\n\n/*\n * @namespace Layer\n * @section Tooltip methods example\n *\n * All layers share a set of methods convenient for binding tooltips to it.\n *\n * ```js\n * var layer = L.Polygon(latlngs).bindTooltip('Hi There!').addTo(map);\n * layer.openTooltip();\n * layer.closeTooltip();\n * ```\n */\n\n// @section Tooltip methods\nLayer.include({\n\n\t// @method bindTooltip(content: String|HTMLElement|Function|Tooltip, options?: Tooltip options): this\n\t// Binds a tooltip to the layer with the passed `content` and sets up the\n\t// necessary event listeners. If a `Function` is passed it will receive\n\t// the layer as the first argument and should return a `String` or `HTMLElement`.\n\tbindTooltip: function (content, options) {\n\n\t\tif (content instanceof Tooltip) {\n\t\t\tsetOptions(content, options);\n\t\t\tthis._tooltip = content;\n\t\t\tcontent._source = this;\n\t\t} else {\n\t\t\tif (!this._tooltip || options) {\n\t\t\t\tthis._tooltip = new Tooltip(options, this);\n\t\t\t}\n\t\t\tthis._tooltip.setContent(content);\n\n\t\t}\n\n\t\tthis._initTooltipInteractions();\n\n\t\tif (this._tooltip.options.permanent && this._map && this._map.hasLayer(this)) {\n\t\t\tthis.openTooltip();\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t// @method unbindTooltip(): this\n\t// Removes the tooltip previously bound with `bindTooltip`.\n\tunbindTooltip: function () {\n\t\tif (this._tooltip) {\n\t\t\tthis._initTooltipInteractions(true);\n\t\t\tthis.closeTooltip();\n\t\t\tthis._tooltip = null;\n\t\t}\n\t\treturn this;\n\t},\n\n\t_initTooltipInteractions: function (remove$$1) {\n\t\tif (!remove$$1 && this._tooltipHandlersAdded) { return; }\n\t\tvar onOff = remove$$1 ? 'off' : 'on',\n\t\t events = {\n\t\t\tremove: this.closeTooltip,\n\t\t\tmove: this._moveTooltip\n\t\t };\n\t\tif (!this._tooltip.options.permanent) {\n\t\t\tevents.mouseover = this._openTooltip;\n\t\t\tevents.mouseout = this.closeTooltip;\n\t\t\tif (this._tooltip.options.sticky) {\n\t\t\t\tevents.mousemove = this._moveTooltip;\n\t\t\t}\n\t\t\tif (touch) {\n\t\t\t\tevents.click = this._openTooltip;\n\t\t\t}\n\t\t} else {\n\t\t\tevents.add = this._openTooltip;\n\t\t}\n\t\tthis[onOff](events);\n\t\tthis._tooltipHandlersAdded = !remove$$1;\n\t},\n\n\t// @method openTooltip(latlng?: LatLng): this\n\t// Opens the bound tooltip at the specified `latlng` or at the default tooltip anchor if no `latlng` is passed.\n\topenTooltip: function (layer, latlng) {\n\t\tif (this._tooltip && this._map) {\n\t\t\tlatlng = this._tooltip._prepareOpen(this, layer, latlng);\n\n\t\t\t// open the tooltip on the map\n\t\t\tthis._map.openTooltip(this._tooltip, latlng);\n\n\t\t\t// Tooltip container may not be defined if not permanent and never\n\t\t\t// opened.\n\t\t\tif (this._tooltip.options.interactive && this._tooltip._container) {\n\t\t\t\taddClass(this._tooltip._container, 'leaflet-clickable');\n\t\t\t\tthis.addInteractiveTarget(this._tooltip._container);\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\t// @method closeTooltip(): this\n\t// Closes the tooltip bound to this layer if it is open.\n\tcloseTooltip: function () {\n\t\tif (this._tooltip) {\n\t\t\tthis._tooltip._close();\n\t\t\tif (this._tooltip.options.interactive && this._tooltip._container) {\n\t\t\t\tremoveClass(this._tooltip._container, 'leaflet-clickable');\n\t\t\t\tthis.removeInteractiveTarget(this._tooltip._container);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method toggleTooltip(): this\n\t// Opens or closes the tooltip bound to this layer depending on its current state.\n\ttoggleTooltip: function (target) {\n\t\tif (this._tooltip) {\n\t\t\tif (this._tooltip._map) {\n\t\t\t\tthis.closeTooltip();\n\t\t\t} else {\n\t\t\t\tthis.openTooltip(target);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method isTooltipOpen(): boolean\n\t// Returns `true` if the tooltip bound to this layer is currently open.\n\tisTooltipOpen: function () {\n\t\treturn this._tooltip.isOpen();\n\t},\n\n\t// @method setTooltipContent(content: String|HTMLElement|Tooltip): this\n\t// Sets the content of the tooltip bound to this layer.\n\tsetTooltipContent: function (content) {\n\t\tif (this._tooltip) {\n\t\t\tthis._tooltip.setContent(content);\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method getTooltip(): Tooltip\n\t// Returns the tooltip bound to this layer.\n\tgetTooltip: function () {\n\t\treturn this._tooltip;\n\t},\n\n\t_openTooltip: function (e) {\n\t\tvar layer = e.layer || e.target;\n\n\t\tif (!this._tooltip || !this._map) {\n\t\t\treturn;\n\t\t}\n\t\tthis.openTooltip(layer, this._tooltip.options.sticky ? e.latlng : undefined);\n\t},\n\n\t_moveTooltip: function (e) {\n\t\tvar latlng = e.latlng, containerPoint, layerPoint;\n\t\tif (this._tooltip.options.sticky && e.originalEvent) {\n\t\t\tcontainerPoint = this._map.mouseEventToContainerPoint(e.originalEvent);\n\t\t\tlayerPoint = this._map.containerPointToLayerPoint(containerPoint);\n\t\t\tlatlng = this._map.layerPointToLatLng(layerPoint);\n\t\t}\n\t\tthis._tooltip.setLatLng(latlng);\n\t}\n});\n\n/*\n * @class DivIcon\n * @aka L.DivIcon\n * @inherits Icon\n *\n * Represents a lightweight icon for markers that uses a simple `<div>`\n * element instead of an image. Inherits from `Icon` but ignores the `iconUrl` and shadow options.\n *\n * @example\n * ```js\n * var myIcon = L.divIcon({className: 'my-div-icon'});\n * // you can set .my-div-icon styles in CSS\n *\n * L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);\n * ```\n *\n * By default, it has a 'leaflet-div-icon' CSS class and is styled as a little white square with a shadow.\n */\n\nvar DivIcon = Icon.extend({\n\toptions: {\n\t\t// @section\n\t\t// @aka DivIcon options\n\t\ticonSize: [12, 12], // also can be set through CSS\n\n\t\t// iconAnchor: (Point),\n\t\t// popupAnchor: (Point),\n\n\t\t// @option html: String|HTMLElement = ''\n\t\t// Custom HTML code to put inside the div element, empty by default. Alternatively,\n\t\t// an instance of `HTMLElement`.\n\t\thtml: false,\n\n\t\t// @option bgPos: Point = [0, 0]\n\t\t// Optional relative position of the background, in pixels\n\t\tbgPos: null,\n\n\t\tclassName: 'leaflet-div-icon'\n\t},\n\n\tcreateIcon: function (oldIcon) {\n\t\tvar div = (oldIcon && oldIcon.tagName === 'DIV') ? oldIcon : document.createElement('div'),\n\t\t options = this.options;\n\n\t\tif (options.html instanceof Element) {\n\t\t\tempty(div);\n\t\t\tdiv.appendChild(options.html);\n\t\t} else {\n\t\t\tdiv.innerHTML = options.html !== false ? options.html : '';\n\t\t}\n\n\t\tif (options.bgPos) {\n\t\t\tvar bgPos = toPoint(options.bgPos);\n\t\t\tdiv.style.backgroundPosition = (-bgPos.x) + 'px ' + (-bgPos.y) + 'px';\n\t\t}\n\t\tthis._setIconStyles(div, 'icon');\n\n\t\treturn div;\n\t},\n\n\tcreateShadow: function () {\n\t\treturn null;\n\t}\n});\n\n// @factory L.divIcon(options: DivIcon options)\n// Creates a `DivIcon` instance with the given options.\nfunction divIcon(options) {\n\treturn new DivIcon(options);\n}\n\nIcon.Default = IconDefault;\n\n/*\n * @class GridLayer\n * @inherits Layer\n * @aka L.GridLayer\n *\n * Generic class for handling a tiled grid of HTML elements. This is the base class for all tile layers and replaces `TileLayer.Canvas`.\n * GridLayer can be extended to create a tiled grid of HTML elements like `<canvas>`, `<img>` or `<div>`. GridLayer will handle creating and animating these DOM elements for you.\n *\n *\n * @section Synchronous usage\n * @example\n *\n * To create a custom layer, extend GridLayer and implement the `createTile()` method, which will be passed a `Point` object with the `x`, `y`, and `z` (zoom level) coordinates to draw your tile.\n *\n * ```js\n * var CanvasLayer = L.GridLayer.extend({\n * createTile: function(coords){\n * // create a <canvas> element for drawing\n * var tile = L.DomUtil.create('canvas', 'leaflet-tile');\n *\n * // setup tile width and height according to the options\n * var size = this.getTileSize();\n * tile.width = size.x;\n * tile.height = size.y;\n *\n * // get a canvas context and draw something on it using coords.x, coords.y and coords.z\n * var ctx = tile.getContext('2d');\n *\n * // return the tile so it can be rendered on screen\n * return tile;\n * }\n * });\n * ```\n *\n * @section Asynchronous usage\n * @example\n *\n * Tile creation can also be asynchronous, this is useful when using a third-party drawing library. Once the tile is finished drawing it can be passed to the `done()` callback.\n *\n * ```js\n * var CanvasLayer = L.GridLayer.extend({\n * createTile: function(coords, done){\n * var error;\n *\n * // create a <canvas> element for drawing\n * var tile = L.DomUtil.create('canvas', 'leaflet-tile');\n *\n * // setup tile width and height according to the options\n * var size = this.getTileSize();\n * tile.width = size.x;\n * tile.height = size.y;\n *\n * // draw something asynchronously and pass the tile to the done() callback\n * setTimeout(function() {\n * done(error, tile);\n * }, 1000);\n *\n * return tile;\n * }\n * });\n * ```\n *\n * @section\n */\n\n\nvar GridLayer = Layer.extend({\n\n\t// @section\n\t// @aka GridLayer options\n\toptions: {\n\t\t// @option tileSize: Number|Point = 256\n\t\t// Width and height of tiles in the grid. Use a number if width and height are equal, or `L.point(width, height)` otherwise.\n\t\ttileSize: 256,\n\n\t\t// @option opacity: Number = 1.0\n\t\t// Opacity of the tiles. Can be used in the `createTile()` function.\n\t\topacity: 1,\n\n\t\t// @option updateWhenIdle: Boolean = (depends)\n\t\t// Load new tiles only when panning ends.\n\t\t// `true` by default on mobile browsers, in order to avoid too many requests and keep smooth navigation.\n\t\t// `false` otherwise in order to display new tiles _during_ panning, since it is easy to pan outside the\n\t\t// [`keepBuffer`](#gridlayer-keepbuffer) option in desktop browsers.\n\t\tupdateWhenIdle: mobile,\n\n\t\t// @option updateWhenZooming: Boolean = true\n\t\t// By default, a smooth zoom animation (during a [touch zoom](#map-touchzoom) or a [`flyTo()`](#map-flyto)) will update grid layers every integer zoom level. Setting this option to `false` will update the grid layer only when the smooth animation ends.\n\t\tupdateWhenZooming: true,\n\n\t\t// @option updateInterval: Number = 200\n\t\t// Tiles will not update more than once every `updateInterval` milliseconds when panning.\n\t\tupdateInterval: 200,\n\n\t\t// @option zIndex: Number = 1\n\t\t// The explicit zIndex of the tile layer.\n\t\tzIndex: 1,\n\n\t\t// @option bounds: LatLngBounds = undefined\n\t\t// If set, tiles will only be loaded inside the set `LatLngBounds`.\n\t\tbounds: null,\n\n\t\t// @option minZoom: Number = 0\n\t\t// The minimum zoom level down to which this layer will be displayed (inclusive).\n\t\tminZoom: 0,\n\n\t\t// @option maxZoom: Number = undefined\n\t\t// The maximum zoom level up to which this layer will be displayed (inclusive).\n\t\tmaxZoom: undefined,\n\n\t\t// @option maxNativeZoom: Number = undefined\n\t\t// Maximum zoom number the tile source has available. If it is specified,\n\t\t// the tiles on all zoom levels higher than `maxNativeZoom` will be loaded\n\t\t// from `maxNativeZoom` level and auto-scaled.\n\t\tmaxNativeZoom: undefined,\n\n\t\t// @option minNativeZoom: Number = undefined\n\t\t// Minimum zoom number the tile source has available. If it is specified,\n\t\t// the tiles on all zoom levels lower than `minNativeZoom` will be loaded\n\t\t// from `minNativeZoom` level and auto-scaled.\n\t\tminNativeZoom: undefined,\n\n\t\t// @option noWrap: Boolean = false\n\t\t// Whether the layer is wrapped around the antimeridian. If `true`, the\n\t\t// GridLayer will only be displayed once at low zoom levels. Has no\n\t\t// effect when the [map CRS](#map-crs) doesn't wrap around. Can be used\n\t\t// in combination with [`bounds`](#gridlayer-bounds) to prevent requesting\n\t\t// tiles outside the CRS limits.\n\t\tnoWrap: false,\n\n\t\t// @option pane: String = 'tilePane'\n\t\t// `Map pane` where the grid layer will be added.\n\t\tpane: 'tilePane',\n\n\t\t// @option className: String = ''\n\t\t// A custom class name to assign to the tile layer. Empty by default.\n\t\tclassName: '',\n\n\t\t// @option keepBuffer: Number = 2\n\t\t// When panning the map, keep this many rows and columns of tiles before unloading them.\n\t\tkeepBuffer: 2\n\t},\n\n\tinitialize: function (options) {\n\t\tsetOptions(this, options);\n\t},\n\n\tonAdd: function () {\n\t\tthis._initContainer();\n\n\t\tthis._levels = {};\n\t\tthis._tiles = {};\n\n\t\tthis._resetView();\n\t\tthis._update();\n\t},\n\n\tbeforeAdd: function (map) {\n\t\tmap._addZoomLimit(this);\n\t},\n\n\tonRemove: function (map) {\n\t\tthis._removeAllTiles();\n\t\tremove(this._container);\n\t\tmap._removeZoomLimit(this);\n\t\tthis._container = null;\n\t\tthis._tileZoom = undefined;\n\t},\n\n\t// @method bringToFront: this\n\t// Brings the tile layer to the top of all tile layers.\n\tbringToFront: function () {\n\t\tif (this._map) {\n\t\t\ttoFront(this._container);\n\t\t\tthis._setAutoZIndex(Math.max);\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method bringToBack: this\n\t// Brings the tile layer to the bottom of all tile layers.\n\tbringToBack: function () {\n\t\tif (this._map) {\n\t\t\ttoBack(this._container);\n\t\t\tthis._setAutoZIndex(Math.min);\n\t\t}\n\t\treturn this;\n\t},\n\n\t// @method getContainer: HTMLElement\n\t// Returns the HTML element that contains the tiles for this layer.\n\tgetContainer: function () {\n\t\treturn this._container;\n\t},\n\n\t// @method setOpacity(opacity: Number): this\n\t// Changes the [opacity](#gridlayer-opacity) of the grid layer.\n\tsetOpacity: function (opacity) {\n\t\tthis.options.opacity = opacity;\n\t\tthis._updateOpacity();\n\t\treturn this;\n\t},\n\n\t// @method setZIndex(zIndex: Number): this\n\t// Changes the [zIndex](#gridlayer-zindex) of the grid layer.\n\tsetZIndex: function (zIndex) {\n\t\tthis.options.zIndex = zIndex;\n\t\tthis._updateZIndex();\n\n\t\treturn this;\n\t},\n\n\t// @method isLoading: Boolean\n\t// Returns `true` if any tile in the grid layer has not finished loading.\n\tisLoading: function () {\n\t\treturn this._loading;\n\t},\n\n\t// @method redraw: this\n\t// Causes the layer to clear all the tiles and request them again.\n\tredraw: function () {\n\t\tif (this._map) {\n\t\t\tthis._removeAllTiles();\n\t\t\tthis._update();\n\t\t}\n\t\treturn this;\n\t},\n\n\tgetEvents: function () {\n\t\tvar events = {\n\t\t\tviewprereset: this._invalidateAll,\n\t\t\tviewreset: this._resetView,\n\t\t\tzoom: this._resetView,\n\t\t\tmoveend: this._onMoveEnd\n\t\t};\n\n\t\tif (!this.options.updateWhenIdle) {\n\t\t\t// update tiles on move, but not more often than once per given interval\n\t\t\tif (!this._onMove) {\n\t\t\t\tthis._onMove = throttle(this._onMoveEnd, this.options.updateInterval, this);\n\t\t\t}\n\n\t\t\tevents.move = this._onMove;\n\t\t}\n\n\t\tif (this._zoomAnimated) {\n\t\t\tevents.zoomanim = this._animateZoom;\n\t\t}\n\n\t\treturn events;\n\t},\n\n\t// @section Extension methods\n\t// Layers extending `GridLayer` shall reimplement the following method.\n\t// @method createTile(coords: Object, done?: Function): HTMLElement\n\t// Called only internally, must be overridden by classes extending `GridLayer`.\n\t// Returns the `HTMLElement` corresponding to the given `coords`. If the `done` callback\n\t// is specified, it must be called when the tile has finished loading and drawing.\n\tcreateTile: function () {\n\t\treturn document.createElement('div');\n\t},\n\n\t// @section\n\t// @method getTileSize: Point\n\t// Normalizes the [tileSize option](#gridlayer-tilesize) into a point. Used by the `createTile()` method.\n\tgetTileSize: function () {\n\t\tvar s = this.options.tileSize;\n\t\treturn s instanceof Point ? s : new Point(s, s);\n\t},\n\n\t_updateZIndex: function () {\n\t\tif (this._container && this.options.zIndex !== undefined && this.options.zIndex !== null) {\n\t\t\tthis._container.style.zIndex = this.options.zIndex;\n\t\t}\n\t},\n\n\t_setAutoZIndex: function (compare) {\n\t\t// go through all other layers of the same pane, set zIndex to max + 1 (front) or min - 1 (back)\n\n\t\tvar layers = this.getPane().children,\n\t\t edgeZIndex = -compare(-Infinity, Infinity); // -Infinity for max, Infinity for min\n\n\t\tfor (var i = 0, len = layers.length, zIndex; i < len; i++) {\n\n\t\t\tzIndex = layers[i].style.zIndex;\n\n\t\t\tif (layers[i] !== this._container && zIndex) {\n\t\t\t\tedgeZIndex = compare(edgeZIndex, +zIndex);\n\t\t\t}\n\t\t}\n\n\t\tif (isFinite(edgeZIndex)) {\n\t\t\tthis.options.zIndex = edgeZIndex + compare(-1, 1);\n\t\t\tthis._updateZIndex();\n\t\t}\n\t},\n\n\t_updateOpacity: function () {\n\t\tif (!this._map) { return; }\n\n\t\t// IE doesn't inherit filter opacity properly, so we're forced to set it on tiles\n\t\tif (ielt9) { return; }\n\n\t\tsetOpacity(this._container, this.options.opacity);\n\n\t\tvar now = +new Date(),\n\t\t nextFrame = false,\n\t\t willPrune = false;\n\n\t\tfor (var key in this._tiles) {\n\t\t\tvar tile = this._tiles[key];\n\t\t\tif (!tile.current || !tile.loaded) { continue; }\n\n\t\t\tvar fade = Math.min(1, (now - tile.loaded) / 200);\n\n\t\t\tsetOpacity(tile.el, fade);\n\t\t\tif (fade < 1) {\n\t\t\t\tnextFrame = true;\n\t\t\t} else {\n\t\t\t\tif (tile.active) {\n\t\t\t\t\twillPrune = true;\n\t\t\t\t} else {\n\t\t\t\t\tthis._onOpaqueTile(tile);\n\t\t\t\t}\n\t\t\t\ttile.active = true;\n\t\t\t}\n\t\t}\n\n\t\tif (willPrune && !this._noPrune) { this._pruneTiles(); }\n\n\t\tif (nextFrame) {\n\t\t\tcancelAnimFrame(this._fadeFrame);\n\t\t\tthis._fadeFrame = requestAnimFrame(this._updateOpacity, this);\n\t\t}\n\t},\n\n\t_onOpaqueTile: falseFn,\n\n\t_initContainer: function () {\n\t\tif (this._container) { return; }\n\n\t\tthis._container = create$1('div', 'leaflet-layer ' + (this.options.className || ''));\n\t\tthis._updateZIndex();\n\n\t\tif (this.options.opacity < 1) {\n\t\t\tthis._updateOpacity();\n\t\t}\n\n\t\tthis.getPane().appendChild(this._container);\n\t},\n\n\t_updateLevels: function () {\n\n\t\tvar zoom = this._tileZoom,\n\t\t maxZoom = this.options.maxZoom;\n\n\t\tif (zoom === undefined) { return undefined; }\n\n\t\tfor (var z in this._levels) {\n\t\t\tif (this._levels[z].el.children.length || z === zoom) {\n\t\t\t\tthis._levels[z].el.style.zIndex = maxZoom - Math.abs(zoom - z);\n\t\t\t\tthis._onUpdateLevel(z);\n\t\t\t} else {\n\t\t\t\tremove(this._levels[z].el);\n\t\t\t\tthis._removeTilesAtZoom(z);\n\t\t\t\tthis._onRemoveLevel(z);\n\t\t\t\tdelete this._levels[z];\n\t\t\t}\n\t\t}\n\n\t\tvar level = this._levels[zoom],\n\t\t map = this._map;\n\n\t\tif (!level) {\n\t\t\tlevel = this._levels[zoom] = {};\n\n\t\t\tlevel.el = create$1('div', 'leaflet-tile-container leaflet-zoom-animated', this._container);\n\t\t\tlevel.el.style.zIndex = maxZoom;\n\n\t\t\tlevel.origin = map.project(map.unproject(map.getPixelOrigin()), zoom).round();\n\t\t\tlevel.zoom = zoom;\n\n\t\t\tthis._setZoomTransform(level, map.getCenter(), map.getZoom());\n\n\t\t\t// force the browser to consider the newly added element for transition\n\t\t\tfalseFn(level.el.offsetWidth);\n\n\t\t\tthis._onCreateLevel(level);\n\t\t}\n\n\t\tthis._level = level;\n\n\t\treturn level;\n\t},\n\n\t_onUpdateLevel: falseFn,\n\n\t_onRemoveLevel: falseFn,\n\n\t_onCreateLevel: falseFn,\n\n\t_pruneTiles: function () {\n\t\tif (!this._map) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar key, tile;\n\n\t\tvar zoom = this._map.getZoom();\n\t\tif (zoom > this.options.maxZoom ||\n\t\t\tzoom < this.options.minZoom) {\n\t\t\tthis._removeAllTiles();\n\t\t\treturn;\n\t\t}\n\n\t\tfor (key in this._tiles) {\n\t\t\ttile = this._tiles[key];\n\t\t\ttile.retain = tile.current;\n\t\t}\n\n\t\tfor (key in this._tiles) {\n\t\t\ttile = this._tiles[key];\n\t\t\tif (tile.current && !tile.active) {\n\t\t\t\tvar coords = tile.coords;\n\t\t\t\tif (!this._retainParent(coords.x, coords.y, coords.z, coords.z - 5)) {\n\t\t\t\t\tthis._retainChildren(coords.x, coords.y, coords.z, coords.z + 2);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (key in this._tiles) {\n\t\t\tif (!this._tiles[key].retain) {\n\t\t\t\tthis._removeTile(key);\n\t\t\t}\n\t\t}\n\t},\n\n\t_removeTilesAtZoom: function (zoom) {\n\t\tfor (var key in this._tiles) {\n\t\t\tif (this._tiles[key].coords.z !== zoom) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthis._removeTile(key);\n\t\t}\n\t},\n\n\t_removeAllTiles: function () {\n\t\tfor (var key in this._tiles) {\n\t\t\tthis._removeTile(key);\n\t\t}\n\t},\n\n\t_invalidateAll: function () {\n\t\tfor (var z in this._levels) {\n\t\t\tremove(this._levels[z].el);\n\t\t\tthis._onRemoveLevel(z);\n\t\t\tdelete this._levels[z];\n\t\t}\n\t\tthis._removeAllTiles();\n\n\t\tthis._tileZoom = undefined;\n\t},\n\n\t_retainParent: function (x, y, z, minZoom) {\n\t\tvar x2 = Math.floor(x / 2),\n\t\t y2 = Math.floor(y / 2),\n\t\t z2 = z - 1,\n\t\t coords2 = new Point(+x2, +y2);\n\t\tcoords2.z = +z2;\n\n\t\tvar key = this._tileCoordsToKey(coords2),\n\t\t tile = this._tiles[key];\n\n\t\tif (tile && tile.active) {\n\t\t\ttile.retain = true;\n\t\t\treturn true;\n\n\t\t} else if (tile && tile.loaded) {\n\t\t\ttile.retain = true;\n\t\t}\n\n\t\tif (z2 > minZoom) {\n\t\t\treturn this._retainParent(x2, y2, z2, minZoom);\n\t\t}\n\n\t\treturn false;\n\t},\n\n\t_retainChildren: function (x, y, z, maxZoom) {\n\n\t\tfor (var i = 2 * x; i < 2 * x + 2; i++) {\n\t\t\tfor (var j = 2 * y; j < 2 * y + 2; j++) {\n\n\t\t\t\tvar coords = new Point(i, j);\n\t\t\t\tcoords.z = z + 1;\n\n\t\t\t\tvar key = this._tileCoordsToKey(coords),\n\t\t\t\t tile = this._tiles[key];\n\n\t\t\t\tif (tile && tile.active) {\n\t\t\t\t\ttile.retain = true;\n\t\t\t\t\tcontinue;\n\n\t\t\t\t} else if (tile && tile.loaded) {\n\t\t\t\t\ttile.retain = true;\n\t\t\t\t}\n\n\t\t\t\tif (z + 1 < maxZoom) {\n\t\t\t\t\tthis._retainChildren(i, j, z + 1, maxZoom);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t_resetView: function (e) {\n\t\tvar animating = e && (e.pinch || e.flyTo);\n\t\tthis._setView(this._map.getCenter(), this._map.getZoom(), animating, animating);\n\t},\n\n\t_animateZoom: function (e) {\n\t\tthis._setView(e.center, e.zoom, true, e.noUpdate);\n\t},\n\n\t_clampZoom: function (zoom) {\n\t\tvar options = this.options;\n\n\t\tif (undefined !== options.minNativeZoom && zoom < options.minNativeZoom) {\n\t\t\treturn options.minNativeZoom;\n\t\t}\n\n\t\tif (undefined !== options.maxNativeZoom && options.maxNativeZoom < zoom) {\n\t\t\treturn options.maxNativeZoom;\n\t\t}\n\n\t\treturn zoom;\n\t},\n\n\t_setView: function (center, zoom, noPrune, noUpdate) {\n\t\tvar tileZoom = this._clampZoom(Math.round(zoom));\n\t\tif ((this.options.maxZoom !== undefined && tileZoom > this.options.maxZoom) ||\n\t\t (this.options.minZoom !== undefined && tileZoom < this.options.minZoom)) {\n\t\t\ttileZoom = undefined;\n\t\t}\n\n\t\tvar tileZoomChanged = this.options.updateWhenZooming && (tileZoom !== this._tileZoom);\n\n\t\tif (!noUpdate || tileZoomChanged) {\n\n\t\t\tthis._tileZoom = tileZoom;\n\n\t\t\tif (this._abortLoading) {\n\t\t\t\tthis._abortLoading();\n\t\t\t}\n\n\t\t\tthis._updateLevels();\n\t\t\tthis._resetGrid();\n\n\t\t\tif (tileZoom !== undefined) {\n\t\t\t\tthis._update(center);\n\t\t\t}\n\n\t\t\tif (!noPrune) {\n\t\t\t\tthis._pruneTiles();\n\t\t\t}\n\n\t\t\t// Flag to prevent _updateOpacity from pruning tiles during\n\t\t\t// a zoom anim or a pinch gesture\n\t\t\tthis._noPrune = !!noPrune;\n\t\t}\n\n\t\tthis._setZoomTransforms(center, zoom);\n\t},\n\n\t_setZoomTransforms: function (center, zoom) {\n\t\tfor (var i in this._levels) {\n\t\t\tthis._setZoomTransform(this._levels[i], center, zoom);\n\t\t}\n\t},\n\n\t_setZoomTransform: function (level, center, zoom) {\n\t\tvar scale = this._map.getZoomScale(zoom, level.zoom),\n\t\t translate = level.origin.multiplyBy(scale)\n\t\t .subtract(this._map._getNewPixelOrigin(center, zoom)).round();\n\n\t\tif (any3d) {\n\t\t\tsetTransform(level.el, translate, scale);\n\t\t} else {\n\t\t\tsetPosition(level.el, translate);\n\t\t}\n\t},\n\n\t_resetGrid: function () {\n\t\tvar map = this._map,\n\t\t crs = map.options.crs,\n\t\t tileSize = this._tileSize = this.getTileSize(),\n\t\t tileZoom = this._tileZoom;\n\n\t\tvar bounds = this._map.getPixelWorldBounds(this._tileZoom);\n\t\tif (bounds) {\n\t\t\tthis._globalTileRange = this._pxBoundsToTileRange(bounds);\n\t\t}\n\n\t\tthis._wrapX = crs.wrapLng && !this.options.noWrap && [\n\t\t\tMath.floor(map.project([0, crs.wrapLng[0]], tileZoom).x / tileSize.x),\n\t\t\tMath.ceil(map.project([0, crs.wrapLng[1]], tileZoom).x / tileSize.y)\n\t\t];\n\t\tthis._wrapY = crs.wrapLat && !this.options.noWrap && [\n\t\t\tMath.floor(map.project([crs.wrapLat[0], 0], tileZoom).y / tileSize.x),\n\t\t\tMath.ceil(map.project([crs.wrapLat[1], 0], tileZoom).y / tileSize.y)\n\t\t];\n\t},\n\n\t_onMoveEnd: function () {\n\t\tif (!this._map || this._map._animatingZoom) { return; }\n\n\t\tthis._update();\n\t},\n\n\t_getTiledPixelBounds: function (center) {\n\t\tvar map = this._map,\n\t\t mapZoom = map._animatingZoom ? Math.max(map._animateToZoom, map.getZoom()) : map.getZoom(),\n\t\t scale = map.getZoomScale(mapZoom, this._tileZoom),\n\t\t pixelCenter = map.project(center, this._tileZoom).floor(),\n\t\t halfSize = map.getSize().divideBy(scale * 2);\n\n\t\treturn new Bounds(pixelCenter.subtract(halfSize), pixelCenter.add(halfSize));\n\t},\n\n\t// Private method to load tiles in the grid's active zoom level according to map bounds\n\t_update: function (center) {\n\t\tvar map = this._map;\n\t\tif (!map) { return; }\n\t\tvar zoom = this._clampZoom(map.getZoom());\n\n\t\tif (center === undefined) { center = map.getCenter(); }\n\t\tif (this._tileZoom === undefined) { return; }\t// if out of minzoom/maxzoom\n\n\t\tvar pixelBounds = this._getTiledPixelBounds(center),\n\t\t tileRange = this._pxBoundsToTileRange(pixelBounds),\n\t\t tileCenter = tileRange.getCenter(),\n\t\t queue = [],\n\t\t margin = this.options.keepBuffer,\n\t\t noPruneRange = new Bounds(tileRange.getBottomLeft().subtract([margin, -margin]),\n\t\t tileRange.getTopRight().add([margin, -margin]));\n\n\t\t// Sanity check: panic if the tile range contains Infinity somewhere.\n\t\tif (!(isFinite(tileRange.min.x) &&\n\t\t isFinite(tileRange.min.y) &&\n\t\t isFinite(tileRange.max.x) &&\n\t\t isFinite(tileRange.max.y))) { throw new Error('Attempted to load an infinite number of tiles'); }\n\n\t\tfor (var key in this._tiles) {\n\t\t\tvar c = this._tiles[key].coords;\n\t\t\tif (c.z !== this._tileZoom || !noPruneRange.contains(new Point(c.x, c.y))) {\n\t\t\t\tthis._tiles[key].current = false;\n\t\t\t}\n\t\t}\n\n\t\t// _update just loads more tiles. If the tile zoom level differs too much\n\t\t// from the map's, let _setView reset levels and prune old tiles.\n\t\tif (Math.abs(zoom - this._tileZoom) > 1) { this._setView(center, zoom); return; }\n\n\t\t// create a queue of coordinates to load tiles from\n\t\tfor (var j = tileRange.min.y; j <= tileRange.max.y; j++) {\n\t\t\tfor (var i = tileRange.min.x; i <= tileRange.max.x; i++) {\n\t\t\t\tvar coords = new Point(i, j);\n\t\t\t\tcoords.z = this._tileZoom;\n\n\t\t\t\tif (!this._isValidTile(coords)) { continue; }\n\n\t\t\t\tvar tile = this._tiles[this._tileCoordsToKey(coords)];\n\t\t\t\tif (tile) {\n\t\t\t\t\ttile.current = true;\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push(coords);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// sort tile queue to load tiles in order of their distance to center\n\t\tqueue.sort(function (a, b) {\n\t\t\treturn a.distanceTo(tileCenter) - b.distanceTo(tileCenter);\n\t\t});\n\n\t\tif (queue.length !== 0) {\n\t\t\t// if it's the first batch of tiles to load\n\t\t\tif (!this._loading) {\n\t\t\t\tthis._loading = true;\n\t\t\t\t// @event loading: Event\n\t\t\t\t// Fired when the grid layer starts loading tiles.\n\t\t\t\tthis.fire('loading');\n\t\t\t}\n\n\t\t\t// create DOM fragment to append tiles in one batch\n\t\t\tvar fragment = document.createDocumentFragment();\n\n\t\t\tfor (i = 0; i < queue.length; i++) {\n\t\t\t\tthis._addTile(queue[i], fragment);\n\t\t\t}\n\n\t\t\tthis._level.el.appendChild(fragment);\n\t\t}\n\t},\n\n\t_isValidTile: function (coords) {\n\t\tvar crs = this._map.options.crs;\n\n\t\tif (!crs.infinite) {\n\t\t\t// don't load tile if it's out of bounds and not wrapped\n\t\t\tvar bounds = this._globalTileRange;\n\t\t\tif ((!crs.wrapLng && (coords.x < bounds.min.x || coords.x > bounds.max.x)) ||\n\t\t\t (!crs.wrapLat && (coords.y < bounds.min.y || coords.y > bounds.max.y))) { return false; }\n\t\t}\n\n\t\tif (!this.options.bounds) { return true; }\n\n\t\t// don't load tile if it doesn't intersect the bounds in options\n\t\tvar tileBounds = this._tileCoordsToBounds(coords);\n\t\treturn toLatLngBounds(this.options.bounds).overlaps(tileBounds);\n\t},\n\n\t_keyToBounds: function (key) {\n\t\treturn this._tileCoordsToBounds(this._keyToTileCoords(key));\n\t},\n\n\t_tileCoordsToNwSe: function (coords) {\n\t\tvar map = this._map,\n\t\t tileSize = this.getTileSize(),\n\t\t nwPoint = coords.scaleBy(tileSize),\n\t\t sePoint = nwPoint.add(tileSize),\n\t\t nw = map.unproject(nwPoint, coords.z),\n\t\t se = map.unproject(sePoint, coords.z);\n\t\treturn [nw, se];\n\t},\n\n\t// converts tile coordinates to its geographical bounds\n\t_tileCoordsToBounds: function (coords) {\n\t\tvar bp = this._tileCoordsToNwSe(coords),\n\t\t bounds = new LatLngBounds(bp[0], bp[1]);\n\n\t\tif (!this.options.noWrap) {\n\t\t\tbounds = this._map.wrapLatLngBounds(bounds);\n\t\t}\n\t\treturn bounds;\n\t},\n\t// converts tile coordinates to key for the tile cache\n\t_tileCoordsToKey: function (coords) {\n\t\treturn coords.x + ':' + coords.y + ':' + coords.z;\n\t},\n\n\t// converts tile cache key to coordinates\n\t_keyToTileCoords: function (key) {\n\t\tvar k = key.split(':'),\n\t\t coords = new Point(+k[0], +k[1]);\n\t\tcoords.z = +k[2];\n\t\treturn coords;\n\t},\n\n\t_removeTile: function (key) {\n\t\tvar tile = this._tiles[key];\n\t\tif (!tile) { return; }\n\n\t\tremove(tile.el);\n\n\t\tdelete this._tiles[key];\n\n\t\t// @event tileunload: TileEvent\n\t\t// Fired when a tile is removed (e.g. when a tile goes off the screen).\n\t\tthis.fire('tileunload', {\n\t\t\ttile: tile.el,\n\t\t\tcoords: this._keyToTileCoords(key)\n\t\t});\n\t},\n\n\t_initTile: function (tile) {\n\t\taddClass(tile, 'leaflet-tile');\n\n\t\tvar tileSize = this.getTileSize();\n\t\ttile.style.width = tileSize.x + 'px';\n\t\ttile.style.height = tileSize.y + 'px';\n\n\t\ttile.onselectstart = falseFn;\n\t\ttile.onmousemove = falseFn;\n\n\t\t// update opacity on tiles in IE7-8 because of filter inheritance problems\n\t\tif (ielt9 && this.options.opacity < 1) {\n\t\t\tsetOpacity(tile, this.options.opacity);\n\t\t}\n\n\t\t// without this hack, tiles disappear after zoom on Chrome for Android\n\t\t// https://github.com/Leaflet/Leaflet/issues/2078\n\t\tif (android && !android23) {\n\t\t\ttile.style.WebkitBackfaceVisibility = 'hidden';\n\t\t}\n\t},\n\n\t_addTile: function (coords, container) {\n\t\tvar tilePos = this._getTilePos(coords),\n\t\t key = this._tileCoordsToKey(coords);\n\n\t\tvar tile = this.createTile(this._wrapCoords(coords), bind(this._tileReady, this, coords));\n\n\t\tthis._initTile(tile);\n\n\t\t// if createTile is defined with a second argument (\"done\" callback),\n\t\t// we know that tile is async and will be ready later; otherwise\n\t\tif (this.createTile.length < 2) {\n\t\t\t// mark tile as ready, but delay one frame for opacity animation to happen\n\t\t\trequestAnimFrame(bind(this._tileReady, this, coords, null, tile));\n\t\t}\n\n\t\tsetPosition(tile, tilePos);\n\n\t\t// save tile in cache\n\t\tthis._tiles[key] = {\n\t\t\tel: tile,\n\t\t\tcoords: coords,\n\t\t\tcurrent: true\n\t\t};\n\n\t\tcontainer.appendChild(tile);\n\t\t// @event tileloadstart: TileEvent\n\t\t// Fired when a tile is requested and starts loading.\n\t\tthis.fire('tileloadstart', {\n\t\t\ttile: tile,\n\t\t\tcoords: coords\n\t\t});\n\t},\n\n\t_tileReady: function (coords, err, tile) {\n\t\tif (err) {\n\t\t\t// @event tileerror: TileErrorEvent\n\t\t\t// Fired when there is an error loading a tile.\n\t\t\tthis.fire('tileerror', {\n\t\t\t\terror: err,\n\t\t\t\ttile: tile,\n\t\t\t\tcoords: coords\n\t\t\t});\n\t\t}\n\n\t\tvar key = this._tileCoordsToKey(coords);\n\n\t\ttile = this._tiles[key];\n\t\tif (!tile) { return; }\n\n\t\ttile.loaded = +new Date();\n\t\tif (this._map._fadeAnimated) {\n\t\t\tsetOpacity(tile.el, 0);\n\t\t\tcancelAnimFrame(this._fadeFrame);\n\t\t\tthis._fadeFrame = requestAnimFrame(this._updateOpacity, this);\n\t\t} else {\n\t\t\ttile.active = true;\n\t\t\tthis._pruneTiles();\n\t\t}\n\n\t\tif (!err) {\n\t\t\taddClass(tile.el, 'leaflet-tile-loaded');\n\n\t\t\t// @event tileload: TileEvent\n\t\t\t// Fired when a tile loads.\n\t\t\tthis.fire('tileload', {\n\t\t\t\ttile: tile.el,\n\t\t\t\tcoords: coords\n\t\t\t});\n\t\t}\n\n\t\tif (this._noTilesToLoad()) {\n\t\t\tthis._loading = false;\n\t\t\t// @event load: Event\n\t\t\t// Fired when the grid layer loaded all visible tiles.\n\t\t\tthis.fire('load');\n\n\t\t\tif (ielt9 || !this._map._fadeAnimated) {\n\t\t\t\trequestAnimFrame(this._pruneTiles, this);\n\t\t\t} else {\n\t\t\t\t// Wait a bit more than 0.2 secs (the duration of the tile fade-in)\n\t\t\t\t// to trigger a pruning.\n\t\t\t\tsetTimeout(bind(this._pruneTiles, this), 250);\n\t\t\t}\n\t\t}\n\t},\n\n\t_getTilePos: function (coords) {\n\t\treturn coords.scaleBy(this.getTileSize()).subtract(this._level.origin);\n\t},\n\n\t_wrapCoords: function (coords) {\n\t\tvar newCoords = new Point(\n\t\t\tthis._wrapX ? wrapNum(coords.x, this._wrapX) : coords.x,\n\t\t\tthis._wrapY ? wrapNum(coords.y, this._wrapY) : coords.y);\n\t\tnewCoords.z = coords.z;\n\t\treturn newCoords;\n\t},\n\n\t_pxBoundsToTileRange: function (bounds) {\n\t\tvar tileSize = this.getTileSize();\n\t\treturn new Bounds(\n\t\t\tbounds.min.unscaleBy(tileSize).floor(),\n\t\t\tbounds.max.unscaleBy(tileSize).ceil().subtract([1, 1]));\n\t},\n\n\t_noTilesToLoad: function () {\n\t\tfor (var key in this._tiles) {\n\t\t\tif (!this._tiles[key].loaded) { return false; }\n\t\t}\n\t\treturn true;\n\t}\n});\n\n// @factory L.gridLayer(options?: GridLayer options)\n// Creates a new instance of GridLayer with the supplied options.\nfunction gridLayer(options) {\n\treturn new GridLayer(options);\n}\n\n/*\r\n * @class TileLayer\r\n * @inherits GridLayer\r\n * @aka L.TileLayer\r\n * Used to load and display tile layers on the map. Note that most tile servers require attribution, which you can set under `Layer`. Extends `GridLayer`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar', attribution: 'Map data &copy; <a href=\"https://www.openstreetmap.org/\">OpenStreetMap</a> contributors, <a href=\"https://creativecommons.org/licenses/by-sa/2.0/\">CC-BY-SA</a>'}).addTo(map);\r\n * ```\r\n *\r\n * @section URL template\r\n * @example\r\n *\r\n * A string of the following form:\r\n *\r\n * ```\r\n * 'http://{s}.somedomain.com/blabla/{z}/{x}/{y}{r}.png'\r\n * ```\r\n *\r\n * `{s}` means one of the available subdomains (used sequentially to help with browser parallel requests per domain limitation; subdomain values are specified in options; `a`, `b` or `c` by default, can be omitted), `{z}` — zoom level, `{x}` and `{y}` — tile coordinates. `{r}` can be used to add \"&commat;2x\" to the URL to load retina tiles.\r\n *\r\n * You can use custom keys in the template, which will be [evaluated](#util-template) from TileLayer options, like this:\r\n *\r\n * ```\r\n * L.tileLayer('http://{s}.somedomain.com/{foo}/{z}/{x}/{y}.png', {foo: 'bar'});\r\n * ```\r\n */\r\n\r\n\r\nvar TileLayer = GridLayer.extend({\r\n\r\n\t// @section\r\n\t// @aka TileLayer options\r\n\toptions: {\r\n\t\t// @option minZoom: Number = 0\r\n\t\t// The minimum zoom level down to which this layer will be displayed (inclusive).\r\n\t\tminZoom: 0,\r\n\r\n\t\t// @option maxZoom: Number = 18\r\n\t\t// The maximum zoom level up to which this layer will be displayed (inclusive).\r\n\t\tmaxZoom: 18,\r\n\r\n\t\t// @option subdomains: String|String[] = 'abc'\r\n\t\t// Subdomains of the tile service. Can be passed in the form of one string (where each letter is a subdomain name) or an array of strings.\r\n\t\tsubdomains: 'abc',\r\n\r\n\t\t// @option errorTileUrl: String = ''\r\n\t\t// URL to the tile image to show in place of the tile that failed to load.\r\n\t\terrorTileUrl: '',\r\n\r\n\t\t// @option zoomOffset: Number = 0\r\n\t\t// The zoom number used in tile URLs will be offset with this value.\r\n\t\tzoomOffset: 0,\r\n\r\n\t\t// @option tms: Boolean = false\r\n\t\t// If `true`, inverses Y axis numbering for tiles (turn this on for [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) services).\r\n\t\ttms: false,\r\n\r\n\t\t// @option zoomReverse: Boolean = false\r\n\t\t// If set to true, the zoom number used in tile URLs will be reversed (`maxZoom - zoom` instead of `zoom`)\r\n\t\tzoomReverse: false,\r\n\r\n\t\t// @option detectRetina: Boolean = false\r\n\t\t// If `true` and user is on a retina display, it will request four tiles of half the specified size and a bigger zoom level in place of one to utilize the high resolution.\r\n\t\tdetectRetina: false,\r\n\r\n\t\t// @option crossOrigin: Boolean|String = false\r\n\t\t// Whether the crossOrigin attribute will be added to the tiles.\r\n\t\t// If a String is provided, all tiles will have their crossOrigin attribute set to the String provided. This is needed if you want to access tile pixel data.\r\n\t\t// Refer to [CORS Settings](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) for valid String values.\r\n\t\tcrossOrigin: false\r\n\t},\r\n\r\n\tinitialize: function (url, options) {\r\n\r\n\t\tthis._url = url;\r\n\r\n\t\toptions = setOptions(this, options);\r\n\r\n\t\t// detecting retina displays, adjusting tileSize and zoom levels\r\n\t\tif (options.detectRetina && retina && options.maxZoom > 0) {\r\n\r\n\t\t\toptions.tileSize = Math.floor(options.tileSize / 2);\r\n\r\n\t\t\tif (!options.zoomReverse) {\r\n\t\t\t\toptions.zoomOffset++;\r\n\t\t\t\toptions.maxZoom--;\r\n\t\t\t} else {\r\n\t\t\t\toptions.zoomOffset--;\r\n\t\t\t\toptions.minZoom++;\r\n\t\t\t}\r\n\r\n\t\t\toptions.minZoom = Math.max(0, options.minZoom);\r\n\t\t}\r\n\r\n\t\tif (typeof options.subdomains === 'string') {\r\n\t\t\toptions.subdomains = options.subdomains.split('');\r\n\t\t}\r\n\r\n\t\t// for https://github.com/Leaflet/Leaflet/issues/137\r\n\t\tif (!android) {\r\n\t\t\tthis.on('tileunload', this._onTileRemove);\r\n\t\t}\r\n\t},\r\n\r\n\t// @method setUrl(url: String, noRedraw?: Boolean): this\r\n\t// Updates the layer's URL template and redraws it (unless `noRedraw` is set to `true`).\r\n\t// If the URL does not change, the layer will not be redrawn unless\r\n\t// the noRedraw parameter is set to false.\r\n\tsetUrl: function (url, noRedraw) {\r\n\t\tif (this._url === url && noRedraw === undefined) {\r\n\t\t\tnoRedraw = true;\r\n\t\t}\r\n\r\n\t\tthis._url = url;\r\n\r\n\t\tif (!noRedraw) {\r\n\t\t\tthis.redraw();\r\n\t\t}\r\n\t\treturn this;\r\n\t},\r\n\r\n\t// @method createTile(coords: Object, done?: Function): HTMLElement\r\n\t// Called only internally, overrides GridLayer's [`createTile()`](#gridlayer-createtile)\r\n\t// to return an `<img>` HTML element with the appropriate image URL given `coords`. The `done`\r\n\t// callback is called when the tile has been loaded.\r\n\tcreateTile: function (coords, done) {\r\n\t\tvar tile = document.createElement('img');\r\n\r\n\t\ton(tile, 'load', bind(this._tileOnLoad, this, done, tile));\r\n\t\ton(tile, 'error', bind(this._tileOnError, this, done, tile));\r\n\r\n\t\tif (this.options.crossOrigin || this.options.crossOrigin === '') {\r\n\t\t\ttile.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;\r\n\t\t}\r\n\r\n\t\t/*\r\n\t\t Alt tag is set to empty string to keep screen readers from reading URL and for compliance reasons\r\n\t\t http://www.w3.org/TR/WCAG20-TECHS/H67\r\n\t\t*/\r\n\t\ttile.alt = '';\r\n\r\n\t\t/*\r\n\t\t Set role=\"presentation\" to force screen readers to ignore this\r\n\t\t https://www.w3.org/TR/wai-aria/roles#textalternativecomputation\r\n\t\t*/\r\n\t\ttile.setAttribute('role', 'presentation');\r\n\r\n\t\ttile.src = this.getTileUrl(coords);\r\n\r\n\t\treturn tile;\r\n\t},\r\n\r\n\t// @section Extension methods\r\n\t// @uninheritable\r\n\t// Layers extending `TileLayer` might reimplement the following method.\r\n\t// @method getTileUrl(coords: Object): String\r\n\t// Called only internally, returns the URL for a tile given its coordinates.\r\n\t// Classes extending `TileLayer` can override this function to provide custom tile URL naming schemes.\r\n\tgetTileUrl: function (coords) {\r\n\t\tvar data = {\r\n\t\t\tr: retina ? '@2x' : '',\r\n\t\t\ts: this._getSubdomain(coords),\r\n\t\t\tx: coords.x,\r\n\t\t\ty: coords.y,\r\n\t\t\tz: this._getZoomForUrl()\r\n\t\t};\r\n\t\tif (this._map && !this._map.options.crs.infinite) {\r\n\t\t\tvar invertedY = this._globalTileRange.max.y - coords.y;\r\n\t\t\tif (this.options.tms) {\r\n\t\t\t\tdata['y'] = invertedY;\r\n\t\t\t}\r\n\t\t\tdata['-y'] = invertedY;\r\n\t\t}\r\n\r\n\t\treturn template(this._url, extend(data, this.options));\r\n\t},\r\n\r\n\t_tileOnLoad: function (done, tile) {\r\n\t\t// For https://github.com/Leaflet/Leaflet/issues/3332\r\n\t\tif (ielt9) {\r\n\t\t\tsetTimeout(bind(done, this, null, tile), 0);\r\n\t\t} else {\r\n\t\t\tdone(null, tile);\r\n\t\t}\r\n\t},\r\n\r\n\t_tileOnError: function (done, tile, e) {\r\n\t\tvar errorUrl = this.options.errorTileUrl;\r\n\t\tif (errorUrl && tile.getAttribute('src') !== errorUrl) {\r\n\t\t\ttile.src = errorUrl;\r\n\t\t}\r\n\t\tdone(e, tile);\r\n\t},\r\n\r\n\t_onTileRemove: function (e) {\r\n\t\te.tile.onload = null;\r\n\t},\r\n\r\n\t_getZoomForUrl: function () {\r\n\t\tvar zoom = this._tileZoom,\r\n\t\tmaxZoom = this.options.maxZoom,\r\n\t\tzoomReverse = this.options.zoomReverse,\r\n\t\tzoomOffset = this.options.zoomOffset;\r\n\r\n\t\tif (zoomReverse) {\r\n\t\t\tzoom = maxZoom - zoom;\r\n\t\t}\r\n\r\n\t\treturn zoom + zoomOffset;\r\n\t},\r\n\r\n\t_getSubdomain: function (tilePoint) {\r\n\t\tvar index = Math.abs(tilePoint.x + tilePoint.y) % this.options.subdomains.length;\r\n\t\treturn this.options.subdomains[index];\r\n\t},\r\n\r\n\t// stops loading all tiles in the background layer\r\n\t_abortLoading: function () {\r\n\t\tvar i, tile;\r\n\t\tfor (i in this._tiles) {\r\n\t\t\tif (this._tiles[i].coords.z !== this._tileZoom) {\r\n\t\t\t\ttile = this._tiles[i].el;\r\n\r\n\t\t\t\ttile.onload = falseFn;\r\n\t\t\t\ttile.onerror = falseFn;\r\n\r\n\t\t\t\tif (!tile.complete) {\r\n\t\t\t\t\ttile.src = emptyImageUrl;\r\n\t\t\t\t\tremove(tile);\r\n\t\t\t\t\tdelete this._tiles[i];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\r\n\t_removeTile: function (key) {\r\n\t\tvar tile = this._tiles[key];\r\n\t\tif (!tile) { return; }\r\n\r\n\t\t// Cancels any pending http requests associated with the tile\r\n\t\t// unless we're on Android's stock browser,\r\n\t\t// see https://github.com/Leaflet/Leaflet/issues/137\r\n\t\tif (!androidStock) {\r\n\t\t\ttile.el.setAttribute('src', emptyImageUrl);\r\n\t\t}\r\n\r\n\t\treturn GridLayer.prototype._removeTile.call(this, key);\r\n\t},\r\n\r\n\t_tileReady: function (coords, err, tile) {\r\n\t\tif (!this._map || (tile && tile.getAttribute('src') === emptyImageUrl)) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\treturn GridLayer.prototype._tileReady.call(this, coords, err, tile);\r\n\t}\r\n});\r\n\r\n\r\n// @factory L.tilelayer(urlTemplate: String, options?: TileLayer options)\r\n// Instantiates a tile layer object given a `URL template` and optionally an options object.\r\n\r\nfunction tileLayer(url, options) {\r\n\treturn new TileLayer(url, options);\r\n}\n\n/*\r\n * @class TileLayer.WMS\r\n * @inherits TileLayer\r\n * @aka L.TileLayer.WMS\r\n * Used to display [WMS](https://en.wikipedia.org/wiki/Web_Map_Service) services as tile layers on the map. Extends `TileLayer`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * var nexrad = L.tileLayer.wms(\"http://mesonet.agron.iastate.edu/cgi-bin/wms/nexrad/n0r.cgi\", {\r\n * \tlayers: 'nexrad-n0r-900913',\r\n * \tformat: 'image/png',\r\n * \ttransparent: true,\r\n * \tattribution: \"Weather data © 2012 IEM Nexrad\"\r\n * });\r\n * ```\r\n */\r\n\r\nvar TileLayerWMS = TileLayer.extend({\r\n\r\n\t// @section\r\n\t// @aka TileLayer.WMS options\r\n\t// If any custom options not documented here are used, they will be sent to the\r\n\t// WMS server as extra parameters in each request URL. This can be useful for\r\n\t// [non-standard vendor WMS parameters](http://docs.geoserver.org/stable/en/user/services/wms/vendor.html).\r\n\tdefaultWmsParams: {\r\n\t\tservice: 'WMS',\r\n\t\trequest: 'GetMap',\r\n\r\n\t\t// @option layers: String = ''\r\n\t\t// **(required)** Comma-separated list of WMS layers to show.\r\n\t\tlayers: '',\r\n\r\n\t\t// @option styles: String = ''\r\n\t\t// Comma-separated list of WMS styles.\r\n\t\tstyles: '',\r\n\r\n\t\t// @option format: String = 'image/jpeg'\r\n\t\t// WMS image format (use `'image/png'` for layers with transparency).\r\n\t\tformat: 'image/jpeg',\r\n\r\n\t\t// @option transparent: Boolean = false\r\n\t\t// If `true`, the WMS service will return images with transparency.\r\n\t\ttransparent: false,\r\n\r\n\t\t// @option version: String = '1.1.1'\r\n\t\t// Version of the WMS service to use\r\n\t\tversion: '1.1.1'\r\n\t},\r\n\r\n\toptions: {\r\n\t\t// @option crs: CRS = null\r\n\t\t// Coordinate Reference System to use for the WMS requests, defaults to\r\n\t\t// map CRS. Don't change this if you're not sure what it means.\r\n\t\tcrs: null,\r\n\r\n\t\t// @option uppercase: Boolean = false\r\n\t\t// If `true`, WMS request parameter keys will be uppercase.\r\n\t\tuppercase: false\r\n\t},\r\n\r\n\tinitialize: function (url, options) {\r\n\r\n\t\tthis._url = url;\r\n\r\n\t\tvar wmsParams = extend({}, this.defaultWmsParams);\r\n\r\n\t\t// all keys that are not TileLayer options go to WMS params\r\n\t\tfor (var i in options) {\r\n\t\t\tif (!(i in this.options)) {\r\n\t\t\t\twmsParams[i] = options[i];\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\toptions = setOptions(this, options);\r\n\r\n\t\tvar realRetina = options.detectRetina && retina ? 2 : 1;\r\n\t\tvar tileSize = this.getTileSize();\r\n\t\twmsParams.width = tileSize.x * realRetina;\r\n\t\twmsParams.height = tileSize.y * realRetina;\r\n\r\n\t\tthis.wmsParams = wmsParams;\r\n\t},\r\n\r\n\tonAdd: function (map) {\r\n\r\n\t\tthis._crs = this.options.crs || map.options.crs;\r\n\t\tthis._wmsVersion = parseFloat(this.wmsParams.version);\r\n\r\n\t\tvar projectionKey = this._wmsVersion >= 1.3 ? 'crs' : 'srs';\r\n\t\tthis.wmsParams[projectionKey] = this._crs.code;\r\n\r\n\t\tTileLayer.prototype.onAdd.call(this, map);\r\n\t},\r\n\r\n\tgetTileUrl: function (coords) {\r\n\r\n\t\tvar tileBounds = this._tileCoordsToNwSe(coords),\r\n\t\t crs = this._crs,\r\n\t\t bounds = toBounds(crs.project(tileBounds[0]), crs.project(tileBounds[1])),\r\n\t\t min = bounds.min,\r\n\t\t max = bounds.max,\r\n\t\t bbox = (this._wmsVersion >= 1.3 && this._crs === EPSG4326 ?\r\n\t\t [min.y, min.x, max.y, max.x] :\r\n\t\t [min.x, min.y, max.x, max.y]).join(','),\r\n\t\t url = TileLayer.prototype.getTileUrl.call(this, coords);\r\n\t\treturn url +\r\n\t\t\tgetParamString(this.wmsParams, url, this.options.uppercase) +\r\n\t\t\t(this.options.uppercase ? '&BBOX=' : '&bbox=') + bbox;\r\n\t},\r\n\r\n\t// @method setParams(params: Object, noRedraw?: Boolean): this\r\n\t// Merges an object with the new parameters and re-requests tiles on the current screen (unless `noRedraw` was set to true).\r\n\tsetParams: function (params, noRedraw) {\r\n\r\n\t\textend(this.wmsParams, params);\r\n\r\n\t\tif (!noRedraw) {\r\n\t\t\tthis.redraw();\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n});\r\n\r\n\r\n// @factory L.tileLayer.wms(baseUrl: String, options: TileLayer.WMS options)\r\n// Instantiates a WMS tile layer object given a base URL of the WMS service and a WMS parameters/options object.\r\nfunction tileLayerWMS(url, options) {\r\n\treturn new TileLayerWMS(url, options);\r\n}\n\nTileLayer.WMS = TileLayerWMS;\ntileLayer.wms = tileLayerWMS;\n\n/*\n * @class Renderer\n * @inherits Layer\n * @aka L.Renderer\n *\n * Base class for vector renderer implementations (`SVG`, `Canvas`). Handles the\n * DOM container of the renderer, its bounds, and its zoom animation.\n *\n * A `Renderer` works as an implicit layer group for all `Path`s - the renderer\n * itself can be added or removed to the map. All paths use a renderer, which can\n * be implicit (the map will decide the type of renderer and use it automatically)\n * or explicit (using the [`renderer`](#path-renderer) option of the path).\n *\n * Do not use this class directly, use `SVG` and `Canvas` instead.\n *\n * @event update: Event\n * Fired when the renderer updates its bounds, center and zoom, for example when\n * its map has moved\n */\n\nvar Renderer = Layer.extend({\n\n\t// @section\n\t// @aka Renderer options\n\toptions: {\n\t\t// @option padding: Number = 0.1\n\t\t// How much to extend the clip area around the map view (relative to its size)\n\t\t// e.g. 0.1 would be 10% of map view in each direction\n\t\tpadding: 0.1,\n\n\t\t// @option tolerance: Number = 0\n\t\t// How much to extend click tolerance round a path/object on the map\n\t\ttolerance : 0\n\t},\n\n\tinitialize: function (options) {\n\t\tsetOptions(this, options);\n\t\tstamp(this);\n\t\tthis._layers = this._layers || {};\n\t},\n\n\tonAdd: function () {\n\t\tif (!this._container) {\n\t\t\tthis._initContainer(); // defined by renderer implementations\n\n\t\t\tif (this._zoomAnimated) {\n\t\t\t\taddClass(this._container, 'leaflet-zoom-animated');\n\t\t\t}\n\t\t}\n\n\t\tthis.getPane().appendChild(this._container);\n\t\tthis._update();\n\t\tthis.on('update', this._updatePaths, this);\n\t},\n\n\tonRemove: function () {\n\t\tthis.off('update', this._updatePaths, this);\n\t\tthis._destroyContainer();\n\t},\n\n\tgetEvents: function () {\n\t\tvar events = {\n\t\t\tviewreset: this._reset,\n\t\t\tzoom: this._onZoom,\n\t\t\tmoveend: this._update,\n\t\t\tzoomend: this._onZoomEnd\n\t\t};\n\t\tif (this._zoomAnimated) {\n\t\t\tevents.zoomanim = this._onAnimZoom;\n\t\t}\n\t\treturn events;\n\t},\n\n\t_onAnimZoom: function (ev) {\n\t\tthis._updateTransform(ev.center, ev.zoom);\n\t},\n\n\t_onZoom: function () {\n\t\tthis._updateTransform(this._map.getCenter(), this._map.getZoom());\n\t},\n\n\t_updateTransform: function (center, zoom) {\n\t\tvar scale = this._map.getZoomScale(zoom, this._zoom),\n\t\t position = getPosition(this._container),\n\t\t viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding),\n\t\t currentCenterPoint = this._map.project(this._center, zoom),\n\t\t destCenterPoint = this._map.project(center, zoom),\n\t\t centerOffset = destCenterPoint.subtract(currentCenterPoint),\n\n\t\t topLeftOffset = viewHalf.multiplyBy(-scale).add(position).add(viewHalf).subtract(centerOffset);\n\n\t\tif (any3d) {\n\t\t\tsetTransform(this._container, topLeftOffset, scale);\n\t\t} else {\n\t\t\tsetPosition(this._container, topLeftOffset);\n\t\t}\n\t},\n\n\t_reset: function () {\n\t\tthis._update();\n\t\tthis._updateTransform(this._center, this._zoom);\n\n\t\tfor (var id in this._layers) {\n\t\t\tthis._layers[id]._reset();\n\t\t}\n\t},\n\n\t_onZoomEnd: function () {\n\t\tfor (var id in this._layers) {\n\t\t\tthis._layers[id]._project();\n\t\t}\n\t},\n\n\t_updatePaths: function () {\n\t\tfor (var id in this._layers) {\n\t\t\tthis._layers[id]._update();\n\t\t}\n\t},\n\n\t_update: function () {\n\t\t// Update pixel bounds of renderer container (for positioning/sizing/clipping later)\n\t\t// Subclasses are responsible of firing the 'update' event.\n\t\tvar p = this.options.padding,\n\t\t size = this._map.getSize(),\n\t\t min = this._map.containerPointToLayerPoint(size.multiplyBy(-p)).round();\n\n\t\tthis._bounds = new Bounds(min, min.add(size.multiplyBy(1 + p * 2)).round());\n\n\t\tthis._center = this._map.getCenter();\n\t\tthis._zoom = this._map.getZoom();\n\t}\n});\n\n/*\n * @class Canvas\n * @inherits Renderer\n * @aka L.Canvas\n *\n * Allows vector layers to be displayed with [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API).\n * Inherits `Renderer`.\n *\n * Due to [technical limitations](http://caniuse.com/#search=canvas), Canvas is not\n * available in all web browsers, notably IE8, and overlapping geometries might\n * not display properly in some edge cases.\n *\n * @example\n *\n * Use Canvas by default for all paths in the map:\n *\n * ```js\n * var map = L.map('map', {\n * \trenderer: L.canvas()\n * });\n * ```\n *\n * Use a Canvas renderer with extra padding for specific vector geometries:\n *\n * ```js\n * var map = L.map('map');\n * var myRenderer = L.canvas({ padding: 0.5 });\n * var line = L.polyline( coordinates, { renderer: myRenderer } );\n * var circle = L.circle( center, { renderer: myRenderer } );\n * ```\n */\n\nvar Canvas = Renderer.extend({\n\tgetEvents: function () {\n\t\tvar events = Renderer.prototype.getEvents.call(this);\n\t\tevents.viewprereset = this._onViewPreReset;\n\t\treturn events;\n\t},\n\n\t_onViewPreReset: function () {\n\t\t// Set a flag so that a viewprereset+moveend+viewreset only updates&redraws once\n\t\tthis._postponeUpdatePaths = true;\n\t},\n\n\tonAdd: function () {\n\t\tRenderer.prototype.onAdd.call(this);\n\n\t\t// Redraw vectors since canvas is cleared upon removal,\n\t\t// in case of removing the renderer itself from the map.\n\t\tthis._draw();\n\t},\n\n\t_initContainer: function () {\n\t\tvar container = this._container = document.createElement('canvas');\n\n\t\ton(container, 'mousemove', throttle(this._onMouseMove, 32, this), this);\n\t\ton(container, 'click dblclick mousedown mouseup contextmenu', this._onClick, this);\n\t\ton(container, 'mouseout', this._handleMouseOut, this);\n\n\t\tthis._ctx = container.getContext('2d');\n\t},\n\n\t_destroyContainer: function () {\n\t\tcancelAnimFrame(this._redrawRequest);\n\t\tdelete this._ctx;\n\t\tremove(this._container);\n\t\toff(this._container);\n\t\tdelete this._container;\n\t},\n\n\t_updatePaths: function () {\n\t\tif (this._postponeUpdatePaths) { return; }\n\n\t\tvar layer;\n\t\tthis._redrawBounds = null;\n\t\tfor (var id in this._layers) {\n\t\t\tlayer = this._layers[id];\n\t\t\tlayer._update();\n\t\t}\n\t\tthis._redraw();\n\t},\n\n\t_update: function () {\n\t\tif (this._map._animatingZoom && this._bounds) { return; }\n\n\t\tRenderer.prototype._update.call(this);\n\n\t\tvar b = this._bounds,\n\t\t container = this._container,\n\t\t size = b.getSize(),\n\t\t m = retina ? 2 : 1;\n\n\t\tsetPosition(container, b.min);\n\n\t\t// set canvas size (also clearing it); use double size on retina\n\t\tcontainer.width = m * size.x;\n\t\tcontainer.height = m * size.y;\n\t\tcontainer.style.width = size.x + 'px';\n\t\tcontainer.style.height = size.y + 'px';\n\n\t\tif (retina) {\n\t\t\tthis._ctx.scale(2, 2);\n\t\t}\n\n\t\t// translate so we use the same path coordinates after canvas element moves\n\t\tthis._ctx.translate(-b.min.x, -b.min.y);\n\n\t\t// Tell paths to redraw themselves\n\t\tthis.fire('update');\n\t},\n\n\t_reset: function () {\n\t\tRenderer.prototype._reset.call(this);\n\n\t\tif (this._postponeUpdatePaths) {\n\t\t\tthis._postponeUpdatePaths = false;\n\t\t\tthis._updatePaths();\n\t\t}\n\t},\n\n\t_initPath: function (layer) {\n\t\tthis._updateDashArray(layer);\n\t\tthis._layers[stamp(layer)] = layer;\n\n\t\tvar order = layer._order = {\n\t\t\tlayer: layer,\n\t\t\tprev: this._drawLast,\n\t\t\tnext: null\n\t\t};\n\t\tif (this._drawLast) { this._drawLast.next = order; }\n\t\tthis._drawLast = order;\n\t\tthis._drawFirst = this._drawFirst || this._drawLast;\n\t},\n\n\t_addPath: function (layer) {\n\t\tthis._requestRedraw(layer);\n\t},\n\n\t_removePath: function (layer) {\n\t\tvar order = layer._order;\n\t\tvar next = order.next;\n\t\tvar prev = order.prev;\n\n\t\tif (next) {\n\t\t\tnext.prev = prev;\n\t\t} else {\n\t\t\tthis._drawLast = prev;\n\t\t}\n\t\tif (prev) {\n\t\t\tprev.next = next;\n\t\t} else {\n\t\t\tthis._drawFirst = next;\n\t\t}\n\n\t\tdelete layer._order;\n\n\t\tdelete this._layers[stamp(layer)];\n\n\t\tthis._requestRedraw(layer);\n\t},\n\n\t_updatePath: function (layer) {\n\t\t// Redraw the union of the layer's old pixel\n\t\t// bounds and the new pixel bounds.\n\t\tthis._extendRedrawBounds(layer);\n\t\tlayer._project();\n\t\tlayer._update();\n\t\t// The redraw will extend the redraw bounds\n\t\t// with the new pixel bounds.\n\t\tthis._requestRedraw(layer);\n\t},\n\n\t_updateStyle: function (layer) {\n\t\tthis._updateDashArray(layer);\n\t\tthis._requestRedraw(layer);\n\t},\n\n\t_updateDashArray: function (layer) {\n\t\tif (typeof layer.options.dashArray === 'string') {\n\t\t\tvar parts = layer.options.dashArray.split(/[, ]+/),\n\t\t\t dashArray = [],\n\t\t\t dashValue,\n\t\t\t i;\n\t\t\tfor (i = 0; i < parts.length; i++) {\n\t\t\t\tdashValue = Number(parts[i]);\n\t\t\t\t// Ignore dash array containing invalid lengths\n\t\t\t\tif (isNaN(dashValue)) { return; }\n\t\t\t\tdashArray.push(dashValue);\n\t\t\t}\n\t\t\tlayer.options._dashArray = dashArray;\n\t\t} else {\n\t\t\tlayer.options._dashArray = layer.options.dashArray;\n\t\t}\n\t},\n\n\t_requestRedraw: function (layer) {\n\t\tif (!this._map) { return; }\n\n\t\tthis._extendRedrawBounds(layer);\n\t\tthis._redrawRequest = this._redrawRequest || requestAnimFrame(this._redraw, this);\n\t},\n\n\t_extendRedrawBounds: function (layer) {\n\t\tif (layer._pxBounds) {\n\t\t\tvar padding = (layer.options.weight || 0) + 1;\n\t\t\tthis._redrawBounds = this._redrawBounds || new Bounds();\n\t\t\tthis._redrawBounds.extend(layer._pxBounds.min.subtract([padding, padding]));\n\t\t\tthis._redrawBounds.extend(layer._pxBounds.max.add([padding, padding]));\n\t\t}\n\t},\n\n\t_redraw: function () {\n\t\tthis._redrawRequest = null;\n\n\t\tif (this._redrawBounds) {\n\t\t\tthis._redrawBounds.min._floor();\n\t\t\tthis._redrawBounds.max._ceil();\n\t\t}\n\n\t\tthis._clear(); // clear layers in redraw bounds\n\t\tthis._draw(); // draw layers\n\n\t\tthis._redrawBounds = null;\n\t},\n\n\t_clear: function () {\n\t\tvar bounds = this._redrawBounds;\n\t\tif (bounds) {\n\t\t\tvar size = bounds.getSize();\n\t\t\tthis._ctx.clearRect(bounds.min.x, bounds.min.y, size.x, size.y);\n\t\t} else {\n\t\t\tthis._ctx.clearRect(0, 0, this._container.width, this._container.height);\n\t\t}\n\t},\n\n\t_draw: function () {\n\t\tvar layer, bounds = this._redrawBounds;\n\t\tthis._ctx.save();\n\t\tif (bounds) {\n\t\t\tvar size = bounds.getSize();\n\t\t\tthis._ctx.beginPath();\n\t\t\tthis._ctx.rect(bounds.min.x, bounds.min.y, size.x, size.y);\n\t\t\tthis._ctx.clip();\n\t\t}\n\n\t\tthis._drawing = true;\n\n\t\tfor (var order = this._drawFirst; order; order = order.next) {\n\t\t\tlayer = order.layer;\n\t\t\tif (!bounds || (layer._pxBounds && layer._pxBounds.intersects(bounds))) {\n\t\t\t\tlayer._updatePath();\n\t\t\t}\n\t\t}\n\n\t\tthis._drawing = false;\n\n\t\tthis._ctx.restore(); // Restore state before clipping.\n\t},\n\n\t_updatePoly: function (layer, closed) {\n\t\tif (!this._drawing) { return; }\n\n\t\tvar i, j, len2, p,\n\t\t parts = layer._parts,\n\t\t len = parts.length,\n\t\t ctx = this._ctx;\n\n\t\tif (!len) { return; }\n\n\t\tctx.beginPath();\n\n\t\tfor (i = 0; i < len; i++) {\n\t\t\tfor (j = 0, len2 = parts[i].length; j < len2; j++) {\n\t\t\t\tp = parts[i][j];\n\t\t\t\tctx[j ? 'lineTo' : 'moveTo'](p.x, p.y);\n\t\t\t}\n\t\t\tif (closed) {\n\t\t\t\tctx.closePath();\n\t\t\t}\n\t\t}\n\n\t\tthis._fillStroke(ctx, layer);\n\n\t\t// TODO optimization: 1 fill/stroke for all features with equal style instead of 1 for each feature\n\t},\n\n\t_updateCircle: function (layer) {\n\n\t\tif (!this._drawing || layer._empty()) { return; }\n\n\t\tvar p = layer._point,\n\t\t ctx = this._ctx,\n\t\t r = Math.max(Math.round(layer._radius), 1),\n\t\t s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;\n\n\t\tif (s !== 1) {\n\t\t\tctx.save();\n\t\t\tctx.scale(1, s);\n\t\t}\n\n\t\tctx.beginPath();\n\t\tctx.arc(p.x, p.y / s, r, 0, Math.PI * 2, false);\n\n\t\tif (s !== 1) {\n\t\t\tctx.restore();\n\t\t}\n\n\t\tthis._fillStroke(ctx, layer);\n\t},\n\n\t_fillStroke: function (ctx, layer) {\n\t\tvar options = layer.options;\n\n\t\tif (options.fill) {\n\t\t\tctx.globalAlpha = options.fillOpacity;\n\t\t\tctx.fillStyle = options.fillColor || options.color;\n\t\t\tctx.fill(options.fillRule || 'evenodd');\n\t\t}\n\n\t\tif (options.stroke && options.weight !== 0) {\n\t\t\tif (ctx.setLineDash) {\n\t\t\t\tctx.setLineDash(layer.options && layer.options._dashArray || []);\n\t\t\t}\n\t\t\tctx.globalAlpha = options.opacity;\n\t\t\tctx.lineWidth = options.weight;\n\t\t\tctx.strokeStyle = options.color;\n\t\t\tctx.lineCap = options.lineCap;\n\t\t\tctx.lineJoin = options.lineJoin;\n\t\t\tctx.stroke();\n\t\t}\n\t},\n\n\t// Canvas obviously doesn't have mouse events for individual drawn objects,\n\t// so we emulate that by calculating what's under the mouse on mousemove/click manually\n\n\t_onClick: function (e) {\n\t\tvar point = this._map.mouseEventToLayerPoint(e), layer, clickedLayer;\n\n\t\tfor (var order = this._drawFirst; order; order = order.next) {\n\t\t\tlayer = order.layer;\n\t\t\tif (layer.options.interactive && layer._containsPoint(point) && !this._map._draggableMoved(layer)) {\n\t\t\t\tclickedLayer = layer;\n\t\t\t}\n\t\t}\n\t\tif (clickedLayer) {\n\t\t\tfakeStop(e);\n\t\t\tthis._fireEvent([clickedLayer], e);\n\t\t}\n\t},\n\n\t_onMouseMove: function (e) {\n\t\tif (!this._map || this._map.dragging.moving() || this._map._animatingZoom) { return; }\n\n\t\tvar point = this._map.mouseEventToLayerPoint(e);\n\t\tthis._handleMouseHover(e, point);\n\t},\n\n\n\t_handleMouseOut: function (e) {\n\t\tvar layer = this._hoveredLayer;\n\t\tif (layer) {\n\t\t\t// if we're leaving the layer, fire mouseout\n\t\t\tremoveClass(this._container, 'leaflet-interactive');\n\t\t\tthis._fireEvent([layer], e, 'mouseout');\n\t\t\tthis._hoveredLayer = null;\n\t\t}\n\t},\n\n\t_handleMouseHover: function (e, point) {\n\t\tvar layer, candidateHoveredLayer;\n\n\t\tfor (var order = this._drawFirst; order; order = order.next) {\n\t\t\tlayer = order.layer;\n\t\t\tif (layer.options.interactive && layer._containsPoint(point)) {\n\t\t\t\tcandidateHoveredLayer = layer;\n\t\t\t}\n\t\t}\n\n\t\tif (candidateHoveredLayer !== this._hoveredLayer) {\n\t\t\tthis._handleMouseOut(e);\n\n\t\t\tif (candidateHoveredLayer) {\n\t\t\t\taddClass(this._container, 'leaflet-interactive'); // change cursor\n\t\t\t\tthis._fireEvent([candidateHoveredLayer], e, 'mouseover');\n\t\t\t\tthis._hoveredLayer = candidateHoveredLayer;\n\t\t\t}\n\t\t}\n\n\t\tif (this._hoveredLayer) {\n\t\t\tthis._fireEvent([this._hoveredLayer], e);\n\t\t}\n\t},\n\n\t_fireEvent: function (layers, e, type) {\n\t\tthis._map._fireDOMEvent(e, type || e.type, layers);\n\t},\n\n\t_bringToFront: function (layer) {\n\t\tvar order = layer._order;\n\n\t\tif (!order) { return; }\n\n\t\tvar next = order.next;\n\t\tvar prev = order.prev;\n\n\t\tif (next) {\n\t\t\tnext.prev = prev;\n\t\t} else {\n\t\t\t// Already last\n\t\t\treturn;\n\t\t}\n\t\tif (prev) {\n\t\t\tprev.next = next;\n\t\t} else if (next) {\n\t\t\t// Update first entry unless this is the\n\t\t\t// single entry\n\t\t\tthis._drawFirst = next;\n\t\t}\n\n\t\torder.prev = this._drawLast;\n\t\tthis._drawLast.next = order;\n\n\t\torder.next = null;\n\t\tthis._drawLast = order;\n\n\t\tthis._requestRedraw(layer);\n\t},\n\n\t_bringToBack: function (layer) {\n\t\tvar order = layer._order;\n\n\t\tif (!order) { return; }\n\n\t\tvar next = order.next;\n\t\tvar prev = order.prev;\n\n\t\tif (prev) {\n\t\t\tprev.next = next;\n\t\t} else {\n\t\t\t// Already first\n\t\t\treturn;\n\t\t}\n\t\tif (next) {\n\t\t\tnext.prev = prev;\n\t\t} else if (prev) {\n\t\t\t// Update last entry unless this is the\n\t\t\t// single entry\n\t\t\tthis._drawLast = prev;\n\t\t}\n\n\t\torder.prev = null;\n\n\t\torder.next = this._drawFirst;\n\t\tthis._drawFirst.prev = order;\n\t\tthis._drawFirst = order;\n\n\t\tthis._requestRedraw(layer);\n\t}\n});\n\n// @factory L.canvas(options?: Renderer options)\n// Creates a Canvas renderer with the given options.\nfunction canvas$1(options) {\n\treturn canvas ? new Canvas(options) : null;\n}\n\n/*\n * Thanks to Dmitry Baranovsky and his Raphael library for inspiration!\n */\n\n\nvar vmlCreate = (function () {\n\ttry {\n\t\tdocument.namespaces.add('lvml', 'urn:schemas-microsoft-com:vml');\n\t\treturn function (name) {\n\t\t\treturn document.createElement('<lvml:' + name + ' class=\"lvml\">');\n\t\t};\n\t} catch (e) {\n\t\treturn function (name) {\n\t\t\treturn document.createElement('<' + name + ' xmlns=\"urn:schemas-microsoft.com:vml\" class=\"lvml\">');\n\t\t};\n\t}\n})();\n\n\n/*\n * @class SVG\n *\n *\n * VML was deprecated in 2012, which means VML functionality exists only for backwards compatibility\n * with old versions of Internet Explorer.\n */\n\n// mixin to redefine some SVG methods to handle VML syntax which is similar but with some differences\nvar vmlMixin = {\n\n\t_initContainer: function () {\n\t\tthis._container = create$1('div', 'leaflet-vml-container');\n\t},\n\n\t_update: function () {\n\t\tif (this._map._animatingZoom) { return; }\n\t\tRenderer.prototype._update.call(this);\n\t\tthis.fire('update');\n\t},\n\n\t_initPath: function (layer) {\n\t\tvar container = layer._container = vmlCreate('shape');\n\n\t\taddClass(container, 'leaflet-vml-shape ' + (this.options.className || ''));\n\n\t\tcontainer.coordsize = '1 1';\n\n\t\tlayer._path = vmlCreate('path');\n\t\tcontainer.appendChild(layer._path);\n\n\t\tthis._updateStyle(layer);\n\t\tthis._layers[stamp(layer)] = layer;\n\t},\n\n\t_addPath: function (layer) {\n\t\tvar container = layer._container;\n\t\tthis._container.appendChild(container);\n\n\t\tif (layer.options.interactive) {\n\t\t\tlayer.addInteractiveTarget(container);\n\t\t}\n\t},\n\n\t_removePath: function (layer) {\n\t\tvar container = layer._container;\n\t\tremove(container);\n\t\tlayer.removeInteractiveTarget(container);\n\t\tdelete this._layers[stamp(layer)];\n\t},\n\n\t_updateStyle: function (layer) {\n\t\tvar stroke = layer._stroke,\n\t\t fill = layer._fill,\n\t\t options = layer.options,\n\t\t container = layer._container;\n\n\t\tcontainer.stroked = !!options.stroke;\n\t\tcontainer.filled = !!options.fill;\n\n\t\tif (options.stroke) {\n\t\t\tif (!stroke) {\n\t\t\t\tstroke = layer._stroke = vmlCreate('stroke');\n\t\t\t}\n\t\t\tcontainer.appendChild(stroke);\n\t\t\tstroke.weight = options.weight + 'px';\n\t\t\tstroke.color = options.color;\n\t\t\tstroke.opacity = options.opacity;\n\n\t\t\tif (options.dashArray) {\n\t\t\t\tstroke.dashStyle = isArray(options.dashArray) ?\n\t\t\t\t options.dashArray.join(' ') :\n\t\t\t\t options.dashArray.replace(/( *, *)/g, ' ');\n\t\t\t} else {\n\t\t\t\tstroke.dashStyle = '';\n\t\t\t}\n\t\t\tstroke.endcap = options.lineCap.replace('butt', 'flat');\n\t\t\tstroke.joinstyle = options.lineJoin;\n\n\t\t} else if (stroke) {\n\t\t\tcontainer.removeChild(stroke);\n\t\t\tlayer._stroke = null;\n\t\t}\n\n\t\tif (options.fill) {\n\t\t\tif (!fill) {\n\t\t\t\tfill = layer._fill = vmlCreate('fill');\n\t\t\t}\n\t\t\tcontainer.appendChild(fill);\n\t\t\tfill.color = options.fillColor || options.color;\n\t\t\tfill.opacity = options.fillOpacity;\n\n\t\t} else if (fill) {\n\t\t\tcontainer.removeChild(fill);\n\t\t\tlayer._fill = null;\n\t\t}\n\t},\n\n\t_updateCircle: function (layer) {\n\t\tvar p = layer._point.round(),\n\t\t r = Math.round(layer._radius),\n\t\t r2 = Math.round(layer._radiusY || r);\n\n\t\tthis._setPath(layer, layer._empty() ? 'M0 0' :\n\t\t\t'AL ' + p.x + ',' + p.y + ' ' + r + ',' + r2 + ' 0,' + (65535 * 360));\n\t},\n\n\t_setPath: function (layer, path) {\n\t\tlayer._path.v = path;\n\t},\n\n\t_bringToFront: function (layer) {\n\t\ttoFront(layer._container);\n\t},\n\n\t_bringToBack: function (layer) {\n\t\ttoBack(layer._container);\n\t}\n};\n\nvar create$2 = vml ? vmlCreate : svgCreate;\n\n/*\n * @class SVG\n * @inherits Renderer\n * @aka L.SVG\n *\n * Allows vector layers to be displayed with [SVG](https://developer.mozilla.org/docs/Web/SVG).\n * Inherits `Renderer`.\n *\n * Due to [technical limitations](http://caniuse.com/#search=svg), SVG is not\n * available in all web browsers, notably Android 2.x and 3.x.\n *\n * Although SVG is not available on IE7 and IE8, these browsers support\n * [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language)\n * (a now deprecated technology), and the SVG renderer will fall back to VML in\n * this case.\n *\n * @example\n *\n * Use SVG by default for all paths in the map:\n *\n * ```js\n * var map = L.map('map', {\n * \trenderer: L.svg()\n * });\n * ```\n *\n * Use a SVG renderer with extra padding for specific vector geometries:\n *\n * ```js\n * var map = L.map('map');\n * var myRenderer = L.svg({ padding: 0.5 });\n * var line = L.polyline( coordinates, { renderer: myRenderer } );\n * var circle = L.circle( center, { renderer: myRenderer } );\n * ```\n */\n\nvar SVG = Renderer.extend({\n\n\tgetEvents: function () {\n\t\tvar events = Renderer.prototype.getEvents.call(this);\n\t\tevents.zoomstart = this._onZoomStart;\n\t\treturn events;\n\t},\n\n\t_initContainer: function () {\n\t\tthis._container = create$2('svg');\n\n\t\t// makes it possible to click through svg root; we'll reset it back in individual paths\n\t\tthis._container.setAttribute('pointer-events', 'none');\n\n\t\tthis._rootGroup = create$2('g');\n\t\tthis._container.appendChild(this._rootGroup);\n\t},\n\n\t_destroyContainer: function () {\n\t\tremove(this._container);\n\t\toff(this._container);\n\t\tdelete this._container;\n\t\tdelete this._rootGroup;\n\t\tdelete this._svgSize;\n\t},\n\n\t_onZoomStart: function () {\n\t\t// Drag-then-pinch interactions might mess up the center and zoom.\n\t\t// In this case, the easiest way to prevent this is re-do the renderer\n\t\t// bounds and padding when the zooming starts.\n\t\tthis._update();\n\t},\n\n\t_update: function () {\n\t\tif (this._map._animatingZoom && this._bounds) { return; }\n\n\t\tRenderer.prototype._update.call(this);\n\n\t\tvar b = this._bounds,\n\t\t size = b.getSize(),\n\t\t container = this._container;\n\n\t\t// set size of svg-container if changed\n\t\tif (!this._svgSize || !this._svgSize.equals(size)) {\n\t\t\tthis._svgSize = size;\n\t\t\tcontainer.setAttribute('width', size.x);\n\t\t\tcontainer.setAttribute('height', size.y);\n\t\t}\n\n\t\t// movement: update container viewBox so that we don't have to change coordinates of individual layers\n\t\tsetPosition(container, b.min);\n\t\tcontainer.setAttribute('viewBox', [b.min.x, b.min.y, size.x, size.y].join(' '));\n\n\t\tthis.fire('update');\n\t},\n\n\t// methods below are called by vector layers implementations\n\n\t_initPath: function (layer) {\n\t\tvar path = layer._path = create$2('path');\n\n\t\t// @namespace Path\n\t\t// @option className: String = null\n\t\t// Custom class name set on an element. Only for SVG renderer.\n\t\tif (layer.options.className) {\n\t\t\taddClass(path, layer.options.className);\n\t\t}\n\n\t\tif (layer.options.interactive) {\n\t\t\taddClass(path, 'leaflet-interactive');\n\t\t}\n\n\t\tthis._updateStyle(layer);\n\t\tthis._layers[stamp(layer)] = layer;\n\t},\n\n\t_addPath: function (layer) {\n\t\tif (!this._rootGroup) { this._initContainer(); }\n\t\tthis._rootGroup.appendChild(layer._path);\n\t\tlayer.addInteractiveTarget(layer._path);\n\t},\n\n\t_removePath: function (layer) {\n\t\tremove(layer._path);\n\t\tlayer.removeInteractiveTarget(layer._path);\n\t\tdelete this._layers[stamp(layer)];\n\t},\n\n\t_updatePath: function (layer) {\n\t\tlayer._project();\n\t\tlayer._update();\n\t},\n\n\t_updateStyle: function (layer) {\n\t\tvar path = layer._path,\n\t\t options = layer.options;\n\n\t\tif (!path) { return; }\n\n\t\tif (options.stroke) {\n\t\t\tpath.setAttribute('stroke', options.color);\n\t\t\tpath.setAttribute('stroke-opacity', options.opacity);\n\t\t\tpath.setAttribute('stroke-width', options.weight);\n\t\t\tpath.setAttribute('stroke-linecap', options.lineCap);\n\t\t\tpath.setAttribute('stroke-linejoin', options.lineJoin);\n\n\t\t\tif (options.dashArray) {\n\t\t\t\tpath.setAttribute('stroke-dasharray', options.dashArray);\n\t\t\t} else {\n\t\t\t\tpath.removeAttribute('stroke-dasharray');\n\t\t\t}\n\n\t\t\tif (options.dashOffset) {\n\t\t\t\tpath.setAttribute('stroke-dashoffset', options.dashOffset);\n\t\t\t} else {\n\t\t\t\tpath.removeAttribute('stroke-dashoffset');\n\t\t\t}\n\t\t} else {\n\t\t\tpath.setAttribute('stroke', 'none');\n\t\t}\n\n\t\tif (options.fill) {\n\t\t\tpath.setAttribute('fill', options.fillColor || options.color);\n\t\t\tpath.setAttribute('fill-opacity', options.fillOpacity);\n\t\t\tpath.setAttribute('fill-rule', options.fillRule || 'evenodd');\n\t\t} else {\n\t\t\tpath.setAttribute('fill', 'none');\n\t\t}\n\t},\n\n\t_updatePoly: function (layer, closed) {\n\t\tthis._setPath(layer, pointsToPath(layer._parts, closed));\n\t},\n\n\t_updateCircle: function (layer) {\n\t\tvar p = layer._point,\n\t\t r = Math.max(Math.round(layer._radius), 1),\n\t\t r2 = Math.max(Math.round(layer._radiusY), 1) || r,\n\t\t arc = 'a' + r + ',' + r2 + ' 0 1,0 ';\n\n\t\t// drawing a circle with two half-arcs\n\t\tvar d = layer._empty() ? 'M0 0' :\n\t\t\t'M' + (p.x - r) + ',' + p.y +\n\t\t\tarc + (r * 2) + ',0 ' +\n\t\t\tarc + (-r * 2) + ',0 ';\n\n\t\tthis._setPath(layer, d);\n\t},\n\n\t_setPath: function (layer, path) {\n\t\tlayer._path.setAttribute('d', path);\n\t},\n\n\t// SVG does not have the concept of zIndex so we resort to changing the DOM order of elements\n\t_bringToFront: function (layer) {\n\t\ttoFront(layer._path);\n\t},\n\n\t_bringToBack: function (layer) {\n\t\ttoBack(layer._path);\n\t}\n});\n\nif (vml) {\n\tSVG.include(vmlMixin);\n}\n\n// @namespace SVG\n// @factory L.svg(options?: Renderer options)\n// Creates a SVG renderer with the given options.\nfunction svg$1(options) {\n\treturn svg || vml ? new SVG(options) : null;\n}\n\nMap.include({\n\t// @namespace Map; @method getRenderer(layer: Path): Renderer\n\t// Returns the instance of `Renderer` that should be used to render the given\n\t// `Path`. It will ensure that the `renderer` options of the map and paths\n\t// are respected, and that the renderers do exist on the map.\n\tgetRenderer: function (layer) {\n\t\t// @namespace Path; @option renderer: Renderer\n\t\t// Use this specific instance of `Renderer` for this path. Takes\n\t\t// precedence over the map's [default renderer](#map-renderer).\n\t\tvar renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;\n\n\t\tif (!renderer) {\n\t\t\trenderer = this._renderer = this._createRenderer();\n\t\t}\n\n\t\tif (!this.hasLayer(renderer)) {\n\t\t\tthis.addLayer(renderer);\n\t\t}\n\t\treturn renderer;\n\t},\n\n\t_getPaneRenderer: function (name) {\n\t\tif (name === 'overlayPane' || name === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar renderer = this._paneRenderers[name];\n\t\tif (renderer === undefined) {\n\t\t\trenderer = this._createRenderer({pane: name});\n\t\t\tthis._paneRenderers[name] = renderer;\n\t\t}\n\t\treturn renderer;\n\t},\n\n\t_createRenderer: function (options) {\n\t\t// @namespace Map; @option preferCanvas: Boolean = false\n\t\t// Whether `Path`s should be rendered on a `Canvas` renderer.\n\t\t// By default, all `Path`s are rendered in a `SVG` renderer.\n\t\treturn (this.options.preferCanvas && canvas$1(options)) || svg$1(options);\n\t}\n});\n\n/*\n * L.Rectangle extends Polygon and creates a rectangle when passed a LatLngBounds object.\n */\n\n/*\n * @class Rectangle\n * @aka L.Rectangle\n * @inherits Polygon\n *\n * A class for drawing rectangle overlays on a map. Extends `Polygon`.\n *\n * @example\n *\n * ```js\n * // define rectangle geographical bounds\n * var bounds = [[54.559322, -5.767822], [56.1210604, -3.021240]];\n *\n * // create an orange rectangle\n * L.rectangle(bounds, {color: \"#ff7800\", weight: 1}).addTo(map);\n *\n * // zoom the map to the rectangle bounds\n * map.fitBounds(bounds);\n * ```\n *\n */\n\n\nvar Rectangle = Polygon.extend({\n\tinitialize: function (latLngBounds, options) {\n\t\tPolygon.prototype.initialize.call(this, this._boundsToLatLngs(latLngBounds), options);\n\t},\n\n\t// @method setBounds(latLngBounds: LatLngBounds): this\n\t// Redraws the rectangle with the passed bounds.\n\tsetBounds: function (latLngBounds) {\n\t\treturn this.setLatLngs(this._boundsToLatLngs(latLngBounds));\n\t},\n\n\t_boundsToLatLngs: function (latLngBounds) {\n\t\tlatLngBounds = toLatLngBounds(latLngBounds);\n\t\treturn [\n\t\t\tlatLngBounds.getSouthWest(),\n\t\t\tlatLngBounds.getNorthWest(),\n\t\t\tlatLngBounds.getNorthEast(),\n\t\t\tlatLngBounds.getSouthEast()\n\t\t];\n\t}\n});\n\n\n// @factory L.rectangle(latLngBounds: LatLngBounds, options?: Polyline options)\nfunction rectangle(latLngBounds, options) {\n\treturn new Rectangle(latLngBounds, options);\n}\n\nSVG.create = create$2;\nSVG.pointsToPath = pointsToPath;\n\nGeoJSON.geometryToLayer = geometryToLayer;\nGeoJSON.coordsToLatLng = coordsToLatLng;\nGeoJSON.coordsToLatLngs = coordsToLatLngs;\nGeoJSON.latLngToCoords = latLngToCoords;\nGeoJSON.latLngsToCoords = latLngsToCoords;\nGeoJSON.getFeature = getFeature;\nGeoJSON.asFeature = asFeature;\n\n/*\n * L.Handler.BoxZoom is used to add shift-drag zoom interaction to the map\n * (zoom to a selected bounding box), enabled by default.\n */\n\n// @namespace Map\n// @section Interaction Options\nMap.mergeOptions({\n\t// @option boxZoom: Boolean = true\n\t// Whether the map can be zoomed to a rectangular area specified by\n\t// dragging the mouse while pressing the shift key.\n\tboxZoom: true\n});\n\nvar BoxZoom = Handler.extend({\n\tinitialize: function (map) {\n\t\tthis._map = map;\n\t\tthis._container = map._container;\n\t\tthis._pane = map._panes.overlayPane;\n\t\tthis._resetStateTimeout = 0;\n\t\tmap.on('unload', this._destroy, this);\n\t},\n\n\taddHooks: function () {\n\t\ton(this._container, 'mousedown', this._onMouseDown, this);\n\t},\n\n\tremoveHooks: function () {\n\t\toff(this._container, 'mousedown', this._onMouseDown, this);\n\t},\n\n\tmoved: function () {\n\t\treturn this._moved;\n\t},\n\n\t_destroy: function () {\n\t\tremove(this._pane);\n\t\tdelete this._pane;\n\t},\n\n\t_resetState: function () {\n\t\tthis._resetStateTimeout = 0;\n\t\tthis._moved = false;\n\t},\n\n\t_clearDeferredResetState: function () {\n\t\tif (this._resetStateTimeout !== 0) {\n\t\t\tclearTimeout(this._resetStateTimeout);\n\t\t\tthis._resetStateTimeout = 0;\n\t\t}\n\t},\n\n\t_onMouseDown: function (e) {\n\t\tif (!e.shiftKey || ((e.which !== 1) && (e.button !== 1))) { return false; }\n\n\t\t// Clear the deferred resetState if it hasn't executed yet, otherwise it\n\t\t// will interrupt the interaction and orphan a box element in the container.\n\t\tthis._clearDeferredResetState();\n\t\tthis._resetState();\n\n\t\tdisableTextSelection();\n\t\tdisableImageDrag();\n\n\t\tthis._startPoint = this._map.mouseEventToContainerPoint(e);\n\n\t\ton(document, {\n\t\t\tcontextmenu: stop,\n\t\t\tmousemove: this._onMouseMove,\n\t\t\tmouseup: this._onMouseUp,\n\t\t\tkeydown: this._onKeyDown\n\t\t}, this);\n\t},\n\n\t_onMouseMove: function (e) {\n\t\tif (!this._moved) {\n\t\t\tthis._moved = true;\n\n\t\t\tthis._box = create$1('div', 'leaflet-zoom-box', this._container);\n\t\t\taddClass(this._container, 'leaflet-crosshair');\n\n\t\t\tthis._map.fire('boxzoomstart');\n\t\t}\n\n\t\tthis._point = this._map.mouseEventToContainerPoint(e);\n\n\t\tvar bounds = new Bounds(this._point, this._startPoint),\n\t\t size = bounds.getSize();\n\n\t\tsetPosition(this._box, bounds.min);\n\n\t\tthis._box.style.width = size.x + 'px';\n\t\tthis._box.style.height = size.y + 'px';\n\t},\n\n\t_finish: function () {\n\t\tif (this._moved) {\n\t\t\tremove(this._box);\n\t\t\tremoveClass(this._container, 'leaflet-crosshair');\n\t\t}\n\n\t\tenableTextSelection();\n\t\tenableImageDrag();\n\n\t\toff(document, {\n\t\t\tcontextmenu: stop,\n\t\t\tmousemove: this._onMouseMove,\n\t\t\tmouseup: this._onMouseUp,\n\t\t\tkeydown: this._onKeyDown\n\t\t}, this);\n\t},\n\n\t_onMouseUp: function (e) {\n\t\tif ((e.which !== 1) && (e.button !== 1)) { return; }\n\n\t\tthis._finish();\n\n\t\tif (!this._moved) { return; }\n\t\t// Postpone to next JS tick so internal click event handling\n\t\t// still see it as \"moved\".\n\t\tthis._clearDeferredResetState();\n\t\tthis._resetStateTimeout = setTimeout(bind(this._resetState, this), 0);\n\n\t\tvar bounds = new LatLngBounds(\n\t\t this._map.containerPointToLatLng(this._startPoint),\n\t\t this._map.containerPointToLatLng(this._point));\n\n\t\tthis._map\n\t\t\t.fitBounds(bounds)\n\t\t\t.fire('boxzoomend', {boxZoomBounds: bounds});\n\t},\n\n\t_onKeyDown: function (e) {\n\t\tif (e.keyCode === 27) {\n\t\t\tthis._finish();\n\t\t}\n\t}\n});\n\n// @section Handlers\n// @property boxZoom: Handler\n// Box (shift-drag with mouse) zoom handler.\nMap.addInitHook('addHandler', 'boxZoom', BoxZoom);\n\n/*\n * L.Handler.DoubleClickZoom is used to handle double-click zoom on the map, enabled by default.\n */\n\n// @namespace Map\n// @section Interaction Options\n\nMap.mergeOptions({\n\t// @option doubleClickZoom: Boolean|String = true\n\t// Whether the map can be zoomed in by double clicking on it and\n\t// zoomed out by double clicking while holding shift. If passed\n\t// `'center'`, double-click zoom will zoom to the center of the\n\t// view regardless of where the mouse was.\n\tdoubleClickZoom: true\n});\n\nvar DoubleClickZoom = Handler.extend({\n\taddHooks: function () {\n\t\tthis._map.on('dblclick', this._onDoubleClick, this);\n\t},\n\n\tremoveHooks: function () {\n\t\tthis._map.off('dblclick', this._onDoubleClick, this);\n\t},\n\n\t_onDoubleClick: function (e) {\n\t\tvar map = this._map,\n\t\t oldZoom = map.getZoom(),\n\t\t delta = map.options.zoomDelta,\n\t\t zoom = e.originalEvent.shiftKey ? oldZoom - delta : oldZoom + delta;\n\n\t\tif (map.options.doubleClickZoom === 'center') {\n\t\t\tmap.setZoom(zoom);\n\t\t} else {\n\t\t\tmap.setZoomAround(e.containerPoint, zoom);\n\t\t}\n\t}\n});\n\n// @section Handlers\n//\n// Map properties include interaction handlers that allow you to control\n// interaction behavior in runtime, enabling or disabling certain features such\n// as dragging or touch zoom (see `Handler` methods). For example:\n//\n// ```js\n// map.doubleClickZoom.disable();\n// ```\n//\n// @property doubleClickZoom: Handler\n// Double click zoom handler.\nMap.addInitHook('addHandler', 'doubleClickZoom', DoubleClickZoom);\n\n/*\n * L.Handler.MapDrag is used to make the map draggable (with panning inertia), enabled by default.\n */\n\n// @namespace Map\n// @section Interaction Options\nMap.mergeOptions({\n\t// @option dragging: Boolean = true\n\t// Whether the map be draggable with mouse/touch or not.\n\tdragging: true,\n\n\t// @section Panning Inertia Options\n\t// @option inertia: Boolean = *\n\t// If enabled, panning of the map will have an inertia effect where\n\t// the map builds momentum while dragging and continues moving in\n\t// the same direction for some time. Feels especially nice on touch\n\t// devices. Enabled by default unless running on old Android devices.\n\tinertia: !android23,\n\n\t// @option inertiaDeceleration: Number = 3000\n\t// The rate with which the inertial movement slows down, in pixels/second².\n\tinertiaDeceleration: 3400, // px/s^2\n\n\t// @option inertiaMaxSpeed: Number = Infinity\n\t// Max speed of the inertial movement, in pixels/second.\n\tinertiaMaxSpeed: Infinity, // px/s\n\n\t// @option easeLinearity: Number = 0.2\n\teaseLinearity: 0.2,\n\n\t// TODO refactor, move to CRS\n\t// @option worldCopyJump: Boolean = false\n\t// With this option enabled, the map tracks when you pan to another \"copy\"\n\t// of the world and seamlessly jumps to the original one so that all overlays\n\t// like markers and vector layers are still visible.\n\tworldCopyJump: false,\n\n\t// @option maxBoundsViscosity: Number = 0.0\n\t// If `maxBounds` is set, this option will control how solid the bounds\n\t// are when dragging the map around. The default value of `0.0` allows the\n\t// user to drag outside the bounds at normal speed, higher values will\n\t// slow down map dragging outside bounds, and `1.0` makes the bounds fully\n\t// solid, preventing the user from dragging outside the bounds.\n\tmaxBoundsViscosity: 0.0\n});\n\nvar Drag = Handler.extend({\n\taddHooks: function () {\n\t\tif (!this._draggable) {\n\t\t\tvar map = this._map;\n\n\t\t\tthis._draggable = new Draggable(map._mapPane, map._container);\n\n\t\t\tthis._draggable.on({\n\t\t\t\tdragstart: this._onDragStart,\n\t\t\t\tdrag: this._onDrag,\n\t\t\t\tdragend: this._onDragEnd\n\t\t\t}, this);\n\n\t\t\tthis._draggable.on('predrag', this._onPreDragLimit, this);\n\t\t\tif (map.options.worldCopyJump) {\n\t\t\t\tthis._draggable.on('predrag', this._onPreDragWrap, this);\n\t\t\t\tmap.on('zoomend', this._onZoomEnd, this);\n\n\t\t\t\tmap.whenReady(this._onZoomEnd, this);\n\t\t\t}\n\t\t}\n\t\taddClass(this._map._container, 'leaflet-grab leaflet-touch-drag');\n\t\tthis._draggable.enable();\n\t\tthis._positions = [];\n\t\tthis._times = [];\n\t},\n\n\tremoveHooks: function () {\n\t\tremoveClass(this._map._container, 'leaflet-grab');\n\t\tremoveClass(this._map._container, 'leaflet-touch-drag');\n\t\tthis._draggable.disable();\n\t},\n\n\tmoved: function () {\n\t\treturn this._draggable && this._draggable._moved;\n\t},\n\n\tmoving: function () {\n\t\treturn this._draggable && this._draggable._moving;\n\t},\n\n\t_onDragStart: function () {\n\t\tvar map = this._map;\n\n\t\tmap._stop();\n\t\tif (this._map.options.maxBounds && this._map.options.maxBoundsViscosity) {\n\t\t\tvar bounds = toLatLngBounds(this._map.options.maxBounds);\n\n\t\t\tthis._offsetLimit = toBounds(\n\t\t\t\tthis._map.latLngToContainerPoint(bounds.getNorthWest()).multiplyBy(-1),\n\t\t\t\tthis._map.latLngToContainerPoint(bounds.getSouthEast()).multiplyBy(-1)\n\t\t\t\t\t.add(this._map.getSize()));\n\n\t\t\tthis._viscosity = Math.min(1.0, Math.max(0.0, this._map.options.maxBoundsViscosity));\n\t\t} else {\n\t\t\tthis._offsetLimit = null;\n\t\t}\n\n\t\tmap\n\t\t .fire('movestart')\n\t\t .fire('dragstart');\n\n\t\tif (map.options.inertia) {\n\t\t\tthis._positions = [];\n\t\t\tthis._times = [];\n\t\t}\n\t},\n\n\t_onDrag: function (e) {\n\t\tif (this._map.options.inertia) {\n\t\t\tvar time = this._lastTime = +new Date(),\n\t\t\t pos = this._lastPos = this._draggable._absPos || this._draggable._newPos;\n\n\t\t\tthis._positions.push(pos);\n\t\t\tthis._times.push(time);\n\n\t\t\tthis._prunePositions(time);\n\t\t}\n\n\t\tthis._map\n\t\t .fire('move', e)\n\t\t .fire('drag', e);\n\t},\n\n\t_prunePositions: function (time) {\n\t\twhile (this._positions.length > 1 && time - this._times[0] > 50) {\n\t\t\tthis._positions.shift();\n\t\t\tthis._times.shift();\n\t\t}\n\t},\n\n\t_onZoomEnd: function () {\n\t\tvar pxCenter = this._map.getSize().divideBy(2),\n\t\t pxWorldCenter = this._map.latLngToLayerPoint([0, 0]);\n\n\t\tthis._initialWorldOffset = pxWorldCenter.subtract(pxCenter).x;\n\t\tthis._worldWidth = this._map.getPixelWorldBounds().getSize().x;\n\t},\n\n\t_viscousLimit: function (value, threshold) {\n\t\treturn value - (value - threshold) * this._viscosity;\n\t},\n\n\t_onPreDragLimit: function () {\n\t\tif (!this._viscosity || !this._offsetLimit) { return; }\n\n\t\tvar offset = this._draggable._newPos.subtract(this._draggable._startPos);\n\n\t\tvar limit = this._offsetLimit;\n\t\tif (offset.x < limit.min.x) { offset.x = this._viscousLimit(offset.x, limit.min.x); }\n\t\tif (offset.y < limit.min.y) { offset.y = this._viscousLimit(offset.y, limit.min.y); }\n\t\tif (offset.x > limit.max.x) { offset.x = this._viscousLimit(offset.x, limit.max.x); }\n\t\tif (offset.y > limit.max.y) { offset.y = this._viscousLimit(offset.y, limit.max.y); }\n\n\t\tthis._draggable._newPos = this._draggable._startPos.add(offset);\n\t},\n\n\t_onPreDragWrap: function () {\n\t\t// TODO refactor to be able to adjust map pane position after zoom\n\t\tvar worldWidth = this._worldWidth,\n\t\t halfWidth = Math.round(worldWidth / 2),\n\t\t dx = this._initialWorldOffset,\n\t\t x = this._draggable._newPos.x,\n\t\t newX1 = (x - halfWidth + dx) % worldWidth + halfWidth - dx,\n\t\t newX2 = (x + halfWidth + dx) % worldWidth - halfWidth - dx,\n\t\t newX = Math.abs(newX1 + dx) < Math.abs(newX2 + dx) ? newX1 : newX2;\n\n\t\tthis._draggable._absPos = this._draggable._newPos.clone();\n\t\tthis._draggable._newPos.x = newX;\n\t},\n\n\t_onDragEnd: function (e) {\n\t\tvar map = this._map,\n\t\t options = map.options,\n\n\t\t noInertia = !options.inertia || this._times.length < 2;\n\n\t\tmap.fire('dragend', e);\n\n\t\tif (noInertia) {\n\t\t\tmap.fire('moveend');\n\n\t\t} else {\n\t\t\tthis._prunePositions(+new Date());\n\n\t\t\tvar direction = this._lastPos.subtract(this._positions[0]),\n\t\t\t duration = (this._lastTime - this._times[0]) / 1000,\n\t\t\t ease = options.easeLinearity,\n\n\t\t\t speedVector = direction.multiplyBy(ease / duration),\n\t\t\t speed = speedVector.distanceTo([0, 0]),\n\n\t\t\t limitedSpeed = Math.min(options.inertiaMaxSpeed, speed),\n\t\t\t limitedSpeedVector = speedVector.multiplyBy(limitedSpeed / speed),\n\n\t\t\t decelerationDuration = limitedSpeed / (options.inertiaDeceleration * ease),\n\t\t\t offset = limitedSpeedVector.multiplyBy(-decelerationDuration / 2).round();\n\n\t\t\tif (!offset.x && !offset.y) {\n\t\t\t\tmap.fire('moveend');\n\n\t\t\t} else {\n\t\t\t\toffset = map._limitOffset(offset, map.options.maxBounds);\n\n\t\t\t\trequestAnimFrame(function () {\n\t\t\t\t\tmap.panBy(offset, {\n\t\t\t\t\t\tduration: decelerationDuration,\n\t\t\t\t\t\teaseLinearity: ease,\n\t\t\t\t\t\tnoMoveStart: true,\n\t\t\t\t\t\tanimate: true\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n});\n\n// @section Handlers\n// @property dragging: Handler\n// Map dragging handler (by both mouse and touch).\nMap.addInitHook('addHandler', 'dragging', Drag);\n\n/*\n * L.Map.Keyboard is handling keyboard interaction with the map, enabled by default.\n */\n\n// @namespace Map\n// @section Keyboard Navigation Options\nMap.mergeOptions({\n\t// @option keyboard: Boolean = true\n\t// Makes the map focusable and allows users to navigate the map with keyboard\n\t// arrows and `+`/`-` keys.\n\tkeyboard: true,\n\n\t// @option keyboardPanDelta: Number = 80\n\t// Amount of pixels to pan when pressing an arrow key.\n\tkeyboardPanDelta: 80\n});\n\nvar Keyboard = Handler.extend({\n\n\tkeyCodes: {\n\t\tleft: [37],\n\t\tright: [39],\n\t\tdown: [40],\n\t\tup: [38],\n\t\tzoomIn: [187, 107, 61, 171],\n\t\tzoomOut: [189, 109, 54, 173]\n\t},\n\n\tinitialize: function (map) {\n\t\tthis._map = map;\n\n\t\tthis._setPanDelta(map.options.keyboardPanDelta);\n\t\tthis._setZoomDelta(map.options.zoomDelta);\n\t},\n\n\taddHooks: function () {\n\t\tvar container = this._map._container;\n\n\t\t// make the container focusable by tabbing\n\t\tif (container.tabIndex <= 0) {\n\t\t\tcontainer.tabIndex = '0';\n\t\t}\n\n\t\ton(container, {\n\t\t\tfocus: this._onFocus,\n\t\t\tblur: this._onBlur,\n\t\t\tmousedown: this._onMouseDown\n\t\t}, this);\n\n\t\tthis._map.on({\n\t\t\tfocus: this._addHooks,\n\t\t\tblur: this._removeHooks\n\t\t}, this);\n\t},\n\n\tremoveHooks: function () {\n\t\tthis._removeHooks();\n\n\t\toff(this._map._container, {\n\t\t\tfocus: this._onFocus,\n\t\t\tblur: this._onBlur,\n\t\t\tmousedown: this._onMouseDown\n\t\t}, this);\n\n\t\tthis._map.off({\n\t\t\tfocus: this._addHooks,\n\t\t\tblur: this._removeHooks\n\t\t}, this);\n\t},\n\n\t_onMouseDown: function () {\n\t\tif (this._focused) { return; }\n\n\t\tvar body = document.body,\n\t\t docEl = document.documentElement,\n\t\t top = body.scrollTop || docEl.scrollTop,\n\t\t left = body.scrollLeft || docEl.scrollLeft;\n\n\t\tthis._map._container.focus();\n\n\t\twindow.scrollTo(left, top);\n\t},\n\n\t_onFocus: function () {\n\t\tthis._focused = true;\n\t\tthis._map.fire('focus');\n\t},\n\n\t_onBlur: function () {\n\t\tthis._focused = false;\n\t\tthis._map.fire('blur');\n\t},\n\n\t_setPanDelta: function (panDelta) {\n\t\tvar keys = this._panKeys = {},\n\t\t codes = this.keyCodes,\n\t\t i, len;\n\n\t\tfor (i = 0, len = codes.left.length; i < len; i++) {\n\t\t\tkeys[codes.left[i]] = [-1 * panDelta, 0];\n\t\t}\n\t\tfor (i = 0, len = codes.right.length; i < len; i++) {\n\t\t\tkeys[codes.right[i]] = [panDelta, 0];\n\t\t}\n\t\tfor (i = 0, len = codes.down.length; i < len; i++) {\n\t\t\tkeys[codes.down[i]] = [0, panDelta];\n\t\t}\n\t\tfor (i = 0, len = codes.up.length; i < len; i++) {\n\t\t\tkeys[codes.up[i]] = [0, -1 * panDelta];\n\t\t}\n\t},\n\n\t_setZoomDelta: function (zoomDelta) {\n\t\tvar keys = this._zoomKeys = {},\n\t\t codes = this.keyCodes,\n\t\t i, len;\n\n\t\tfor (i = 0, len = codes.zoomIn.length; i < len; i++) {\n\t\t\tkeys[codes.zoomIn[i]] = zoomDelta;\n\t\t}\n\t\tfor (i = 0, len = codes.zoomOut.length; i < len; i++) {\n\t\t\tkeys[codes.zoomOut[i]] = -zoomDelta;\n\t\t}\n\t},\n\n\t_addHooks: function () {\n\t\ton(document, 'keydown', this._onKeyDown, this);\n\t},\n\n\t_removeHooks: function () {\n\t\toff(document, 'keydown', this._onKeyDown, this);\n\t},\n\n\t_onKeyDown: function (e) {\n\t\tif (e.altKey || e.ctrlKey || e.metaKey) { return; }\n\n\t\tvar key = e.keyCode,\n\t\t map = this._map,\n\t\t offset;\n\n\t\tif (key in this._panKeys) {\n\t\t\tif (!map._panAnim || !map._panAnim._inProgress) {\n\t\t\t\toffset = this._panKeys[key];\n\t\t\t\tif (e.shiftKey) {\n\t\t\t\t\toffset = toPoint(offset).multiplyBy(3);\n\t\t\t\t}\n\n\t\t\t\tmap.panBy(offset);\n\n\t\t\t\tif (map.options.maxBounds) {\n\t\t\t\t\tmap.panInsideBounds(map.options.maxBounds);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (key in this._zoomKeys) {\n\t\t\tmap.setZoom(map.getZoom() + (e.shiftKey ? 3 : 1) * this._zoomKeys[key]);\n\n\t\t} else if (key === 27 && map._popup && map._popup.options.closeOnEscapeKey) {\n\t\t\tmap.closePopup();\n\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\tstop(e);\n\t}\n});\n\n// @section Handlers\n// @section Handlers\n// @property keyboard: Handler\n// Keyboard navigation handler.\nMap.addInitHook('addHandler', 'keyboard', Keyboard);\n\n/*\n * L.Handler.ScrollWheelZoom is used by L.Map to enable mouse scroll wheel zoom on the map.\n */\n\n// @namespace Map\n// @section Interaction Options\nMap.mergeOptions({\n\t// @section Mousewheel options\n\t// @option scrollWheelZoom: Boolean|String = true\n\t// Whether the map can be zoomed by using the mouse wheel. If passed `'center'`,\n\t// it will zoom to the center of the view regardless of where the mouse was.\n\tscrollWheelZoom: true,\n\n\t// @option wheelDebounceTime: Number = 40\n\t// Limits the rate at which a wheel can fire (in milliseconds). By default\n\t// user can't zoom via wheel more often than once per 40 ms.\n\twheelDebounceTime: 40,\n\n\t// @option wheelPxPerZoomLevel: Number = 60\n\t// How many scroll pixels (as reported by [L.DomEvent.getWheelDelta](#domevent-getwheeldelta))\n\t// mean a change of one full zoom level. Smaller values will make wheel-zooming\n\t// faster (and vice versa).\n\twheelPxPerZoomLevel: 60\n});\n\nvar ScrollWheelZoom = Handler.extend({\n\taddHooks: function () {\n\t\ton(this._map._container, 'mousewheel', this._onWheelScroll, this);\n\n\t\tthis._delta = 0;\n\t},\n\n\tremoveHooks: function () {\n\t\toff(this._map._container, 'mousewheel', this._onWheelScroll, this);\n\t},\n\n\t_onWheelScroll: function (e) {\n\t\tvar delta = getWheelDelta(e);\n\n\t\tvar debounce = this._map.options.wheelDebounceTime;\n\n\t\tthis._delta += delta;\n\t\tthis._lastMousePos = this._map.mouseEventToContainerPoint(e);\n\n\t\tif (!this._startTime) {\n\t\t\tthis._startTime = +new Date();\n\t\t}\n\n\t\tvar left = Math.max(debounce - (+new Date() - this._startTime), 0);\n\n\t\tclearTimeout(this._timer);\n\t\tthis._timer = setTimeout(bind(this._performZoom, this), left);\n\n\t\tstop(e);\n\t},\n\n\t_performZoom: function () {\n\t\tvar map = this._map,\n\t\t zoom = map.getZoom(),\n\t\t snap = this._map.options.zoomSnap || 0;\n\n\t\tmap._stop(); // stop panning and fly animations if any\n\n\t\t// map the delta with a sigmoid function to -4..4 range leaning on -1..1\n\t\tvar d2 = this._delta / (this._map.options.wheelPxPerZoomLevel * 4),\n\t\t d3 = 4 * Math.log(2 / (1 + Math.exp(-Math.abs(d2)))) / Math.LN2,\n\t\t d4 = snap ? Math.ceil(d3 / snap) * snap : d3,\n\t\t delta = map._limitZoom(zoom + (this._delta > 0 ? d4 : -d4)) - zoom;\n\n\t\tthis._delta = 0;\n\t\tthis._startTime = null;\n\n\t\tif (!delta) { return; }\n\n\t\tif (map.options.scrollWheelZoom === 'center') {\n\t\t\tmap.setZoom(zoom + delta);\n\t\t} else {\n\t\t\tmap.setZoomAround(this._lastMousePos, zoom + delta);\n\t\t}\n\t}\n});\n\n// @section Handlers\n// @property scrollWheelZoom: Handler\n// Scroll wheel zoom handler.\nMap.addInitHook('addHandler', 'scrollWheelZoom', ScrollWheelZoom);\n\n/*\n * L.Map.Tap is used to enable mobile hacks like quick taps and long hold.\n */\n\n// @namespace Map\n// @section Interaction Options\nMap.mergeOptions({\n\t// @section Touch interaction options\n\t// @option tap: Boolean = true\n\t// Enables mobile hacks for supporting instant taps (fixing 200ms click\n\t// delay on iOS/Android) and touch holds (fired as `contextmenu` events).\n\ttap: true,\n\n\t// @option tapTolerance: Number = 15\n\t// The max number of pixels a user can shift his finger during touch\n\t// for it to be considered a valid tap.\n\ttapTolerance: 15\n});\n\nvar Tap = Handler.extend({\n\taddHooks: function () {\n\t\ton(this._map._container, 'touchstart', this._onDown, this);\n\t},\n\n\tremoveHooks: function () {\n\t\toff(this._map._container, 'touchstart', this._onDown, this);\n\t},\n\n\t_onDown: function (e) {\n\t\tif (!e.touches) { return; }\n\n\t\tpreventDefault(e);\n\n\t\tthis._fireClick = true;\n\n\t\t// don't simulate click or track longpress if more than 1 touch\n\t\tif (e.touches.length > 1) {\n\t\t\tthis._fireClick = false;\n\t\t\tclearTimeout(this._holdTimeout);\n\t\t\treturn;\n\t\t}\n\n\t\tvar first = e.touches[0],\n\t\t el = first.target;\n\n\t\tthis._startPos = this._newPos = new Point(first.clientX, first.clientY);\n\n\t\t// if touching a link, highlight it\n\t\tif (el.tagName && el.tagName.toLowerCase() === 'a') {\n\t\t\taddClass(el, 'leaflet-active');\n\t\t}\n\n\t\t// simulate long hold but setting a timeout\n\t\tthis._holdTimeout = setTimeout(bind(function () {\n\t\t\tif (this._isTapValid()) {\n\t\t\t\tthis._fireClick = false;\n\t\t\t\tthis._onUp();\n\t\t\t\tthis._simulateEvent('contextmenu', first);\n\t\t\t}\n\t\t}, this), 1000);\n\n\t\tthis._simulateEvent('mousedown', first);\n\n\t\ton(document, {\n\t\t\ttouchmove: this._onMove,\n\t\t\ttouchend: this._onUp\n\t\t}, this);\n\t},\n\n\t_onUp: function (e) {\n\t\tclearTimeout(this._holdTimeout);\n\n\t\toff(document, {\n\t\t\ttouchmove: this._onMove,\n\t\t\ttouchend: this._onUp\n\t\t}, this);\n\n\t\tif (this._fireClick && e && e.changedTouches) {\n\n\t\t\tvar first = e.changedTouches[0],\n\t\t\t el = first.target;\n\n\t\t\tif (el && el.tagName && el.tagName.toLowerCase() === 'a') {\n\t\t\t\tremoveClass(el, 'leaflet-active');\n\t\t\t}\n\n\t\t\tthis._simulateEvent('mouseup', first);\n\n\t\t\t// simulate click if the touch didn't move too much\n\t\t\tif (this._isTapValid()) {\n\t\t\t\tthis._simulateEvent('click', first);\n\t\t\t}\n\t\t}\n\t},\n\n\t_isTapValid: function () {\n\t\treturn this._newPos.distanceTo(this._startPos) <= this._map.options.tapTolerance;\n\t},\n\n\t_onMove: function (e) {\n\t\tvar first = e.touches[0];\n\t\tthis._newPos = new Point(first.clientX, first.clientY);\n\t\tthis._simulateEvent('mousemove', first);\n\t},\n\n\t_simulateEvent: function (type, e) {\n\t\tvar simulatedEvent = document.createEvent('MouseEvents');\n\n\t\tsimulatedEvent._simulated = true;\n\t\te.target._simulatedClick = true;\n\n\t\tsimulatedEvent.initMouseEvent(\n\t\t type, true, true, window, 1,\n\t\t e.screenX, e.screenY,\n\t\t e.clientX, e.clientY,\n\t\t false, false, false, false, 0, null);\n\n\t\te.target.dispatchEvent(simulatedEvent);\n\t}\n});\n\n// @section Handlers\n// @property tap: Handler\n// Mobile touch hacks (quick tap and touch hold) handler.\nif (touch && !pointer) {\n\tMap.addInitHook('addHandler', 'tap', Tap);\n}\n\n/*\n * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers.\n */\n\n// @namespace Map\n// @section Interaction Options\nMap.mergeOptions({\n\t// @section Touch interaction options\n\t// @option touchZoom: Boolean|String = *\n\t// Whether the map can be zoomed by touch-dragging with two fingers. If\n\t// passed `'center'`, it will zoom to the center of the view regardless of\n\t// where the touch events (fingers) were. Enabled for touch-capable web\n\t// browsers except for old Androids.\n\ttouchZoom: touch && !android23,\n\n\t// @option bounceAtZoomLimits: Boolean = true\n\t// Set it to false if you don't want the map to zoom beyond min/max zoom\n\t// and then bounce back when pinch-zooming.\n\tbounceAtZoomLimits: true\n});\n\nvar TouchZoom = Handler.extend({\n\taddHooks: function () {\n\t\taddClass(this._map._container, 'leaflet-touch-zoom');\n\t\ton(this._map._container, 'touchstart', this._onTouchStart, this);\n\t},\n\n\tremoveHooks: function () {\n\t\tremoveClass(this._map._container, 'leaflet-touch-zoom');\n\t\toff(this._map._container, 'touchstart', this._onTouchStart, this);\n\t},\n\n\t_onTouchStart: function (e) {\n\t\tvar map = this._map;\n\t\tif (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; }\n\n\t\tvar p1 = map.mouseEventToContainerPoint(e.touches[0]),\n\t\t p2 = map.mouseEventToContainerPoint(e.touches[1]);\n\n\t\tthis._centerPoint = map.getSize()._divideBy(2);\n\t\tthis._startLatLng = map.containerPointToLatLng(this._centerPoint);\n\t\tif (map.options.touchZoom !== 'center') {\n\t\t\tthis._pinchStartLatLng = map.containerPointToLatLng(p1.add(p2)._divideBy(2));\n\t\t}\n\n\t\tthis._startDist = p1.distanceTo(p2);\n\t\tthis._startZoom = map.getZoom();\n\n\t\tthis._moved = false;\n\t\tthis._zooming = true;\n\n\t\tmap._stop();\n\n\t\ton(document, 'touchmove', this._onTouchMove, this);\n\t\ton(document, 'touchend', this._onTouchEnd, this);\n\n\t\tpreventDefault(e);\n\t},\n\n\t_onTouchMove: function (e) {\n\t\tif (!e.touches || e.touches.length !== 2 || !this._zooming) { return; }\n\n\t\tvar map = this._map,\n\t\t p1 = map.mouseEventToContainerPoint(e.touches[0]),\n\t\t p2 = map.mouseEventToContainerPoint(e.touches[1]),\n\t\t scale = p1.distanceTo(p2) / this._startDist;\n\n\t\tthis._zoom = map.getScaleZoom(scale, this._startZoom);\n\n\t\tif (!map.options.bounceAtZoomLimits && (\n\t\t\t(this._zoom < map.getMinZoom() && scale < 1) ||\n\t\t\t(this._zoom > map.getMaxZoom() && scale > 1))) {\n\t\t\tthis._zoom = map._limitZoom(this._zoom);\n\t\t}\n\n\t\tif (map.options.touchZoom === 'center') {\n\t\t\tthis._center = this._startLatLng;\n\t\t\tif (scale === 1) { return; }\n\t\t} else {\n\t\t\t// Get delta from pinch to center, so centerLatLng is delta applied to initial pinchLatLng\n\t\t\tvar delta = p1._add(p2)._divideBy(2)._subtract(this._centerPoint);\n\t\t\tif (scale === 1 && delta.x === 0 && delta.y === 0) { return; }\n\t\t\tthis._center = map.unproject(map.project(this._pinchStartLatLng, this._zoom).subtract(delta), this._zoom);\n\t\t}\n\n\t\tif (!this._moved) {\n\t\t\tmap._moveStart(true, false);\n\t\t\tthis._moved = true;\n\t\t}\n\n\t\tcancelAnimFrame(this._animRequest);\n\n\t\tvar moveFn = bind(map._move, map, this._center, this._zoom, {pinch: true, round: false});\n\t\tthis._animRequest = requestAnimFrame(moveFn, this, true);\n\n\t\tpreventDefault(e);\n\t},\n\n\t_onTouchEnd: function () {\n\t\tif (!this._moved || !this._zooming) {\n\t\t\tthis._zooming = false;\n\t\t\treturn;\n\t\t}\n\n\t\tthis._zooming = false;\n\t\tcancelAnimFrame(this._animRequest);\n\n\t\toff(document, 'touchmove', this._onTouchMove);\n\t\toff(document, 'touchend', this._onTouchEnd);\n\n\t\t// Pinch updates GridLayers' levels only when zoomSnap is off, so zoomSnap becomes noUpdate.\n\t\tif (this._map.options.zoomAnimation) {\n\t\t\tthis._map._animateZoom(this._center, this._map._limitZoom(this._zoom), true, this._map.options.zoomSnap);\n\t\t} else {\n\t\t\tthis._map._resetView(this._center, this._map._limitZoom(this._zoom));\n\t\t}\n\t}\n});\n\n// @section Handlers\n// @property touchZoom: Handler\n// Touch zoom handler.\nMap.addInitHook('addHandler', 'touchZoom', TouchZoom);\n\nMap.BoxZoom = BoxZoom;\nMap.DoubleClickZoom = DoubleClickZoom;\nMap.Drag = Drag;\nMap.Keyboard = Keyboard;\nMap.ScrollWheelZoom = ScrollWheelZoom;\nMap.Tap = Tap;\nMap.TouchZoom = TouchZoom;\n\nObject.freeze = freeze;\n\nexports.version = version;\nexports.Control = Control;\nexports.control = control;\nexports.Browser = Browser;\nexports.Evented = Evented;\nexports.Mixin = Mixin;\nexports.Util = Util;\nexports.Class = Class;\nexports.Handler = Handler;\nexports.extend = extend;\nexports.bind = bind;\nexports.stamp = stamp;\nexports.setOptions = setOptions;\nexports.DomEvent = DomEvent;\nexports.DomUtil = DomUtil;\nexports.PosAnimation = PosAnimation;\nexports.Draggable = Draggable;\nexports.LineUtil = LineUtil;\nexports.PolyUtil = PolyUtil;\nexports.Point = Point;\nexports.point = toPoint;\nexports.Bounds = Bounds;\nexports.bounds = toBounds;\nexports.Transformation = Transformation;\nexports.transformation = toTransformation;\nexports.Projection = index;\nexports.LatLng = LatLng;\nexports.latLng = toLatLng;\nexports.LatLngBounds = LatLngBounds;\nexports.latLngBounds = toLatLngBounds;\nexports.CRS = CRS;\nexports.GeoJSON = GeoJSON;\nexports.geoJSON = geoJSON;\nexports.geoJson = geoJson;\nexports.Layer = Layer;\nexports.LayerGroup = LayerGroup;\nexports.layerGroup = layerGroup;\nexports.FeatureGroup = FeatureGroup;\nexports.featureGroup = featureGroup;\nexports.ImageOverlay = ImageOverlay;\nexports.imageOverlay = imageOverlay;\nexports.VideoOverlay = VideoOverlay;\nexports.videoOverlay = videoOverlay;\nexports.SVGOverlay = SVGOverlay;\nexports.svgOverlay = svgOverlay;\nexports.DivOverlay = DivOverlay;\nexports.Popup = Popup;\nexports.popup = popup;\nexports.Tooltip = Tooltip;\nexports.tooltip = tooltip;\nexports.Icon = Icon;\nexports.icon = icon;\nexports.DivIcon = DivIcon;\nexports.divIcon = divIcon;\nexports.Marker = Marker;\nexports.marker = marker;\nexports.TileLayer = TileLayer;\nexports.tileLayer = tileLayer;\nexports.GridLayer = GridLayer;\nexports.gridLayer = gridLayer;\nexports.SVG = SVG;\nexports.svg = svg$1;\nexports.Renderer = Renderer;\nexports.Canvas = Canvas;\nexports.canvas = canvas$1;\nexports.Path = Path;\nexports.CircleMarker = CircleMarker;\nexports.circleMarker = circleMarker;\nexports.Circle = Circle;\nexports.circle = circle;\nexports.Polyline = Polyline;\nexports.polyline = polyline;\nexports.Polygon = Polygon;\nexports.polygon = polygon;\nexports.Rectangle = Rectangle;\nexports.rectangle = rectangle;\nexports.Map = Map;\nexports.map = createMap;\n\nvar oldL = window.L;\nexports.noConflict = function() {\n\twindow.L = oldL;\n\treturn this;\n}\n\n// Always export us to window global (see #2364)\nwindow.L = exports;\n\n})));\n//# sourceMappingURL=leaflet-src.js.map\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbGVhZmxldC9kaXN0L2xlYWZsZXQtc3JjLmpzPzllYjciXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDLEtBQTREO0FBQzdEO0FBQ0Esd0JBQXdCO0FBQ3hCLENBQUMsNEJBQTRCOztBQUU3Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZ0NBQWdDLFlBQVk7O0FBRTVDO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQyxTQUFTO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0JBQW9CLGNBQWM7O0FBRWxDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDBEQUEwRCxtQkFBbUI7QUFDN0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0JBQW9CLGVBQWU7O0FBRW5DO0FBQ0EsOEVBQThFLEVBQUUsR0FBRyxFQUFFO0FBQ3JGLDRCQUE0QixtQkFBbUI7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0Isa0JBQWtCO0FBQ2xDLHdCQUF3QixVQUFVO0FBQ2xDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQzs7QUFFcEM7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsK0RBQStELHlCQUF5Qjs7QUFFeEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsOEJBQThCLFFBQVE7O0FBRXRDO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxnREFBZ0QsU0FBUztBQUN6RDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUNBQW1DO0FBQ25DOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtEQUFrRCxRQUFROztBQUUxRDs7QUFFQSxnQkFBZ0IscUJBQXFCO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLHVDQUF1QztBQUNyRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBOztBQUVBLHNDQUFzQyxTQUFTO0FBQy9DO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDs7QUFFQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUIscUJBQXFCO0FBQzFDOztBQUVBO0FBQ0EseUNBQXlDLFNBQVM7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixRQUFROztBQUU5Qjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHNDQUFzQyxTQUFTO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBLDRCQUE0QixVQUFVO0FBQ3RDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxhQUFhOztBQUVwRCx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQSwyQ0FBMkMsU0FBUztBQUNwRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxhQUFhOztBQUVuRDtBQUNBO0FBQ0E7QUFDQSwwREFBMEQsYUFBYTtBQUN2RTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQSxXQUFXOztBQUVYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx3Q0FBd0MscUJBQXFCO0FBQzdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVLFFBQVE7O0FBRWxCOztBQUVBLHFDQUFxQyxTQUFTO0FBQzlDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEIsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEIsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHlDQUF5QztBQUN6QyxnQkFBZ0IsUUFBUTs7QUFFeEI7O0FBRUEsc0NBQXNDLFNBQVM7QUFDL0M7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBOztBQUVBLHNCQUFzQixhQUFhOztBQUVuQyxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixjQUFjOztBQUU5Qjs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxpQkFBaUI7QUFDL0IsY0FBYyxpQkFBaUI7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLGNBQWM7O0FBRTNCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7OztBQUlBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5Q0FBeUMseUJBQXlCLE9BQU8sc0NBQXNDOztBQUUvRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGFBQWE7O0FBRW5DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUJBQXFCO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDO0FBQ3hDO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0JBQXdCO0FBQ3hCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGLENBQUM7O0FBRUQsMEJBQTBCO0FBQzFCO0FBQ0EsQ0FBQzs7QUFFRCxrQkFBa0I7QUFDbEI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdDQUFnQyxTQUFTO0FBQ3pDOztBQUVBLG1DQUFtQyxVQUFVO0FBQzdDO0FBQ0E7QUFDQTs7QUFFQSxrQ0FBa0M7QUFDbEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSx5QkFBeUI7QUFDekI7O0FBRUEsNEJBQTRCO0FBQzVCOztBQUVBLDJCQUEyQjtBQUMzQjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGdDQUFnQztBQUNoQzs7QUFFQTtBQUNBLGdGQUFnRjtBQUNoRixtQ0FBbUM7QUFDbkM7O0FBRUEsNEJBQTRCO0FBQzVCOztBQUVBLDZCQUE2QjtBQUM3Qjs7QUFFQSw0QkFBNEI7QUFDNUI7O0FBRUEsNkJBQTZCO0FBQzdCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwwQkFBMEI7QUFDMUI7O0FBRUEsMkJBQTJCO0FBQzNCOztBQUVBLCtCQUErQjtBQUMvQjs7QUFFQSw4QkFBOEI7QUFDOUI7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDZCQUE2QjtBQUM3Qjs7QUFFQSxtQ0FBbUM7QUFDbkM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDO0FBQ2xDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsRUFBRTtBQUNGO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEVBQUU7QUFDRjs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7O0FBRUEsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1HQUFtRyxRQUFROztBQUUzRztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDhDQUE4QyxRQUFRO0FBQ3REO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUEsa0JBQWtCLFFBQVE7O0FBRTFCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLFFBQVE7QUFDdkQ7QUFDQSxxQkFBcUI7QUFDckI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsU0FBUztBQUNoRDtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxvQkFBb0IsUUFBUTtBQUM1Qjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxnQkFBZ0Isa0JBQWtCO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLFFBQVE7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QixRQUFRO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0Q0FBNEM7O0FBRTVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNkNBQTZDLHVDQUF1QztBQUNwRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0RBQWdELHVDQUF1QztBQUN2Rjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLDRDQUE0QyxhQUFhOztBQUV6RDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUEsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxnQkFBZ0IsYUFBYTs7QUFFN0I7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUEsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFLDRCQUE0QjtBQUM5QjtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsdUNBQXVDOztBQUV2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBLGdCQUFnQixhQUFhOztBQUU3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsUUFBUTs7QUFFbEM7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkRBQTZEO0FBQzdEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRixxQ0FBcUM7QUFDckM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EseURBQXlELFlBQVk7QUFDckU7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7OztBQUdGOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBLDJCQUEyQix5QkFBeUI7QUFDcEQsMEJBQTBCLHFEQUFxRDtBQUMvRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsY0FBYztBQUM3RCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsd0NBQXdDLGNBQWM7QUFDdEQsRUFBRTs7QUFFRjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxvQ0FBb0M7QUFDcEMsMkNBQTJDLGFBQWE7QUFDeEQsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxvQkFBb0IseUNBQXlDO0FBQzdELG9CQUFvQix5Q0FBeUM7QUFDN0Qsb0JBQW9CLDBCQUEwQjs7QUFFOUM7O0FBRUEsaUJBQWlCLDZDQUE2QztBQUM5RCxpQkFBaUIsK0RBQStEOztBQUVoRix1QkFBdUIsaUNBQWlDOztBQUV4RDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTSxZQUFZOztBQUVsQixJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsYUFBYTs7QUFFbkM7QUFDQTtBQUNBO0FBQ0EsR0FBRyxzQkFBc0IsY0FBYzs7QUFFdkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtCQUErQixhQUFhOztBQUU1QztBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxpRUFBaUUsWUFBWTtBQUM3RTtBQUNBLE1BQU0sY0FBYztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGFBQWE7O0FBRW5DOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0RBQW9EO0FBQ3BEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHlEQUF5RDtBQUN6RDtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0M7QUFDL0M7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLCtDQUErQztBQUMvQztBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUM7QUFDbkM7QUFDQSxFQUFFOzs7QUFHRjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsNENBQTRDO0FBQzVDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHNCQUFzQixzQkFBc0IsRUFBRSxFQUFFO0FBQ3ZFLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsT0FBTztBQUN0RDtBQUNBLGtCQUFrQixPQUFPO0FBQ3pCO0FBQ0EsaUNBQWlDLE9BQU87QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLG9DQUFvQyxRQUFROztBQUU1Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsUUFBUTs7QUFFM0I7QUFDQTs7QUFFQSx3QkFBd0IsUUFBUTs7QUFFaEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlCQUFpQixvQkFBb0I7QUFDckM7QUFDQTtBQUNBLG9HQUFvRyxRQUFRO0FBQzVHO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0EsOENBQThDLFNBQVM7QUFDdkQ7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLGFBQWE7QUFDaEQsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBLGdCQUFnQixlQUFlOztBQUUvQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxnQkFBZ0IsZUFBZTs7QUFFL0I7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrRkFBa0YsY0FBYzs7QUFFaEc7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGOztBQUVBLDRCQUE0QixhQUFhOztBQUV6Qzs7QUFFQTtBQUNBO0FBQ0EsOEVBQThFLGNBQWM7O0FBRTVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHFFQUFxRSxjQUFjOztBQUVuRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSxFQUFFOztBQUVGO0FBQ0EsdUJBQXVCLFFBQVE7O0FBRS9CO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLDZCQUE2QixRQUFROztBQUVyQztBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSx5Q0FBeUM7QUFDekM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsaUJBQWlCLHlCQUF5QjtBQUMxQztBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQSxpQkFBaUIseUJBQXlCO0FBQzFDO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxpQkFBaUIseUJBQXlCOztBQUUxQztBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSx5QkFBeUIsYUFBYTs7QUFFdEM7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGFBQWEseUJBQXlCO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxpQ0FBaUMsUUFBUTtBQUN6QztBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0EsYUFBYSwwQkFBMEI7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLHdCQUF3QjtBQUNyQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxpQ0FBaUMsUUFBUTtBQUN6QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSw0Q0FBNEM7QUFDNUM7QUFDQSx3QkFBd0I7O0FBRXhCO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSx1REFBdUQ7QUFDdkQ7QUFDQSxjQUFjLGFBQWE7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxjQUFjLGFBQWE7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLG1CQUFtQixRQUFROztBQUUzQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGFBQWE7O0FBRW5DO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLGFBQWE7O0FBRXBDO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsUUFBUTs7QUFFOUI7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixRQUFROztBQUUvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxzQkFBc0I7QUFDdEI7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQSx1Q0FBdUMsUUFBUTs7QUFFL0M7O0FBRUEscURBQXFELFFBQVE7O0FBRTdELGlHQUFpRyxRQUFRO0FBQ3pHLDZCQUE2Qjs7QUFFN0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEscUJBQXFCLFFBQVE7O0FBRTdCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLHNCQUFzQjtBQUN0QjtBQUNBLHVDQUF1QztBQUN2QztBQUNBLHVDQUF1QyxRQUFROztBQUUvQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLCtCQUErQixRQUFRO0FBQ3ZDLDhFQUE4RSxRQUFROztBQUV0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxXQUFXOztBQUVYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0Esc0JBQXNCO0FBQ3RCO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0EsdUNBQXVDLFFBQVE7QUFDL0M7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxZQUFZLFNBQVM7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLG9CQUFvQixlQUFlO0FBQ25DOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsK0NBQStDLFNBQVM7QUFDeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdCQUFnQjtBQUNoQjtBQUNBOztBQUVBLEVBQUUscUJBQXFCO0FBQ3ZCO0FBQ0E7O0FBRUEsRUFBRSxxQkFBcUI7QUFDdkI7QUFDQTs7QUFFQSxFQUFFLHFCQUFxQjtBQUN2QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLDBCQUEwQjtBQUMxQjtBQUNBLEVBQUUsK0JBQStCO0FBQ2pDO0FBQ0E7O0FBRUEsMEJBQTBCO0FBQzFCO0FBQ0EsRUFBRSwrQkFBK0I7QUFDakM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxpQ0FBaUMsU0FBUztBQUMxQztBQUNBOztBQUVBO0FBQ0EsWUFBWSxPQUFPO0FBQ25CO0FBQ0E7O0FBRUEsK0NBQStDLFNBQVM7QUFDeEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtDQUFrQyxpQ0FBaUM7QUFDbkU7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRixDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx3QkFBd0I7QUFDeEI7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0JBQXNCO0FBQ3RCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBLDRCQUE0QixRQUFROztBQUVwQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0Esd0JBQXdCLFlBQVk7QUFDcEM7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVEQUF1RCx5QkFBeUI7QUFDaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHlCQUF5QixhQUFhO0FBQ3RDOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsMEJBQTBCLGFBQWE7O0FBRXZDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSw2QkFBNkIsYUFBYTtBQUMxQztBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQSxtQ0FBbUMsU0FBUztBQUM1QztBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2Qiw0Q0FBNEMsRUFBRTtBQUMzRTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGdDQUFnQyxhQUFhO0FBQzdDLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLG1DQUFtQyxhQUFhO0FBQ2hELEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsOEJBQThCLGFBQWE7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0EsK0JBQStCO0FBQy9CO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsNkNBQTZDOztBQUU3Qzs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsd0JBQXdCLGVBQWU7O0FBRXZDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNEJBQTRCLDJDQUEyQztBQUN2RSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQSxrQ0FBa0MsUUFBUTs7QUFFMUM7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEIscUJBQXFCO0FBQ2pELEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsWUFBWTtBQUN2QztBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixrQkFBa0IsZ0JBQWdCO0FBQ3hEO0FBQ0E7QUFDQTs7QUFFQSxtQ0FBbUMsZ0RBQWdEOztBQUVuRjtBQUNBO0FBQ0EsNEJBQTRCO0FBQzVCO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxnREFBZ0Q7QUFDaEQ7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxhQUFhO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0Q0FBNEMsVUFBVTtBQUN0RDs7QUFFQSx1Q0FBdUMsU0FBUztBQUNoRDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsYUFBYSxhQUFhOztBQUUxQixpQ0FBaUM7O0FBRWpDLDJCQUEyQixhQUFhO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCLGFBQWE7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGLG1FQUFtRTtBQUNuRTtBQUNBO0FBQ0E7O0FBRUEsdUNBQXVDLFNBQVM7QUFDaEQ7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjLFNBQVM7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsY0FBYyxTQUFTO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsOENBQThDLFNBQVM7QUFDdkQ7O0FBRUEsb0NBQW9DLGNBQWM7QUFDbEQ7O0FBRUEsbUJBQW1CLFVBQVU7O0FBRTdCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHFDQUFxQyxTQUFTO0FBQzlDO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0EsbUJBQW1CLFFBQVE7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsdURBQXVELGNBQWM7O0FBRXJFO0FBQ0EsdUNBQXVDLFNBQVM7QUFDaEQ7O0FBRUEsZ0RBQWdELFVBQVU7QUFDMUQsK0JBQStCLFVBQVU7O0FBRXpDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUMsYUFBYTtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxhQUFhLGFBQWE7O0FBRTFCLGdDQUFnQzs7QUFFaEM7O0FBRUEsMEJBQTBCLFNBQVM7QUFDbkM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9EQUFvRCxTQUFTO0FBQzdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHVEQUF1RCxjQUFjOztBQUVyRTtBQUNBLHVDQUF1QyxTQUFTO0FBQ2hEOztBQUVBLGdEQUFnRCxVQUFVO0FBQzFEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxJQUFJO0FBQ0o7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHFDQUFxQyxTQUFTO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsbURBQW1ELGFBQWE7O0FBRWhFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQyxTQUFTO0FBQzNDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsK0NBQStDLFNBQVM7QUFDeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw2Q0FBNkMsU0FBUztBQUN0RDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxrQkFBa0Isc0JBQXNCO0FBQ25EO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRiw4Q0FBOEM7QUFDOUM7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQix3Q0FBd0M7QUFDbkUsK0JBQStCLHVDQUF1Qzs7QUFFdEU7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkJBQTJCLHdDQUF3Qzs7QUFFbkU7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLDJCQUEyQjtBQUM3QztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSw0QkFBNEIseUJBQXlCOztBQUVyRCwrRUFBK0UsaUNBQWlDO0FBQ2hIO0FBQ0E7QUFDQSxpQkFBaUIsc0JBQXNCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQix1Q0FBdUM7O0FBRWxFO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsUUFBUTs7QUFFM0I7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSx1QkFBdUIsUUFBUTs7QUFFL0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxtQkFBbUIsUUFBUTs7QUFFM0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QixZQUFZOztBQUVyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLFlBQVk7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLFlBQVk7O0FBRXRDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0MsWUFBWTtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQzs7QUFFbEM7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSw4QkFBOEIsUUFBUTtBQUN0QywyQkFBMkIsMkJBQTJCOztBQUV0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtEQUErRDtBQUMvRDtBQUNBO0FBQ0EsOENBQThDO0FBQzlDO0FBQ0E7QUFDQSxnRUFBZ0U7QUFDaEU7QUFDQTtBQUNBLDhDQUE4QztBQUM5QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsY0FBYzs7QUFFekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxjQUFjO0FBQ25EO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLGNBQWM7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0MsY0FBYztBQUNwRDtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGLDhCQUE4Qjs7QUFFOUIsMkJBQTJCOztBQUUzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLGlEQUFpRCxRQUFRO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLHlCQUF5QjtBQUNwRDtBQUNBO0FBQ0EsOEJBQThCLGFBQWE7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBLGlEQUFpRDs7QUFFakQsOENBQThDLFNBQVM7O0FBRXZEOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLG1CQUFtQixRQUFROztBQUUzQjtBQUNBLGNBQWMsUUFBUTs7QUFFdEI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx1Q0FBdUMsVUFBVTs7QUFFakQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQ0FBb0Msb0JBQW9COztBQUV4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQSx3QkFBd0IsUUFBUTs7QUFFaEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7O0FBRUEsMkJBQTJCLGtCQUFrQjs7QUFFN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBLHFCQUFxQixlQUFlO0FBQ3BDLHNCQUFzQixlQUFlOztBQUVyQztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLCtDQUErQyxRQUFROztBQUV2RDtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7O0FBRUEsNkJBQTZCLDBCQUEwQjtBQUN2RCxxQ0FBcUMsUUFBUSxFQUFFOztBQUUvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxrRUFBa0U7O0FBRXZHO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNENBQTRDLDZCQUE2QixRQUFROztBQUVqRjtBQUNBLCtCQUErQixzQkFBc0I7QUFDckQsZ0NBQWdDLHNCQUFzQjtBQUN0RDtBQUNBOztBQUVBLHFDQUFxQyxVQUFVOztBQUUvQztBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsY0FBYyxrQkFBa0I7QUFDaEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0ZBQWdGLGNBQWM7QUFDOUY7O0FBRUEsNkJBQTZCLGFBQWE7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxjQUFjLFFBQVE7O0FBRXRCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBLHdEQUF3RDtBQUN4RDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTs7QUFFQTtBQUNBLGNBQWMsUUFBUTs7QUFFdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxrQ0FBa0MsY0FBYztBQUNoRDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLEVBQUUseUJBQXlCLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxNQUFNLElBQUksSUFBSSx5Q0FBeUMsa0pBQWtKO0FBQ3ZRO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLEVBQUUsd0JBQXdCLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFO0FBQ25EO0FBQ0E7QUFDQSxLQUFLLEVBQUUsd0hBQXdILDJDQUEyQyxnREFBZ0QsRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsd0JBQXdCLEVBQUUsOEJBQThCO0FBQ2xUO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLEVBQUUsaUJBQWlCLElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsUUFBUSxXQUFXO0FBQzlFO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxjQUFjLFFBQVE7O0FBRXRCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTs7QUFFQSwyQkFBMkI7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EseUJBQXlCOztBQUV6QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixlQUFlO0FBQzdDLHdDQUF3Qyx1QkFBdUI7QUFDL0QsbUNBQW1DLHVCQUF1QjtBQUMxRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0Esa0NBQWtDLFFBQVE7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLGlEQUFpRCxRQUFROztBQUV6RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsNkJBQTZCO0FBQ3BEO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsa0JBQWtCO0FBQ2hDO0FBQ0E7QUFDQSwyQkFBMkIsUUFBUTtBQUNuQztBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxtQkFBbUIsUUFBUTs7QUFFM0I7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCO0FBQ2hCLGVBQWU7O0FBRWY7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1DQUFtQyxPQUFPO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsc0JBQXNCO0FBQ3RCLEVBQUU7O0FBRUY7QUFDQSx1QkFBdUIsUUFBUTs7QUFFL0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsYUFBYSxRQUFROztBQUVyQjs7QUFFQSxhQUFhLFNBQVM7QUFDdEIsc0NBQXNDLFVBQVU7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBLHlDQUF5QyxRQUFROztBQUVqRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxtQ0FBbUMsT0FBTztBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0EsOEVBQThFLFFBQVE7O0FBRXRGO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBLG1DQUFtQyxPQUFPO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLHFEQUFxRDtBQUNyRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUEsZUFBZSxRQUFROztBQUV2QjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUEsZUFBZSxRQUFROztBQUV2QjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxpQ0FBaUMsUUFBUTtBQUN6QztBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixlQUFlO0FBQzFDLHdDQUF3Qyx1QkFBdUI7QUFDL0QsbUNBQW1DLHVCQUF1QjtBQUMxRDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBLGlEQUFpRDtBQUNqRDs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0EsaURBQWlELFFBQVE7O0FBRXpEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSx5QkFBeUIsdUJBQXVCO0FBQ2hEO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLFFBQVE7O0FBRXRCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG1CQUFtQjtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0NBQW9DLFdBQVc7QUFDL0M7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLG9CQUFvQjtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsNEJBQTRCO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLDZEQUE2RCxjQUFjOztBQUUzRTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBLDRDQUE0QyxRQUFROztBQUVwRDs7QUFFQSxxQkFBcUIsUUFBUTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHdCQUF3QixzQkFBc0I7QUFDOUMsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSwrQ0FBK0MsUUFBUTs7QUFFdkQ7O0FBRUE7QUFDQSwrQkFBK0Isc0RBQXNEO0FBQ3JGLCtCQUErQixzREFBc0Q7QUFDckYsK0JBQStCLHNEQUFzRDtBQUNyRiwrQkFBK0Isc0RBQXNEOztBQUVyRjtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0Esc0JBQXNCLFFBQVE7O0FBRTlCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTs7QUFFQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBO0FBQ0EsdUNBQXVDLFNBQVM7QUFDaEQ7QUFDQTtBQUNBLHNDQUFzQyxTQUFTO0FBQy9DO0FBQ0E7QUFDQSxvQ0FBb0MsU0FBUztBQUM3QztBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLGdDQUFnQztBQUNoQztBQUNBOztBQUVBLHdDQUF3QyxTQUFTO0FBQ2pEO0FBQ0E7QUFDQSx5Q0FBeUMsU0FBUztBQUNsRDtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLDJDQUEyQyxRQUFROztBQUVuRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBLEdBQUc7QUFDSDs7QUFFQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxjQUFjOztBQUVkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxlQUFlLFFBQVE7O0FBRXZCO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLG1CQUFtQixRQUFROztBQUUzQjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0Esb0ZBQW9GLFFBQVE7O0FBRTVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSwrREFBK0QsUUFBUTs7QUFFdkU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EscUJBQXFCLFFBQVE7QUFDN0IsR0FBRztBQUNIO0FBQ0E7QUFDQSx1REFBdUQsUUFBUTtBQUMvRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLCtEQUErRCwwQkFBMEI7QUFDekY7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsQ0FBQztBQUNEIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2xlYWZsZXQvZGlzdC9sZWFmbGV0LXNyYy5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIEBwcmVzZXJ2ZVxuICogTGVhZmxldCAxLjUuMStidWlsZC4yZTNlMGZmLCBhIEpTIGxpYnJhcnkgZm9yIGludGVyYWN0aXZlIG1hcHMuIGh0dHA6Ly9sZWFmbGV0anMuY29tXG4gKiAoYykgMjAxMC0yMDE4IFZsYWRpbWlyIEFnYWZvbmtpbiwgKGMpIDIwMTAtMjAxMSBDbG91ZE1hZGVcbiAqL1xuXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuTCA9IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG52YXIgdmVyc2lvbiA9IFwiMS41LjErYnVpbGQuMmUzZTBmZmJcIjtcblxuLypcclxuICogQG5hbWVzcGFjZSBVdGlsXHJcbiAqXHJcbiAqIFZhcmlvdXMgdXRpbGl0eSBmdW5jdGlvbnMsIHVzZWQgYnkgTGVhZmxldCBpbnRlcm5hbGx5LlxyXG4gKi9cclxuXHJcbnZhciBmcmVlemUgPSBPYmplY3QuZnJlZXplO1xyXG5PYmplY3QuZnJlZXplID0gZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gb2JqOyB9O1xyXG5cclxuLy8gQGZ1bmN0aW9uIGV4dGVuZChkZXN0OiBPYmplY3QsIHNyYz86IE9iamVjdCk6IE9iamVjdFxyXG4vLyBNZXJnZXMgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGBzcmNgIG9iamVjdCAob3IgbXVsdGlwbGUgb2JqZWN0cykgaW50byBgZGVzdGAgb2JqZWN0IGFuZCByZXR1cm5zIHRoZSBsYXR0ZXIuIEhhcyBhbiBgTC5leHRlbmRgIHNob3J0Y3V0LlxyXG5mdW5jdGlvbiBleHRlbmQoZGVzdCkge1xyXG5cdHZhciBpLCBqLCBsZW4sIHNyYztcclxuXHJcblx0Zm9yIChqID0gMSwgbGVuID0gYXJndW1lbnRzLmxlbmd0aDsgaiA8IGxlbjsgaisrKSB7XHJcblx0XHRzcmMgPSBhcmd1bWVudHNbal07XHJcblx0XHRmb3IgKGkgaW4gc3JjKSB7XHJcblx0XHRcdGRlc3RbaV0gPSBzcmNbaV07XHJcblx0XHR9XHJcblx0fVxyXG5cdHJldHVybiBkZXN0O1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gY3JlYXRlKHByb3RvOiBPYmplY3QsIHByb3BlcnRpZXM/OiBPYmplY3QpOiBPYmplY3RcclxuLy8gQ29tcGF0aWJpbGl0eSBwb2x5ZmlsbCBmb3IgW09iamVjdC5jcmVhdGVdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL09iamVjdC9jcmVhdGUpXHJcbnZhciBjcmVhdGUgPSBPYmplY3QuY3JlYXRlIHx8IChmdW5jdGlvbiAoKSB7XHJcblx0ZnVuY3Rpb24gRigpIHt9XHJcblx0cmV0dXJuIGZ1bmN0aW9uIChwcm90bykge1xyXG5cdFx0Ri5wcm90b3R5cGUgPSBwcm90bztcclxuXHRcdHJldHVybiBuZXcgRigpO1xyXG5cdH07XHJcbn0pKCk7XHJcblxyXG4vLyBAZnVuY3Rpb24gYmluZChmbjogRnVuY3Rpb24sIOKApik6IEZ1bmN0aW9uXHJcbi8vIFJldHVybnMgYSBuZXcgZnVuY3Rpb24gYm91bmQgdG8gdGhlIGFyZ3VtZW50cyBwYXNzZWQsIGxpa2UgW0Z1bmN0aW9uLnByb3RvdHlwZS5iaW5kXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9GdW5jdGlvbi9iaW5kKS5cclxuLy8gSGFzIGEgYEwuYmluZCgpYCBzaG9ydGN1dC5cclxuZnVuY3Rpb24gYmluZChmbiwgb2JqKSB7XHJcblx0dmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xyXG5cclxuXHRpZiAoZm4uYmluZCkge1xyXG5cdFx0cmV0dXJuIGZuLmJpbmQuYXBwbHkoZm4sIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XHJcblx0fVxyXG5cclxuXHR2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcclxuXHJcblx0cmV0dXJuIGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiBmbi5hcHBseShvYmosIGFyZ3MubGVuZ3RoID8gYXJncy5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMpKSA6IGFyZ3VtZW50cyk7XHJcblx0fTtcclxufVxyXG5cclxuLy8gQHByb3BlcnR5IGxhc3RJZDogTnVtYmVyXHJcbi8vIExhc3QgdW5pcXVlIElEIHVzZWQgYnkgW2BzdGFtcCgpYF0oI3V0aWwtc3RhbXApXHJcbnZhciBsYXN0SWQgPSAwO1xyXG5cclxuLy8gQGZ1bmN0aW9uIHN0YW1wKG9iajogT2JqZWN0KTogTnVtYmVyXHJcbi8vIFJldHVybnMgdGhlIHVuaXF1ZSBJRCBvZiBhbiBvYmplY3QsIGFzc2lnbmluZyBpdCBvbmUgaWYgaXQgZG9lc24ndCBoYXZlIGl0LlxyXG5mdW5jdGlvbiBzdGFtcChvYmopIHtcclxuXHQvKmVzbGludC1kaXNhYmxlICovXHJcblx0b2JqLl9sZWFmbGV0X2lkID0gb2JqLl9sZWFmbGV0X2lkIHx8ICsrbGFzdElkO1xyXG5cdHJldHVybiBvYmouX2xlYWZsZXRfaWQ7XHJcblx0LyogZXNsaW50LWVuYWJsZSAqL1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gdGhyb3R0bGUoZm46IEZ1bmN0aW9uLCB0aW1lOiBOdW1iZXIsIGNvbnRleHQ6IE9iamVjdCk6IEZ1bmN0aW9uXHJcbi8vIFJldHVybnMgYSBmdW5jdGlvbiB3aGljaCBleGVjdXRlcyBmdW5jdGlvbiBgZm5gIHdpdGggdGhlIGdpdmVuIHNjb3BlIGBjb250ZXh0YFxyXG4vLyAoc28gdGhhdCB0aGUgYHRoaXNgIGtleXdvcmQgcmVmZXJzIHRvIGBjb250ZXh0YCBpbnNpZGUgYGZuYCdzIGNvZGUpLiBUaGUgZnVuY3Rpb25cclxuLy8gYGZuYCB3aWxsIGJlIGNhbGxlZCBubyBtb3JlIHRoYW4gb25lIHRpbWUgcGVyIGdpdmVuIGFtb3VudCBvZiBgdGltZWAuIFRoZSBhcmd1bWVudHNcclxuLy8gcmVjZWl2ZWQgYnkgdGhlIGJvdW5kIGZ1bmN0aW9uIHdpbGwgYmUgYW55IGFyZ3VtZW50cyBwYXNzZWQgd2hlbiBiaW5kaW5nIHRoZVxyXG4vLyBmdW5jdGlvbiwgZm9sbG93ZWQgYnkgYW55IGFyZ3VtZW50cyBwYXNzZWQgd2hlbiBpbnZva2luZyB0aGUgYm91bmQgZnVuY3Rpb24uXHJcbi8vIEhhcyBhbiBgTC50aHJvdHRsZWAgc2hvcnRjdXQuXHJcbmZ1bmN0aW9uIHRocm90dGxlKGZuLCB0aW1lLCBjb250ZXh0KSB7XHJcblx0dmFyIGxvY2ssIGFyZ3MsIHdyYXBwZXJGbiwgbGF0ZXI7XHJcblxyXG5cdGxhdGVyID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0Ly8gcmVzZXQgbG9jayBhbmQgY2FsbCBpZiBxdWV1ZWRcclxuXHRcdGxvY2sgPSBmYWxzZTtcclxuXHRcdGlmIChhcmdzKSB7XHJcblx0XHRcdHdyYXBwZXJGbi5hcHBseShjb250ZXh0LCBhcmdzKTtcclxuXHRcdFx0YXJncyA9IGZhbHNlO1xyXG5cdFx0fVxyXG5cdH07XHJcblxyXG5cdHdyYXBwZXJGbiA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmIChsb2NrKSB7XHJcblx0XHRcdC8vIGNhbGxlZCB0b28gc29vbiwgcXVldWUgdG8gY2FsbCBsYXRlclxyXG5cdFx0XHRhcmdzID0gYXJndW1lbnRzO1xyXG5cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdC8vIGNhbGwgYW5kIGxvY2sgdW50aWwgbGF0ZXJcclxuXHRcdFx0Zm4uYXBwbHkoY29udGV4dCwgYXJndW1lbnRzKTtcclxuXHRcdFx0c2V0VGltZW91dChsYXRlciwgdGltZSk7XHJcblx0XHRcdGxvY2sgPSB0cnVlO1xyXG5cdFx0fVxyXG5cdH07XHJcblxyXG5cdHJldHVybiB3cmFwcGVyRm47XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiB3cmFwTnVtKG51bTogTnVtYmVyLCByYW5nZTogTnVtYmVyW10sIGluY2x1ZGVNYXg/OiBCb29sZWFuKTogTnVtYmVyXHJcbi8vIFJldHVybnMgdGhlIG51bWJlciBgbnVtYCBtb2R1bG8gYHJhbmdlYCBpbiBzdWNoIGEgd2F5IHNvIGl0IGxpZXMgd2l0aGluXHJcbi8vIGByYW5nZVswXWAgYW5kIGByYW5nZVsxXWAuIFRoZSByZXR1cm5lZCB2YWx1ZSB3aWxsIGJlIGFsd2F5cyBzbWFsbGVyIHRoYW5cclxuLy8gYHJhbmdlWzFdYCB1bmxlc3MgYGluY2x1ZGVNYXhgIGlzIHNldCB0byBgdHJ1ZWAuXHJcbmZ1bmN0aW9uIHdyYXBOdW0oeCwgcmFuZ2UsIGluY2x1ZGVNYXgpIHtcclxuXHR2YXIgbWF4ID0gcmFuZ2VbMV0sXHJcblx0ICAgIG1pbiA9IHJhbmdlWzBdLFxyXG5cdCAgICBkID0gbWF4IC0gbWluO1xyXG5cdHJldHVybiB4ID09PSBtYXggJiYgaW5jbHVkZU1heCA/IHggOiAoKHggLSBtaW4pICUgZCArIGQpICUgZCArIG1pbjtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGZhbHNlRm4oKTogRnVuY3Rpb25cclxuLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHdoaWNoIGFsd2F5cyByZXR1cm5zIGBmYWxzZWAuXHJcbmZ1bmN0aW9uIGZhbHNlRm4oKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cclxuLy8gQGZ1bmN0aW9uIGZvcm1hdE51bShudW06IE51bWJlciwgZGlnaXRzPzogTnVtYmVyKTogTnVtYmVyXHJcbi8vIFJldHVybnMgdGhlIG51bWJlciBgbnVtYCByb3VuZGVkIHRvIGBkaWdpdHNgIGRlY2ltYWxzLCBvciB0byA2IGRlY2ltYWxzIGJ5IGRlZmF1bHQuXHJcbmZ1bmN0aW9uIGZvcm1hdE51bShudW0sIGRpZ2l0cykge1xyXG5cdGRpZ2l0cyA9IChkaWdpdHMgPT09IHVuZGVmaW5lZCA/IDYgOiBkaWdpdHMpO1xyXG5cdHJldHVybiArKE1hdGgucm91bmQobnVtICsgKCdlKycgKyBkaWdpdHMpKSArICgnZS0nICsgZGlnaXRzKSk7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiB0cmltKHN0cjogU3RyaW5nKTogU3RyaW5nXHJcbi8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtTdHJpbmcucHJvdG90eXBlLnRyaW1dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL1N0cmluZy9UcmltKVxyXG5mdW5jdGlvbiB0cmltKHN0cikge1xyXG5cdHJldHVybiBzdHIudHJpbSA/IHN0ci50cmltKCkgOiBzdHIucmVwbGFjZSgvXlxccyt8XFxzKyQvZywgJycpO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gc3BsaXRXb3JkcyhzdHI6IFN0cmluZyk6IFN0cmluZ1tdXHJcbi8vIFRyaW1zIGFuZCBzcGxpdHMgdGhlIHN0cmluZyBvbiB3aGl0ZXNwYWNlIGFuZCByZXR1cm5zIHRoZSBhcnJheSBvZiBwYXJ0cy5cclxuZnVuY3Rpb24gc3BsaXRXb3JkcyhzdHIpIHtcclxuXHRyZXR1cm4gdHJpbShzdHIpLnNwbGl0KC9cXHMrLyk7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBzZXRPcHRpb25zKG9iajogT2JqZWN0LCBvcHRpb25zOiBPYmplY3QpOiBPYmplY3RcclxuLy8gTWVyZ2VzIHRoZSBnaXZlbiBwcm9wZXJ0aWVzIHRvIHRoZSBgb3B0aW9uc2Agb2YgdGhlIGBvYmpgIG9iamVjdCwgcmV0dXJuaW5nIHRoZSByZXN1bHRpbmcgb3B0aW9ucy4gU2VlIGBDbGFzcyBvcHRpb25zYC4gSGFzIGFuIGBMLnNldE9wdGlvbnNgIHNob3J0Y3V0LlxyXG5mdW5jdGlvbiBzZXRPcHRpb25zKG9iaiwgb3B0aW9ucykge1xyXG5cdGlmICghb2JqLmhhc093blByb3BlcnR5KCdvcHRpb25zJykpIHtcclxuXHRcdG9iai5vcHRpb25zID0gb2JqLm9wdGlvbnMgPyBjcmVhdGUob2JqLm9wdGlvbnMpIDoge307XHJcblx0fVxyXG5cdGZvciAodmFyIGkgaW4gb3B0aW9ucykge1xyXG5cdFx0b2JqLm9wdGlvbnNbaV0gPSBvcHRpb25zW2ldO1xyXG5cdH1cclxuXHRyZXR1cm4gb2JqLm9wdGlvbnM7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBnZXRQYXJhbVN0cmluZyhvYmo6IE9iamVjdCwgZXhpc3RpbmdVcmw/OiBTdHJpbmcsIHVwcGVyY2FzZT86IEJvb2xlYW4pOiBTdHJpbmdcclxuLy8gQ29udmVydHMgYW4gb2JqZWN0IGludG8gYSBwYXJhbWV0ZXIgVVJMIHN0cmluZywgZS5nLiBge2E6IFwiZm9vXCIsIGI6IFwiYmFyXCJ9YFxyXG4vLyB0cmFuc2xhdGVzIHRvIGAnP2E9Zm9vJmI9YmFyJ2AuIElmIGBleGlzdGluZ1VybGAgaXMgc2V0LCB0aGUgcGFyYW1ldGVycyB3aWxsXHJcbi8vIGJlIGFwcGVuZGVkIGF0IHRoZSBlbmQuIElmIGB1cHBlcmNhc2VgIGlzIGB0cnVlYCwgdGhlIHBhcmFtZXRlciBuYW1lcyB3aWxsXHJcbi8vIGJlIHVwcGVyY2FzZWQgKGUuZy4gYCc/QT1mb28mQj1iYXInYClcclxuZnVuY3Rpb24gZ2V0UGFyYW1TdHJpbmcob2JqLCBleGlzdGluZ1VybCwgdXBwZXJjYXNlKSB7XHJcblx0dmFyIHBhcmFtcyA9IFtdO1xyXG5cdGZvciAodmFyIGkgaW4gb2JqKSB7XHJcblx0XHRwYXJhbXMucHVzaChlbmNvZGVVUklDb21wb25lbnQodXBwZXJjYXNlID8gaS50b1VwcGVyQ2FzZSgpIDogaSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQob2JqW2ldKSk7XHJcblx0fVxyXG5cdHJldHVybiAoKCFleGlzdGluZ1VybCB8fCBleGlzdGluZ1VybC5pbmRleE9mKCc/JykgPT09IC0xKSA/ICc/JyA6ICcmJykgKyBwYXJhbXMuam9pbignJicpO1xyXG59XHJcblxyXG52YXIgdGVtcGxhdGVSZSA9IC9cXHsgKihbXFx3Xy1dKykgKlxcfS9nO1xyXG5cclxuLy8gQGZ1bmN0aW9uIHRlbXBsYXRlKHN0cjogU3RyaW5nLCBkYXRhOiBPYmplY3QpOiBTdHJpbmdcclxuLy8gU2ltcGxlIHRlbXBsYXRpbmcgZmFjaWxpdHksIGFjY2VwdHMgYSB0ZW1wbGF0ZSBzdHJpbmcgb2YgdGhlIGZvcm0gYCdIZWxsbyB7YX0sIHtifSdgXHJcbi8vIGFuZCBhIGRhdGEgb2JqZWN0IGxpa2UgYHthOiAnZm9vJywgYjogJ2Jhcid9YCwgcmV0dXJucyBldmFsdWF0ZWQgc3RyaW5nXHJcbi8vIGAoJ0hlbGxvIGZvbywgYmFyJylgLiBZb3UgY2FuIGFsc28gc3BlY2lmeSBmdW5jdGlvbnMgaW5zdGVhZCBvZiBzdHJpbmdzIGZvclxyXG4vLyBkYXRhIHZhbHVlcyDigJQgdGhleSB3aWxsIGJlIGV2YWx1YXRlZCBwYXNzaW5nIGBkYXRhYCBhcyBhbiBhcmd1bWVudC5cclxuZnVuY3Rpb24gdGVtcGxhdGUoc3RyLCBkYXRhKSB7XHJcblx0cmV0dXJuIHN0ci5yZXBsYWNlKHRlbXBsYXRlUmUsIGZ1bmN0aW9uIChzdHIsIGtleSkge1xyXG5cdFx0dmFyIHZhbHVlID0gZGF0YVtrZXldO1xyXG5cclxuXHRcdGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XHJcblx0XHRcdHRocm93IG5ldyBFcnJvcignTm8gdmFsdWUgcHJvdmlkZWQgZm9yIHZhcmlhYmxlICcgKyBzdHIpO1xyXG5cclxuXHRcdH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XHJcblx0XHRcdHZhbHVlID0gdmFsdWUoZGF0YSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdmFsdWU7XHJcblx0fSk7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBpc0FycmF5KG9iaik6IEJvb2xlYW5cclxuLy8gQ29tcGF0aWJpbGl0eSBwb2x5ZmlsbCBmb3IgW0FycmF5LmlzQXJyYXldKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2lzQXJyYXkpXHJcbnZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiAob2JqKSB7XHJcblx0cmV0dXJuIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgQXJyYXldJyk7XHJcbn07XHJcblxyXG4vLyBAZnVuY3Rpb24gaW5kZXhPZihhcnJheTogQXJyYXksIGVsOiBPYmplY3QpOiBOdW1iZXJcclxuLy8gQ29tcGF0aWJpbGl0eSBwb2x5ZmlsbCBmb3IgW0FycmF5LnByb3RvdHlwZS5pbmRleE9mXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9pbmRleE9mKVxyXG5mdW5jdGlvbiBpbmRleE9mKGFycmF5LCBlbCkge1xyXG5cdGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcclxuXHRcdGlmIChhcnJheVtpXSA9PT0gZWwpIHsgcmV0dXJuIGk7IH1cclxuXHR9XHJcblx0cmV0dXJuIC0xO1xyXG59XHJcblxyXG4vLyBAcHJvcGVydHkgZW1wdHlJbWFnZVVybDogU3RyaW5nXHJcbi8vIERhdGEgVVJJIHN0cmluZyBjb250YWluaW5nIGEgYmFzZTY0LWVuY29kZWQgZW1wdHkgR0lGIGltYWdlLlxyXG4vLyBVc2VkIGFzIGEgaGFjayB0byBmcmVlIG1lbW9yeSBmcm9tIHVudXNlZCBpbWFnZXMgb24gV2ViS2l0LXBvd2VyZWRcclxuLy8gbW9iaWxlIGRldmljZXMgKGJ5IHNldHRpbmcgaW1hZ2UgYHNyY2AgdG8gdGhpcyBzdHJpbmcpLlxyXG52YXIgZW1wdHlJbWFnZVVybCA9ICdkYXRhOmltYWdlL2dpZjtiYXNlNjQsUjBsR09EbGhBUUFCQUFEL0FDd0FBQUFBQVFBQkFBQUNBRHM9JztcclxuXHJcbi8vIGluc3BpcmVkIGJ5IGh0dHA6Ly9wYXVsaXJpc2guY29tLzIwMTEvcmVxdWVzdGFuaW1hdGlvbmZyYW1lLWZvci1zbWFydC1hbmltYXRpbmcvXHJcblxyXG5mdW5jdGlvbiBnZXRQcmVmaXhlZChuYW1lKSB7XHJcblx0cmV0dXJuIHdpbmRvd1snd2Via2l0JyArIG5hbWVdIHx8IHdpbmRvd1snbW96JyArIG5hbWVdIHx8IHdpbmRvd1snbXMnICsgbmFtZV07XHJcbn1cclxuXHJcbnZhciBsYXN0VGltZSA9IDA7XHJcblxyXG4vLyBmYWxsYmFjayBmb3IgSUUgNy04XHJcbmZ1bmN0aW9uIHRpbWVvdXREZWZlcihmbikge1xyXG5cdHZhciB0aW1lID0gK25ldyBEYXRlKCksXHJcblx0ICAgIHRpbWVUb0NhbGwgPSBNYXRoLm1heCgwLCAxNiAtICh0aW1lIC0gbGFzdFRpbWUpKTtcclxuXHJcblx0bGFzdFRpbWUgPSB0aW1lICsgdGltZVRvQ2FsbDtcclxuXHRyZXR1cm4gd2luZG93LnNldFRpbWVvdXQoZm4sIHRpbWVUb0NhbGwpO1xyXG59XHJcblxyXG52YXIgcmVxdWVzdEZuID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSB8fCBnZXRQcmVmaXhlZCgnUmVxdWVzdEFuaW1hdGlvbkZyYW1lJykgfHwgdGltZW91dERlZmVyO1xyXG52YXIgY2FuY2VsRm4gPSB3aW5kb3cuY2FuY2VsQW5pbWF0aW9uRnJhbWUgfHwgZ2V0UHJlZml4ZWQoJ0NhbmNlbEFuaW1hdGlvbkZyYW1lJykgfHxcclxuXHRcdGdldFByZWZpeGVkKCdDYW5jZWxSZXF1ZXN0QW5pbWF0aW9uRnJhbWUnKSB8fCBmdW5jdGlvbiAoaWQpIHsgd2luZG93LmNsZWFyVGltZW91dChpZCk7IH07XHJcblxyXG4vLyBAZnVuY3Rpb24gcmVxdWVzdEFuaW1GcmFtZShmbjogRnVuY3Rpb24sIGNvbnRleHQ/OiBPYmplY3QsIGltbWVkaWF0ZT86IEJvb2xlYW4pOiBOdW1iZXJcclxuLy8gU2NoZWR1bGVzIGBmbmAgdG8gYmUgZXhlY3V0ZWQgd2hlbiB0aGUgYnJvd3NlciByZXBhaW50cy4gYGZuYCBpcyBib3VuZCB0b1xyXG4vLyBgY29udGV4dGAgaWYgZ2l2ZW4uIFdoZW4gYGltbWVkaWF0ZWAgaXMgc2V0LCBgZm5gIGlzIGNhbGxlZCBpbW1lZGlhdGVseSBpZlxyXG4vLyB0aGUgYnJvd3NlciBkb2Vzbid0IGhhdmUgbmF0aXZlIHN1cHBvcnQgZm9yXHJcbi8vIFtgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZWBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS93aW5kb3cvcmVxdWVzdEFuaW1hdGlvbkZyYW1lKSxcclxuLy8gb3RoZXJ3aXNlIGl0J3MgZGVsYXllZC4gUmV0dXJucyBhIHJlcXVlc3QgSUQgdGhhdCBjYW4gYmUgdXNlZCB0byBjYW5jZWwgdGhlIHJlcXVlc3QuXHJcbmZ1bmN0aW9uIHJlcXVlc3RBbmltRnJhbWUoZm4sIGNvbnRleHQsIGltbWVkaWF0ZSkge1xyXG5cdGlmIChpbW1lZGlhdGUgJiYgcmVxdWVzdEZuID09PSB0aW1lb3V0RGVmZXIpIHtcclxuXHRcdGZuLmNhbGwoY29udGV4dCk7XHJcblx0fSBlbHNlIHtcclxuXHRcdHJldHVybiByZXF1ZXN0Rm4uY2FsbCh3aW5kb3csIGJpbmQoZm4sIGNvbnRleHQpKTtcclxuXHR9XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBjYW5jZWxBbmltRnJhbWUoaWQ6IE51bWJlcik6IHVuZGVmaW5lZFxyXG4vLyBDYW5jZWxzIGEgcHJldmlvdXMgYHJlcXVlc3RBbmltRnJhbWVgLiBTZWUgYWxzbyBbd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvd2luZG93L2NhbmNlbEFuaW1hdGlvbkZyYW1lKS5cclxuZnVuY3Rpb24gY2FuY2VsQW5pbUZyYW1lKGlkKSB7XHJcblx0aWYgKGlkKSB7XHJcblx0XHRjYW5jZWxGbi5jYWxsKHdpbmRvdywgaWQpO1xyXG5cdH1cclxufVxyXG5cblxudmFyIFV0aWwgPSAoT2JqZWN0LmZyZWV6ZSB8fCBPYmplY3QpKHtcblx0ZnJlZXplOiBmcmVlemUsXG5cdGV4dGVuZDogZXh0ZW5kLFxuXHRjcmVhdGU6IGNyZWF0ZSxcblx0YmluZDogYmluZCxcblx0bGFzdElkOiBsYXN0SWQsXG5cdHN0YW1wOiBzdGFtcCxcblx0dGhyb3R0bGU6IHRocm90dGxlLFxuXHR3cmFwTnVtOiB3cmFwTnVtLFxuXHRmYWxzZUZuOiBmYWxzZUZuLFxuXHRmb3JtYXROdW06IGZvcm1hdE51bSxcblx0dHJpbTogdHJpbSxcblx0c3BsaXRXb3Jkczogc3BsaXRXb3Jkcyxcblx0c2V0T3B0aW9uczogc2V0T3B0aW9ucyxcblx0Z2V0UGFyYW1TdHJpbmc6IGdldFBhcmFtU3RyaW5nLFxuXHR0ZW1wbGF0ZTogdGVtcGxhdGUsXG5cdGlzQXJyYXk6IGlzQXJyYXksXG5cdGluZGV4T2Y6IGluZGV4T2YsXG5cdGVtcHR5SW1hZ2VVcmw6IGVtcHR5SW1hZ2VVcmwsXG5cdHJlcXVlc3RGbjogcmVxdWVzdEZuLFxuXHRjYW5jZWxGbjogY2FuY2VsRm4sXG5cdHJlcXVlc3RBbmltRnJhbWU6IHJlcXVlc3RBbmltRnJhbWUsXG5cdGNhbmNlbEFuaW1GcmFtZTogY2FuY2VsQW5pbUZyYW1lXG59KTtcblxuLy8gQGNsYXNzIENsYXNzXHJcbi8vIEBha2EgTC5DbGFzc1xyXG5cclxuLy8gQHNlY3Rpb25cclxuLy8gQHVuaW5oZXJpdGFibGVcclxuXHJcbi8vIFRoYW5rcyB0byBKb2huIFJlc2lnIGFuZCBEZWFuIEVkd2FyZHMgZm9yIGluc3BpcmF0aW9uIVxyXG5cclxuZnVuY3Rpb24gQ2xhc3MoKSB7fVxyXG5cclxuQ2xhc3MuZXh0ZW5kID0gZnVuY3Rpb24gKHByb3BzKSB7XHJcblxyXG5cdC8vIEBmdW5jdGlvbiBleHRlbmQocHJvcHM6IE9iamVjdCk6IEZ1bmN0aW9uXHJcblx0Ly8gW0V4dGVuZHMgdGhlIGN1cnJlbnQgY2xhc3NdKCNjbGFzcy1pbmhlcml0YW5jZSkgZ2l2ZW4gdGhlIHByb3BlcnRpZXMgdG8gYmUgaW5jbHVkZWQuXHJcblx0Ly8gUmV0dXJucyBhIEphdmFzY3JpcHQgZnVuY3Rpb24gdGhhdCBpcyBhIGNsYXNzIGNvbnN0cnVjdG9yICh0byBiZSBjYWxsZWQgd2l0aCBgbmV3YCkuXHJcblx0dmFyIE5ld0NsYXNzID0gZnVuY3Rpb24gKCkge1xyXG5cclxuXHRcdC8vIGNhbGwgdGhlIGNvbnN0cnVjdG9yXHJcblx0XHRpZiAodGhpcy5pbml0aWFsaXplKSB7XHJcblx0XHRcdHRoaXMuaW5pdGlhbGl6ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIGNhbGwgYWxsIGNvbnN0cnVjdG9yIGhvb2tzXHJcblx0XHR0aGlzLmNhbGxJbml0SG9va3MoKTtcclxuXHR9O1xyXG5cclxuXHR2YXIgcGFyZW50UHJvdG8gPSBOZXdDbGFzcy5fX3N1cGVyX18gPSB0aGlzLnByb3RvdHlwZTtcclxuXHJcblx0dmFyIHByb3RvID0gY3JlYXRlKHBhcmVudFByb3RvKTtcclxuXHRwcm90by5jb25zdHJ1Y3RvciA9IE5ld0NsYXNzO1xyXG5cclxuXHROZXdDbGFzcy5wcm90b3R5cGUgPSBwcm90bztcclxuXHJcblx0Ly8gaW5oZXJpdCBwYXJlbnQncyBzdGF0aWNzXHJcblx0Zm9yICh2YXIgaSBpbiB0aGlzKSB7XHJcblx0XHRpZiAodGhpcy5oYXNPd25Qcm9wZXJ0eShpKSAmJiBpICE9PSAncHJvdG90eXBlJyAmJiBpICE9PSAnX19zdXBlcl9fJykge1xyXG5cdFx0XHROZXdDbGFzc1tpXSA9IHRoaXNbaV07XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvLyBtaXggc3RhdGljIHByb3BlcnRpZXMgaW50byB0aGUgY2xhc3NcclxuXHRpZiAocHJvcHMuc3RhdGljcykge1xyXG5cdFx0ZXh0ZW5kKE5ld0NsYXNzLCBwcm9wcy5zdGF0aWNzKTtcclxuXHRcdGRlbGV0ZSBwcm9wcy5zdGF0aWNzO1xyXG5cdH1cclxuXHJcblx0Ly8gbWl4IGluY2x1ZGVzIGludG8gdGhlIHByb3RvdHlwZVxyXG5cdGlmIChwcm9wcy5pbmNsdWRlcykge1xyXG5cdFx0Y2hlY2tEZXByZWNhdGVkTWl4aW5FdmVudHMocHJvcHMuaW5jbHVkZXMpO1xyXG5cdFx0ZXh0ZW5kLmFwcGx5KG51bGwsIFtwcm90b10uY29uY2F0KHByb3BzLmluY2x1ZGVzKSk7XHJcblx0XHRkZWxldGUgcHJvcHMuaW5jbHVkZXM7XHJcblx0fVxyXG5cclxuXHQvLyBtZXJnZSBvcHRpb25zXHJcblx0aWYgKHByb3RvLm9wdGlvbnMpIHtcclxuXHRcdHByb3BzLm9wdGlvbnMgPSBleHRlbmQoY3JlYXRlKHByb3RvLm9wdGlvbnMpLCBwcm9wcy5vcHRpb25zKTtcclxuXHR9XHJcblxyXG5cdC8vIG1peCBnaXZlbiBwcm9wZXJ0aWVzIGludG8gdGhlIHByb3RvdHlwZVxyXG5cdGV4dGVuZChwcm90bywgcHJvcHMpO1xyXG5cclxuXHRwcm90by5faW5pdEhvb2tzID0gW107XHJcblxyXG5cdC8vIGFkZCBtZXRob2QgZm9yIGNhbGxpbmcgYWxsIGhvb2tzXHJcblx0cHJvdG8uY2FsbEluaXRIb29rcyA9IGZ1bmN0aW9uICgpIHtcclxuXHJcblx0XHRpZiAodGhpcy5faW5pdEhvb2tzQ2FsbGVkKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdGlmIChwYXJlbnRQcm90by5jYWxsSW5pdEhvb2tzKSB7XHJcblx0XHRcdHBhcmVudFByb3RvLmNhbGxJbml0SG9va3MuY2FsbCh0aGlzKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9pbml0SG9va3NDYWxsZWQgPSB0cnVlO1xyXG5cclxuXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBwcm90by5faW5pdEhvb2tzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdHByb3RvLl9pbml0SG9va3NbaV0uY2FsbCh0aGlzKTtcclxuXHRcdH1cclxuXHR9O1xyXG5cclxuXHRyZXR1cm4gTmV3Q2xhc3M7XHJcbn07XHJcblxyXG5cclxuLy8gQGZ1bmN0aW9uIGluY2x1ZGUocHJvcGVydGllczogT2JqZWN0KTogdGhpc1xyXG4vLyBbSW5jbHVkZXMgYSBtaXhpbl0oI2NsYXNzLWluY2x1ZGVzKSBpbnRvIHRoZSBjdXJyZW50IGNsYXNzLlxyXG5DbGFzcy5pbmNsdWRlID0gZnVuY3Rpb24gKHByb3BzKSB7XHJcblx0ZXh0ZW5kKHRoaXMucHJvdG90eXBlLCBwcm9wcyk7XHJcblx0cmV0dXJuIHRoaXM7XHJcbn07XHJcblxyXG4vLyBAZnVuY3Rpb24gbWVyZ2VPcHRpb25zKG9wdGlvbnM6IE9iamVjdCk6IHRoaXNcclxuLy8gW01lcmdlcyBgb3B0aW9uc2BdKCNjbGFzcy1vcHRpb25zKSBpbnRvIHRoZSBkZWZhdWx0cyBvZiB0aGUgY2xhc3MuXHJcbkNsYXNzLm1lcmdlT3B0aW9ucyA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblx0ZXh0ZW5kKHRoaXMucHJvdG90eXBlLm9wdGlvbnMsIG9wdGlvbnMpO1xyXG5cdHJldHVybiB0aGlzO1xyXG59O1xyXG5cclxuLy8gQGZ1bmN0aW9uIGFkZEluaXRIb29rKGZuOiBGdW5jdGlvbik6IHRoaXNcclxuLy8gQWRkcyBhIFtjb25zdHJ1Y3RvciBob29rXSgjY2xhc3MtY29uc3RydWN0b3ItaG9va3MpIHRvIHRoZSBjbGFzcy5cclxuQ2xhc3MuYWRkSW5pdEhvb2sgPSBmdW5jdGlvbiAoZm4pIHsgLy8gKEZ1bmN0aW9uKSB8fCAoU3RyaW5nLCBhcmdzLi4uKVxyXG5cdHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcclxuXHJcblx0dmFyIGluaXQgPSB0eXBlb2YgZm4gPT09ICdmdW5jdGlvbicgPyBmbiA6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXNbZm5dLmFwcGx5KHRoaXMsIGFyZ3MpO1xyXG5cdH07XHJcblxyXG5cdHRoaXMucHJvdG90eXBlLl9pbml0SG9va3MgPSB0aGlzLnByb3RvdHlwZS5faW5pdEhvb2tzIHx8IFtdO1xyXG5cdHRoaXMucHJvdG90eXBlLl9pbml0SG9va3MucHVzaChpbml0KTtcclxuXHRyZXR1cm4gdGhpcztcclxufTtcclxuXHJcbmZ1bmN0aW9uIGNoZWNrRGVwcmVjYXRlZE1peGluRXZlbnRzKGluY2x1ZGVzKSB7XHJcblx0aWYgKHR5cGVvZiBMID09PSAndW5kZWZpbmVkJyB8fCAhTCB8fCAhTC5NaXhpbikgeyByZXR1cm47IH1cclxuXHJcblx0aW5jbHVkZXMgPSBpc0FycmF5KGluY2x1ZGVzKSA/IGluY2x1ZGVzIDogW2luY2x1ZGVzXTtcclxuXHJcblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBpbmNsdWRlcy5sZW5ndGg7IGkrKykge1xyXG5cdFx0aWYgKGluY2x1ZGVzW2ldID09PSBMLk1peGluLkV2ZW50cykge1xyXG5cdFx0XHRjb25zb2xlLndhcm4oJ0RlcHJlY2F0ZWQgaW5jbHVkZSBvZiBMLk1peGluLkV2ZW50czogJyArXHJcblx0XHRcdFx0J3RoaXMgcHJvcGVydHkgd2lsbCBiZSByZW1vdmVkIGluIGZ1dHVyZSByZWxlYXNlcywgJyArXHJcblx0XHRcdFx0J3BsZWFzZSBpbmhlcml0IGZyb20gTC5FdmVudGVkIGluc3RlYWQuJywgbmV3IEVycm9yKCkuc3RhY2spO1xyXG5cdFx0fVxyXG5cdH1cclxufVxuXG4vKlxyXG4gKiBAY2xhc3MgRXZlbnRlZFxyXG4gKiBAYWthIEwuRXZlbnRlZFxyXG4gKiBAaW5oZXJpdHMgQ2xhc3NcclxuICpcclxuICogQSBzZXQgb2YgbWV0aG9kcyBzaGFyZWQgYmV0d2VlbiBldmVudC1wb3dlcmVkIGNsYXNzZXMgKGxpa2UgYE1hcGAgYW5kIGBNYXJrZXJgKS4gR2VuZXJhbGx5LCBldmVudHMgYWxsb3cgeW91IHRvIGV4ZWN1dGUgc29tZSBmdW5jdGlvbiB3aGVuIHNvbWV0aGluZyBoYXBwZW5zIHdpdGggYW4gb2JqZWN0IChlLmcuIHRoZSB1c2VyIGNsaWNrcyBvbiB0aGUgbWFwLCBjYXVzaW5nIHRoZSBtYXAgdG8gZmlyZSBgJ2NsaWNrJ2AgZXZlbnQpLlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiBtYXAub24oJ2NsaWNrJywgZnVuY3Rpb24oZSkge1xyXG4gKiBcdGFsZXJ0KGUubGF0bG5nKTtcclxuICogfSApO1xyXG4gKiBgYGBcclxuICpcclxuICogTGVhZmxldCBkZWFscyB3aXRoIGV2ZW50IGxpc3RlbmVycyBieSByZWZlcmVuY2UsIHNvIGlmIHlvdSB3YW50IHRvIGFkZCBhIGxpc3RlbmVyIGFuZCB0aGVuIHJlbW92ZSBpdCwgZGVmaW5lIGl0IGFzIGEgZnVuY3Rpb246XHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIGZ1bmN0aW9uIG9uQ2xpY2soZSkgeyAuLi4gfVxyXG4gKlxyXG4gKiBtYXAub24oJ2NsaWNrJywgb25DbGljayk7XHJcbiAqIG1hcC5vZmYoJ2NsaWNrJywgb25DbGljayk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBFdmVudHMgPSB7XHJcblx0LyogQG1ldGhvZCBvbih0eXBlOiBTdHJpbmcsIGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuXHQgKiBBZGRzIGEgbGlzdGVuZXIgZnVuY3Rpb24gKGBmbmApIHRvIGEgcGFydGljdWxhciBldmVudCB0eXBlIG9mIHRoZSBvYmplY3QuIFlvdSBjYW4gb3B0aW9uYWxseSBzcGVjaWZ5IHRoZSBjb250ZXh0IG9mIHRoZSBsaXN0ZW5lciAob2JqZWN0IHRoZSB0aGlzIGtleXdvcmQgd2lsbCBwb2ludCB0bykuIFlvdSBjYW4gYWxzbyBwYXNzIHNldmVyYWwgc3BhY2Utc2VwYXJhdGVkIHR5cGVzIChlLmcuIGAnY2xpY2sgZGJsY2xpY2snYCkuXHJcblx0ICpcclxuXHQgKiBAYWx0ZXJuYXRpdmVcclxuXHQgKiBAbWV0aG9kIG9uKGV2ZW50TWFwOiBPYmplY3QpOiB0aGlzXHJcblx0ICogQWRkcyBhIHNldCBvZiB0eXBlL2xpc3RlbmVyIHBhaXJzLCBlLmcuIGB7Y2xpY2s6IG9uQ2xpY2ssIG1vdXNlbW92ZTogb25Nb3VzZU1vdmV9YFxyXG5cdCAqL1xyXG5cdG9uOiBmdW5jdGlvbiAodHlwZXMsIGZuLCBjb250ZXh0KSB7XHJcblxyXG5cdFx0Ly8gdHlwZXMgY2FuIGJlIGEgbWFwIG9mIHR5cGVzL2hhbmRsZXJzXHJcblx0XHRpZiAodHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG5cdFx0XHRmb3IgKHZhciB0eXBlIGluIHR5cGVzKSB7XHJcblx0XHRcdFx0Ly8gd2UgZG9uJ3QgcHJvY2VzcyBzcGFjZS1zZXBhcmF0ZWQgZXZlbnRzIGhlcmUgZm9yIHBlcmZvcm1hbmNlO1xyXG5cdFx0XHRcdC8vIGl0J3MgYSBob3QgcGF0aCBzaW5jZSBMYXllciB1c2VzIHRoZSBvbihvYmopIHN5bnRheFxyXG5cdFx0XHRcdHRoaXMuX29uKHR5cGUsIHR5cGVzW3R5cGVdLCBmbik7XHJcblx0XHRcdH1cclxuXHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHQvLyB0eXBlcyBjYW4gYmUgYSBzdHJpbmcgb2Ygc3BhY2Utc2VwYXJhdGVkIHdvcmRzXHJcblx0XHRcdHR5cGVzID0gc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG5cdFx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gdHlwZXMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0XHR0aGlzLl9vbih0eXBlc1tpXSwgZm4sIGNvbnRleHQpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0LyogQG1ldGhvZCBvZmYodHlwZTogU3RyaW5nLCBmbj86IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG5cdCAqIFJlbW92ZXMgYSBwcmV2aW91c2x5IGFkZGVkIGxpc3RlbmVyIGZ1bmN0aW9uLiBJZiBubyBmdW5jdGlvbiBpcyBzcGVjaWZpZWQsIGl0IHdpbGwgcmVtb3ZlIGFsbCB0aGUgbGlzdGVuZXJzIG9mIHRoYXQgcGFydGljdWxhciBldmVudCBmcm9tIHRoZSBvYmplY3QuIE5vdGUgdGhhdCBpZiB5b3UgcGFzc2VkIGEgY3VzdG9tIGNvbnRleHQgdG8gYG9uYCwgeW91IG11c3QgcGFzcyB0aGUgc2FtZSBjb250ZXh0IHRvIGBvZmZgIGluIG9yZGVyIHRvIHJlbW92ZSB0aGUgbGlzdGVuZXIuXHJcblx0ICpcclxuXHQgKiBAYWx0ZXJuYXRpdmVcclxuXHQgKiBAbWV0aG9kIG9mZihldmVudE1hcDogT2JqZWN0KTogdGhpc1xyXG5cdCAqIFJlbW92ZXMgYSBzZXQgb2YgdHlwZS9saXN0ZW5lciBwYWlycy5cclxuXHQgKlxyXG5cdCAqIEBhbHRlcm5hdGl2ZVxyXG5cdCAqIEBtZXRob2Qgb2ZmOiB0aGlzXHJcblx0ICogUmVtb3ZlcyBhbGwgbGlzdGVuZXJzIHRvIGFsbCBldmVudHMgb24gdGhlIG9iamVjdC4gVGhpcyBpbmNsdWRlcyBpbXBsaWNpdGx5IGF0dGFjaGVkIGV2ZW50cy5cclxuXHQgKi9cclxuXHRvZmY6IGZ1bmN0aW9uICh0eXBlcywgZm4sIGNvbnRleHQpIHtcclxuXHJcblx0XHRpZiAoIXR5cGVzKSB7XHJcblx0XHRcdC8vIGNsZWFyIGFsbCBsaXN0ZW5lcnMgaWYgY2FsbGVkIHdpdGhvdXQgYXJndW1lbnRzXHJcblx0XHRcdGRlbGV0ZSB0aGlzLl9ldmVudHM7XHJcblxyXG5cdFx0fSBlbHNlIGlmICh0eXBlb2YgdHlwZXMgPT09ICdvYmplY3QnKSB7XHJcblx0XHRcdGZvciAodmFyIHR5cGUgaW4gdHlwZXMpIHtcclxuXHRcdFx0XHR0aGlzLl9vZmYodHlwZSwgdHlwZXNbdHlwZV0sIGZuKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHR5cGVzID0gc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG5cdFx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gdHlwZXMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0XHR0aGlzLl9vZmYodHlwZXNbaV0sIGZuLCBjb250ZXh0KTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIGF0dGFjaCBsaXN0ZW5lciAod2l0aG91dCBzeW50YWN0aWMgc3VnYXIgbm93KVxyXG5cdF9vbjogZnVuY3Rpb24gKHR5cGUsIGZuLCBjb250ZXh0KSB7XHJcblx0XHR0aGlzLl9ldmVudHMgPSB0aGlzLl9ldmVudHMgfHwge307XHJcblxyXG5cdFx0LyogZ2V0L2luaXQgbGlzdGVuZXJzIGZvciB0eXBlICovXHJcblx0XHR2YXIgdHlwZUxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcclxuXHRcdGlmICghdHlwZUxpc3RlbmVycykge1xyXG5cdFx0XHR0eXBlTGlzdGVuZXJzID0gW107XHJcblx0XHRcdHRoaXMuX2V2ZW50c1t0eXBlXSA9IHR5cGVMaXN0ZW5lcnM7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKGNvbnRleHQgPT09IHRoaXMpIHtcclxuXHRcdFx0Ly8gTGVzcyBtZW1vcnkgZm9vdHByaW50LlxyXG5cdFx0XHRjb250ZXh0ID0gdW5kZWZpbmVkO1xyXG5cdFx0fVxyXG5cdFx0dmFyIG5ld0xpc3RlbmVyID0ge2ZuOiBmbiwgY3R4OiBjb250ZXh0fSxcclxuXHRcdCAgICBsaXN0ZW5lcnMgPSB0eXBlTGlzdGVuZXJzO1xyXG5cclxuXHRcdC8vIGNoZWNrIGlmIGZuIGFscmVhZHkgdGhlcmVcclxuXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0aWYgKGxpc3RlbmVyc1tpXS5mbiA9PT0gZm4gJiYgbGlzdGVuZXJzW2ldLmN0eCA9PT0gY29udGV4dCkge1xyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdGxpc3RlbmVycy5wdXNoKG5ld0xpc3RlbmVyKTtcclxuXHR9LFxyXG5cclxuXHRfb2ZmOiBmdW5jdGlvbiAodHlwZSwgZm4sIGNvbnRleHQpIHtcclxuXHRcdHZhciBsaXN0ZW5lcnMsXHJcblx0XHQgICAgaSxcclxuXHRcdCAgICBsZW47XHJcblxyXG5cdFx0aWYgKCF0aGlzLl9ldmVudHMpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0bGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xyXG5cclxuXHRcdGlmICghbGlzdGVuZXJzKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIWZuKSB7XHJcblx0XHRcdC8vIFNldCBhbGwgcmVtb3ZlZCBsaXN0ZW5lcnMgdG8gbm9vcCBzbyB0aGV5IGFyZSBub3QgY2FsbGVkIGlmIHJlbW92ZSBoYXBwZW5zIGluIGZpcmVcclxuXHRcdFx0Zm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0bGlzdGVuZXJzW2ldLmZuID0gZmFsc2VGbjtcclxuXHRcdFx0fVxyXG5cdFx0XHQvLyBjbGVhciBhbGwgbGlzdGVuZXJzIGZvciBhIHR5cGUgaWYgZnVuY3Rpb24gaXNuJ3Qgc3BlY2lmaWVkXHJcblx0XHRcdGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoY29udGV4dCA9PT0gdGhpcykge1xyXG5cdFx0XHRjb250ZXh0ID0gdW5kZWZpbmVkO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChsaXN0ZW5lcnMpIHtcclxuXHJcblx0XHRcdC8vIGZpbmQgZm4gYW5kIHJlbW92ZSBpdFxyXG5cdFx0XHRmb3IgKGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0XHR2YXIgbCA9IGxpc3RlbmVyc1tpXTtcclxuXHRcdFx0XHRpZiAobC5jdHggIT09IGNvbnRleHQpIHsgY29udGludWU7IH1cclxuXHRcdFx0XHRpZiAobC5mbiA9PT0gZm4pIHtcclxuXHJcblx0XHRcdFx0XHQvLyBzZXQgdGhlIHJlbW92ZWQgbGlzdGVuZXIgdG8gbm9vcCBzbyB0aGF0J3Mgbm90IGNhbGxlZCBpZiByZW1vdmUgaGFwcGVucyBpbiBmaXJlXHJcblx0XHRcdFx0XHRsLmZuID0gZmFsc2VGbjtcclxuXHJcblx0XHRcdFx0XHRpZiAodGhpcy5fZmlyaW5nQ291bnQpIHtcclxuXHRcdFx0XHRcdFx0LyogY29weSBhcnJheSBpbiBjYXNlIGV2ZW50cyBhcmUgYmVpbmcgZmlyZWQgKi9cclxuXHRcdFx0XHRcdFx0dGhpcy5fZXZlbnRzW3R5cGVdID0gbGlzdGVuZXJzID0gbGlzdGVuZXJzLnNsaWNlKCk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRsaXN0ZW5lcnMuc3BsaWNlKGksIDEpO1xyXG5cclxuXHRcdFx0XHRcdHJldHVybjtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGZpcmUodHlwZTogU3RyaW5nLCBkYXRhPzogT2JqZWN0LCBwcm9wYWdhdGU/OiBCb29sZWFuKTogdGhpc1xyXG5cdC8vIEZpcmVzIGFuIGV2ZW50IG9mIHRoZSBzcGVjaWZpZWQgdHlwZS4gWW91IGNhbiBvcHRpb25hbGx5IHByb3ZpZGUgYW4gZGF0YVxyXG5cdC8vIG9iamVjdCDigJQgdGhlIGZpcnN0IGFyZ3VtZW50IG9mIHRoZSBsaXN0ZW5lciBmdW5jdGlvbiB3aWxsIGNvbnRhaW4gaXRzXHJcblx0Ly8gcHJvcGVydGllcy4gVGhlIGV2ZW50IGNhbiBvcHRpb25hbGx5IGJlIHByb3BhZ2F0ZWQgdG8gZXZlbnQgcGFyZW50cy5cclxuXHRmaXJlOiBmdW5jdGlvbiAodHlwZSwgZGF0YSwgcHJvcGFnYXRlKSB7XHJcblx0XHRpZiAoIXRoaXMubGlzdGVucyh0eXBlLCBwcm9wYWdhdGUpKSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG5cdFx0dmFyIGV2ZW50ID0gZXh0ZW5kKHt9LCBkYXRhLCB7XHJcblx0XHRcdHR5cGU6IHR5cGUsXHJcblx0XHRcdHRhcmdldDogdGhpcyxcclxuXHRcdFx0c291cmNlVGFyZ2V0OiBkYXRhICYmIGRhdGEuc291cmNlVGFyZ2V0IHx8IHRoaXNcclxuXHRcdH0pO1xyXG5cclxuXHRcdGlmICh0aGlzLl9ldmVudHMpIHtcclxuXHRcdFx0dmFyIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcclxuXHJcblx0XHRcdGlmIChsaXN0ZW5lcnMpIHtcclxuXHRcdFx0XHR0aGlzLl9maXJpbmdDb3VudCA9ICh0aGlzLl9maXJpbmdDb3VudCArIDEpIHx8IDE7XHJcblx0XHRcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0XHRcdFx0dmFyIGwgPSBsaXN0ZW5lcnNbaV07XHJcblx0XHRcdFx0XHRsLmZuLmNhbGwobC5jdHggfHwgdGhpcywgZXZlbnQpO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0dGhpcy5fZmlyaW5nQ291bnQtLTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChwcm9wYWdhdGUpIHtcclxuXHRcdFx0Ly8gcHJvcGFnYXRlIHRoZSBldmVudCB0byBwYXJlbnRzIChzZXQgd2l0aCBhZGRFdmVudFBhcmVudClcclxuXHRcdFx0dGhpcy5fcHJvcGFnYXRlRXZlbnQoZXZlbnQpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgbGlzdGVucyh0eXBlOiBTdHJpbmcpOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgYSBwYXJ0aWN1bGFyIGV2ZW50IHR5cGUgaGFzIGFueSBsaXN0ZW5lcnMgYXR0YWNoZWQgdG8gaXQuXHJcblx0bGlzdGVuczogZnVuY3Rpb24gKHR5cGUsIHByb3BhZ2F0ZSkge1xyXG5cdFx0dmFyIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50cyAmJiB0aGlzLl9ldmVudHNbdHlwZV07XHJcblx0XHRpZiAobGlzdGVuZXJzICYmIGxpc3RlbmVycy5sZW5ndGgpIHsgcmV0dXJuIHRydWU7IH1cclxuXHJcblx0XHRpZiAocHJvcGFnYXRlKSB7XHJcblx0XHRcdC8vIGFsc28gY2hlY2sgcGFyZW50cyBmb3IgbGlzdGVuZXJzIGlmIGV2ZW50IHByb3BhZ2F0ZXNcclxuXHRcdFx0Zm9yICh2YXIgaWQgaW4gdGhpcy5fZXZlbnRQYXJlbnRzKSB7XHJcblx0XHRcdFx0aWYgKHRoaXMuX2V2ZW50UGFyZW50c1tpZF0ubGlzdGVucyh0eXBlLCBwcm9wYWdhdGUpKSB7IHJldHVybiB0cnVlOyB9XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdHJldHVybiBmYWxzZTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIG9uY2Uo4oCmKTogdGhpc1xyXG5cdC8vIEJlaGF2ZXMgYXMgW2BvbijigKYpYF0oI2V2ZW50ZWQtb24pLCBleGNlcHQgdGhlIGxpc3RlbmVyIHdpbGwgb25seSBnZXQgZmlyZWQgb25jZSBhbmQgdGhlbiByZW1vdmVkLlxyXG5cdG9uY2U6IGZ1bmN0aW9uICh0eXBlcywgZm4sIGNvbnRleHQpIHtcclxuXHJcblx0XHRpZiAodHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG5cdFx0XHRmb3IgKHZhciB0eXBlIGluIHR5cGVzKSB7XHJcblx0XHRcdFx0dGhpcy5vbmNlKHR5cGUsIHR5cGVzW3R5cGVdLCBmbik7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIGhhbmRsZXIgPSBiaW5kKGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0dGhpc1xyXG5cdFx0XHQgICAgLm9mZih0eXBlcywgZm4sIGNvbnRleHQpXHJcblx0XHRcdCAgICAub2ZmKHR5cGVzLCBoYW5kbGVyLCBjb250ZXh0KTtcclxuXHRcdH0sIHRoaXMpO1xyXG5cclxuXHRcdC8vIGFkZCBhIGxpc3RlbmVyIHRoYXQncyBleGVjdXRlZCBvbmNlIGFuZCByZW1vdmVkIGFmdGVyIHRoYXRcclxuXHRcdHJldHVybiB0aGlzXHJcblx0XHQgICAgLm9uKHR5cGVzLCBmbiwgY29udGV4dClcclxuXHRcdCAgICAub24odHlwZXMsIGhhbmRsZXIsIGNvbnRleHQpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgYWRkRXZlbnRQYXJlbnQob2JqOiBFdmVudGVkKTogdGhpc1xyXG5cdC8vIEFkZHMgYW4gZXZlbnQgcGFyZW50IC0gYW4gYEV2ZW50ZWRgIHRoYXQgd2lsbCByZWNlaXZlIHByb3BhZ2F0ZWQgZXZlbnRzXHJcblx0YWRkRXZlbnRQYXJlbnQ6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdHRoaXMuX2V2ZW50UGFyZW50cyA9IHRoaXMuX2V2ZW50UGFyZW50cyB8fCB7fTtcclxuXHRcdHRoaXMuX2V2ZW50UGFyZW50c1tzdGFtcChvYmopXSA9IG9iajtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgcmVtb3ZlRXZlbnRQYXJlbnQob2JqOiBFdmVudGVkKTogdGhpc1xyXG5cdC8vIFJlbW92ZXMgYW4gZXZlbnQgcGFyZW50LCBzbyBpdCB3aWxsIHN0b3AgcmVjZWl2aW5nIHByb3BhZ2F0ZWQgZXZlbnRzXHJcblx0cmVtb3ZlRXZlbnRQYXJlbnQ6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdGlmICh0aGlzLl9ldmVudFBhcmVudHMpIHtcclxuXHRcdFx0ZGVsZXRlIHRoaXMuX2V2ZW50UGFyZW50c1tzdGFtcChvYmopXTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdF9wcm9wYWdhdGVFdmVudDogZnVuY3Rpb24gKGUpIHtcclxuXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2V2ZW50UGFyZW50cykge1xyXG5cdFx0XHR0aGlzLl9ldmVudFBhcmVudHNbaWRdLmZpcmUoZS50eXBlLCBleHRlbmQoe1xyXG5cdFx0XHRcdGxheWVyOiBlLnRhcmdldCxcclxuXHRcdFx0XHRwcm9wYWdhdGVkRnJvbTogZS50YXJnZXRcclxuXHRcdFx0fSwgZSksIHRydWUpO1xyXG5cdFx0fVxyXG5cdH1cclxufTtcclxuXHJcbi8vIGFsaWFzZXM7IHdlIHNob3VsZCBkaXRjaCB0aG9zZSBldmVudHVhbGx5XHJcblxyXG4vLyBAbWV0aG9kIGFkZEV2ZW50TGlzdGVuZXIo4oCmKTogdGhpc1xyXG4vLyBBbGlhcyB0byBbYG9uKOKApilgXSgjZXZlbnRlZC1vbilcclxuRXZlbnRzLmFkZEV2ZW50TGlzdGVuZXIgPSBFdmVudHMub247XHJcblxyXG4vLyBAbWV0aG9kIHJlbW92ZUV2ZW50TGlzdGVuZXIo4oCmKTogdGhpc1xyXG4vLyBBbGlhcyB0byBbYG9mZijigKYpYF0oI2V2ZW50ZWQtb2ZmKVxyXG5cclxuLy8gQG1ldGhvZCBjbGVhckFsbEV2ZW50TGlzdGVuZXJzKOKApik6IHRoaXNcclxuLy8gQWxpYXMgdG8gW2BvZmYoKWBdKCNldmVudGVkLW9mZilcclxuRXZlbnRzLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBFdmVudHMuY2xlYXJBbGxFdmVudExpc3RlbmVycyA9IEV2ZW50cy5vZmY7XHJcblxyXG4vLyBAbWV0aG9kIGFkZE9uZVRpbWVFdmVudExpc3RlbmVyKOKApik6IHRoaXNcclxuLy8gQWxpYXMgdG8gW2BvbmNlKOKApilgXSgjZXZlbnRlZC1vbmNlKVxyXG5FdmVudHMuYWRkT25lVGltZUV2ZW50TGlzdGVuZXIgPSBFdmVudHMub25jZTtcclxuXHJcbi8vIEBtZXRob2QgZmlyZUV2ZW50KOKApik6IHRoaXNcclxuLy8gQWxpYXMgdG8gW2BmaXJlKOKApilgXSgjZXZlbnRlZC1maXJlKVxyXG5FdmVudHMuZmlyZUV2ZW50ID0gRXZlbnRzLmZpcmU7XHJcblxyXG4vLyBAbWV0aG9kIGhhc0V2ZW50TGlzdGVuZXJzKOKApik6IEJvb2xlYW5cclxuLy8gQWxpYXMgdG8gW2BsaXN0ZW5zKOKApilgXSgjZXZlbnRlZC1saXN0ZW5zKVxyXG5FdmVudHMuaGFzRXZlbnRMaXN0ZW5lcnMgPSBFdmVudHMubGlzdGVucztcclxuXHJcbnZhciBFdmVudGVkID0gQ2xhc3MuZXh0ZW5kKEV2ZW50cyk7XG5cbi8qXHJcbiAqIEBjbGFzcyBQb2ludFxyXG4gKiBAYWthIEwuUG9pbnRcclxuICpcclxuICogUmVwcmVzZW50cyBhIHBvaW50IHdpdGggYHhgIGFuZCBgeWAgY29vcmRpbmF0ZXMgaW4gcGl4ZWxzLlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiB2YXIgcG9pbnQgPSBMLnBvaW50KDIwMCwgMzAwKTtcclxuICogYGBgXHJcbiAqXHJcbiAqIEFsbCBMZWFmbGV0IG1ldGhvZHMgYW5kIG9wdGlvbnMgdGhhdCBhY2NlcHQgYFBvaW50YCBvYmplY3RzIGFsc28gYWNjZXB0IHRoZW0gaW4gYSBzaW1wbGUgQXJyYXkgZm9ybSAodW5sZXNzIG5vdGVkIG90aGVyd2lzZSksIHNvIHRoZXNlIGxpbmVzIGFyZSBlcXVpdmFsZW50OlxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiBtYXAucGFuQnkoWzIwMCwgMzAwXSk7XHJcbiAqIG1hcC5wYW5CeShMLnBvaW50KDIwMCwgMzAwKSk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBOb3RlIHRoYXQgYFBvaW50YCBkb2VzIG5vdCBpbmhlcml0IGZyb20gTGVhZmV0J3MgYENsYXNzYCBvYmplY3QsXHJcbiAqIHdoaWNoIG1lYW5zIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSBpdCwgYW5kIG5ldyBtZXRob2RzXHJcbiAqIGNhbid0IGJlIGFkZGVkIHRvIGl0IHdpdGggdGhlIGBpbmNsdWRlYCBmdW5jdGlvbi5cclxuICovXHJcblxyXG5mdW5jdGlvbiBQb2ludCh4LCB5LCByb3VuZCkge1xyXG5cdC8vIEBwcm9wZXJ0eSB4OiBOdW1iZXI7IFRoZSBgeGAgY29vcmRpbmF0ZSBvZiB0aGUgcG9pbnRcclxuXHR0aGlzLnggPSAocm91bmQgPyBNYXRoLnJvdW5kKHgpIDogeCk7XHJcblx0Ly8gQHByb3BlcnR5IHk6IE51bWJlcjsgVGhlIGB5YCBjb29yZGluYXRlIG9mIHRoZSBwb2ludFxyXG5cdHRoaXMueSA9IChyb3VuZCA/IE1hdGgucm91bmQoeSkgOiB5KTtcclxufVxyXG5cclxudmFyIHRydW5jID0gTWF0aC50cnVuYyB8fCBmdW5jdGlvbiAodikge1xyXG5cdHJldHVybiB2ID4gMCA/IE1hdGguZmxvb3IodikgOiBNYXRoLmNlaWwodik7XHJcbn07XHJcblxyXG5Qb2ludC5wcm90b3R5cGUgPSB7XHJcblxyXG5cdC8vIEBtZXRob2QgY2xvbmUoKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludC5cclxuXHRjbG9uZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIG5ldyBQb2ludCh0aGlzLngsIHRoaXMueSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBhZGQob3RoZXJQb2ludDogUG9pbnQpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgdGhlIHJlc3VsdCBvZiBhZGRpdGlvbiBvZiB0aGUgY3VycmVudCBhbmQgdGhlIGdpdmVuIHBvaW50cy5cclxuXHRhZGQ6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0Ly8gbm9uLWRlc3RydWN0aXZlLCByZXR1cm5zIGEgbmV3IHBvaW50XHJcblx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9hZGQodG9Qb2ludChwb2ludCkpO1xyXG5cdH0sXHJcblxyXG5cdF9hZGQ6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0Ly8gZGVzdHJ1Y3RpdmUsIHVzZWQgZGlyZWN0bHkgZm9yIHBlcmZvcm1hbmNlIGluIHNpdHVhdGlvbnMgd2hlcmUgaXQncyBzYWZlIHRvIG1vZGlmeSBleGlzdGluZyBwb2ludFxyXG5cdFx0dGhpcy54ICs9IHBvaW50Lng7XHJcblx0XHR0aGlzLnkgKz0gcG9pbnQueTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc3VidHJhY3Qob3RoZXJQb2ludDogUG9pbnQpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgdGhlIHJlc3VsdCBvZiBzdWJ0cmFjdGlvbiBvZiB0aGUgZ2l2ZW4gcG9pbnQgZnJvbSB0aGUgY3VycmVudC5cclxuXHRzdWJ0cmFjdDogZnVuY3Rpb24gKHBvaW50KSB7XHJcblx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9zdWJ0cmFjdCh0b1BvaW50KHBvaW50KSk7XHJcblx0fSxcclxuXHJcblx0X3N1YnRyYWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuXHRcdHRoaXMueCAtPSBwb2ludC54O1xyXG5cdFx0dGhpcy55IC09IHBvaW50Lnk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGRpdmlkZUJ5KG51bTogTnVtYmVyKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2YgZGl2aXNpb24gb2YgdGhlIGN1cnJlbnQgcG9pbnQgYnkgdGhlIGdpdmVuIG51bWJlci5cclxuXHRkaXZpZGVCeTogZnVuY3Rpb24gKG51bSkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fZGl2aWRlQnkobnVtKTtcclxuXHR9LFxyXG5cclxuXHRfZGl2aWRlQnk6IGZ1bmN0aW9uIChudW0pIHtcclxuXHRcdHRoaXMueCAvPSBudW07XHJcblx0XHR0aGlzLnkgLz0gbnVtO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBtdWx0aXBseUJ5KG51bTogTnVtYmVyKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2YgbXVsdGlwbGljYXRpb24gb2YgdGhlIGN1cnJlbnQgcG9pbnQgYnkgdGhlIGdpdmVuIG51bWJlci5cclxuXHRtdWx0aXBseUJ5OiBmdW5jdGlvbiAobnVtKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9tdWx0aXBseUJ5KG51bSk7XHJcblx0fSxcclxuXHJcblx0X211bHRpcGx5Qnk6IGZ1bmN0aW9uIChudW0pIHtcclxuXHRcdHRoaXMueCAqPSBudW07XHJcblx0XHR0aGlzLnkgKj0gbnVtO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzY2FsZUJ5KHNjYWxlOiBQb2ludCk6IFBvaW50XHJcblx0Ly8gTXVsdGlwbHkgZWFjaCBjb29yZGluYXRlIG9mIHRoZSBjdXJyZW50IHBvaW50IGJ5IGVhY2ggY29vcmRpbmF0ZSBvZlxyXG5cdC8vIGBzY2FsZWAuIEluIGxpbmVhciBhbGdlYnJhIHRlcm1zLCBtdWx0aXBseSB0aGUgcG9pbnQgYnkgdGhlXHJcblx0Ly8gW3NjYWxpbmcgbWF0cml4XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TY2FsaW5nXyUyOGdlb21ldHJ5JTI5I01hdHJpeF9yZXByZXNlbnRhdGlvbilcclxuXHQvLyBkZWZpbmVkIGJ5IGBzY2FsZWAuXHJcblx0c2NhbGVCeTogZnVuY3Rpb24gKHBvaW50KSB7XHJcblx0XHRyZXR1cm4gbmV3IFBvaW50KHRoaXMueCAqIHBvaW50LngsIHRoaXMueSAqIHBvaW50LnkpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgdW5zY2FsZUJ5KHNjYWxlOiBQb2ludCk6IFBvaW50XHJcblx0Ly8gSW52ZXJzZSBvZiBgc2NhbGVCeWAuIERpdmlkZSBlYWNoIGNvb3JkaW5hdGUgb2YgdGhlIGN1cnJlbnQgcG9pbnQgYnlcclxuXHQvLyBlYWNoIGNvb3JkaW5hdGUgb2YgYHNjYWxlYC5cclxuXHR1bnNjYWxlQnk6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0cmV0dXJuIG5ldyBQb2ludCh0aGlzLnggLyBwb2ludC54LCB0aGlzLnkgLyBwb2ludC55KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHJvdW5kKCk6IFBvaW50XHJcblx0Ly8gUmV0dXJucyBhIGNvcHkgb2YgdGhlIGN1cnJlbnQgcG9pbnQgd2l0aCByb3VuZGVkIGNvb3JkaW5hdGVzLlxyXG5cdHJvdW5kOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9yb3VuZCgpO1xyXG5cdH0sXHJcblxyXG5cdF9yb3VuZDogZnVuY3Rpb24gKCkge1xyXG5cdFx0dGhpcy54ID0gTWF0aC5yb3VuZCh0aGlzLngpO1xyXG5cdFx0dGhpcy55ID0gTWF0aC5yb3VuZCh0aGlzLnkpO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBmbG9vcigpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgYSBjb3B5IG9mIHRoZSBjdXJyZW50IHBvaW50IHdpdGggZmxvb3JlZCBjb29yZGluYXRlcyAocm91bmRlZCBkb3duKS5cclxuXHRmbG9vcjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fZmxvb3IoKTtcclxuXHR9LFxyXG5cclxuXHRfZmxvb3I6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMueCA9IE1hdGguZmxvb3IodGhpcy54KTtcclxuXHRcdHRoaXMueSA9IE1hdGguZmxvb3IodGhpcy55KTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY2VpbCgpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgYSBjb3B5IG9mIHRoZSBjdXJyZW50IHBvaW50IHdpdGggY2VpbGVkIGNvb3JkaW5hdGVzIChyb3VuZGVkIHVwKS5cclxuXHRjZWlsOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLl9jZWlsKCk7XHJcblx0fSxcclxuXHJcblx0X2NlaWw6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMueCA9IE1hdGguY2VpbCh0aGlzLngpO1xyXG5cdFx0dGhpcy55ID0gTWF0aC5jZWlsKHRoaXMueSk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHRydW5jKCk6IFBvaW50XHJcblx0Ly8gUmV0dXJucyBhIGNvcHkgb2YgdGhlIGN1cnJlbnQgcG9pbnQgd2l0aCB0cnVuY2F0ZWQgY29vcmRpbmF0ZXMgKHJvdW5kZWQgdG93YXJkcyB6ZXJvKS5cclxuXHR0cnVuYzogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fdHJ1bmMoKTtcclxuXHR9LFxyXG5cclxuXHRfdHJ1bmM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMueCA9IHRydW5jKHRoaXMueCk7XHJcblx0XHR0aGlzLnkgPSB0cnVuYyh0aGlzLnkpO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBkaXN0YW5jZVRvKG90aGVyUG9pbnQ6IFBvaW50KTogTnVtYmVyXHJcblx0Ly8gUmV0dXJucyB0aGUgY2FydGVzaWFuIGRpc3RhbmNlIGJldHdlZW4gdGhlIGN1cnJlbnQgYW5kIHRoZSBnaXZlbiBwb2ludHMuXHJcblx0ZGlzdGFuY2VUbzogZnVuY3Rpb24gKHBvaW50KSB7XHJcblx0XHRwb2ludCA9IHRvUG9pbnQocG9pbnQpO1xyXG5cclxuXHRcdHZhciB4ID0gcG9pbnQueCAtIHRoaXMueCxcclxuXHRcdCAgICB5ID0gcG9pbnQueSAtIHRoaXMueTtcclxuXHJcblx0XHRyZXR1cm4gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZXF1YWxzKG90aGVyUG9pbnQ6IFBvaW50KTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiBwb2ludCBoYXMgdGhlIHNhbWUgY29vcmRpbmF0ZXMuXHJcblx0ZXF1YWxzOiBmdW5jdGlvbiAocG9pbnQpIHtcclxuXHRcdHBvaW50ID0gdG9Qb2ludChwb2ludCk7XHJcblxyXG5cdFx0cmV0dXJuIHBvaW50LnggPT09IHRoaXMueCAmJlxyXG5cdFx0ICAgICAgIHBvaW50LnkgPT09IHRoaXMueTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGNvbnRhaW5zKG90aGVyUG9pbnQ6IFBvaW50KTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIGJvdGggY29vcmRpbmF0ZXMgb2YgdGhlIGdpdmVuIHBvaW50IGFyZSBsZXNzIHRoYW4gdGhlIGNvcnJlc3BvbmRpbmcgY3VycmVudCBwb2ludCBjb29yZGluYXRlcyAoaW4gYWJzb2x1dGUgdmFsdWVzKS5cclxuXHRjb250YWluczogZnVuY3Rpb24gKHBvaW50KSB7XHJcblx0XHRwb2ludCA9IHRvUG9pbnQocG9pbnQpO1xyXG5cclxuXHRcdHJldHVybiBNYXRoLmFicyhwb2ludC54KSA8PSBNYXRoLmFicyh0aGlzLngpICYmXHJcblx0XHQgICAgICAgTWF0aC5hYnMocG9pbnQueSkgPD0gTWF0aC5hYnModGhpcy55KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHRvU3RyaW5nKCk6IFN0cmluZ1xyXG5cdC8vIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50IGZvciBkZWJ1Z2dpbmcgcHVycG9zZXMuXHJcblx0dG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiAnUG9pbnQoJyArXHJcblx0XHQgICAgICAgIGZvcm1hdE51bSh0aGlzLngpICsgJywgJyArXHJcblx0XHQgICAgICAgIGZvcm1hdE51bSh0aGlzLnkpICsgJyknO1xyXG5cdH1cclxufTtcclxuXHJcbi8vIEBmYWN0b3J5IEwucG9pbnQoeDogTnVtYmVyLCB5OiBOdW1iZXIsIHJvdW5kPzogQm9vbGVhbilcclxuLy8gQ3JlYXRlcyBhIFBvaW50IG9iamVjdCB3aXRoIHRoZSBnaXZlbiBgeGAgYW5kIGB5YCBjb29yZGluYXRlcy4gSWYgb3B0aW9uYWwgYHJvdW5kYCBpcyBzZXQgdG8gdHJ1ZSwgcm91bmRzIHRoZSBgeGAgYW5kIGB5YCB2YWx1ZXMuXHJcblxyXG4vLyBAYWx0ZXJuYXRpdmVcclxuLy8gQGZhY3RvcnkgTC5wb2ludChjb29yZHM6IE51bWJlcltdKVxyXG4vLyBFeHBlY3RzIGFuIGFycmF5IG9mIHRoZSBmb3JtIGBbeCwgeV1gIGluc3RlYWQuXHJcblxyXG4vLyBAYWx0ZXJuYXRpdmVcclxuLy8gQGZhY3RvcnkgTC5wb2ludChjb29yZHM6IE9iamVjdClcclxuLy8gRXhwZWN0cyBhIHBsYWluIG9iamVjdCBvZiB0aGUgZm9ybSBge3g6IE51bWJlciwgeTogTnVtYmVyfWAgaW5zdGVhZC5cclxuZnVuY3Rpb24gdG9Qb2ludCh4LCB5LCByb3VuZCkge1xyXG5cdGlmICh4IGluc3RhbmNlb2YgUG9pbnQpIHtcclxuXHRcdHJldHVybiB4O1xyXG5cdH1cclxuXHRpZiAoaXNBcnJheSh4KSkge1xyXG5cdFx0cmV0dXJuIG5ldyBQb2ludCh4WzBdLCB4WzFdKTtcclxuXHR9XHJcblx0aWYgKHggPT09IHVuZGVmaW5lZCB8fCB4ID09PSBudWxsKSB7XHJcblx0XHRyZXR1cm4geDtcclxuXHR9XHJcblx0aWYgKHR5cGVvZiB4ID09PSAnb2JqZWN0JyAmJiAneCcgaW4geCAmJiAneScgaW4geCkge1xyXG5cdFx0cmV0dXJuIG5ldyBQb2ludCh4LngsIHgueSk7XHJcblx0fVxyXG5cdHJldHVybiBuZXcgUG9pbnQoeCwgeSwgcm91bmQpO1xyXG59XG5cbi8qXHJcbiAqIEBjbGFzcyBCb3VuZHNcclxuICogQGFrYSBMLkJvdW5kc1xyXG4gKlxyXG4gKiBSZXByZXNlbnRzIGEgcmVjdGFuZ3VsYXIgYXJlYSBpbiBwaXhlbCBjb29yZGluYXRlcy5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogdmFyIHAxID0gTC5wb2ludCgxMCwgMTApLFxyXG4gKiBwMiA9IEwucG9pbnQoNDAsIDYwKSxcclxuICogYm91bmRzID0gTC5ib3VuZHMocDEsIHAyKTtcclxuICogYGBgXHJcbiAqXHJcbiAqIEFsbCBMZWFmbGV0IG1ldGhvZHMgdGhhdCBhY2NlcHQgYEJvdW5kc2Agb2JqZWN0cyBhbHNvIGFjY2VwdCB0aGVtIGluIGEgc2ltcGxlIEFycmF5IGZvcm0gKHVubGVzcyBub3RlZCBvdGhlcndpc2UpLCBzbyB0aGUgYm91bmRzIGV4YW1wbGUgYWJvdmUgY2FuIGJlIHBhc3NlZCBsaWtlIHRoaXM6XHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIG90aGVyQm91bmRzLmludGVyc2VjdHMoW1sxMCwgMTBdLCBbNDAsIDYwXV0pO1xyXG4gKiBgYGBcclxuICpcclxuICogTm90ZSB0aGF0IGBCb3VuZHNgIGRvZXMgbm90IGluaGVyaXQgZnJvbSBMZWFmZXQncyBgQ2xhc3NgIG9iamVjdCxcclxuICogd2hpY2ggbWVhbnMgbmV3IGNsYXNzZXMgY2FuJ3QgaW5oZXJpdCBmcm9tIGl0LCBhbmQgbmV3IG1ldGhvZHNcclxuICogY2FuJ3QgYmUgYWRkZWQgdG8gaXQgd2l0aCB0aGUgYGluY2x1ZGVgIGZ1bmN0aW9uLlxyXG4gKi9cclxuXHJcbmZ1bmN0aW9uIEJvdW5kcyhhLCBiKSB7XHJcblx0aWYgKCFhKSB7IHJldHVybjsgfVxyXG5cclxuXHR2YXIgcG9pbnRzID0gYiA/IFthLCBiXSA6IGE7XHJcblxyXG5cdGZvciAodmFyIGkgPSAwLCBsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdHRoaXMuZXh0ZW5kKHBvaW50c1tpXSk7XHJcblx0fVxyXG59XHJcblxyXG5Cb3VuZHMucHJvdG90eXBlID0ge1xyXG5cdC8vIEBtZXRob2QgZXh0ZW5kKHBvaW50OiBQb2ludCk6IHRoaXNcclxuXHQvLyBFeHRlbmRzIHRoZSBib3VuZHMgdG8gY29udGFpbiB0aGUgZ2l2ZW4gcG9pbnQuXHJcblx0ZXh0ZW5kOiBmdW5jdGlvbiAocG9pbnQpIHsgLy8gKFBvaW50KVxyXG5cdFx0cG9pbnQgPSB0b1BvaW50KHBvaW50KTtcclxuXHJcblx0XHQvLyBAcHJvcGVydHkgbWluOiBQb2ludFxyXG5cdFx0Ly8gVGhlIHRvcCBsZWZ0IGNvcm5lciBvZiB0aGUgcmVjdGFuZ2xlLlxyXG5cdFx0Ly8gQHByb3BlcnR5IG1heDogUG9pbnRcclxuXHRcdC8vIFRoZSBib3R0b20gcmlnaHQgY29ybmVyIG9mIHRoZSByZWN0YW5nbGUuXHJcblx0XHRpZiAoIXRoaXMubWluICYmICF0aGlzLm1heCkge1xyXG5cdFx0XHR0aGlzLm1pbiA9IHBvaW50LmNsb25lKCk7XHJcblx0XHRcdHRoaXMubWF4ID0gcG9pbnQuY2xvbmUoKTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHRoaXMubWluLnggPSBNYXRoLm1pbihwb2ludC54LCB0aGlzLm1pbi54KTtcclxuXHRcdFx0dGhpcy5tYXgueCA9IE1hdGgubWF4KHBvaW50LngsIHRoaXMubWF4LngpO1xyXG5cdFx0XHR0aGlzLm1pbi55ID0gTWF0aC5taW4ocG9pbnQueSwgdGhpcy5taW4ueSk7XHJcblx0XHRcdHRoaXMubWF4LnkgPSBNYXRoLm1heChwb2ludC55LCB0aGlzLm1heC55KTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0Q2VudGVyKHJvdW5kPzogQm9vbGVhbik6IFBvaW50XHJcblx0Ly8gUmV0dXJucyB0aGUgY2VudGVyIHBvaW50IG9mIHRoZSBib3VuZHMuXHJcblx0Z2V0Q2VudGVyOiBmdW5jdGlvbiAocm91bmQpIHtcclxuXHRcdHJldHVybiBuZXcgUG9pbnQoXHJcblx0XHQgICAgICAgICh0aGlzLm1pbi54ICsgdGhpcy5tYXgueCkgLyAyLFxyXG5cdFx0ICAgICAgICAodGhpcy5taW4ueSArIHRoaXMubWF4LnkpIC8gMiwgcm91bmQpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0Qm90dG9tTGVmdCgpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgdGhlIGJvdHRvbS1sZWZ0IHBvaW50IG9mIHRoZSBib3VuZHMuXHJcblx0Z2V0Qm90dG9tTGVmdDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIG5ldyBQb2ludCh0aGlzLm1pbi54LCB0aGlzLm1heC55KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldFRvcFJpZ2h0KCk6IFBvaW50XHJcblx0Ly8gUmV0dXJucyB0aGUgdG9wLXJpZ2h0IHBvaW50IG9mIHRoZSBib3VuZHMuXHJcblx0Z2V0VG9wUmlnaHQ6IGZ1bmN0aW9uICgpIHsgLy8gLT4gUG9pbnRcclxuXHRcdHJldHVybiBuZXcgUG9pbnQodGhpcy5tYXgueCwgdGhpcy5taW4ueSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRUb3BMZWZ0KCk6IFBvaW50XHJcblx0Ly8gUmV0dXJucyB0aGUgdG9wLWxlZnQgcG9pbnQgb2YgdGhlIGJvdW5kcyAoaS5lLiBbYHRoaXMubWluYF0oI2JvdW5kcy1taW4pKS5cclxuXHRnZXRUb3BMZWZ0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5taW47IC8vIGxlZnQsIHRvcFxyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0Qm90dG9tUmlnaHQoKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIHRoZSBib3R0b20tcmlnaHQgcG9pbnQgb2YgdGhlIGJvdW5kcyAoaS5lLiBbYHRoaXMubWF4YF0oI2JvdW5kcy1tYXgpKS5cclxuXHRnZXRCb3R0b21SaWdodDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMubWF4OyAvLyByaWdodCwgYm90dG9tXHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRTaXplKCk6IFBvaW50XHJcblx0Ly8gUmV0dXJucyB0aGUgc2l6ZSBvZiB0aGUgZ2l2ZW4gYm91bmRzXHJcblx0Z2V0U2l6ZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMubWF4LnN1YnRyYWN0KHRoaXMubWluKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGNvbnRhaW5zKG90aGVyQm91bmRzOiBCb3VuZHMpOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBjb250YWlucyB0aGUgZ2l2ZW4gb25lLlxyXG5cdC8vIEBhbHRlcm5hdGl2ZVxyXG5cdC8vIEBtZXRob2QgY29udGFpbnMocG9pbnQ6IFBvaW50KTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgY29udGFpbnMgdGhlIGdpdmVuIHBvaW50LlxyXG5cdGNvbnRhaW5zOiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHR2YXIgbWluLCBtYXg7XHJcblxyXG5cdFx0aWYgKHR5cGVvZiBvYmpbMF0gPT09ICdudW1iZXInIHx8IG9iaiBpbnN0YW5jZW9mIFBvaW50KSB7XHJcblx0XHRcdG9iaiA9IHRvUG9pbnQob2JqKTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdG9iaiA9IHRvQm91bmRzKG9iaik7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKG9iaiBpbnN0YW5jZW9mIEJvdW5kcykge1xyXG5cdFx0XHRtaW4gPSBvYmoubWluO1xyXG5cdFx0XHRtYXggPSBvYmoubWF4O1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0bWluID0gbWF4ID0gb2JqO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiAobWluLnggPj0gdGhpcy5taW4ueCkgJiZcclxuXHRcdCAgICAgICAobWF4LnggPD0gdGhpcy5tYXgueCkgJiZcclxuXHRcdCAgICAgICAobWluLnkgPj0gdGhpcy5taW4ueSkgJiZcclxuXHRcdCAgICAgICAobWF4LnkgPD0gdGhpcy5tYXgueSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBpbnRlcnNlY3RzKG90aGVyQm91bmRzOiBCb3VuZHMpOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBpbnRlcnNlY3RzIHRoZSBnaXZlbiBib3VuZHMuIFR3byBib3VuZHNcclxuXHQvLyBpbnRlcnNlY3QgaWYgdGhleSBoYXZlIGF0IGxlYXN0IG9uZSBwb2ludCBpbiBjb21tb24uXHJcblx0aW50ZXJzZWN0czogZnVuY3Rpb24gKGJvdW5kcykgeyAvLyAoQm91bmRzKSAtPiBCb29sZWFuXHJcblx0XHRib3VuZHMgPSB0b0JvdW5kcyhib3VuZHMpO1xyXG5cclxuXHRcdHZhciBtaW4gPSB0aGlzLm1pbixcclxuXHRcdCAgICBtYXggPSB0aGlzLm1heCxcclxuXHRcdCAgICBtaW4yID0gYm91bmRzLm1pbixcclxuXHRcdCAgICBtYXgyID0gYm91bmRzLm1heCxcclxuXHRcdCAgICB4SW50ZXJzZWN0cyA9IChtYXgyLnggPj0gbWluLngpICYmIChtaW4yLnggPD0gbWF4LngpLFxyXG5cdFx0ICAgIHlJbnRlcnNlY3RzID0gKG1heDIueSA+PSBtaW4ueSkgJiYgKG1pbjIueSA8PSBtYXgueSk7XHJcblxyXG5cdFx0cmV0dXJuIHhJbnRlcnNlY3RzICYmIHlJbnRlcnNlY3RzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgb3ZlcmxhcHMob3RoZXJCb3VuZHM6IEJvdW5kcyk6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIG92ZXJsYXBzIHRoZSBnaXZlbiBib3VuZHMuIFR3byBib3VuZHNcclxuXHQvLyBvdmVybGFwIGlmIHRoZWlyIGludGVyc2VjdGlvbiBpcyBhbiBhcmVhLlxyXG5cdG92ZXJsYXBzOiBmdW5jdGlvbiAoYm91bmRzKSB7IC8vIChCb3VuZHMpIC0+IEJvb2xlYW5cclxuXHRcdGJvdW5kcyA9IHRvQm91bmRzKGJvdW5kcyk7XHJcblxyXG5cdFx0dmFyIG1pbiA9IHRoaXMubWluLFxyXG5cdFx0ICAgIG1heCA9IHRoaXMubWF4LFxyXG5cdFx0ICAgIG1pbjIgPSBib3VuZHMubWluLFxyXG5cdFx0ICAgIG1heDIgPSBib3VuZHMubWF4LFxyXG5cdFx0ICAgIHhPdmVybGFwcyA9IChtYXgyLnggPiBtaW4ueCkgJiYgKG1pbjIueCA8IG1heC54KSxcclxuXHRcdCAgICB5T3ZlcmxhcHMgPSAobWF4Mi55ID4gbWluLnkpICYmIChtaW4yLnkgPCBtYXgueSk7XHJcblxyXG5cdFx0cmV0dXJuIHhPdmVybGFwcyAmJiB5T3ZlcmxhcHM7XHJcblx0fSxcclxuXHJcblx0aXNWYWxpZDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuICEhKHRoaXMubWluICYmIHRoaXMubWF4KTtcclxuXHR9XHJcbn07XHJcblxyXG5cclxuLy8gQGZhY3RvcnkgTC5ib3VuZHMoY29ybmVyMTogUG9pbnQsIGNvcm5lcjI6IFBvaW50KVxyXG4vLyBDcmVhdGVzIGEgQm91bmRzIG9iamVjdCBmcm9tIHR3byBjb3JuZXJzIGNvb3JkaW5hdGUgcGFpcnMuXHJcbi8vIEBhbHRlcm5hdGl2ZVxyXG4vLyBAZmFjdG9yeSBMLmJvdW5kcyhwb2ludHM6IFBvaW50W10pXHJcbi8vIENyZWF0ZXMgYSBCb3VuZHMgb2JqZWN0IGZyb20gdGhlIGdpdmVuIGFycmF5IG9mIHBvaW50cy5cclxuZnVuY3Rpb24gdG9Cb3VuZHMoYSwgYikge1xyXG5cdGlmICghYSB8fCBhIGluc3RhbmNlb2YgQm91bmRzKSB7XHJcblx0XHRyZXR1cm4gYTtcclxuXHR9XHJcblx0cmV0dXJuIG5ldyBCb3VuZHMoYSwgYik7XHJcbn1cblxuLypcclxuICogQGNsYXNzIExhdExuZ0JvdW5kc1xyXG4gKiBAYWthIEwuTGF0TG5nQm91bmRzXHJcbiAqXHJcbiAqIFJlcHJlc2VudHMgYSByZWN0YW5ndWxhciBnZW9ncmFwaGljYWwgYXJlYSBvbiBhIG1hcC5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogdmFyIGNvcm5lcjEgPSBMLmxhdExuZyg0MC43MTIsIC03NC4yMjcpLFxyXG4gKiBjb3JuZXIyID0gTC5sYXRMbmcoNDAuNzc0LCAtNzQuMTI1KSxcclxuICogYm91bmRzID0gTC5sYXRMbmdCb3VuZHMoY29ybmVyMSwgY29ybmVyMik7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBBbGwgTGVhZmxldCBtZXRob2RzIHRoYXQgYWNjZXB0IExhdExuZ0JvdW5kcyBvYmplY3RzIGFsc28gYWNjZXB0IHRoZW0gaW4gYSBzaW1wbGUgQXJyYXkgZm9ybSAodW5sZXNzIG5vdGVkIG90aGVyd2lzZSksIHNvIHRoZSBib3VuZHMgZXhhbXBsZSBhYm92ZSBjYW4gYmUgcGFzc2VkIGxpa2UgdGhpczpcclxuICpcclxuICogYGBganNcclxuICogbWFwLmZpdEJvdW5kcyhbXHJcbiAqIFx0WzQwLjcxMiwgLTc0LjIyN10sXHJcbiAqIFx0WzQwLjc3NCwgLTc0LjEyNV1cclxuICogXSk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBDYXV0aW9uOiBpZiB0aGUgYXJlYSBjcm9zc2VzIHRoZSBhbnRpbWVyaWRpYW4gKG9mdGVuIGNvbmZ1c2VkIHdpdGggdGhlIEludGVybmF0aW9uYWwgRGF0ZSBMaW5lKSwgeW91IG11c3Qgc3BlY2lmeSBjb3JuZXJzIF9vdXRzaWRlXyB0aGUgWy0xODAsIDE4MF0gZGVncmVlcyBsb25naXR1ZGUgcmFuZ2UuXHJcbiAqXHJcbiAqIE5vdGUgdGhhdCBgTGF0TG5nQm91bmRzYCBkb2VzIG5vdCBpbmhlcml0IGZyb20gTGVhZmV0J3MgYENsYXNzYCBvYmplY3QsXHJcbiAqIHdoaWNoIG1lYW5zIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSBpdCwgYW5kIG5ldyBtZXRob2RzXHJcbiAqIGNhbid0IGJlIGFkZGVkIHRvIGl0IHdpdGggdGhlIGBpbmNsdWRlYCBmdW5jdGlvbi5cclxuICovXHJcblxyXG5mdW5jdGlvbiBMYXRMbmdCb3VuZHMoY29ybmVyMSwgY29ybmVyMikgeyAvLyAoTGF0TG5nLCBMYXRMbmcpIG9yIChMYXRMbmdbXSlcclxuXHRpZiAoIWNvcm5lcjEpIHsgcmV0dXJuOyB9XHJcblxyXG5cdHZhciBsYXRsbmdzID0gY29ybmVyMiA/IFtjb3JuZXIxLCBjb3JuZXIyXSA6IGNvcm5lcjE7XHJcblxyXG5cdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsYXRsbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHR0aGlzLmV4dGVuZChsYXRsbmdzW2ldKTtcclxuXHR9XHJcbn1cclxuXHJcbkxhdExuZ0JvdW5kcy5wcm90b3R5cGUgPSB7XHJcblxyXG5cdC8vIEBtZXRob2QgZXh0ZW5kKGxhdGxuZzogTGF0TG5nKTogdGhpc1xyXG5cdC8vIEV4dGVuZCB0aGUgYm91bmRzIHRvIGNvbnRhaW4gdGhlIGdpdmVuIHBvaW50XHJcblxyXG5cdC8vIEBhbHRlcm5hdGl2ZVxyXG5cdC8vIEBtZXRob2QgZXh0ZW5kKG90aGVyQm91bmRzOiBMYXRMbmdCb3VuZHMpOiB0aGlzXHJcblx0Ly8gRXh0ZW5kIHRoZSBib3VuZHMgdG8gY29udGFpbiB0aGUgZ2l2ZW4gYm91bmRzXHJcblx0ZXh0ZW5kOiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHR2YXIgc3cgPSB0aGlzLl9zb3V0aFdlc3QsXHJcblx0XHQgICAgbmUgPSB0aGlzLl9ub3J0aEVhc3QsXHJcblx0XHQgICAgc3cyLCBuZTI7XHJcblxyXG5cdFx0aWYgKG9iaiBpbnN0YW5jZW9mIExhdExuZykge1xyXG5cdFx0XHRzdzIgPSBvYmo7XHJcblx0XHRcdG5lMiA9IG9iajtcclxuXHJcblx0XHR9IGVsc2UgaWYgKG9iaiBpbnN0YW5jZW9mIExhdExuZ0JvdW5kcykge1xyXG5cdFx0XHRzdzIgPSBvYmouX3NvdXRoV2VzdDtcclxuXHRcdFx0bmUyID0gb2JqLl9ub3J0aEVhc3Q7XHJcblxyXG5cdFx0XHRpZiAoIXN3MiB8fCAhbmUyKSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cmV0dXJuIG9iaiA/IHRoaXMuZXh0ZW5kKHRvTGF0TG5nKG9iaikgfHwgdG9MYXRMbmdCb3VuZHMob2JqKSkgOiB0aGlzO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICghc3cgJiYgIW5lKSB7XHJcblx0XHRcdHRoaXMuX3NvdXRoV2VzdCA9IG5ldyBMYXRMbmcoc3cyLmxhdCwgc3cyLmxuZyk7XHJcblx0XHRcdHRoaXMuX25vcnRoRWFzdCA9IG5ldyBMYXRMbmcobmUyLmxhdCwgbmUyLmxuZyk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRzdy5sYXQgPSBNYXRoLm1pbihzdzIubGF0LCBzdy5sYXQpO1xyXG5cdFx0XHRzdy5sbmcgPSBNYXRoLm1pbihzdzIubG5nLCBzdy5sbmcpO1xyXG5cdFx0XHRuZS5sYXQgPSBNYXRoLm1heChuZTIubGF0LCBuZS5sYXQpO1xyXG5cdFx0XHRuZS5sbmcgPSBNYXRoLm1heChuZTIubG5nLCBuZS5sbmcpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgcGFkKGJ1ZmZlclJhdGlvOiBOdW1iZXIpOiBMYXRMbmdCb3VuZHNcclxuXHQvLyBSZXR1cm5zIGJvdW5kcyBjcmVhdGVkIGJ5IGV4dGVuZGluZyBvciByZXRyYWN0aW5nIHRoZSBjdXJyZW50IGJvdW5kcyBieSBhIGdpdmVuIHJhdGlvIGluIGVhY2ggZGlyZWN0aW9uLlxyXG5cdC8vIEZvciBleGFtcGxlLCBhIHJhdGlvIG9mIDAuNSBleHRlbmRzIHRoZSBib3VuZHMgYnkgNTAlIGluIGVhY2ggZGlyZWN0aW9uLlxyXG5cdC8vIE5lZ2F0aXZlIHZhbHVlcyB3aWxsIHJldHJhY3QgdGhlIGJvdW5kcy5cclxuXHRwYWQ6IGZ1bmN0aW9uIChidWZmZXJSYXRpbykge1xyXG5cdFx0dmFyIHN3ID0gdGhpcy5fc291dGhXZXN0LFxyXG5cdFx0ICAgIG5lID0gdGhpcy5fbm9ydGhFYXN0LFxyXG5cdFx0ICAgIGhlaWdodEJ1ZmZlciA9IE1hdGguYWJzKHN3LmxhdCAtIG5lLmxhdCkgKiBidWZmZXJSYXRpbyxcclxuXHRcdCAgICB3aWR0aEJ1ZmZlciA9IE1hdGguYWJzKHN3LmxuZyAtIG5lLmxuZykgKiBidWZmZXJSYXRpbztcclxuXHJcblx0XHRyZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhcclxuXHRcdCAgICAgICAgbmV3IExhdExuZyhzdy5sYXQgLSBoZWlnaHRCdWZmZXIsIHN3LmxuZyAtIHdpZHRoQnVmZmVyKSxcclxuXHRcdCAgICAgICAgbmV3IExhdExuZyhuZS5sYXQgKyBoZWlnaHRCdWZmZXIsIG5lLmxuZyArIHdpZHRoQnVmZmVyKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRDZW50ZXIoKTogTGF0TG5nXHJcblx0Ly8gUmV0dXJucyB0aGUgY2VudGVyIHBvaW50IG9mIHRoZSBib3VuZHMuXHJcblx0Z2V0Q2VudGVyOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gbmV3IExhdExuZyhcclxuXHRcdCAgICAgICAgKHRoaXMuX3NvdXRoV2VzdC5sYXQgKyB0aGlzLl9ub3J0aEVhc3QubGF0KSAvIDIsXHJcblx0XHQgICAgICAgICh0aGlzLl9zb3V0aFdlc3QubG5nICsgdGhpcy5fbm9ydGhFYXN0LmxuZykgLyAyKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldFNvdXRoV2VzdCgpOiBMYXRMbmdcclxuXHQvLyBSZXR1cm5zIHRoZSBzb3V0aC13ZXN0IHBvaW50IG9mIHRoZSBib3VuZHMuXHJcblx0Z2V0U291dGhXZXN0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fc291dGhXZXN0O1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0Tm9ydGhFYXN0KCk6IExhdExuZ1xyXG5cdC8vIFJldHVybnMgdGhlIG5vcnRoLWVhc3QgcG9pbnQgb2YgdGhlIGJvdW5kcy5cclxuXHRnZXROb3J0aEVhc3Q6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9ub3J0aEVhc3Q7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXROb3J0aFdlc3QoKTogTGF0TG5nXHJcblx0Ly8gUmV0dXJucyB0aGUgbm9ydGgtd2VzdCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG5cdGdldE5vcnRoV2VzdDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIG5ldyBMYXRMbmcodGhpcy5nZXROb3J0aCgpLCB0aGlzLmdldFdlc3QoKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRTb3V0aEVhc3QoKTogTGF0TG5nXHJcblx0Ly8gUmV0dXJucyB0aGUgc291dGgtZWFzdCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG5cdGdldFNvdXRoRWFzdDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIG5ldyBMYXRMbmcodGhpcy5nZXRTb3V0aCgpLCB0aGlzLmdldEVhc3QoKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRXZXN0KCk6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIHdlc3QgbG9uZ2l0dWRlIG9mIHRoZSBib3VuZHNcclxuXHRnZXRXZXN0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fc291dGhXZXN0LmxuZztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldFNvdXRoKCk6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIHNvdXRoIGxhdGl0dWRlIG9mIHRoZSBib3VuZHNcclxuXHRnZXRTb3V0aDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuX3NvdXRoV2VzdC5sYXQ7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRFYXN0KCk6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIGVhc3QgbG9uZ2l0dWRlIG9mIHRoZSBib3VuZHNcclxuXHRnZXRFYXN0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fbm9ydGhFYXN0LmxuZztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldE5vcnRoKCk6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIG5vcnRoIGxhdGl0dWRlIG9mIHRoZSBib3VuZHNcclxuXHRnZXROb3J0aDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuX25vcnRoRWFzdC5sYXQ7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBjb250YWlucyhvdGhlckJvdW5kczogTGF0TG5nQm91bmRzKTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgY29udGFpbnMgdGhlIGdpdmVuIG9uZS5cclxuXHJcblx0Ly8gQGFsdGVybmF0aXZlXHJcblx0Ly8gQG1ldGhvZCBjb250YWlucyAobGF0bG5nOiBMYXRMbmcpOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBjb250YWlucyB0aGUgZ2l2ZW4gcG9pbnQuXHJcblx0Y29udGFpbnM6IGZ1bmN0aW9uIChvYmopIHsgLy8gKExhdExuZ0JvdW5kcykgb3IgKExhdExuZykgLT4gQm9vbGVhblxyXG5cdFx0aWYgKHR5cGVvZiBvYmpbMF0gPT09ICdudW1iZXInIHx8IG9iaiBpbnN0YW5jZW9mIExhdExuZyB8fCAnbGF0JyBpbiBvYmopIHtcclxuXHRcdFx0b2JqID0gdG9MYXRMbmcob2JqKTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdG9iaiA9IHRvTGF0TG5nQm91bmRzKG9iaik7XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIHN3ID0gdGhpcy5fc291dGhXZXN0LFxyXG5cdFx0ICAgIG5lID0gdGhpcy5fbm9ydGhFYXN0LFxyXG5cdFx0ICAgIHN3MiwgbmUyO1xyXG5cclxuXHRcdGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmdCb3VuZHMpIHtcclxuXHRcdFx0c3cyID0gb2JqLmdldFNvdXRoV2VzdCgpO1xyXG5cdFx0XHRuZTIgPSBvYmouZ2V0Tm9ydGhFYXN0KCk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRzdzIgPSBuZTIgPSBvYmo7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIChzdzIubGF0ID49IHN3LmxhdCkgJiYgKG5lMi5sYXQgPD0gbmUubGF0KSAmJlxyXG5cdFx0ICAgICAgIChzdzIubG5nID49IHN3LmxuZykgJiYgKG5lMi5sbmcgPD0gbmUubG5nKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGludGVyc2VjdHMob3RoZXJCb3VuZHM6IExhdExuZ0JvdW5kcyk6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIGludGVyc2VjdHMgdGhlIGdpdmVuIGJvdW5kcy4gVHdvIGJvdW5kcyBpbnRlcnNlY3QgaWYgdGhleSBoYXZlIGF0IGxlYXN0IG9uZSBwb2ludCBpbiBjb21tb24uXHJcblx0aW50ZXJzZWN0czogZnVuY3Rpb24gKGJvdW5kcykge1xyXG5cdFx0Ym91bmRzID0gdG9MYXRMbmdCb3VuZHMoYm91bmRzKTtcclxuXHJcblx0XHR2YXIgc3cgPSB0aGlzLl9zb3V0aFdlc3QsXHJcblx0XHQgICAgbmUgPSB0aGlzLl9ub3J0aEVhc3QsXHJcblx0XHQgICAgc3cyID0gYm91bmRzLmdldFNvdXRoV2VzdCgpLFxyXG5cdFx0ICAgIG5lMiA9IGJvdW5kcy5nZXROb3J0aEVhc3QoKSxcclxuXHJcblx0XHQgICAgbGF0SW50ZXJzZWN0cyA9IChuZTIubGF0ID49IHN3LmxhdCkgJiYgKHN3Mi5sYXQgPD0gbmUubGF0KSxcclxuXHRcdCAgICBsbmdJbnRlcnNlY3RzID0gKG5lMi5sbmcgPj0gc3cubG5nKSAmJiAoc3cyLmxuZyA8PSBuZS5sbmcpO1xyXG5cclxuXHRcdHJldHVybiBsYXRJbnRlcnNlY3RzICYmIGxuZ0ludGVyc2VjdHM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBvdmVybGFwcyhvdGhlckJvdW5kczogQm91bmRzKTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgb3ZlcmxhcHMgdGhlIGdpdmVuIGJvdW5kcy4gVHdvIGJvdW5kcyBvdmVybGFwIGlmIHRoZWlyIGludGVyc2VjdGlvbiBpcyBhbiBhcmVhLlxyXG5cdG92ZXJsYXBzOiBmdW5jdGlvbiAoYm91bmRzKSB7XHJcblx0XHRib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuXHRcdHZhciBzdyA9IHRoaXMuX3NvdXRoV2VzdCxcclxuXHRcdCAgICBuZSA9IHRoaXMuX25vcnRoRWFzdCxcclxuXHRcdCAgICBzdzIgPSBib3VuZHMuZ2V0U291dGhXZXN0KCksXHJcblx0XHQgICAgbmUyID0gYm91bmRzLmdldE5vcnRoRWFzdCgpLFxyXG5cclxuXHRcdCAgICBsYXRPdmVybGFwcyA9IChuZTIubGF0ID4gc3cubGF0KSAmJiAoc3cyLmxhdCA8IG5lLmxhdCksXHJcblx0XHQgICAgbG5nT3ZlcmxhcHMgPSAobmUyLmxuZyA+IHN3LmxuZykgJiYgKHN3Mi5sbmcgPCBuZS5sbmcpO1xyXG5cclxuXHRcdHJldHVybiBsYXRPdmVybGFwcyAmJiBsbmdPdmVybGFwcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHRvQkJveFN0cmluZygpOiBTdHJpbmdcclxuXHQvLyBSZXR1cm5zIGEgc3RyaW5nIHdpdGggYm91bmRpbmcgYm94IGNvb3JkaW5hdGVzIGluIGEgJ3NvdXRod2VzdF9sbmcsc291dGh3ZXN0X2xhdCxub3J0aGVhc3RfbG5nLG5vcnRoZWFzdF9sYXQnIGZvcm1hdC4gVXNlZnVsIGZvciBzZW5kaW5nIHJlcXVlc3RzIHRvIHdlYiBzZXJ2aWNlcyB0aGF0IHJldHVybiBnZW8gZGF0YS5cclxuXHR0b0JCb3hTdHJpbmc6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiBbdGhpcy5nZXRXZXN0KCksIHRoaXMuZ2V0U291dGgoKSwgdGhpcy5nZXRFYXN0KCksIHRoaXMuZ2V0Tm9ydGgoKV0uam9pbignLCcpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZXF1YWxzKG90aGVyQm91bmRzOiBMYXRMbmdCb3VuZHMsIG1heE1hcmdpbj86IE51bWJlcik6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIGlzIGVxdWl2YWxlbnQgKHdpdGhpbiBhIHNtYWxsIG1hcmdpbiBvZiBlcnJvcikgdG8gdGhlIGdpdmVuIGJvdW5kcy4gVGhlIG1hcmdpbiBvZiBlcnJvciBjYW4gYmUgb3ZlcnJpZGRlbiBieSBzZXR0aW5nIGBtYXhNYXJnaW5gIHRvIGEgc21hbGwgbnVtYmVyLlxyXG5cdGVxdWFsczogZnVuY3Rpb24gKGJvdW5kcywgbWF4TWFyZ2luKSB7XHJcblx0XHRpZiAoIWJvdW5kcykgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcblx0XHRib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuXHRcdHJldHVybiB0aGlzLl9zb3V0aFdlc3QuZXF1YWxzKGJvdW5kcy5nZXRTb3V0aFdlc3QoKSwgbWF4TWFyZ2luKSAmJlxyXG5cdFx0ICAgICAgIHRoaXMuX25vcnRoRWFzdC5lcXVhbHMoYm91bmRzLmdldE5vcnRoRWFzdCgpLCBtYXhNYXJnaW4pO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgaXNWYWxpZCgpOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGJvdW5kcyBhcmUgcHJvcGVybHkgaW5pdGlhbGl6ZWQuXHJcblx0aXNWYWxpZDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuICEhKHRoaXMuX3NvdXRoV2VzdCAmJiB0aGlzLl9ub3J0aEVhc3QpO1xyXG5cdH1cclxufTtcclxuXHJcbi8vIFRPRE8gSW50ZXJuYXRpb25hbCBkYXRlIGxpbmU/XHJcblxyXG4vLyBAZmFjdG9yeSBMLmxhdExuZ0JvdW5kcyhjb3JuZXIxOiBMYXRMbmcsIGNvcm5lcjI6IExhdExuZylcclxuLy8gQ3JlYXRlcyBhIGBMYXRMbmdCb3VuZHNgIG9iamVjdCBieSBkZWZpbmluZyB0d28gZGlhZ29uYWxseSBvcHBvc2l0ZSBjb3JuZXJzIG9mIHRoZSByZWN0YW5nbGUuXHJcblxyXG4vLyBAYWx0ZXJuYXRpdmVcclxuLy8gQGZhY3RvcnkgTC5sYXRMbmdCb3VuZHMobGF0bG5nczogTGF0TG5nW10pXHJcbi8vIENyZWF0ZXMgYSBgTGF0TG5nQm91bmRzYCBvYmplY3QgZGVmaW5lZCBieSB0aGUgZ2VvZ3JhcGhpY2FsIHBvaW50cyBpdCBjb250YWlucy4gVmVyeSB1c2VmdWwgZm9yIHpvb21pbmcgdGhlIG1hcCB0byBmaXQgYSBwYXJ0aWN1bGFyIHNldCBvZiBsb2NhdGlvbnMgd2l0aCBbYGZpdEJvdW5kc2BdKCNtYXAtZml0Ym91bmRzKS5cclxuZnVuY3Rpb24gdG9MYXRMbmdCb3VuZHMoYSwgYikge1xyXG5cdGlmIChhIGluc3RhbmNlb2YgTGF0TG5nQm91bmRzKSB7XHJcblx0XHRyZXR1cm4gYTtcclxuXHR9XHJcblx0cmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoYSwgYik7XHJcbn1cblxuLyogQGNsYXNzIExhdExuZ1xyXG4gKiBAYWthIEwuTGF0TG5nXHJcbiAqXHJcbiAqIFJlcHJlc2VudHMgYSBnZW9ncmFwaGljYWwgcG9pbnQgd2l0aCBhIGNlcnRhaW4gbGF0aXR1ZGUgYW5kIGxvbmdpdHVkZS5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBgXHJcbiAqIHZhciBsYXRsbmcgPSBMLmxhdExuZyg1MC41LCAzMC41KTtcclxuICogYGBgXHJcbiAqXHJcbiAqIEFsbCBMZWFmbGV0IG1ldGhvZHMgdGhhdCBhY2NlcHQgTGF0TG5nIG9iamVjdHMgYWxzbyBhY2NlcHQgdGhlbSBpbiBhIHNpbXBsZSBBcnJheSBmb3JtIGFuZCBzaW1wbGUgb2JqZWN0IGZvcm0gKHVubGVzcyBub3RlZCBvdGhlcndpc2UpLCBzbyB0aGVzZSBsaW5lcyBhcmUgZXF1aXZhbGVudDpcclxuICpcclxuICogYGBgXHJcbiAqIG1hcC5wYW5UbyhbNTAsIDMwXSk7XHJcbiAqIG1hcC5wYW5Ubyh7bG9uOiAzMCwgbGF0OiA1MH0pO1xyXG4gKiBtYXAucGFuVG8oe2xhdDogNTAsIGxuZzogMzB9KTtcclxuICogbWFwLnBhblRvKEwubGF0TG5nKDUwLCAzMCkpO1xyXG4gKiBgYGBcclxuICpcclxuICogTm90ZSB0aGF0IGBMYXRMbmdgIGRvZXMgbm90IGluaGVyaXQgZnJvbSBMZWFmbGV0J3MgYENsYXNzYCBvYmplY3QsXHJcbiAqIHdoaWNoIG1lYW5zIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSBpdCwgYW5kIG5ldyBtZXRob2RzXHJcbiAqIGNhbid0IGJlIGFkZGVkIHRvIGl0IHdpdGggdGhlIGBpbmNsdWRlYCBmdW5jdGlvbi5cclxuICovXHJcblxyXG5mdW5jdGlvbiBMYXRMbmcobGF0LCBsbmcsIGFsdCkge1xyXG5cdGlmIChpc05hTihsYXQpIHx8IGlzTmFOKGxuZykpIHtcclxuXHRcdHRocm93IG5ldyBFcnJvcignSW52YWxpZCBMYXRMbmcgb2JqZWN0OiAoJyArIGxhdCArICcsICcgKyBsbmcgKyAnKScpO1xyXG5cdH1cclxuXHJcblx0Ly8gQHByb3BlcnR5IGxhdDogTnVtYmVyXHJcblx0Ly8gTGF0aXR1ZGUgaW4gZGVncmVlc1xyXG5cdHRoaXMubGF0ID0gK2xhdDtcclxuXHJcblx0Ly8gQHByb3BlcnR5IGxuZzogTnVtYmVyXHJcblx0Ly8gTG9uZ2l0dWRlIGluIGRlZ3JlZXNcclxuXHR0aGlzLmxuZyA9ICtsbmc7XHJcblxyXG5cdC8vIEBwcm9wZXJ0eSBhbHQ6IE51bWJlclxyXG5cdC8vIEFsdGl0dWRlIGluIG1ldGVycyAob3B0aW9uYWwpXHJcblx0aWYgKGFsdCAhPT0gdW5kZWZpbmVkKSB7XHJcblx0XHR0aGlzLmFsdCA9ICthbHQ7XHJcblx0fVxyXG59XHJcblxyXG5MYXRMbmcucHJvdG90eXBlID0ge1xyXG5cdC8vIEBtZXRob2QgZXF1YWxzKG90aGVyTGF0TG5nOiBMYXRMbmcsIG1heE1hcmdpbj86IE51bWJlcik6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gYExhdExuZ2AgcG9pbnQgaXMgYXQgdGhlIHNhbWUgcG9zaXRpb24gKHdpdGhpbiBhIHNtYWxsIG1hcmdpbiBvZiBlcnJvcikuIFRoZSBtYXJnaW4gb2YgZXJyb3IgY2FuIGJlIG92ZXJyaWRkZW4gYnkgc2V0dGluZyBgbWF4TWFyZ2luYCB0byBhIHNtYWxsIG51bWJlci5cclxuXHRlcXVhbHM6IGZ1bmN0aW9uIChvYmosIG1heE1hcmdpbikge1xyXG5cdFx0aWYgKCFvYmopIHsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG5cdFx0b2JqID0gdG9MYXRMbmcob2JqKTtcclxuXHJcblx0XHR2YXIgbWFyZ2luID0gTWF0aC5tYXgoXHJcblx0XHQgICAgICAgIE1hdGguYWJzKHRoaXMubGF0IC0gb2JqLmxhdCksXHJcblx0XHQgICAgICAgIE1hdGguYWJzKHRoaXMubG5nIC0gb2JqLmxuZykpO1xyXG5cclxuXHRcdHJldHVybiBtYXJnaW4gPD0gKG1heE1hcmdpbiA9PT0gdW5kZWZpbmVkID8gMS4wRS05IDogbWF4TWFyZ2luKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHRvU3RyaW5nKCk6IFN0cmluZ1xyXG5cdC8vIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50IChmb3IgZGVidWdnaW5nIHB1cnBvc2VzKS5cclxuXHR0b1N0cmluZzogZnVuY3Rpb24gKHByZWNpc2lvbikge1xyXG5cdFx0cmV0dXJuICdMYXRMbmcoJyArXHJcblx0XHQgICAgICAgIGZvcm1hdE51bSh0aGlzLmxhdCwgcHJlY2lzaW9uKSArICcsICcgK1xyXG5cdFx0ICAgICAgICBmb3JtYXROdW0odGhpcy5sbmcsIHByZWNpc2lvbikgKyAnKSc7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBkaXN0YW5jZVRvKG90aGVyTGF0TG5nOiBMYXRMbmcpOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBkaXN0YW5jZSAoaW4gbWV0ZXJzKSB0byB0aGUgZ2l2ZW4gYExhdExuZ2AgY2FsY3VsYXRlZCB1c2luZyB0aGUgW1NwaGVyaWNhbCBMYXcgb2YgQ29zaW5lc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU3BoZXJpY2FsX2xhd19vZl9jb3NpbmVzKS5cclxuXHRkaXN0YW5jZVRvOiBmdW5jdGlvbiAob3RoZXIpIHtcclxuXHRcdHJldHVybiBFYXJ0aC5kaXN0YW5jZSh0aGlzLCB0b0xhdExuZyhvdGhlcikpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgd3JhcCgpOiBMYXRMbmdcclxuXHQvLyBSZXR1cm5zIGEgbmV3IGBMYXRMbmdgIG9iamVjdCB3aXRoIHRoZSBsb25naXR1ZGUgd3JhcHBlZCBzbyBpdCdzIGFsd2F5cyBiZXR3ZWVuIC0xODAgYW5kICsxODAgZGVncmVlcy5cclxuXHR3cmFwOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gRWFydGgud3JhcExhdExuZyh0aGlzKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHRvQm91bmRzKHNpemVJbk1ldGVyczogTnVtYmVyKTogTGF0TG5nQm91bmRzXHJcblx0Ly8gUmV0dXJucyBhIG5ldyBgTGF0TG5nQm91bmRzYCBvYmplY3QgaW4gd2hpY2ggZWFjaCBib3VuZGFyeSBpcyBgc2l6ZUluTWV0ZXJzLzJgIG1ldGVycyBhcGFydCBmcm9tIHRoZSBgTGF0TG5nYC5cclxuXHR0b0JvdW5kczogZnVuY3Rpb24gKHNpemVJbk1ldGVycykge1xyXG5cdFx0dmFyIGxhdEFjY3VyYWN5ID0gMTgwICogc2l6ZUluTWV0ZXJzIC8gNDAwNzUwMTcsXHJcblx0XHQgICAgbG5nQWNjdXJhY3kgPSBsYXRBY2N1cmFjeSAvIE1hdGguY29zKChNYXRoLlBJIC8gMTgwKSAqIHRoaXMubGF0KTtcclxuXHJcblx0XHRyZXR1cm4gdG9MYXRMbmdCb3VuZHMoXHJcblx0XHQgICAgICAgIFt0aGlzLmxhdCAtIGxhdEFjY3VyYWN5LCB0aGlzLmxuZyAtIGxuZ0FjY3VyYWN5XSxcclxuXHRcdCAgICAgICAgW3RoaXMubGF0ICsgbGF0QWNjdXJhY3ksIHRoaXMubG5nICsgbG5nQWNjdXJhY3ldKTtcclxuXHR9LFxyXG5cclxuXHRjbG9uZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIG5ldyBMYXRMbmcodGhpcy5sYXQsIHRoaXMubG5nLCB0aGlzLmFsdCk7XHJcblx0fVxyXG59O1xyXG5cclxuXHJcblxyXG4vLyBAZmFjdG9yeSBMLmxhdExuZyhsYXRpdHVkZTogTnVtYmVyLCBsb25naXR1ZGU6IE51bWJlciwgYWx0aXR1ZGU/OiBOdW1iZXIpOiBMYXRMbmdcclxuLy8gQ3JlYXRlcyBhbiBvYmplY3QgcmVwcmVzZW50aW5nIGEgZ2VvZ3JhcGhpY2FsIHBvaW50IHdpdGggdGhlIGdpdmVuIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgKGFuZCBvcHRpb25hbGx5IGFsdGl0dWRlKS5cclxuXHJcbi8vIEBhbHRlcm5hdGl2ZVxyXG4vLyBAZmFjdG9yeSBMLmxhdExuZyhjb29yZHM6IEFycmF5KTogTGF0TG5nXHJcbi8vIEV4cGVjdHMgYW4gYXJyYXkgb2YgdGhlIGZvcm0gYFtOdW1iZXIsIE51bWJlcl1gIG9yIGBbTnVtYmVyLCBOdW1iZXIsIE51bWJlcl1gIGluc3RlYWQuXHJcblxyXG4vLyBAYWx0ZXJuYXRpdmVcclxuLy8gQGZhY3RvcnkgTC5sYXRMbmcoY29vcmRzOiBPYmplY3QpOiBMYXRMbmdcclxuLy8gRXhwZWN0cyBhbiBwbGFpbiBvYmplY3Qgb2YgdGhlIGZvcm0gYHtsYXQ6IE51bWJlciwgbG5nOiBOdW1iZXJ9YCBvciBge2xhdDogTnVtYmVyLCBsbmc6IE51bWJlciwgYWx0OiBOdW1iZXJ9YCBpbnN0ZWFkLlxyXG5cclxuZnVuY3Rpb24gdG9MYXRMbmcoYSwgYiwgYykge1xyXG5cdGlmIChhIGluc3RhbmNlb2YgTGF0TG5nKSB7XHJcblx0XHRyZXR1cm4gYTtcclxuXHR9XHJcblx0aWYgKGlzQXJyYXkoYSkgJiYgdHlwZW9mIGFbMF0gIT09ICdvYmplY3QnKSB7XHJcblx0XHRpZiAoYS5sZW5ndGggPT09IDMpIHtcclxuXHRcdFx0cmV0dXJuIG5ldyBMYXRMbmcoYVswXSwgYVsxXSwgYVsyXSk7XHJcblx0XHR9XHJcblx0XHRpZiAoYS5sZW5ndGggPT09IDIpIHtcclxuXHRcdFx0cmV0dXJuIG5ldyBMYXRMbmcoYVswXSwgYVsxXSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gbnVsbDtcclxuXHR9XHJcblx0aWYgKGEgPT09IHVuZGVmaW5lZCB8fCBhID09PSBudWxsKSB7XHJcblx0XHRyZXR1cm4gYTtcclxuXHR9XHJcblx0aWYgKHR5cGVvZiBhID09PSAnb2JqZWN0JyAmJiAnbGF0JyBpbiBhKSB7XHJcblx0XHRyZXR1cm4gbmV3IExhdExuZyhhLmxhdCwgJ2xuZycgaW4gYSA/IGEubG5nIDogYS5sb24sIGEuYWx0KTtcclxuXHR9XHJcblx0aWYgKGIgPT09IHVuZGVmaW5lZCkge1xyXG5cdFx0cmV0dXJuIG51bGw7XHJcblx0fVxyXG5cdHJldHVybiBuZXcgTGF0TG5nKGEsIGIsIGMpO1xyXG59XG5cbi8qXHJcbiAqIEBuYW1lc3BhY2UgQ1JTXHJcbiAqIEBjcnMgTC5DUlMuQmFzZVxyXG4gKiBPYmplY3QgdGhhdCBkZWZpbmVzIGNvb3JkaW5hdGUgcmVmZXJlbmNlIHN5c3RlbXMgZm9yIHByb2plY3RpbmdcclxuICogZ2VvZ3JhcGhpY2FsIHBvaW50cyBpbnRvIHBpeGVsIChzY3JlZW4pIGNvb3JkaW5hdGVzIGFuZCBiYWNrIChhbmQgdG9cclxuICogY29vcmRpbmF0ZXMgaW4gb3RoZXIgdW5pdHMgZm9yIFtXTVNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dlYl9NYXBfU2VydmljZSkgc2VydmljZXMpLiBTZWVcclxuICogW3NwYXRpYWwgcmVmZXJlbmNlIHN5c3RlbV0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db29yZGluYXRlX3JlZmVyZW5jZV9zeXN0ZW0pLlxyXG4gKlxyXG4gKiBMZWFmbGV0IGRlZmluZXMgdGhlIG1vc3QgdXN1YWwgQ1JTcyBieSBkZWZhdWx0LiBJZiB5b3Ugd2FudCB0byB1c2UgYVxyXG4gKiBDUlMgbm90IGRlZmluZWQgYnkgZGVmYXVsdCwgdGFrZSBhIGxvb2sgYXQgdGhlXHJcbiAqIFtQcm9qNExlYWZsZXRdKGh0dHBzOi8vZ2l0aHViLmNvbS9rYXJ0ZW5hL1Byb2o0TGVhZmxldCkgcGx1Z2luLlxyXG4gKlxyXG4gKiBOb3RlIHRoYXQgdGhlIENSUyBpbnN0YW5jZXMgZG8gbm90IGluaGVyaXQgZnJvbSBMZWFmZXQncyBgQ2xhc3NgIG9iamVjdCxcclxuICogYW5kIGNhbid0IGJlIGluc3RhbnRpYXRlZC4gQWxzbywgbmV3IGNsYXNzZXMgY2FuJ3QgaW5oZXJpdCBmcm9tIHRoZW0sXHJcbiAqIGFuZCBtZXRob2RzIGNhbid0IGJlIGFkZGVkIHRvIHRoZW0gd2l0aCB0aGUgYGluY2x1ZGVgIGZ1bmN0aW9uLlxyXG4gKi9cclxuXHJcbnZhciBDUlMgPSB7XHJcblx0Ly8gQG1ldGhvZCBsYXRMbmdUb1BvaW50KGxhdGxuZzogTGF0TG5nLCB6b29tOiBOdW1iZXIpOiBQb2ludFxyXG5cdC8vIFByb2plY3RzIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlcyBpbnRvIHBpeGVsIGNvb3JkaW5hdGVzIGZvciBhIGdpdmVuIHpvb20uXHJcblx0bGF0TG5nVG9Qb2ludDogZnVuY3Rpb24gKGxhdGxuZywgem9vbSkge1xyXG5cdFx0dmFyIHByb2plY3RlZFBvaW50ID0gdGhpcy5wcm9qZWN0aW9uLnByb2plY3QobGF0bG5nKSxcclxuXHRcdCAgICBzY2FsZSA9IHRoaXMuc2NhbGUoem9vbSk7XHJcblxyXG5cdFx0cmV0dXJuIHRoaXMudHJhbnNmb3JtYXRpb24uX3RyYW5zZm9ybShwcm9qZWN0ZWRQb2ludCwgc2NhbGUpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgcG9pbnRUb0xhdExuZyhwb2ludDogUG9pbnQsIHpvb206IE51bWJlcik6IExhdExuZ1xyXG5cdC8vIFRoZSBpbnZlcnNlIG9mIGBsYXRMbmdUb1BvaW50YC4gUHJvamVjdHMgcGl4ZWwgY29vcmRpbmF0ZXMgb24gYSBnaXZlblxyXG5cdC8vIHpvb20gaW50byBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMuXHJcblx0cG9pbnRUb0xhdExuZzogZnVuY3Rpb24gKHBvaW50LCB6b29tKSB7XHJcblx0XHR2YXIgc2NhbGUgPSB0aGlzLnNjYWxlKHpvb20pLFxyXG5cdFx0ICAgIHVudHJhbnNmb3JtZWRQb2ludCA9IHRoaXMudHJhbnNmb3JtYXRpb24udW50cmFuc2Zvcm0ocG9pbnQsIHNjYWxlKTtcclxuXHJcblx0XHRyZXR1cm4gdGhpcy5wcm9qZWN0aW9uLnVucHJvamVjdCh1bnRyYW5zZm9ybWVkUG9pbnQpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgcHJvamVjdChsYXRsbmc6IExhdExuZyk6IFBvaW50XHJcblx0Ly8gUHJvamVjdHMgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGludG8gY29vcmRpbmF0ZXMgaW4gdW5pdHMgYWNjZXB0ZWQgZm9yXHJcblx0Ly8gdGhpcyBDUlMgKGUuZy4gbWV0ZXJzIGZvciBFUFNHOjM4NTcsIGZvciBwYXNzaW5nIGl0IHRvIFdNUyBzZXJ2aWNlcykuXHJcblx0cHJvamVjdDogZnVuY3Rpb24gKGxhdGxuZykge1xyXG5cdFx0cmV0dXJuIHRoaXMucHJvamVjdGlvbi5wcm9qZWN0KGxhdGxuZyk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB1bnByb2plY3QocG9pbnQ6IFBvaW50KTogTGF0TG5nXHJcblx0Ly8gR2l2ZW4gYSBwcm9qZWN0ZWQgY29vcmRpbmF0ZSByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIExhdExuZy5cclxuXHQvLyBUaGUgaW52ZXJzZSBvZiBgcHJvamVjdGAuXHJcblx0dW5wcm9qZWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuXHRcdHJldHVybiB0aGlzLnByb2plY3Rpb24udW5wcm9qZWN0KHBvaW50KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNjYWxlKHpvb206IE51bWJlcik6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIHNjYWxlIHVzZWQgd2hlbiB0cmFuc2Zvcm1pbmcgcHJvamVjdGVkIGNvb3JkaW5hdGVzIGludG9cclxuXHQvLyBwaXhlbCBjb29yZGluYXRlcyBmb3IgYSBwYXJ0aWN1bGFyIHpvb20uIEZvciBleGFtcGxlLCBpdCByZXR1cm5zXHJcblx0Ly8gYDI1NiAqIDJeem9vbWAgZm9yIE1lcmNhdG9yLWJhc2VkIENSUy5cclxuXHRzY2FsZTogZnVuY3Rpb24gKHpvb20pIHtcclxuXHRcdHJldHVybiAyNTYgKiBNYXRoLnBvdygyLCB6b29tKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHpvb20oc2NhbGU6IE51bWJlcik6IE51bWJlclxyXG5cdC8vIEludmVyc2Ugb2YgYHNjYWxlKClgLCByZXR1cm5zIHRoZSB6b29tIGxldmVsIGNvcnJlc3BvbmRpbmcgdG8gYSBzY2FsZVxyXG5cdC8vIGZhY3RvciBvZiBgc2NhbGVgLlxyXG5cdHpvb206IGZ1bmN0aW9uIChzY2FsZSkge1xyXG5cdFx0cmV0dXJuIE1hdGgubG9nKHNjYWxlIC8gMjU2KSAvIE1hdGguTE4yO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0UHJvamVjdGVkQm91bmRzKHpvb206IE51bWJlcik6IEJvdW5kc1xyXG5cdC8vIFJldHVybnMgdGhlIHByb2plY3Rpb24ncyBib3VuZHMgc2NhbGVkIGFuZCB0cmFuc2Zvcm1lZCBmb3IgdGhlIHByb3ZpZGVkIGB6b29tYC5cclxuXHRnZXRQcm9qZWN0ZWRCb3VuZHM6IGZ1bmN0aW9uICh6b29tKSB7XHJcblx0XHRpZiAodGhpcy5pbmZpbml0ZSkgeyByZXR1cm4gbnVsbDsgfVxyXG5cclxuXHRcdHZhciBiID0gdGhpcy5wcm9qZWN0aW9uLmJvdW5kcyxcclxuXHRcdCAgICBzID0gdGhpcy5zY2FsZSh6b29tKSxcclxuXHRcdCAgICBtaW4gPSB0aGlzLnRyYW5zZm9ybWF0aW9uLnRyYW5zZm9ybShiLm1pbiwgcyksXHJcblx0XHQgICAgbWF4ID0gdGhpcy50cmFuc2Zvcm1hdGlvbi50cmFuc2Zvcm0oYi5tYXgsIHMpO1xyXG5cclxuXHRcdHJldHVybiBuZXcgQm91bmRzKG1pbiwgbWF4KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGRpc3RhbmNlKGxhdGxuZzE6IExhdExuZywgbGF0bG5nMjogTGF0TG5nKTogTnVtYmVyXHJcblx0Ly8gUmV0dXJucyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0d28gZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzLlxyXG5cclxuXHQvLyBAcHJvcGVydHkgY29kZTogU3RyaW5nXHJcblx0Ly8gU3RhbmRhcmQgY29kZSBuYW1lIG9mIHRoZSBDUlMgcGFzc2VkIGludG8gV01TIHNlcnZpY2VzIChlLmcuIGAnRVBTRzozODU3J2ApXHJcblx0Ly9cclxuXHQvLyBAcHJvcGVydHkgd3JhcExuZzogTnVtYmVyW11cclxuXHQvLyBBbiBhcnJheSBvZiB0d28gbnVtYmVycyBkZWZpbmluZyB3aGV0aGVyIHRoZSBsb25naXR1ZGUgKGhvcml6b250YWwpIGNvb3JkaW5hdGVcclxuXHQvLyBheGlzIHdyYXBzIGFyb3VuZCBhIGdpdmVuIHJhbmdlIGFuZCBob3cuIERlZmF1bHRzIHRvIGBbLTE4MCwgMTgwXWAgaW4gbW9zdFxyXG5cdC8vIGdlb2dyYXBoaWNhbCBDUlNzLiBJZiBgdW5kZWZpbmVkYCwgdGhlIGxvbmdpdHVkZSBheGlzIGRvZXMgbm90IHdyYXAgYXJvdW5kLlxyXG5cdC8vXHJcblx0Ly8gQHByb3BlcnR5IHdyYXBMYXQ6IE51bWJlcltdXHJcblx0Ly8gTGlrZSBgd3JhcExuZ2AsIGJ1dCBmb3IgdGhlIGxhdGl0dWRlICh2ZXJ0aWNhbCkgYXhpcy5cclxuXHJcblx0Ly8gd3JhcExuZzogW21pbiwgbWF4XSxcclxuXHQvLyB3cmFwTGF0OiBbbWluLCBtYXhdLFxyXG5cclxuXHQvLyBAcHJvcGVydHkgaW5maW5pdGU6IEJvb2xlYW5cclxuXHQvLyBJZiB0cnVlLCB0aGUgY29vcmRpbmF0ZSBzcGFjZSB3aWxsIGJlIHVuYm91bmRlZCAoaW5maW5pdGUgaW4gYm90aCBheGVzKVxyXG5cdGluZmluaXRlOiBmYWxzZSxcclxuXHJcblx0Ly8gQG1ldGhvZCB3cmFwTGF0TG5nKGxhdGxuZzogTGF0TG5nKTogTGF0TG5nXHJcblx0Ly8gUmV0dXJucyBhIGBMYXRMbmdgIHdoZXJlIGxhdCBhbmQgbG5nIGhhcyBiZWVuIHdyYXBwZWQgYWNjb3JkaW5nIHRvIHRoZVxyXG5cdC8vIENSUydzIGB3cmFwTGF0YCBhbmQgYHdyYXBMbmdgIHByb3BlcnRpZXMsIGlmIHRoZXkgYXJlIG91dHNpZGUgdGhlIENSUydzIGJvdW5kcy5cclxuXHR3cmFwTGF0TG5nOiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHR2YXIgbG5nID0gdGhpcy53cmFwTG5nID8gd3JhcE51bShsYXRsbmcubG5nLCB0aGlzLndyYXBMbmcsIHRydWUpIDogbGF0bG5nLmxuZyxcclxuXHRcdCAgICBsYXQgPSB0aGlzLndyYXBMYXQgPyB3cmFwTnVtKGxhdGxuZy5sYXQsIHRoaXMud3JhcExhdCwgdHJ1ZSkgOiBsYXRsbmcubGF0LFxyXG5cdFx0ICAgIGFsdCA9IGxhdGxuZy5hbHQ7XHJcblxyXG5cdFx0cmV0dXJuIG5ldyBMYXRMbmcobGF0LCBsbmcsIGFsdCk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB3cmFwTGF0TG5nQm91bmRzKGJvdW5kczogTGF0TG5nQm91bmRzKTogTGF0TG5nQm91bmRzXHJcblx0Ly8gUmV0dXJucyBhIGBMYXRMbmdCb3VuZHNgIHdpdGggdGhlIHNhbWUgc2l6ZSBhcyB0aGUgZ2l2ZW4gb25lLCBlbnN1cmluZ1xyXG5cdC8vIHRoYXQgaXRzIGNlbnRlciBpcyB3aXRoaW4gdGhlIENSUydzIGJvdW5kcy5cclxuXHQvLyBPbmx5IGFjY2VwdHMgYWN0dWFsIGBMLkxhdExuZ0JvdW5kc2AgaW5zdGFuY2VzLCBub3QgYXJyYXlzLlxyXG5cdHdyYXBMYXRMbmdCb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMpIHtcclxuXHRcdHZhciBjZW50ZXIgPSBib3VuZHMuZ2V0Q2VudGVyKCksXHJcblx0XHQgICAgbmV3Q2VudGVyID0gdGhpcy53cmFwTGF0TG5nKGNlbnRlciksXHJcblx0XHQgICAgbGF0U2hpZnQgPSBjZW50ZXIubGF0IC0gbmV3Q2VudGVyLmxhdCxcclxuXHRcdCAgICBsbmdTaGlmdCA9IGNlbnRlci5sbmcgLSBuZXdDZW50ZXIubG5nO1xyXG5cclxuXHRcdGlmIChsYXRTaGlmdCA9PT0gMCAmJiBsbmdTaGlmdCA9PT0gMCkge1xyXG5cdFx0XHRyZXR1cm4gYm91bmRzO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBzdyA9IGJvdW5kcy5nZXRTb3V0aFdlc3QoKSxcclxuXHRcdCAgICBuZSA9IGJvdW5kcy5nZXROb3J0aEVhc3QoKSxcclxuXHRcdCAgICBuZXdTdyA9IG5ldyBMYXRMbmcoc3cubGF0IC0gbGF0U2hpZnQsIHN3LmxuZyAtIGxuZ1NoaWZ0KSxcclxuXHRcdCAgICBuZXdOZSA9IG5ldyBMYXRMbmcobmUubGF0IC0gbGF0U2hpZnQsIG5lLmxuZyAtIGxuZ1NoaWZ0KTtcclxuXHJcblx0XHRyZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhuZXdTdywgbmV3TmUpO1xyXG5cdH1cclxufTtcblxuLypcbiAqIEBuYW1lc3BhY2UgQ1JTXG4gKiBAY3JzIEwuQ1JTLkVhcnRoXG4gKlxuICogU2VydmVzIGFzIHRoZSBiYXNlIGZvciBDUlMgdGhhdCBhcmUgZ2xvYmFsIHN1Y2ggdGhhdCB0aGV5IGNvdmVyIHRoZSBlYXJ0aC5cbiAqIENhbiBvbmx5IGJlIHVzZWQgYXMgdGhlIGJhc2UgZm9yIG90aGVyIENSUyBhbmQgY2Fubm90IGJlIHVzZWQgZGlyZWN0bHksXG4gKiBzaW5jZSBpdCBkb2VzIG5vdCBoYXZlIGEgYGNvZGVgLCBgcHJvamVjdGlvbmAgb3IgYHRyYW5zZm9ybWF0aW9uYC4gYGRpc3RhbmNlKClgIHJldHVybnNcbiAqIG1ldGVycy5cbiAqL1xuXG52YXIgRWFydGggPSBleHRlbmQoe30sIENSUywge1xuXHR3cmFwTG5nOiBbLTE4MCwgMTgwXSxcblxuXHQvLyBNZWFuIEVhcnRoIFJhZGl1cywgYXMgcmVjb21tZW5kZWQgZm9yIHVzZSBieVxuXHQvLyB0aGUgSW50ZXJuYXRpb25hbCBVbmlvbiBvZiBHZW9kZXN5IGFuZCBHZW9waHlzaWNzLFxuXHQvLyBzZWUgaHR0cDovL3Jvc2V0dGFjb2RlLm9yZy93aWtpL0hhdmVyc2luZV9mb3JtdWxhXG5cdFI6IDYzNzEwMDAsXG5cblx0Ly8gZGlzdGFuY2UgYmV0d2VlbiB0d28gZ2VvZ3JhcGhpY2FsIHBvaW50cyB1c2luZyBzcGhlcmljYWwgbGF3IG9mIGNvc2luZXMgYXBwcm94aW1hdGlvblxuXHRkaXN0YW5jZTogZnVuY3Rpb24gKGxhdGxuZzEsIGxhdGxuZzIpIHtcblx0XHR2YXIgcmFkID0gTWF0aC5QSSAvIDE4MCxcblx0XHQgICAgbGF0MSA9IGxhdGxuZzEubGF0ICogcmFkLFxuXHRcdCAgICBsYXQyID0gbGF0bG5nMi5sYXQgKiByYWQsXG5cdFx0ICAgIHNpbkRMYXQgPSBNYXRoLnNpbigobGF0bG5nMi5sYXQgLSBsYXRsbmcxLmxhdCkgKiByYWQgLyAyKSxcblx0XHQgICAgc2luRExvbiA9IE1hdGguc2luKChsYXRsbmcyLmxuZyAtIGxhdGxuZzEubG5nKSAqIHJhZCAvIDIpLFxuXHRcdCAgICBhID0gc2luRExhdCAqIHNpbkRMYXQgKyBNYXRoLmNvcyhsYXQxKSAqIE1hdGguY29zKGxhdDIpICogc2luRExvbiAqIHNpbkRMb24sXG5cdFx0ICAgIGMgPSAyICogTWF0aC5hdGFuMihNYXRoLnNxcnQoYSksIE1hdGguc3FydCgxIC0gYSkpO1xuXHRcdHJldHVybiB0aGlzLlIgKiBjO1xuXHR9XG59KTtcblxuLypcclxuICogQG5hbWVzcGFjZSBQcm9qZWN0aW9uXHJcbiAqIEBwcm9qZWN0aW9uIEwuUHJvamVjdGlvbi5TcGhlcmljYWxNZXJjYXRvclxyXG4gKlxyXG4gKiBTcGhlcmljYWwgTWVyY2F0b3IgcHJvamVjdGlvbiDigJQgdGhlIG1vc3QgY29tbW9uIHByb2plY3Rpb24gZm9yIG9ubGluZSBtYXBzLFxyXG4gKiB1c2VkIGJ5IGFsbW9zdCBhbGwgZnJlZSBhbmQgY29tbWVyY2lhbCB0aWxlIHByb3ZpZGVycy4gQXNzdW1lcyB0aGF0IEVhcnRoIGlzXHJcbiAqIGEgc3BoZXJlLiBVc2VkIGJ5IHRoZSBgRVBTRzozODU3YCBDUlMuXHJcbiAqL1xyXG5cclxudmFyIGVhcnRoUmFkaXVzID0gNjM3ODEzNztcclxuXHJcbnZhciBTcGhlcmljYWxNZXJjYXRvciA9IHtcclxuXHJcblx0UjogZWFydGhSYWRpdXMsXHJcblx0TUFYX0xBVElUVURFOiA4NS4wNTExMjg3Nzk4LFxyXG5cclxuXHRwcm9qZWN0OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHR2YXIgZCA9IE1hdGguUEkgLyAxODAsXHJcblx0XHQgICAgbWF4ID0gdGhpcy5NQVhfTEFUSVRVREUsXHJcblx0XHQgICAgbGF0ID0gTWF0aC5tYXgoTWF0aC5taW4obWF4LCBsYXRsbmcubGF0KSwgLW1heCksXHJcblx0XHQgICAgc2luID0gTWF0aC5zaW4obGF0ICogZCk7XHJcblxyXG5cdFx0cmV0dXJuIG5ldyBQb2ludChcclxuXHRcdFx0dGhpcy5SICogbGF0bG5nLmxuZyAqIGQsXHJcblx0XHRcdHRoaXMuUiAqIE1hdGgubG9nKCgxICsgc2luKSAvICgxIC0gc2luKSkgLyAyKTtcclxuXHR9LFxyXG5cclxuXHR1bnByb2plY3Q6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0dmFyIGQgPSAxODAgLyBNYXRoLlBJO1xyXG5cclxuXHRcdHJldHVybiBuZXcgTGF0TG5nKFxyXG5cdFx0XHQoMiAqIE1hdGguYXRhbihNYXRoLmV4cChwb2ludC55IC8gdGhpcy5SKSkgLSAoTWF0aC5QSSAvIDIpKSAqIGQsXHJcblx0XHRcdHBvaW50LnggKiBkIC8gdGhpcy5SKTtcclxuXHR9LFxyXG5cclxuXHRib3VuZHM6IChmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgZCA9IGVhcnRoUmFkaXVzICogTWF0aC5QSTtcclxuXHRcdHJldHVybiBuZXcgQm91bmRzKFstZCwgLWRdLCBbZCwgZF0pO1xyXG5cdH0pKClcclxufTtcblxuLypcclxuICogQGNsYXNzIFRyYW5zZm9ybWF0aW9uXHJcbiAqIEBha2EgTC5UcmFuc2Zvcm1hdGlvblxyXG4gKlxyXG4gKiBSZXByZXNlbnRzIGFuIGFmZmluZSB0cmFuc2Zvcm1hdGlvbjogYSBzZXQgb2YgY29lZmZpY2llbnRzIGBhYCwgYGJgLCBgY2AsIGBkYFxyXG4gKiBmb3IgdHJhbnNmb3JtaW5nIGEgcG9pbnQgb2YgYSBmb3JtIGAoeCwgeSlgIGludG8gYChhKnggKyBiLCBjKnkgKyBkKWAgYW5kIGRvaW5nXHJcbiAqIHRoZSByZXZlcnNlLiBVc2VkIGJ5IExlYWZsZXQgaW4gaXRzIHByb2plY3Rpb25zIGNvZGUuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciB0cmFuc2Zvcm1hdGlvbiA9IEwudHJhbnNmb3JtYXRpb24oMiwgNSwgLTEsIDEwKSxcclxuICogXHRwID0gTC5wb2ludCgxLCAyKSxcclxuICogXHRwMiA9IHRyYW5zZm9ybWF0aW9uLnRyYW5zZm9ybShwKSwgLy8gIEwucG9pbnQoNywgOClcclxuICogXHRwMyA9IHRyYW5zZm9ybWF0aW9uLnVudHJhbnNmb3JtKHAyKTsgLy8gIEwucG9pbnQoMSwgMilcclxuICogYGBgXHJcbiAqL1xyXG5cclxuXHJcbi8vIGZhY3RvcnkgbmV3IEwuVHJhbnNmb3JtYXRpb24oYTogTnVtYmVyLCBiOiBOdW1iZXIsIGM6IE51bWJlciwgZDogTnVtYmVyKVxyXG4vLyBDcmVhdGVzIGEgYFRyYW5zZm9ybWF0aW9uYCBvYmplY3Qgd2l0aCB0aGUgZ2l2ZW4gY29lZmZpY2llbnRzLlxyXG5mdW5jdGlvbiBUcmFuc2Zvcm1hdGlvbihhLCBiLCBjLCBkKSB7XHJcblx0aWYgKGlzQXJyYXkoYSkpIHtcclxuXHRcdC8vIHVzZSBhcnJheSBwcm9wZXJ0aWVzXHJcblx0XHR0aGlzLl9hID0gYVswXTtcclxuXHRcdHRoaXMuX2IgPSBhWzFdO1xyXG5cdFx0dGhpcy5fYyA9IGFbMl07XHJcblx0XHR0aGlzLl9kID0gYVszXTtcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblx0dGhpcy5fYSA9IGE7XHJcblx0dGhpcy5fYiA9IGI7XHJcblx0dGhpcy5fYyA9IGM7XHJcblx0dGhpcy5fZCA9IGQ7XHJcbn1cclxuXHJcblRyYW5zZm9ybWF0aW9uLnByb3RvdHlwZSA9IHtcclxuXHQvLyBAbWV0aG9kIHRyYW5zZm9ybShwb2ludDogUG9pbnQsIHNjYWxlPzogTnVtYmVyKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIGEgdHJhbnNmb3JtZWQgcG9pbnQsIG9wdGlvbmFsbHkgbXVsdGlwbGllZCBieSB0aGUgZ2l2ZW4gc2NhbGUuXHJcblx0Ly8gT25seSBhY2NlcHRzIGFjdHVhbCBgTC5Qb2ludGAgaW5zdGFuY2VzLCBub3QgYXJyYXlzLlxyXG5cdHRyYW5zZm9ybTogZnVuY3Rpb24gKHBvaW50LCBzY2FsZSkgeyAvLyAoUG9pbnQsIE51bWJlcikgLT4gUG9pbnRcclxuXHRcdHJldHVybiB0aGlzLl90cmFuc2Zvcm0ocG9pbnQuY2xvbmUoKSwgc2NhbGUpO1xyXG5cdH0sXHJcblxyXG5cdC8vIGRlc3RydWN0aXZlIHRyYW5zZm9ybSAoZmFzdGVyKVxyXG5cdF90cmFuc2Zvcm06IGZ1bmN0aW9uIChwb2ludCwgc2NhbGUpIHtcclxuXHRcdHNjYWxlID0gc2NhbGUgfHwgMTtcclxuXHRcdHBvaW50LnggPSBzY2FsZSAqICh0aGlzLl9hICogcG9pbnQueCArIHRoaXMuX2IpO1xyXG5cdFx0cG9pbnQueSA9IHNjYWxlICogKHRoaXMuX2MgKiBwb2ludC55ICsgdGhpcy5fZCk7XHJcblx0XHRyZXR1cm4gcG9pbnQ7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB1bnRyYW5zZm9ybShwb2ludDogUG9pbnQsIHNjYWxlPzogTnVtYmVyKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIHRoZSByZXZlcnNlIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSBnaXZlbiBwb2ludCwgb3B0aW9uYWxseSBkaXZpZGVkXHJcblx0Ly8gYnkgdGhlIGdpdmVuIHNjYWxlLiBPbmx5IGFjY2VwdHMgYWN0dWFsIGBMLlBvaW50YCBpbnN0YW5jZXMsIG5vdCBhcnJheXMuXHJcblx0dW50cmFuc2Zvcm06IGZ1bmN0aW9uIChwb2ludCwgc2NhbGUpIHtcclxuXHRcdHNjYWxlID0gc2NhbGUgfHwgMTtcclxuXHRcdHJldHVybiBuZXcgUG9pbnQoXHJcblx0XHQgICAgICAgIChwb2ludC54IC8gc2NhbGUgLSB0aGlzLl9iKSAvIHRoaXMuX2EsXHJcblx0XHQgICAgICAgIChwb2ludC55IC8gc2NhbGUgLSB0aGlzLl9kKSAvIHRoaXMuX2MpO1xyXG5cdH1cclxufTtcclxuXHJcbi8vIGZhY3RvcnkgTC50cmFuc2Zvcm1hdGlvbihhOiBOdW1iZXIsIGI6IE51bWJlciwgYzogTnVtYmVyLCBkOiBOdW1iZXIpXHJcblxyXG4vLyBAZmFjdG9yeSBMLnRyYW5zZm9ybWF0aW9uKGE6IE51bWJlciwgYjogTnVtYmVyLCBjOiBOdW1iZXIsIGQ6IE51bWJlcilcclxuLy8gSW5zdGFudGlhdGVzIGEgVHJhbnNmb3JtYXRpb24gb2JqZWN0IHdpdGggdGhlIGdpdmVuIGNvZWZmaWNpZW50cy5cclxuXHJcbi8vIEBhbHRlcm5hdGl2ZVxyXG4vLyBAZmFjdG9yeSBMLnRyYW5zZm9ybWF0aW9uKGNvZWZmaWNpZW50czogQXJyYXkpOiBUcmFuc2Zvcm1hdGlvblxyXG4vLyBFeHBlY3RzIGFuIGNvZWZmaWNpZW50cyBhcnJheSBvZiB0aGUgZm9ybVxyXG4vLyBgW2E6IE51bWJlciwgYjogTnVtYmVyLCBjOiBOdW1iZXIsIGQ6IE51bWJlcl1gLlxyXG5cclxuZnVuY3Rpb24gdG9UcmFuc2Zvcm1hdGlvbihhLCBiLCBjLCBkKSB7XHJcblx0cmV0dXJuIG5ldyBUcmFuc2Zvcm1hdGlvbihhLCBiLCBjLCBkKTtcclxufVxuXG4vKlxyXG4gKiBAbmFtZXNwYWNlIENSU1xyXG4gKiBAY3JzIEwuQ1JTLkVQU0czODU3XHJcbiAqXHJcbiAqIFRoZSBtb3N0IGNvbW1vbiBDUlMgZm9yIG9ubGluZSBtYXBzLCB1c2VkIGJ5IGFsbW9zdCBhbGwgZnJlZSBhbmQgY29tbWVyY2lhbFxyXG4gKiB0aWxlIHByb3ZpZGVycy4gVXNlcyBTcGhlcmljYWwgTWVyY2F0b3IgcHJvamVjdGlvbi4gU2V0IGluIGJ5IGRlZmF1bHQgaW5cclxuICogTWFwJ3MgYGNyc2Agb3B0aW9uLlxyXG4gKi9cclxuXHJcbnZhciBFUFNHMzg1NyA9IGV4dGVuZCh7fSwgRWFydGgsIHtcclxuXHRjb2RlOiAnRVBTRzozODU3JyxcclxuXHRwcm9qZWN0aW9uOiBTcGhlcmljYWxNZXJjYXRvcixcclxuXHJcblx0dHJhbnNmb3JtYXRpb246IChmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgc2NhbGUgPSAwLjUgLyAoTWF0aC5QSSAqIFNwaGVyaWNhbE1lcmNhdG9yLlIpO1xyXG5cdFx0cmV0dXJuIHRvVHJhbnNmb3JtYXRpb24oc2NhbGUsIDAuNSwgLXNjYWxlLCAwLjUpO1xyXG5cdH0oKSlcclxufSk7XHJcblxyXG52YXIgRVBTRzkwMDkxMyA9IGV4dGVuZCh7fSwgRVBTRzM4NTcsIHtcclxuXHRjb2RlOiAnRVBTRzo5MDA5MTMnXHJcbn0pO1xuXG4vLyBAbmFtZXNwYWNlIFNWRzsgQHNlY3Rpb25cbi8vIFRoZXJlIGFyZSBzZXZlcmFsIHN0YXRpYyBmdW5jdGlvbnMgd2hpY2ggY2FuIGJlIGNhbGxlZCB3aXRob3V0IGluc3RhbnRpYXRpbmcgTC5TVkc6XG5cbi8vIEBmdW5jdGlvbiBjcmVhdGUobmFtZTogU3RyaW5nKTogU1ZHRWxlbWVudFxuLy8gUmV0dXJucyBhIGluc3RhbmNlIG9mIFtTVkdFbGVtZW50XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvU1ZHRWxlbWVudCksXG4vLyBjb3JyZXNwb25kaW5nIHRvIHRoZSBjbGFzcyBuYW1lIHBhc3NlZC4gRm9yIGV4YW1wbGUsIHVzaW5nICdsaW5lJyB3aWxsIHJldHVyblxuLy8gYW4gaW5zdGFuY2Ugb2YgW1NWR0xpbmVFbGVtZW50XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvU1ZHTGluZUVsZW1lbnQpLlxuZnVuY3Rpb24gc3ZnQ3JlYXRlKG5hbWUpIHtcblx0cmV0dXJuIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUygnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnLCBuYW1lKTtcbn1cblxuLy8gQGZ1bmN0aW9uIHBvaW50c1RvUGF0aChyaW5nczogUG9pbnRbXSwgY2xvc2VkOiBCb29sZWFuKTogU3RyaW5nXG4vLyBHZW5lcmF0ZXMgYSBTVkcgcGF0aCBzdHJpbmcgZm9yIG11bHRpcGxlIHJpbmdzLCB3aXRoIGVhY2ggcmluZyB0dXJuaW5nXG4vLyBpbnRvIFwiTS4uTC4uTC4uXCIgaW5zdHJ1Y3Rpb25zXG5mdW5jdGlvbiBwb2ludHNUb1BhdGgocmluZ3MsIGNsb3NlZCkge1xuXHR2YXIgc3RyID0gJycsXG5cdGksIGosIGxlbiwgbGVuMiwgcG9pbnRzLCBwO1xuXG5cdGZvciAoaSA9IDAsIGxlbiA9IHJpbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0cG9pbnRzID0gcmluZ3NbaV07XG5cblx0XHRmb3IgKGogPSAwLCBsZW4yID0gcG9pbnRzLmxlbmd0aDsgaiA8IGxlbjI7IGorKykge1xuXHRcdFx0cCA9IHBvaW50c1tqXTtcblx0XHRcdHN0ciArPSAoaiA/ICdMJyA6ICdNJykgKyBwLnggKyAnICcgKyBwLnk7XG5cdFx0fVxuXG5cdFx0Ly8gY2xvc2VzIHRoZSByaW5nIGZvciBwb2x5Z29uczsgXCJ4XCIgaXMgVk1MIHN5bnRheFxuXHRcdHN0ciArPSBjbG9zZWQgPyAoc3ZnID8gJ3onIDogJ3gnKSA6ICcnO1xuXHR9XG5cblx0Ly8gU1ZHIGNvbXBsYWlucyBhYm91dCBlbXB0eSBwYXRoIHN0cmluZ3Ncblx0cmV0dXJuIHN0ciB8fCAnTTAgMCc7XG59XG5cbi8qXHJcbiAqIEBuYW1lc3BhY2UgQnJvd3NlclxyXG4gKiBAYWthIEwuQnJvd3NlclxyXG4gKlxyXG4gKiBBIG5hbWVzcGFjZSB3aXRoIHN0YXRpYyBwcm9wZXJ0aWVzIGZvciBicm93c2VyL2ZlYXR1cmUgZGV0ZWN0aW9uIHVzZWQgYnkgTGVhZmxldCBpbnRlcm5hbGx5LlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiBpZiAoTC5Ccm93c2VyLmllbHQ5KSB7XHJcbiAqICAgYWxlcnQoJ1VwZ3JhZGUgeW91ciBicm93c2VyLCBkdWRlIScpO1xyXG4gKiB9XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBzdHlsZSQxID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlO1xyXG5cclxuLy8gQHByb3BlcnR5IGllOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGFsbCBJbnRlcm5ldCBFeHBsb3JlciB2ZXJzaW9ucyAobm90IEVkZ2UpLlxyXG52YXIgaWUgPSAnQWN0aXZlWE9iamVjdCcgaW4gd2luZG93O1xyXG5cclxuLy8gQHByb3BlcnR5IGllbHQ5OiBCb29sZWFuOyBgdHJ1ZWAgZm9yIEludGVybmV0IEV4cGxvcmVyIHZlcnNpb25zIGxlc3MgdGhhbiA5LlxyXG52YXIgaWVsdDkgPSBpZSAmJiAhZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcjtcclxuXHJcbi8vIEBwcm9wZXJ0eSBlZGdlOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIHRoZSBFZGdlIHdlYiBicm93c2VyLlxyXG52YXIgZWRnZSA9ICdtc0xhdW5jaFVyaScgaW4gbmF2aWdhdG9yICYmICEoJ2RvY3VtZW50TW9kZScgaW4gZG9jdW1lbnQpO1xyXG5cclxuLy8gQHByb3BlcnR5IHdlYmtpdDogQm9vbGVhbjtcclxuLy8gYHRydWVgIGZvciB3ZWJraXQtYmFzZWQgYnJvd3NlcnMgbGlrZSBDaHJvbWUgYW5kIFNhZmFyaSAoaW5jbHVkaW5nIG1vYmlsZSB2ZXJzaW9ucykuXHJcbnZhciB3ZWJraXQgPSB1c2VyQWdlbnRDb250YWlucygnd2Via2l0Jyk7XHJcblxyXG4vLyBAcHJvcGVydHkgYW5kcm9pZDogQm9vbGVhblxyXG4vLyBgdHJ1ZWAgZm9yIGFueSBicm93c2VyIHJ1bm5pbmcgb24gYW4gQW5kcm9pZCBwbGF0Zm9ybS5cclxudmFyIGFuZHJvaWQgPSB1c2VyQWdlbnRDb250YWlucygnYW5kcm9pZCcpO1xyXG5cclxuLy8gQHByb3BlcnR5IGFuZHJvaWQyMzogQm9vbGVhbjsgYHRydWVgIGZvciBicm93c2VycyBydW5uaW5nIG9uIEFuZHJvaWQgMiBvciBBbmRyb2lkIDMuXHJcbnZhciBhbmRyb2lkMjMgPSB1c2VyQWdlbnRDb250YWlucygnYW5kcm9pZCAyJykgfHwgdXNlckFnZW50Q29udGFpbnMoJ2FuZHJvaWQgMycpO1xyXG5cclxuLyogU2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xNzk2MTI2NiBmb3IgZGV0YWlscyBvbiBkZXRlY3Rpbmcgc3RvY2sgQW5kcm9pZCAqL1xyXG52YXIgd2Via2l0VmVyID0gcGFyc2VJbnQoL1dlYktpdFxcLyhbMC05XSspfCQvLmV4ZWMobmF2aWdhdG9yLnVzZXJBZ2VudClbMV0sIDEwKTsgLy8gYWxzbyBtYXRjaGVzIEFwcGxlV2ViS2l0XHJcbi8vIEBwcm9wZXJ0eSBhbmRyb2lkU3RvY2s6IEJvb2xlYW47IGB0cnVlYCBmb3IgdGhlIEFuZHJvaWQgc3RvY2sgYnJvd3NlciAoaS5lLiBub3QgQ2hyb21lKVxyXG52YXIgYW5kcm9pZFN0b2NrID0gYW5kcm9pZCAmJiB1c2VyQWdlbnRDb250YWlucygnR29vZ2xlJykgJiYgd2Via2l0VmVyIDwgNTM3ICYmICEoJ0F1ZGlvTm9kZScgaW4gd2luZG93KTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBvcGVyYTogQm9vbGVhbjsgYHRydWVgIGZvciB0aGUgT3BlcmEgYnJvd3NlclxyXG52YXIgb3BlcmEgPSAhIXdpbmRvdy5vcGVyYTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBjaHJvbWU6IEJvb2xlYW47IGB0cnVlYCBmb3IgdGhlIENocm9tZSBicm93c2VyLlxyXG52YXIgY2hyb21lID0gdXNlckFnZW50Q29udGFpbnMoJ2Nocm9tZScpO1xyXG5cclxuLy8gQHByb3BlcnR5IGdlY2tvOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGdlY2tvLWJhc2VkIGJyb3dzZXJzIGxpa2UgRmlyZWZveC5cclxudmFyIGdlY2tvID0gdXNlckFnZW50Q29udGFpbnMoJ2dlY2tvJykgJiYgIXdlYmtpdCAmJiAhb3BlcmEgJiYgIWllO1xyXG5cclxuLy8gQHByb3BlcnR5IHNhZmFyaTogQm9vbGVhbjsgYHRydWVgIGZvciB0aGUgU2FmYXJpIGJyb3dzZXIuXHJcbnZhciBzYWZhcmkgPSAhY2hyb21lICYmIHVzZXJBZ2VudENvbnRhaW5zKCdzYWZhcmknKTtcclxuXHJcbnZhciBwaGFudG9tID0gdXNlckFnZW50Q29udGFpbnMoJ3BoYW50b20nKTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBvcGVyYTEyOiBCb29sZWFuXHJcbi8vIGB0cnVlYCBmb3IgdGhlIE9wZXJhIGJyb3dzZXIgc3VwcG9ydGluZyBDU1MgdHJhbnNmb3JtcyAodmVyc2lvbiAxMiBvciBsYXRlcikuXHJcbnZhciBvcGVyYTEyID0gJ09UcmFuc2l0aW9uJyBpbiBzdHlsZSQxO1xyXG5cclxuLy8gQHByb3BlcnR5IHdpbjogQm9vbGVhbjsgYHRydWVgIHdoZW4gdGhlIGJyb3dzZXIgaXMgcnVubmluZyBpbiBhIFdpbmRvd3MgcGxhdGZvcm1cclxudmFyIHdpbiA9IG5hdmlnYXRvci5wbGF0Zm9ybS5pbmRleE9mKCdXaW4nKSA9PT0gMDtcclxuXHJcbi8vIEBwcm9wZXJ0eSBpZTNkOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGFsbCBJbnRlcm5ldCBFeHBsb3JlciB2ZXJzaW9ucyBzdXBwb3J0aW5nIENTUyB0cmFuc2Zvcm1zLlxyXG52YXIgaWUzZCA9IGllICYmICgndHJhbnNpdGlvbicgaW4gc3R5bGUkMSk7XHJcblxyXG4vLyBAcHJvcGVydHkgd2Via2l0M2Q6IEJvb2xlYW47IGB0cnVlYCBmb3Igd2Via2l0LWJhc2VkIGJyb3dzZXJzIHN1cHBvcnRpbmcgQ1NTIHRyYW5zZm9ybXMuXHJcbnZhciB3ZWJraXQzZCA9ICgnV2ViS2l0Q1NTTWF0cml4JyBpbiB3aW5kb3cpICYmICgnbTExJyBpbiBuZXcgd2luZG93LldlYktpdENTU01hdHJpeCgpKSAmJiAhYW5kcm9pZDIzO1xyXG5cclxuLy8gQHByb3BlcnR5IGdlY2tvM2Q6IEJvb2xlYW47IGB0cnVlYCBmb3IgZ2Vja28tYmFzZWQgYnJvd3NlcnMgc3VwcG9ydGluZyBDU1MgdHJhbnNmb3Jtcy5cclxudmFyIGdlY2tvM2QgPSAnTW96UGVyc3BlY3RpdmUnIGluIHN0eWxlJDE7XHJcblxyXG4vLyBAcHJvcGVydHkgYW55M2Q6IEJvb2xlYW5cclxuLy8gYHRydWVgIGZvciBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBDU1MgdHJhbnNmb3Jtcy5cclxudmFyIGFueTNkID0gIXdpbmRvdy5MX0RJU0FCTEVfM0QgJiYgKGllM2QgfHwgd2Via2l0M2QgfHwgZ2Vja28zZCkgJiYgIW9wZXJhMTIgJiYgIXBoYW50b207XHJcblxyXG4vLyBAcHJvcGVydHkgbW9iaWxlOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGFsbCBicm93c2VycyBydW5uaW5nIGluIGEgbW9iaWxlIGRldmljZS5cclxudmFyIG1vYmlsZSA9IHR5cGVvZiBvcmllbnRhdGlvbiAhPT0gJ3VuZGVmaW5lZCcgfHwgdXNlckFnZW50Q29udGFpbnMoJ21vYmlsZScpO1xyXG5cclxuLy8gQHByb3BlcnR5IG1vYmlsZVdlYmtpdDogQm9vbGVhbjsgYHRydWVgIGZvciBhbGwgd2Via2l0LWJhc2VkIGJyb3dzZXJzIGluIGEgbW9iaWxlIGRldmljZS5cclxudmFyIG1vYmlsZVdlYmtpdCA9IG1vYmlsZSAmJiB3ZWJraXQ7XHJcblxyXG4vLyBAcHJvcGVydHkgbW9iaWxlV2Via2l0M2Q6IEJvb2xlYW5cclxuLy8gYHRydWVgIGZvciBhbGwgd2Via2l0LWJhc2VkIGJyb3dzZXJzIGluIGEgbW9iaWxlIGRldmljZSBzdXBwb3J0aW5nIENTUyB0cmFuc2Zvcm1zLlxyXG52YXIgbW9iaWxlV2Via2l0M2QgPSBtb2JpbGUgJiYgd2Via2l0M2Q7XHJcblxyXG4vLyBAcHJvcGVydHkgbXNQb2ludGVyOiBCb29sZWFuXHJcbi8vIGB0cnVlYCBmb3IgYnJvd3NlcnMgaW1wbGVtZW50aW5nIHRoZSBNaWNyb3NvZnQgdG91Y2ggZXZlbnRzIG1vZGVsIChub3RhYmx5IElFMTApLlxyXG52YXIgbXNQb2ludGVyID0gIXdpbmRvdy5Qb2ludGVyRXZlbnQgJiYgd2luZG93Lk1TUG9pbnRlckV2ZW50O1xyXG5cclxuLy8gQHByb3BlcnR5IHBvaW50ZXI6IEJvb2xlYW5cclxuLy8gYHRydWVgIGZvciBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBbcG9pbnRlciBldmVudHNdKGh0dHBzOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvZG40MzMyNDQlMjh2PXZzLjg1JTI5LmFzcHgpLlxyXG52YXIgcG9pbnRlciA9ICEhKHdpbmRvdy5Qb2ludGVyRXZlbnQgfHwgbXNQb2ludGVyKTtcclxuXHJcbi8vIEBwcm9wZXJ0eSB0b3VjaDogQm9vbGVhblxyXG4vLyBgdHJ1ZWAgZm9yIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFt0b3VjaCBldmVudHNdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9Ub3VjaF9ldmVudHMpLlxyXG4vLyBUaGlzIGRvZXMgbm90IG5lY2Vzc2FyaWx5IG1lYW4gdGhhdCB0aGUgYnJvd3NlciBpcyBydW5uaW5nIGluIGEgY29tcHV0ZXIgd2l0aFxyXG4vLyBhIHRvdWNoc2NyZWVuLCBpdCBvbmx5IG1lYW5zIHRoYXQgdGhlIGJyb3dzZXIgaXMgY2FwYWJsZSBvZiB1bmRlcnN0YW5kaW5nXHJcbi8vIHRvdWNoIGV2ZW50cy5cclxudmFyIHRvdWNoID0gIXdpbmRvdy5MX05PX1RPVUNIICYmIChwb2ludGVyIHx8ICdvbnRvdWNoc3RhcnQnIGluIHdpbmRvdyB8fFxyXG5cdFx0KHdpbmRvdy5Eb2N1bWVudFRvdWNoICYmIGRvY3VtZW50IGluc3RhbmNlb2Ygd2luZG93LkRvY3VtZW50VG91Y2gpKTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBtb2JpbGVPcGVyYTogQm9vbGVhbjsgYHRydWVgIGZvciB0aGUgT3BlcmEgYnJvd3NlciBpbiBhIG1vYmlsZSBkZXZpY2UuXHJcbnZhciBtb2JpbGVPcGVyYSA9IG1vYmlsZSAmJiBvcGVyYTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBtb2JpbGVHZWNrbzogQm9vbGVhblxyXG4vLyBgdHJ1ZWAgZm9yIGdlY2tvLWJhc2VkIGJyb3dzZXJzIHJ1bm5pbmcgaW4gYSBtb2JpbGUgZGV2aWNlLlxyXG52YXIgbW9iaWxlR2Vja28gPSBtb2JpbGUgJiYgZ2Vja287XHJcblxyXG4vLyBAcHJvcGVydHkgcmV0aW5hOiBCb29sZWFuXHJcbi8vIGB0cnVlYCBmb3IgYnJvd3NlcnMgb24gYSBoaWdoLXJlc29sdXRpb24gXCJyZXRpbmFcIiBzY3JlZW4gb3Igb24gYW55IHNjcmVlbiB3aGVuIGJyb3dzZXIncyBkaXNwbGF5IHpvb20gaXMgbW9yZSB0aGFuIDEwMCUuXHJcbnZhciByZXRpbmEgPSAod2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgKHdpbmRvdy5zY3JlZW4uZGV2aWNlWERQSSAvIHdpbmRvdy5zY3JlZW4ubG9naWNhbFhEUEkpKSA+IDE7XHJcblxyXG5cclxuLy8gQHByb3BlcnR5IGNhbnZhczogQm9vbGVhblxyXG4vLyBgdHJ1ZWAgd2hlbiB0aGUgYnJvd3NlciBzdXBwb3J0cyBbYDxjYW52YXM+YF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0NhbnZhc19BUEkpLlxyXG52YXIgY2FudmFzID0gKGZ1bmN0aW9uICgpIHtcclxuXHRyZXR1cm4gISFkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKS5nZXRDb250ZXh0O1xyXG59KCkpO1xyXG5cclxuLy8gQHByb3BlcnR5IHN2ZzogQm9vbGVhblxyXG4vLyBgdHJ1ZWAgd2hlbiB0aGUgYnJvd3NlciBzdXBwb3J0cyBbU1ZHXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcpLlxyXG52YXIgc3ZnID0gISEoZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TICYmIHN2Z0NyZWF0ZSgnc3ZnJykuY3JlYXRlU1ZHUmVjdCk7XHJcblxyXG4vLyBAcHJvcGVydHkgdm1sOiBCb29sZWFuXHJcbi8vIGB0cnVlYCBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBbVk1MXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9WZWN0b3JfTWFya3VwX0xhbmd1YWdlKS5cclxudmFyIHZtbCA9ICFzdmcgJiYgKGZ1bmN0aW9uICgpIHtcclxuXHR0cnkge1xyXG5cdFx0dmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG5cdFx0ZGl2LmlubmVySFRNTCA9ICc8djpzaGFwZSBhZGo9XCIxXCIvPic7XHJcblxyXG5cdFx0dmFyIHNoYXBlID0gZGl2LmZpcnN0Q2hpbGQ7XHJcblx0XHRzaGFwZS5zdHlsZS5iZWhhdmlvciA9ICd1cmwoI2RlZmF1bHQjVk1MKSc7XHJcblxyXG5cdFx0cmV0dXJuIHNoYXBlICYmICh0eXBlb2Ygc2hhcGUuYWRqID09PSAnb2JqZWN0Jyk7XHJcblxyXG5cdH0gY2F0Y2ggKGUpIHtcclxuXHRcdHJldHVybiBmYWxzZTtcclxuXHR9XHJcbn0oKSk7XHJcblxyXG5cclxuZnVuY3Rpb24gdXNlckFnZW50Q29udGFpbnMoc3RyKSB7XHJcblx0cmV0dXJuIG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKS5pbmRleE9mKHN0cikgPj0gMDtcclxufVxyXG5cblxudmFyIEJyb3dzZXIgPSAoT2JqZWN0LmZyZWV6ZSB8fCBPYmplY3QpKHtcblx0aWU6IGllLFxuXHRpZWx0OTogaWVsdDksXG5cdGVkZ2U6IGVkZ2UsXG5cdHdlYmtpdDogd2Via2l0LFxuXHRhbmRyb2lkOiBhbmRyb2lkLFxuXHRhbmRyb2lkMjM6IGFuZHJvaWQyMyxcblx0YW5kcm9pZFN0b2NrOiBhbmRyb2lkU3RvY2ssXG5cdG9wZXJhOiBvcGVyYSxcblx0Y2hyb21lOiBjaHJvbWUsXG5cdGdlY2tvOiBnZWNrbyxcblx0c2FmYXJpOiBzYWZhcmksXG5cdHBoYW50b206IHBoYW50b20sXG5cdG9wZXJhMTI6IG9wZXJhMTIsXG5cdHdpbjogd2luLFxuXHRpZTNkOiBpZTNkLFxuXHR3ZWJraXQzZDogd2Via2l0M2QsXG5cdGdlY2tvM2Q6IGdlY2tvM2QsXG5cdGFueTNkOiBhbnkzZCxcblx0bW9iaWxlOiBtb2JpbGUsXG5cdG1vYmlsZVdlYmtpdDogbW9iaWxlV2Via2l0LFxuXHRtb2JpbGVXZWJraXQzZDogbW9iaWxlV2Via2l0M2QsXG5cdG1zUG9pbnRlcjogbXNQb2ludGVyLFxuXHRwb2ludGVyOiBwb2ludGVyLFxuXHR0b3VjaDogdG91Y2gsXG5cdG1vYmlsZU9wZXJhOiBtb2JpbGVPcGVyYSxcblx0bW9iaWxlR2Vja286IG1vYmlsZUdlY2tvLFxuXHRyZXRpbmE6IHJldGluYSxcblx0Y2FudmFzOiBjYW52YXMsXG5cdHN2Zzogc3ZnLFxuXHR2bWw6IHZtbFxufSk7XG5cbi8qXG4gKiBFeHRlbmRzIEwuRG9tRXZlbnQgdG8gcHJvdmlkZSB0b3VjaCBzdXBwb3J0IGZvciBJbnRlcm5ldCBFeHBsb3JlciBhbmQgV2luZG93cy1iYXNlZCBkZXZpY2VzLlxuICovXG5cblxudmFyIFBPSU5URVJfRE9XTiA9ICAgbXNQb2ludGVyID8gJ01TUG9pbnRlckRvd24nICAgOiAncG9pbnRlcmRvd24nO1xudmFyIFBPSU5URVJfTU9WRSA9ICAgbXNQb2ludGVyID8gJ01TUG9pbnRlck1vdmUnICAgOiAncG9pbnRlcm1vdmUnO1xudmFyIFBPSU5URVJfVVAgPSAgICAgbXNQb2ludGVyID8gJ01TUG9pbnRlclVwJyAgICAgOiAncG9pbnRlcnVwJztcbnZhciBQT0lOVEVSX0NBTkNFTCA9IG1zUG9pbnRlciA/ICdNU1BvaW50ZXJDYW5jZWwnIDogJ3BvaW50ZXJjYW5jZWwnO1xudmFyIFRBR19XSElURV9MSVNUID0gWydJTlBVVCcsICdTRUxFQ1QnLCAnT1BUSU9OJ107XG5cbnZhciBfcG9pbnRlcnMgPSB7fTtcbnZhciBfcG9pbnRlckRvY0xpc3RlbmVyID0gZmFsc2U7XG5cbi8vIERvbUV2ZW50LkRvdWJsZVRhcCBuZWVkcyB0byBrbm93IGFib3V0IHRoaXNcbnZhciBfcG9pbnRlcnNDb3VudCA9IDA7XG5cbi8vIFByb3ZpZGVzIGEgdG91Y2ggZXZlbnRzIHdyYXBwZXIgZm9yIChtcylwb2ludGVyIGV2ZW50cy5cbi8vIHJlZiBodHRwOi8vd3d3LnczLm9yZy9UUi9wb2ludGVyZXZlbnRzLyBodHRwczovL3d3dy53My5vcmcvQnVncy9QdWJsaWMvc2hvd19idWcuY2dpP2lkPTIyODkwXG5cbmZ1bmN0aW9uIGFkZFBvaW50ZXJMaXN0ZW5lcihvYmosIHR5cGUsIGhhbmRsZXIsIGlkKSB7XG5cdGlmICh0eXBlID09PSAndG91Y2hzdGFydCcpIHtcblx0XHRfYWRkUG9pbnRlclN0YXJ0KG9iaiwgaGFuZGxlciwgaWQpO1xuXG5cdH0gZWxzZSBpZiAodHlwZSA9PT0gJ3RvdWNobW92ZScpIHtcblx0XHRfYWRkUG9pbnRlck1vdmUob2JqLCBoYW5kbGVyLCBpZCk7XG5cblx0fSBlbHNlIGlmICh0eXBlID09PSAndG91Y2hlbmQnKSB7XG5cdFx0X2FkZFBvaW50ZXJFbmQob2JqLCBoYW5kbGVyLCBpZCk7XG5cdH1cblxuXHRyZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gcmVtb3ZlUG9pbnRlckxpc3RlbmVyKG9iaiwgdHlwZSwgaWQpIHtcblx0dmFyIGhhbmRsZXIgPSBvYmpbJ19sZWFmbGV0XycgKyB0eXBlICsgaWRdO1xuXG5cdGlmICh0eXBlID09PSAndG91Y2hzdGFydCcpIHtcblx0XHRvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcihQT0lOVEVSX0RPV04sIGhhbmRsZXIsIGZhbHNlKTtcblxuXHR9IGVsc2UgaWYgKHR5cGUgPT09ICd0b3VjaG1vdmUnKSB7XG5cdFx0b2JqLnJlbW92ZUV2ZW50TGlzdGVuZXIoUE9JTlRFUl9NT1ZFLCBoYW5kbGVyLCBmYWxzZSk7XG5cblx0fSBlbHNlIGlmICh0eXBlID09PSAndG91Y2hlbmQnKSB7XG5cdFx0b2JqLnJlbW92ZUV2ZW50TGlzdGVuZXIoUE9JTlRFUl9VUCwgaGFuZGxlciwgZmFsc2UpO1xuXHRcdG9iai5yZW1vdmVFdmVudExpc3RlbmVyKFBPSU5URVJfQ0FOQ0VMLCBoYW5kbGVyLCBmYWxzZSk7XG5cdH1cblxuXHRyZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gX2FkZFBvaW50ZXJTdGFydChvYmosIGhhbmRsZXIsIGlkKSB7XG5cdHZhciBvbkRvd24gPSBiaW5kKGZ1bmN0aW9uIChlKSB7XG5cdFx0aWYgKGUucG9pbnRlclR5cGUgIT09ICdtb3VzZScgJiYgZS5NU1BPSU5URVJfVFlQRV9NT1VTRSAmJiBlLnBvaW50ZXJUeXBlICE9PSBlLk1TUE9JTlRFUl9UWVBFX01PVVNFKSB7XG5cdFx0XHQvLyBJbiBJRTExLCBzb21lIHRvdWNoIGV2ZW50cyBuZWVkcyB0byBmaXJlIGZvciBmb3JtIGNvbnRyb2xzLCBvclxuXHRcdFx0Ly8gdGhlIGNvbnRyb2xzIHdpbGwgc3RvcCB3b3JraW5nLiBXZSBrZWVwIGEgd2hpdGVsaXN0IG9mIHRhZyBuYW1lcyB0aGF0XG5cdFx0XHQvLyBuZWVkIHRoZXNlIGV2ZW50cy4gRm9yIG90aGVyIHRhcmdldCB0YWdzLCB3ZSBwcmV2ZW50IGRlZmF1bHQgb24gdGhlIGV2ZW50LlxuXHRcdFx0aWYgKFRBR19XSElURV9MSVNULmluZGV4T2YoZS50YXJnZXQudGFnTmFtZSkgPCAwKSB7XG5cdFx0XHRcdHByZXZlbnREZWZhdWx0KGUpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdF9oYW5kbGVQb2ludGVyKGUsIGhhbmRsZXIpO1xuXHR9KTtcblxuXHRvYmpbJ19sZWFmbGV0X3RvdWNoc3RhcnQnICsgaWRdID0gb25Eb3duO1xuXHRvYmouYWRkRXZlbnRMaXN0ZW5lcihQT0lOVEVSX0RPV04sIG9uRG93biwgZmFsc2UpO1xuXG5cdC8vIG5lZWQgdG8ga2VlcCB0cmFjayBvZiB3aGF0IHBvaW50ZXJzIGFuZCBob3cgbWFueSBhcmUgYWN0aXZlIHRvIHByb3ZpZGUgZS50b3VjaGVzIGVtdWxhdGlvblxuXHRpZiAoIV9wb2ludGVyRG9jTGlzdGVuZXIpIHtcblx0XHQvLyB3ZSBsaXN0ZW4gZG9jdW1lbnRFbGVtZW50IGFzIGFueSBkcmFncyB0aGF0IGVuZCBieSBtb3ZpbmcgdGhlIHRvdWNoIG9mZiB0aGUgc2NyZWVuIGdldCBmaXJlZCB0aGVyZVxuXHRcdGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFBPSU5URVJfRE9XTiwgX2dsb2JhbFBvaW50ZXJEb3duLCB0cnVlKTtcblx0XHRkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihQT0lOVEVSX01PVkUsIF9nbG9iYWxQb2ludGVyTW92ZSwgdHJ1ZSk7XG5cdFx0ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoUE9JTlRFUl9VUCwgX2dsb2JhbFBvaW50ZXJVcCwgdHJ1ZSk7XG5cdFx0ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoUE9JTlRFUl9DQU5DRUwsIF9nbG9iYWxQb2ludGVyVXAsIHRydWUpO1xuXG5cdFx0X3BvaW50ZXJEb2NMaXN0ZW5lciA9IHRydWU7XG5cdH1cbn1cblxuZnVuY3Rpb24gX2dsb2JhbFBvaW50ZXJEb3duKGUpIHtcblx0X3BvaW50ZXJzW2UucG9pbnRlcklkXSA9IGU7XG5cdF9wb2ludGVyc0NvdW50Kys7XG59XG5cbmZ1bmN0aW9uIF9nbG9iYWxQb2ludGVyTW92ZShlKSB7XG5cdGlmIChfcG9pbnRlcnNbZS5wb2ludGVySWRdKSB7XG5cdFx0X3BvaW50ZXJzW2UucG9pbnRlcklkXSA9IGU7XG5cdH1cbn1cblxuZnVuY3Rpb24gX2dsb2JhbFBvaW50ZXJVcChlKSB7XG5cdGRlbGV0ZSBfcG9pbnRlcnNbZS5wb2ludGVySWRdO1xuXHRfcG9pbnRlcnNDb3VudC0tO1xufVxuXG5mdW5jdGlvbiBfaGFuZGxlUG9pbnRlcihlLCBoYW5kbGVyKSB7XG5cdGUudG91Y2hlcyA9IFtdO1xuXHRmb3IgKHZhciBpIGluIF9wb2ludGVycykge1xuXHRcdGUudG91Y2hlcy5wdXNoKF9wb2ludGVyc1tpXSk7XG5cdH1cblx0ZS5jaGFuZ2VkVG91Y2hlcyA9IFtlXTtcblxuXHRoYW5kbGVyKGUpO1xufVxuXG5mdW5jdGlvbiBfYWRkUG9pbnRlck1vdmUob2JqLCBoYW5kbGVyLCBpZCkge1xuXHR2YXIgb25Nb3ZlID0gZnVuY3Rpb24gKGUpIHtcblx0XHQvLyBkb24ndCBmaXJlIHRvdWNoIG1vdmVzIHdoZW4gbW91c2UgaXNuJ3QgZG93blxuXHRcdGlmICgoZS5wb2ludGVyVHlwZSA9PT0gZS5NU1BPSU5URVJfVFlQRV9NT1VTRSB8fCBlLnBvaW50ZXJUeXBlID09PSAnbW91c2UnKSAmJiBlLmJ1dHRvbnMgPT09IDApIHsgcmV0dXJuOyB9XG5cblx0XHRfaGFuZGxlUG9pbnRlcihlLCBoYW5kbGVyKTtcblx0fTtcblxuXHRvYmpbJ19sZWFmbGV0X3RvdWNobW92ZScgKyBpZF0gPSBvbk1vdmU7XG5cdG9iai5hZGRFdmVudExpc3RlbmVyKFBPSU5URVJfTU9WRSwgb25Nb3ZlLCBmYWxzZSk7XG59XG5cbmZ1bmN0aW9uIF9hZGRQb2ludGVyRW5kKG9iaiwgaGFuZGxlciwgaWQpIHtcblx0dmFyIG9uVXAgPSBmdW5jdGlvbiAoZSkge1xuXHRcdF9oYW5kbGVQb2ludGVyKGUsIGhhbmRsZXIpO1xuXHR9O1xuXG5cdG9ialsnX2xlYWZsZXRfdG91Y2hlbmQnICsgaWRdID0gb25VcDtcblx0b2JqLmFkZEV2ZW50TGlzdGVuZXIoUE9JTlRFUl9VUCwgb25VcCwgZmFsc2UpO1xuXHRvYmouYWRkRXZlbnRMaXN0ZW5lcihQT0lOVEVSX0NBTkNFTCwgb25VcCwgZmFsc2UpO1xufVxuXG4vKlxyXG4gKiBFeHRlbmRzIHRoZSBldmVudCBoYW5kbGluZyBjb2RlIHdpdGggZG91YmxlIHRhcCBzdXBwb3J0IGZvciBtb2JpbGUgYnJvd3NlcnMuXHJcbiAqL1xyXG5cclxudmFyIF90b3VjaHN0YXJ0ID0gbXNQb2ludGVyID8gJ01TUG9pbnRlckRvd24nIDogcG9pbnRlciA/ICdwb2ludGVyZG93bicgOiAndG91Y2hzdGFydCc7XHJcbnZhciBfdG91Y2hlbmQgPSBtc1BvaW50ZXIgPyAnTVNQb2ludGVyVXAnIDogcG9pbnRlciA/ICdwb2ludGVydXAnIDogJ3RvdWNoZW5kJztcclxudmFyIF9wcmUgPSAnX2xlYWZsZXRfJztcclxuXHJcbi8vIGluc3BpcmVkIGJ5IFplcHRvIHRvdWNoIGNvZGUgYnkgVGhvbWFzIEZ1Y2hzXHJcbmZ1bmN0aW9uIGFkZERvdWJsZVRhcExpc3RlbmVyKG9iaiwgaGFuZGxlciwgaWQpIHtcclxuXHR2YXIgbGFzdCwgdG91Y2gkJDEsXHJcblx0ICAgIGRvdWJsZVRhcCA9IGZhbHNlLFxyXG5cdCAgICBkZWxheSA9IDI1MDtcclxuXHJcblx0ZnVuY3Rpb24gb25Ub3VjaFN0YXJ0KGUpIHtcclxuXHRcdHZhciBjb3VudDtcclxuXHJcblx0XHRpZiAocG9pbnRlcikge1xyXG5cdFx0XHRpZiAoKCFlZGdlKSB8fCBlLnBvaW50ZXJUeXBlID09PSAnbW91c2UnKSB7IHJldHVybjsgfVxyXG5cdFx0XHRjb3VudCA9IF9wb2ludGVyc0NvdW50O1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0Y291bnQgPSBlLnRvdWNoZXMubGVuZ3RoO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChjb3VudCA+IDEpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0dmFyIG5vdyA9IERhdGUubm93KCksXHJcblx0XHQgICAgZGVsdGEgPSBub3cgLSAobGFzdCB8fCBub3cpO1xyXG5cclxuXHRcdHRvdWNoJCQxID0gZS50b3VjaGVzID8gZS50b3VjaGVzWzBdIDogZTtcclxuXHRcdGRvdWJsZVRhcCA9IChkZWx0YSA+IDAgJiYgZGVsdGEgPD0gZGVsYXkpO1xyXG5cdFx0bGFzdCA9IG5vdztcclxuXHR9XHJcblxyXG5cdGZ1bmN0aW9uIG9uVG91Y2hFbmQoZSkge1xyXG5cdFx0aWYgKGRvdWJsZVRhcCAmJiAhdG91Y2gkJDEuY2FuY2VsQnViYmxlKSB7XHJcblx0XHRcdGlmIChwb2ludGVyKSB7XHJcblx0XHRcdFx0aWYgKCghZWRnZSkgfHwgZS5wb2ludGVyVHlwZSA9PT0gJ21vdXNlJykgeyByZXR1cm47IH1cclxuXHRcdFx0XHQvLyB3b3JrIGFyb3VuZCAudHlwZSBiZWluZyByZWFkb25seSB3aXRoIE1TUG9pbnRlciogZXZlbnRzXHJcblx0XHRcdFx0dmFyIG5ld1RvdWNoID0ge30sXHJcblx0XHRcdFx0ICAgIHByb3AsIGk7XHJcblxyXG5cdFx0XHRcdGZvciAoaSBpbiB0b3VjaCQkMSkge1xyXG5cdFx0XHRcdFx0cHJvcCA9IHRvdWNoJCQxW2ldO1xyXG5cdFx0XHRcdFx0bmV3VG91Y2hbaV0gPSBwcm9wICYmIHByb3AuYmluZCA/IHByb3AuYmluZCh0b3VjaCQkMSkgOiBwcm9wO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHR0b3VjaCQkMSA9IG5ld1RvdWNoO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRvdWNoJCQxLnR5cGUgPSAnZGJsY2xpY2snO1xyXG5cdFx0XHR0b3VjaCQkMS5idXR0b24gPSAwO1xyXG5cdFx0XHRoYW5kbGVyKHRvdWNoJCQxKTtcclxuXHRcdFx0bGFzdCA9IG51bGw7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRvYmpbX3ByZSArIF90b3VjaHN0YXJ0ICsgaWRdID0gb25Ub3VjaFN0YXJ0O1xyXG5cdG9ialtfcHJlICsgX3RvdWNoZW5kICsgaWRdID0gb25Ub3VjaEVuZDtcclxuXHRvYmpbX3ByZSArICdkYmxjbGljaycgKyBpZF0gPSBoYW5kbGVyO1xyXG5cclxuXHRvYmouYWRkRXZlbnRMaXN0ZW5lcihfdG91Y2hzdGFydCwgb25Ub3VjaFN0YXJ0LCBmYWxzZSk7XHJcblx0b2JqLmFkZEV2ZW50TGlzdGVuZXIoX3RvdWNoZW5kLCBvblRvdWNoRW5kLCBmYWxzZSk7XHJcblxyXG5cdC8vIE9uIHNvbWUgcGxhdGZvcm1zIChub3RhYmx5LCBjaHJvbWU8NTUgb24gd2luMTAgKyB0b3VjaHNjcmVlbiArIG1vdXNlKSxcclxuXHQvLyB0aGUgYnJvd3NlciBkb2Vzbid0IGZpcmUgdG91Y2hlbmQvcG9pbnRlcnVwIGV2ZW50cyBidXQgZG9lcyBmaXJlXHJcblx0Ly8gbmF0aXZlIGRibGNsaWNrcy4gU2VlICM0MTI3LlxyXG5cdC8vIEVkZ2UgMTQgYWxzbyBmaXJlcyBuYXRpdmUgZGJsY2xpY2tzLCBidXQgb25seSBmb3IgcG9pbnRlclR5cGUgbW91c2UsIHNlZSAjNTE4MC5cclxuXHRvYmouYWRkRXZlbnRMaXN0ZW5lcignZGJsY2xpY2snLCBoYW5kbGVyLCBmYWxzZSk7XHJcblxyXG5cdHJldHVybiB0aGlzO1xyXG59XHJcblxyXG5mdW5jdGlvbiByZW1vdmVEb3VibGVUYXBMaXN0ZW5lcihvYmosIGlkKSB7XHJcblx0dmFyIHRvdWNoc3RhcnQgPSBvYmpbX3ByZSArIF90b3VjaHN0YXJ0ICsgaWRdLFxyXG5cdCAgICB0b3VjaGVuZCA9IG9ialtfcHJlICsgX3RvdWNoZW5kICsgaWRdLFxyXG5cdCAgICBkYmxjbGljayA9IG9ialtfcHJlICsgJ2RibGNsaWNrJyArIGlkXTtcclxuXHJcblx0b2JqLnJlbW92ZUV2ZW50TGlzdGVuZXIoX3RvdWNoc3RhcnQsIHRvdWNoc3RhcnQsIGZhbHNlKTtcclxuXHRvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcihfdG91Y2hlbmQsIHRvdWNoZW5kLCBmYWxzZSk7XHJcblx0aWYgKCFlZGdlKSB7XHJcblx0XHRvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcignZGJsY2xpY2snLCBkYmxjbGljaywgZmFsc2UpO1xyXG5cdH1cclxuXHJcblx0cmV0dXJuIHRoaXM7XHJcbn1cblxuLypcclxuICogQG5hbWVzcGFjZSBEb21VdGlsXHJcbiAqXHJcbiAqIFV0aWxpdHkgZnVuY3Rpb25zIHRvIHdvcmsgd2l0aCB0aGUgW0RPTV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0RvY3VtZW50X09iamVjdF9Nb2RlbClcclxuICogdHJlZSwgdXNlZCBieSBMZWFmbGV0IGludGVybmFsbHkuXHJcbiAqXHJcbiAqIE1vc3QgZnVuY3Rpb25zIGV4cGVjdGluZyBvciByZXR1cm5pbmcgYSBgSFRNTEVsZW1lbnRgIGFsc28gd29yayBmb3JcclxuICogU1ZHIGVsZW1lbnRzLiBUaGUgb25seSBkaWZmZXJlbmNlIGlzIHRoYXQgY2xhc3NlcyByZWZlciB0byBDU1MgY2xhc3Nlc1xyXG4gKiBpbiBIVE1MIGFuZCBTVkcgY2xhc3NlcyBpbiBTVkcuXHJcbiAqL1xyXG5cclxuXHJcbi8vIEBwcm9wZXJ0eSBUUkFOU0ZPUk06IFN0cmluZ1xyXG4vLyBWZW5kb3ItcHJlZml4ZWQgdHJhbnNmb3JtIHN0eWxlIG5hbWUgKGUuZy4gYCd3ZWJraXRUcmFuc2Zvcm0nYCBmb3IgV2ViS2l0KS5cclxudmFyIFRSQU5TRk9STSA9IHRlc3RQcm9wKFxyXG5cdFsndHJhbnNmb3JtJywgJ3dlYmtpdFRyYW5zZm9ybScsICdPVHJhbnNmb3JtJywgJ01velRyYW5zZm9ybScsICdtc1RyYW5zZm9ybSddKTtcclxuXHJcbi8vIHdlYmtpdFRyYW5zaXRpb24gY29tZXMgZmlyc3QgYmVjYXVzZSBzb21lIGJyb3dzZXIgdmVyc2lvbnMgdGhhdCBkcm9wIHZlbmRvciBwcmVmaXggZG9uJ3QgZG9cclxuLy8gdGhlIHNhbWUgZm9yIHRoZSB0cmFuc2l0aW9uZW5kIGV2ZW50LCBpbiBwYXJ0aWN1bGFyIHRoZSBBbmRyb2lkIDQuMSBzdG9jayBicm93c2VyXHJcblxyXG4vLyBAcHJvcGVydHkgVFJBTlNJVElPTjogU3RyaW5nXHJcbi8vIFZlbmRvci1wcmVmaXhlZCB0cmFuc2l0aW9uIHN0eWxlIG5hbWUuXHJcbnZhciBUUkFOU0lUSU9OID0gdGVzdFByb3AoXHJcblx0Wyd3ZWJraXRUcmFuc2l0aW9uJywgJ3RyYW5zaXRpb24nLCAnT1RyYW5zaXRpb24nLCAnTW96VHJhbnNpdGlvbicsICdtc1RyYW5zaXRpb24nXSk7XHJcblxyXG4vLyBAcHJvcGVydHkgVFJBTlNJVElPTl9FTkQ6IFN0cmluZ1xyXG4vLyBWZW5kb3ItcHJlZml4ZWQgdHJhbnNpdGlvbmVuZCBldmVudCBuYW1lLlxyXG52YXIgVFJBTlNJVElPTl9FTkQgPVxyXG5cdFRSQU5TSVRJT04gPT09ICd3ZWJraXRUcmFuc2l0aW9uJyB8fCBUUkFOU0lUSU9OID09PSAnT1RyYW5zaXRpb24nID8gVFJBTlNJVElPTiArICdFbmQnIDogJ3RyYW5zaXRpb25lbmQnO1xyXG5cclxuXHJcbi8vIEBmdW5jdGlvbiBnZXQoaWQ6IFN0cmluZ3xIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50XHJcbi8vIFJldHVybnMgYW4gZWxlbWVudCBnaXZlbiBpdHMgRE9NIGlkLCBvciByZXR1cm5zIHRoZSBlbGVtZW50IGl0c2VsZlxyXG4vLyBpZiBpdCB3YXMgcGFzc2VkIGRpcmVjdGx5LlxyXG5mdW5jdGlvbiBnZXQoaWQpIHtcclxuXHRyZXR1cm4gdHlwZW9mIGlkID09PSAnc3RyaW5nJyA/IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGlkKSA6IGlkO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gZ2V0U3R5bGUoZWw6IEhUTUxFbGVtZW50LCBzdHlsZUF0dHJpYjogU3RyaW5nKTogU3RyaW5nXHJcbi8vIFJldHVybnMgdGhlIHZhbHVlIGZvciBhIGNlcnRhaW4gc3R5bGUgYXR0cmlidXRlIG9uIGFuIGVsZW1lbnQsXHJcbi8vIGluY2x1ZGluZyBjb21wdXRlZCB2YWx1ZXMgb3IgdmFsdWVzIHNldCB0aHJvdWdoIENTUy5cclxuZnVuY3Rpb24gZ2V0U3R5bGUoZWwsIHN0eWxlKSB7XHJcblx0dmFyIHZhbHVlID0gZWwuc3R5bGVbc3R5bGVdIHx8IChlbC5jdXJyZW50U3R5bGUgJiYgZWwuY3VycmVudFN0eWxlW3N0eWxlXSk7XHJcblxyXG5cdGlmICgoIXZhbHVlIHx8IHZhbHVlID09PSAnYXV0bycpICYmIGRvY3VtZW50LmRlZmF1bHRWaWV3KSB7XHJcblx0XHR2YXIgY3NzID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShlbCwgbnVsbCk7XHJcblx0XHR2YWx1ZSA9IGNzcyA/IGNzc1tzdHlsZV0gOiBudWxsO1xyXG5cdH1cclxuXHRyZXR1cm4gdmFsdWUgPT09ICdhdXRvJyA/IG51bGwgOiB2YWx1ZTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGNyZWF0ZSh0YWdOYW1lOiBTdHJpbmcsIGNsYXNzTmFtZT86IFN0cmluZywgY29udGFpbmVyPzogSFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudFxyXG4vLyBDcmVhdGVzIGFuIEhUTUwgZWxlbWVudCB3aXRoIGB0YWdOYW1lYCwgc2V0cyBpdHMgY2xhc3MgdG8gYGNsYXNzTmFtZWAsIGFuZCBvcHRpb25hbGx5IGFwcGVuZHMgaXQgdG8gYGNvbnRhaW5lcmAgZWxlbWVudC5cclxuZnVuY3Rpb24gY3JlYXRlJDEodGFnTmFtZSwgY2xhc3NOYW1lLCBjb250YWluZXIpIHtcclxuXHR2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KHRhZ05hbWUpO1xyXG5cdGVsLmNsYXNzTmFtZSA9IGNsYXNzTmFtZSB8fCAnJztcclxuXHJcblx0aWYgKGNvbnRhaW5lcikge1xyXG5cdFx0Y29udGFpbmVyLmFwcGVuZENoaWxkKGVsKTtcclxuXHR9XHJcblx0cmV0dXJuIGVsO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gcmVtb3ZlKGVsOiBIVE1MRWxlbWVudClcclxuLy8gUmVtb3ZlcyBgZWxgIGZyb20gaXRzIHBhcmVudCBlbGVtZW50XHJcbmZ1bmN0aW9uIHJlbW92ZShlbCkge1xyXG5cdHZhciBwYXJlbnQgPSBlbC5wYXJlbnROb2RlO1xyXG5cdGlmIChwYXJlbnQpIHtcclxuXHRcdHBhcmVudC5yZW1vdmVDaGlsZChlbCk7XHJcblx0fVxyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gZW1wdHkoZWw6IEhUTUxFbGVtZW50KVxyXG4vLyBSZW1vdmVzIGFsbCBvZiBgZWxgJ3MgY2hpbGRyZW4gZWxlbWVudHMgZnJvbSBgZWxgXHJcbmZ1bmN0aW9uIGVtcHR5KGVsKSB7XHJcblx0d2hpbGUgKGVsLmZpcnN0Q2hpbGQpIHtcclxuXHRcdGVsLnJlbW92ZUNoaWxkKGVsLmZpcnN0Q2hpbGQpO1xyXG5cdH1cclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHRvRnJvbnQoZWw6IEhUTUxFbGVtZW50KVxyXG4vLyBNYWtlcyBgZWxgIHRoZSBsYXN0IGNoaWxkIG9mIGl0cyBwYXJlbnQsIHNvIGl0IHJlbmRlcnMgaW4gZnJvbnQgb2YgdGhlIG90aGVyIGNoaWxkcmVuLlxyXG5mdW5jdGlvbiB0b0Zyb250KGVsKSB7XHJcblx0dmFyIHBhcmVudCA9IGVsLnBhcmVudE5vZGU7XHJcblx0aWYgKHBhcmVudCAmJiBwYXJlbnQubGFzdENoaWxkICE9PSBlbCkge1xyXG5cdFx0cGFyZW50LmFwcGVuZENoaWxkKGVsKTtcclxuXHR9XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiB0b0JhY2soZWw6IEhUTUxFbGVtZW50KVxyXG4vLyBNYWtlcyBgZWxgIHRoZSBmaXJzdCBjaGlsZCBvZiBpdHMgcGFyZW50LCBzbyBpdCByZW5kZXJzIGJlaGluZCB0aGUgb3RoZXIgY2hpbGRyZW4uXHJcbmZ1bmN0aW9uIHRvQmFjayhlbCkge1xyXG5cdHZhciBwYXJlbnQgPSBlbC5wYXJlbnROb2RlO1xyXG5cdGlmIChwYXJlbnQgJiYgcGFyZW50LmZpcnN0Q2hpbGQgIT09IGVsKSB7XHJcblx0XHRwYXJlbnQuaW5zZXJ0QmVmb3JlKGVsLCBwYXJlbnQuZmlyc3RDaGlsZCk7XHJcblx0fVxyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gaGFzQ2xhc3MoZWw6IEhUTUxFbGVtZW50LCBuYW1lOiBTdHJpbmcpOiBCb29sZWFuXHJcbi8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBlbGVtZW50J3MgY2xhc3MgYXR0cmlidXRlIGNvbnRhaW5zIGBuYW1lYC5cclxuZnVuY3Rpb24gaGFzQ2xhc3MoZWwsIG5hbWUpIHtcclxuXHRpZiAoZWwuY2xhc3NMaXN0ICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdHJldHVybiBlbC5jbGFzc0xpc3QuY29udGFpbnMobmFtZSk7XHJcblx0fVxyXG5cdHZhciBjbGFzc05hbWUgPSBnZXRDbGFzcyhlbCk7XHJcblx0cmV0dXJuIGNsYXNzTmFtZS5sZW5ndGggPiAwICYmIG5ldyBSZWdFeHAoJyhefFxcXFxzKScgKyBuYW1lICsgJyhcXFxcc3wkKScpLnRlc3QoY2xhc3NOYW1lKTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGFkZENsYXNzKGVsOiBIVE1MRWxlbWVudCwgbmFtZTogU3RyaW5nKVxyXG4vLyBBZGRzIGBuYW1lYCB0byB0aGUgZWxlbWVudCdzIGNsYXNzIGF0dHJpYnV0ZS5cclxuZnVuY3Rpb24gYWRkQ2xhc3MoZWwsIG5hbWUpIHtcclxuXHRpZiAoZWwuY2xhc3NMaXN0ICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdHZhciBjbGFzc2VzID0gc3BsaXRXb3JkcyhuYW1lKTtcclxuXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBjbGFzc2VzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdGVsLmNsYXNzTGlzdC5hZGQoY2xhc3Nlc1tpXSk7XHJcblx0XHR9XHJcblx0fSBlbHNlIGlmICghaGFzQ2xhc3MoZWwsIG5hbWUpKSB7XHJcblx0XHR2YXIgY2xhc3NOYW1lID0gZ2V0Q2xhc3MoZWwpO1xyXG5cdFx0c2V0Q2xhc3MoZWwsIChjbGFzc05hbWUgPyBjbGFzc05hbWUgKyAnICcgOiAnJykgKyBuYW1lKTtcclxuXHR9XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiByZW1vdmVDbGFzcyhlbDogSFRNTEVsZW1lbnQsIG5hbWU6IFN0cmluZylcclxuLy8gUmVtb3ZlcyBgbmFtZWAgZnJvbSB0aGUgZWxlbWVudCdzIGNsYXNzIGF0dHJpYnV0ZS5cclxuZnVuY3Rpb24gcmVtb3ZlQ2xhc3MoZWwsIG5hbWUpIHtcclxuXHRpZiAoZWwuY2xhc3NMaXN0ICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdGVsLmNsYXNzTGlzdC5yZW1vdmUobmFtZSk7XHJcblx0fSBlbHNlIHtcclxuXHRcdHNldENsYXNzKGVsLCB0cmltKCgnICcgKyBnZXRDbGFzcyhlbCkgKyAnICcpLnJlcGxhY2UoJyAnICsgbmFtZSArICcgJywgJyAnKSkpO1xyXG5cdH1cclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHNldENsYXNzKGVsOiBIVE1MRWxlbWVudCwgbmFtZTogU3RyaW5nKVxyXG4vLyBTZXRzIHRoZSBlbGVtZW50J3MgY2xhc3MuXHJcbmZ1bmN0aW9uIHNldENsYXNzKGVsLCBuYW1lKSB7XHJcblx0aWYgKGVsLmNsYXNzTmFtZS5iYXNlVmFsID09PSB1bmRlZmluZWQpIHtcclxuXHRcdGVsLmNsYXNzTmFtZSA9IG5hbWU7XHJcblx0fSBlbHNlIHtcclxuXHRcdC8vIGluIGNhc2Ugb2YgU1ZHIGVsZW1lbnRcclxuXHRcdGVsLmNsYXNzTmFtZS5iYXNlVmFsID0gbmFtZTtcclxuXHR9XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBnZXRDbGFzcyhlbDogSFRNTEVsZW1lbnQpOiBTdHJpbmdcclxuLy8gUmV0dXJucyB0aGUgZWxlbWVudCdzIGNsYXNzLlxyXG5mdW5jdGlvbiBnZXRDbGFzcyhlbCkge1xyXG5cdC8vIENoZWNrIGlmIHRoZSBlbGVtZW50IGlzIGFuIFNWR0VsZW1lbnRJbnN0YW5jZSBhbmQgdXNlIHRoZSBjb3JyZXNwb25kaW5nRWxlbWVudCBpbnN0ZWFkXHJcblx0Ly8gKFJlcXVpcmVkIGZvciBsaW5rZWQgU1ZHIGVsZW1lbnRzIGluIElFMTEuKVxyXG5cdGlmIChlbC5jb3JyZXNwb25kaW5nRWxlbWVudCkge1xyXG5cdFx0ZWwgPSBlbC5jb3JyZXNwb25kaW5nRWxlbWVudDtcclxuXHR9XHJcblx0cmV0dXJuIGVsLmNsYXNzTmFtZS5iYXNlVmFsID09PSB1bmRlZmluZWQgPyBlbC5jbGFzc05hbWUgOiBlbC5jbGFzc05hbWUuYmFzZVZhbDtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHNldE9wYWNpdHkoZWw6IEhUTUxFbGVtZW50LCBvcGFjaXR5OiBOdW1iZXIpXHJcbi8vIFNldCB0aGUgb3BhY2l0eSBvZiBhbiBlbGVtZW50IChpbmNsdWRpbmcgb2xkIElFIHN1cHBvcnQpLlxyXG4vLyBgb3BhY2l0eWAgbXVzdCBiZSBhIG51bWJlciBmcm9tIGAwYCB0byBgMWAuXHJcbmZ1bmN0aW9uIHNldE9wYWNpdHkoZWwsIHZhbHVlKSB7XHJcblx0aWYgKCdvcGFjaXR5JyBpbiBlbC5zdHlsZSkge1xyXG5cdFx0ZWwuc3R5bGUub3BhY2l0eSA9IHZhbHVlO1xyXG5cdH0gZWxzZSBpZiAoJ2ZpbHRlcicgaW4gZWwuc3R5bGUpIHtcclxuXHRcdF9zZXRPcGFjaXR5SUUoZWwsIHZhbHVlKTtcclxuXHR9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIF9zZXRPcGFjaXR5SUUoZWwsIHZhbHVlKSB7XHJcblx0dmFyIGZpbHRlciA9IGZhbHNlLFxyXG5cdCAgICBmaWx0ZXJOYW1lID0gJ0RYSW1hZ2VUcmFuc2Zvcm0uTWljcm9zb2Z0LkFscGhhJztcclxuXHJcblx0Ly8gZmlsdGVycyBjb2xsZWN0aW9uIHRocm93cyBhbiBlcnJvciBpZiB3ZSB0cnkgdG8gcmV0cmlldmUgYSBmaWx0ZXIgdGhhdCBkb2Vzbid0IGV4aXN0XHJcblx0dHJ5IHtcclxuXHRcdGZpbHRlciA9IGVsLmZpbHRlcnMuaXRlbShmaWx0ZXJOYW1lKTtcclxuXHR9IGNhdGNoIChlKSB7XHJcblx0XHQvLyBkb24ndCBzZXQgb3BhY2l0eSB0byAxIGlmIHdlIGhhdmVuJ3QgYWxyZWFkeSBzZXQgYW4gb3BhY2l0eSxcclxuXHRcdC8vIGl0IGlzbid0IG5lZWRlZCBhbmQgYnJlYWtzIHRyYW5zcGFyZW50IHBuZ3MuXHJcblx0XHRpZiAodmFsdWUgPT09IDEpIHsgcmV0dXJuOyB9XHJcblx0fVxyXG5cclxuXHR2YWx1ZSA9IE1hdGgucm91bmQodmFsdWUgKiAxMDApO1xyXG5cclxuXHRpZiAoZmlsdGVyKSB7XHJcblx0XHRmaWx0ZXIuRW5hYmxlZCA9ICh2YWx1ZSAhPT0gMTAwKTtcclxuXHRcdGZpbHRlci5PcGFjaXR5ID0gdmFsdWU7XHJcblx0fSBlbHNlIHtcclxuXHRcdGVsLnN0eWxlLmZpbHRlciArPSAnIHByb2dpZDonICsgZmlsdGVyTmFtZSArICcob3BhY2l0eT0nICsgdmFsdWUgKyAnKSc7XHJcblx0fVxyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gdGVzdFByb3AocHJvcHM6IFN0cmluZ1tdKTogU3RyaW5nfGZhbHNlXHJcbi8vIEdvZXMgdGhyb3VnaCB0aGUgYXJyYXkgb2Ygc3R5bGUgbmFtZXMgYW5kIHJldHVybnMgdGhlIGZpcnN0IG5hbWVcclxuLy8gdGhhdCBpcyBhIHZhbGlkIHN0eWxlIG5hbWUgZm9yIGFuIGVsZW1lbnQuIElmIG5vIHN1Y2ggbmFtZSBpcyBmb3VuZCxcclxuLy8gaXQgcmV0dXJucyBmYWxzZS4gVXNlZnVsIGZvciB2ZW5kb3ItcHJlZml4ZWQgc3R5bGVzIGxpa2UgYHRyYW5zZm9ybWAuXHJcbmZ1bmN0aW9uIHRlc3RQcm9wKHByb3BzKSB7XHJcblx0dmFyIHN0eWxlID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlO1xyXG5cclxuXHRmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRpZiAocHJvcHNbaV0gaW4gc3R5bGUpIHtcclxuXHRcdFx0cmV0dXJuIHByb3BzW2ldO1xyXG5cdFx0fVxyXG5cdH1cclxuXHRyZXR1cm4gZmFsc2U7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBzZXRUcmFuc2Zvcm0oZWw6IEhUTUxFbGVtZW50LCBvZmZzZXQ6IFBvaW50LCBzY2FsZT86IE51bWJlcilcclxuLy8gUmVzZXRzIHRoZSAzRCBDU1MgdHJhbnNmb3JtIG9mIGBlbGAgc28gaXQgaXMgdHJhbnNsYXRlZCBieSBgb2Zmc2V0YCBwaXhlbHNcclxuLy8gYW5kIG9wdGlvbmFsbHkgc2NhbGVkIGJ5IGBzY2FsZWAuIERvZXMgbm90IGhhdmUgYW4gZWZmZWN0IGlmIHRoZVxyXG4vLyBicm93c2VyIGRvZXNuJ3Qgc3VwcG9ydCAzRCBDU1MgdHJhbnNmb3Jtcy5cclxuZnVuY3Rpb24gc2V0VHJhbnNmb3JtKGVsLCBvZmZzZXQsIHNjYWxlKSB7XHJcblx0dmFyIHBvcyA9IG9mZnNldCB8fCBuZXcgUG9pbnQoMCwgMCk7XHJcblxyXG5cdGVsLnN0eWxlW1RSQU5TRk9STV0gPVxyXG5cdFx0KGllM2QgP1xyXG5cdFx0XHQndHJhbnNsYXRlKCcgKyBwb3MueCArICdweCwnICsgcG9zLnkgKyAncHgpJyA6XHJcblx0XHRcdCd0cmFuc2xhdGUzZCgnICsgcG9zLnggKyAncHgsJyArIHBvcy55ICsgJ3B4LDApJykgK1xyXG5cdFx0KHNjYWxlID8gJyBzY2FsZSgnICsgc2NhbGUgKyAnKScgOiAnJyk7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBzZXRQb3NpdGlvbihlbDogSFRNTEVsZW1lbnQsIHBvc2l0aW9uOiBQb2ludClcclxuLy8gU2V0cyB0aGUgcG9zaXRpb24gb2YgYGVsYCB0byBjb29yZGluYXRlcyBzcGVjaWZpZWQgYnkgYHBvc2l0aW9uYCxcclxuLy8gdXNpbmcgQ1NTIHRyYW5zbGF0ZSBvciB0b3AvbGVmdCBwb3NpdGlvbmluZyBkZXBlbmRpbmcgb24gdGhlIGJyb3dzZXJcclxuLy8gKHVzZWQgYnkgTGVhZmxldCBpbnRlcm5hbGx5IHRvIHBvc2l0aW9uIGl0cyBsYXllcnMpLlxyXG5mdW5jdGlvbiBzZXRQb3NpdGlvbihlbCwgcG9pbnQpIHtcclxuXHJcblx0Lyplc2xpbnQtZGlzYWJsZSAqL1xyXG5cdGVsLl9sZWFmbGV0X3BvcyA9IHBvaW50O1xyXG5cdC8qIGVzbGludC1lbmFibGUgKi9cclxuXHJcblx0aWYgKGFueTNkKSB7XHJcblx0XHRzZXRUcmFuc2Zvcm0oZWwsIHBvaW50KTtcclxuXHR9IGVsc2Uge1xyXG5cdFx0ZWwuc3R5bGUubGVmdCA9IHBvaW50LnggKyAncHgnO1xyXG5cdFx0ZWwuc3R5bGUudG9wID0gcG9pbnQueSArICdweCc7XHJcblx0fVxyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gZ2V0UG9zaXRpb24oZWw6IEhUTUxFbGVtZW50KTogUG9pbnRcclxuLy8gUmV0dXJucyB0aGUgY29vcmRpbmF0ZXMgb2YgYW4gZWxlbWVudCBwcmV2aW91c2x5IHBvc2l0aW9uZWQgd2l0aCBzZXRQb3NpdGlvbi5cclxuZnVuY3Rpb24gZ2V0UG9zaXRpb24oZWwpIHtcclxuXHQvLyB0aGlzIG1ldGhvZCBpcyBvbmx5IHVzZWQgZm9yIGVsZW1lbnRzIHByZXZpb3VzbHkgcG9zaXRpb25lZCB1c2luZyBzZXRQb3NpdGlvbixcclxuXHQvLyBzbyBpdCdzIHNhZmUgdG8gY2FjaGUgdGhlIHBvc2l0aW9uIGZvciBwZXJmb3JtYW5jZVxyXG5cclxuXHRyZXR1cm4gZWwuX2xlYWZsZXRfcG9zIHx8IG5ldyBQb2ludCgwLCAwKTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGRpc2FibGVUZXh0U2VsZWN0aW9uKClcclxuLy8gUHJldmVudHMgdGhlIHVzZXIgZnJvbSBnZW5lcmF0aW5nIGBzZWxlY3RzdGFydGAgRE9NIGV2ZW50cywgdXN1YWxseSBnZW5lcmF0ZWRcclxuLy8gd2hlbiB0aGUgdXNlciBkcmFncyB0aGUgbW91c2UgdGhyb3VnaCBhIHBhZ2Ugd2l0aCB0ZXh0LiBVc2VkIGludGVybmFsbHlcclxuLy8gYnkgTGVhZmxldCB0byBvdmVycmlkZSB0aGUgYmVoYXZpb3VyIG9mIGFueSBjbGljay1hbmQtZHJhZyBpbnRlcmFjdGlvbiBvblxyXG4vLyB0aGUgbWFwLiBBZmZlY3RzIGRyYWcgaW50ZXJhY3Rpb25zIG9uIHRoZSB3aG9sZSBkb2N1bWVudC5cclxuXHJcbi8vIEBmdW5jdGlvbiBlbmFibGVUZXh0U2VsZWN0aW9uKClcclxuLy8gQ2FuY2VscyB0aGUgZWZmZWN0cyBvZiBhIHByZXZpb3VzIFtgTC5Eb21VdGlsLmRpc2FibGVUZXh0U2VsZWN0aW9uYF0oI2RvbXV0aWwtZGlzYWJsZXRleHRzZWxlY3Rpb24pLlxyXG52YXIgZGlzYWJsZVRleHRTZWxlY3Rpb247XHJcbnZhciBlbmFibGVUZXh0U2VsZWN0aW9uO1xyXG52YXIgX3VzZXJTZWxlY3Q7XHJcbmlmICgnb25zZWxlY3RzdGFydCcgaW4gZG9jdW1lbnQpIHtcclxuXHRkaXNhYmxlVGV4dFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdG9uKHdpbmRvdywgJ3NlbGVjdHN0YXJ0JywgcHJldmVudERlZmF1bHQpO1xyXG5cdH07XHJcblx0ZW5hYmxlVGV4dFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdG9mZih3aW5kb3csICdzZWxlY3RzdGFydCcsIHByZXZlbnREZWZhdWx0KTtcclxuXHR9O1xyXG59IGVsc2Uge1xyXG5cdHZhciB1c2VyU2VsZWN0UHJvcGVydHkgPSB0ZXN0UHJvcChcclxuXHRcdFsndXNlclNlbGVjdCcsICdXZWJraXRVc2VyU2VsZWN0JywgJ09Vc2VyU2VsZWN0JywgJ01velVzZXJTZWxlY3QnLCAnbXNVc2VyU2VsZWN0J10pO1xyXG5cclxuXHRkaXNhYmxlVGV4dFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh1c2VyU2VsZWN0UHJvcGVydHkpIHtcclxuXHRcdFx0dmFyIHN0eWxlID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlO1xyXG5cdFx0XHRfdXNlclNlbGVjdCA9IHN0eWxlW3VzZXJTZWxlY3RQcm9wZXJ0eV07XHJcblx0XHRcdHN0eWxlW3VzZXJTZWxlY3RQcm9wZXJ0eV0gPSAnbm9uZSc7XHJcblx0XHR9XHJcblx0fTtcclxuXHRlbmFibGVUZXh0U2VsZWN0aW9uID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKHVzZXJTZWxlY3RQcm9wZXJ0eSkge1xyXG5cdFx0XHRkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGVbdXNlclNlbGVjdFByb3BlcnR5XSA9IF91c2VyU2VsZWN0O1xyXG5cdFx0XHRfdXNlclNlbGVjdCA9IHVuZGVmaW5lZDtcclxuXHRcdH1cclxuXHR9O1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gZGlzYWJsZUltYWdlRHJhZygpXHJcbi8vIEFzIFtgTC5Eb21VdGlsLmRpc2FibGVUZXh0U2VsZWN0aW9uYF0oI2RvbXV0aWwtZGlzYWJsZXRleHRzZWxlY3Rpb24pLCBidXRcclxuLy8gZm9yIGBkcmFnc3RhcnRgIERPTSBldmVudHMsIHVzdWFsbHkgZ2VuZXJhdGVkIHdoZW4gdGhlIHVzZXIgZHJhZ3MgYW4gaW1hZ2UuXHJcbmZ1bmN0aW9uIGRpc2FibGVJbWFnZURyYWcoKSB7XHJcblx0b24od2luZG93LCAnZHJhZ3N0YXJ0JywgcHJldmVudERlZmF1bHQpO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gZW5hYmxlSW1hZ2VEcmFnKClcclxuLy8gQ2FuY2VscyB0aGUgZWZmZWN0cyBvZiBhIHByZXZpb3VzIFtgTC5Eb21VdGlsLmRpc2FibGVJbWFnZURyYWdgXSgjZG9tdXRpbC1kaXNhYmxldGV4dHNlbGVjdGlvbikuXHJcbmZ1bmN0aW9uIGVuYWJsZUltYWdlRHJhZygpIHtcclxuXHRvZmYod2luZG93LCAnZHJhZ3N0YXJ0JywgcHJldmVudERlZmF1bHQpO1xyXG59XHJcblxyXG52YXIgX291dGxpbmVFbGVtZW50O1xudmFyIF9vdXRsaW5lU3R5bGU7XHJcbi8vIEBmdW5jdGlvbiBwcmV2ZW50T3V0bGluZShlbDogSFRNTEVsZW1lbnQpXHJcbi8vIE1ha2VzIHRoZSBbb3V0bGluZV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQ1NTL291dGxpbmUpXHJcbi8vIG9mIHRoZSBlbGVtZW50IGBlbGAgaW52aXNpYmxlLiBVc2VkIGludGVybmFsbHkgYnkgTGVhZmxldCB0byBwcmV2ZW50XHJcbi8vIGZvY3VzYWJsZSBlbGVtZW50cyBmcm9tIGRpc3BsYXlpbmcgYW4gb3V0bGluZSB3aGVuIHRoZSB1c2VyIHBlcmZvcm1zIGFcclxuLy8gZHJhZyBpbnRlcmFjdGlvbiBvbiB0aGVtLlxyXG5mdW5jdGlvbiBwcmV2ZW50T3V0bGluZShlbGVtZW50KSB7XHJcblx0d2hpbGUgKGVsZW1lbnQudGFiSW5kZXggPT09IC0xKSB7XHJcblx0XHRlbGVtZW50ID0gZWxlbWVudC5wYXJlbnROb2RlO1xyXG5cdH1cclxuXHRpZiAoIWVsZW1lbnQuc3R5bGUpIHsgcmV0dXJuOyB9XHJcblx0cmVzdG9yZU91dGxpbmUoKTtcclxuXHRfb3V0bGluZUVsZW1lbnQgPSBlbGVtZW50O1xyXG5cdF9vdXRsaW5lU3R5bGUgPSBlbGVtZW50LnN0eWxlLm91dGxpbmU7XHJcblx0ZWxlbWVudC5zdHlsZS5vdXRsaW5lID0gJ25vbmUnO1xyXG5cdG9uKHdpbmRvdywgJ2tleWRvd24nLCByZXN0b3JlT3V0bGluZSk7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiByZXN0b3JlT3V0bGluZSgpXHJcbi8vIENhbmNlbHMgdGhlIGVmZmVjdHMgb2YgYSBwcmV2aW91cyBbYEwuRG9tVXRpbC5wcmV2ZW50T3V0bGluZWBdKCkuXHJcbmZ1bmN0aW9uIHJlc3RvcmVPdXRsaW5lKCkge1xyXG5cdGlmICghX291dGxpbmVFbGVtZW50KSB7IHJldHVybjsgfVxyXG5cdF9vdXRsaW5lRWxlbWVudC5zdHlsZS5vdXRsaW5lID0gX291dGxpbmVTdHlsZTtcclxuXHRfb3V0bGluZUVsZW1lbnQgPSB1bmRlZmluZWQ7XHJcblx0X291dGxpbmVTdHlsZSA9IHVuZGVmaW5lZDtcclxuXHRvZmYod2luZG93LCAna2V5ZG93bicsIHJlc3RvcmVPdXRsaW5lKTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGdldFNpemVkUGFyZW50Tm9kZShlbDogSFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudFxyXG4vLyBGaW5kcyB0aGUgY2xvc2VzdCBwYXJlbnQgbm9kZSB3aGljaCBzaXplICh3aWR0aCBhbmQgaGVpZ2h0KSBpcyBub3QgbnVsbC5cclxuZnVuY3Rpb24gZ2V0U2l6ZWRQYXJlbnROb2RlKGVsZW1lbnQpIHtcclxuXHRkbyB7XHJcblx0XHRlbGVtZW50ID0gZWxlbWVudC5wYXJlbnROb2RlO1xyXG5cdH0gd2hpbGUgKCghZWxlbWVudC5vZmZzZXRXaWR0aCB8fCAhZWxlbWVudC5vZmZzZXRIZWlnaHQpICYmIGVsZW1lbnQgIT09IGRvY3VtZW50LmJvZHkpO1xyXG5cdHJldHVybiBlbGVtZW50O1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gZ2V0U2NhbGUoZWw6IEhUTUxFbGVtZW50KTogT2JqZWN0XHJcbi8vIENvbXB1dGVzIHRoZSBDU1Mgc2NhbGUgY3VycmVudGx5IGFwcGxpZWQgb24gdGhlIGVsZW1lbnQuXHJcbi8vIFJldHVybnMgYW4gb2JqZWN0IHdpdGggYHhgIGFuZCBgeWAgbWVtYmVycyBhcyBob3Jpem9udGFsIGFuZCB2ZXJ0aWNhbCBzY2FsZXMgcmVzcGVjdGl2ZWx5LFxyXG4vLyBhbmQgYGJvdW5kaW5nQ2xpZW50UmVjdGAgYXMgdGhlIHJlc3VsdCBvZiBbYGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpYF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0VsZW1lbnQvZ2V0Qm91bmRpbmdDbGllbnRSZWN0KS5cclxuZnVuY3Rpb24gZ2V0U2NhbGUoZWxlbWVudCkge1xyXG5cdHZhciByZWN0ID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsgLy8gUmVhZC1vbmx5IGluIG9sZCBicm93c2Vycy5cclxuXHJcblx0cmV0dXJuIHtcclxuXHRcdHg6IHJlY3Qud2lkdGggLyBlbGVtZW50Lm9mZnNldFdpZHRoIHx8IDEsXHJcblx0XHR5OiByZWN0LmhlaWdodCAvIGVsZW1lbnQub2Zmc2V0SGVpZ2h0IHx8IDEsXHJcblx0XHRib3VuZGluZ0NsaWVudFJlY3Q6IHJlY3RcclxuXHR9O1xyXG59XHJcblxuXG52YXIgRG9tVXRpbCA9IChPYmplY3QuZnJlZXplIHx8IE9iamVjdCkoe1xuXHRUUkFOU0ZPUk06IFRSQU5TRk9STSxcblx0VFJBTlNJVElPTjogVFJBTlNJVElPTixcblx0VFJBTlNJVElPTl9FTkQ6IFRSQU5TSVRJT05fRU5ELFxuXHRnZXQ6IGdldCxcblx0Z2V0U3R5bGU6IGdldFN0eWxlLFxuXHRjcmVhdGU6IGNyZWF0ZSQxLFxuXHRyZW1vdmU6IHJlbW92ZSxcblx0ZW1wdHk6IGVtcHR5LFxuXHR0b0Zyb250OiB0b0Zyb250LFxuXHR0b0JhY2s6IHRvQmFjayxcblx0aGFzQ2xhc3M6IGhhc0NsYXNzLFxuXHRhZGRDbGFzczogYWRkQ2xhc3MsXG5cdHJlbW92ZUNsYXNzOiByZW1vdmVDbGFzcyxcblx0c2V0Q2xhc3M6IHNldENsYXNzLFxuXHRnZXRDbGFzczogZ2V0Q2xhc3MsXG5cdHNldE9wYWNpdHk6IHNldE9wYWNpdHksXG5cdHRlc3RQcm9wOiB0ZXN0UHJvcCxcblx0c2V0VHJhbnNmb3JtOiBzZXRUcmFuc2Zvcm0sXG5cdHNldFBvc2l0aW9uOiBzZXRQb3NpdGlvbixcblx0Z2V0UG9zaXRpb246IGdldFBvc2l0aW9uLFxuXHRkaXNhYmxlVGV4dFNlbGVjdGlvbjogZGlzYWJsZVRleHRTZWxlY3Rpb24sXG5cdGVuYWJsZVRleHRTZWxlY3Rpb246IGVuYWJsZVRleHRTZWxlY3Rpb24sXG5cdGRpc2FibGVJbWFnZURyYWc6IGRpc2FibGVJbWFnZURyYWcsXG5cdGVuYWJsZUltYWdlRHJhZzogZW5hYmxlSW1hZ2VEcmFnLFxuXHRwcmV2ZW50T3V0bGluZTogcHJldmVudE91dGxpbmUsXG5cdHJlc3RvcmVPdXRsaW5lOiByZXN0b3JlT3V0bGluZSxcblx0Z2V0U2l6ZWRQYXJlbnROb2RlOiBnZXRTaXplZFBhcmVudE5vZGUsXG5cdGdldFNjYWxlOiBnZXRTY2FsZVxufSk7XG5cbi8qXHJcbiAqIEBuYW1lc3BhY2UgRG9tRXZlbnRcclxuICogVXRpbGl0eSBmdW5jdGlvbnMgdG8gd29yayB3aXRoIHRoZSBbRE9NIGV2ZW50c10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0V2ZW50KSwgdXNlZCBieSBMZWFmbGV0IGludGVybmFsbHkuXHJcbiAqL1xyXG5cclxuLy8gSW5zcGlyZWQgYnkgSm9obiBSZXNpZywgRGVhbiBFZHdhcmRzIGFuZCBZVUkgYWRkRXZlbnQgaW1wbGVtZW50YXRpb25zLlxyXG5cclxuLy8gQGZ1bmN0aW9uIG9uKGVsOiBIVE1MRWxlbWVudCwgdHlwZXM6IFN0cmluZywgZm46IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG4vLyBBZGRzIGEgbGlzdGVuZXIgZnVuY3Rpb24gKGBmbmApIHRvIGEgcGFydGljdWxhciBET00gZXZlbnQgdHlwZSBvZiB0aGVcclxuLy8gZWxlbWVudCBgZWxgLiBZb3UgY2FuIG9wdGlvbmFsbHkgc3BlY2lmeSB0aGUgY29udGV4dCBvZiB0aGUgbGlzdGVuZXJcclxuLy8gKG9iamVjdCB0aGUgYHRoaXNgIGtleXdvcmQgd2lsbCBwb2ludCB0bykuIFlvdSBjYW4gYWxzbyBwYXNzIHNldmVyYWxcclxuLy8gc3BhY2Utc2VwYXJhdGVkIHR5cGVzIChlLmcuIGAnY2xpY2sgZGJsY2xpY2snYCkuXHJcblxyXG4vLyBAYWx0ZXJuYXRpdmVcclxuLy8gQGZ1bmN0aW9uIG9uKGVsOiBIVE1MRWxlbWVudCwgZXZlbnRNYXA6IE9iamVjdCwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuLy8gQWRkcyBhIHNldCBvZiB0eXBlL2xpc3RlbmVyIHBhaXJzLCBlLmcuIGB7Y2xpY2s6IG9uQ2xpY2ssIG1vdXNlbW92ZTogb25Nb3VzZU1vdmV9YFxyXG5mdW5jdGlvbiBvbihvYmosIHR5cGVzLCBmbiwgY29udGV4dCkge1xyXG5cclxuXHRpZiAodHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG5cdFx0Zm9yICh2YXIgdHlwZSBpbiB0eXBlcykge1xyXG5cdFx0XHRhZGRPbmUob2JqLCB0eXBlLCB0eXBlc1t0eXBlXSwgZm4pO1xyXG5cdFx0fVxyXG5cdH0gZWxzZSB7XHJcblx0XHR0eXBlcyA9IHNwbGl0V29yZHModHlwZXMpO1xyXG5cclxuXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSB0eXBlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0XHRhZGRPbmUob2JqLCB0eXBlc1tpXSwgZm4sIGNvbnRleHQpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cmV0dXJuIHRoaXM7XHJcbn1cclxuXHJcbnZhciBldmVudHNLZXkgPSAnX2xlYWZsZXRfZXZlbnRzJztcclxuXHJcbi8vIEBmdW5jdGlvbiBvZmYoZWw6IEhUTUxFbGVtZW50LCB0eXBlczogU3RyaW5nLCBmbjogRnVuY3Rpb24sIGNvbnRleHQ/OiBPYmplY3QpOiB0aGlzXHJcbi8vIFJlbW92ZXMgYSBwcmV2aW91c2x5IGFkZGVkIGxpc3RlbmVyIGZ1bmN0aW9uLlxyXG4vLyBOb3RlIHRoYXQgaWYgeW91IHBhc3NlZCBhIGN1c3RvbSBjb250ZXh0IHRvIG9uLCB5b3UgbXVzdCBwYXNzIHRoZSBzYW1lXHJcbi8vIGNvbnRleHQgdG8gYG9mZmAgaW4gb3JkZXIgdG8gcmVtb3ZlIHRoZSBsaXN0ZW5lci5cclxuXHJcbi8vIEBhbHRlcm5hdGl2ZVxyXG4vLyBAZnVuY3Rpb24gb2ZmKGVsOiBIVE1MRWxlbWVudCwgZXZlbnRNYXA6IE9iamVjdCwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuLy8gUmVtb3ZlcyBhIHNldCBvZiB0eXBlL2xpc3RlbmVyIHBhaXJzLCBlLmcuIGB7Y2xpY2s6IG9uQ2xpY2ssIG1vdXNlbW92ZTogb25Nb3VzZU1vdmV9YFxyXG5mdW5jdGlvbiBvZmYob2JqLCB0eXBlcywgZm4sIGNvbnRleHQpIHtcclxuXHJcblx0aWYgKHR5cGVvZiB0eXBlcyA9PT0gJ29iamVjdCcpIHtcclxuXHRcdGZvciAodmFyIHR5cGUgaW4gdHlwZXMpIHtcclxuXHRcdFx0cmVtb3ZlT25lKG9iaiwgdHlwZSwgdHlwZXNbdHlwZV0sIGZuKTtcclxuXHRcdH1cclxuXHR9IGVsc2UgaWYgKHR5cGVzKSB7XHJcblx0XHR0eXBlcyA9IHNwbGl0V29yZHModHlwZXMpO1xyXG5cclxuXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSB0eXBlcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0XHRyZW1vdmVPbmUob2JqLCB0eXBlc1tpXSwgZm4sIGNvbnRleHQpO1xyXG5cdFx0fVxyXG5cdH0gZWxzZSB7XHJcblx0XHRmb3IgKHZhciBqIGluIG9ialtldmVudHNLZXldKSB7XHJcblx0XHRcdHJlbW92ZU9uZShvYmosIGosIG9ialtldmVudHNLZXldW2pdKTtcclxuXHRcdH1cclxuXHRcdGRlbGV0ZSBvYmpbZXZlbnRzS2V5XTtcclxuXHR9XHJcblxyXG5cdHJldHVybiB0aGlzO1xyXG59XHJcblxyXG5mdW5jdGlvbiBhZGRPbmUob2JqLCB0eXBlLCBmbiwgY29udGV4dCkge1xyXG5cdHZhciBpZCA9IHR5cGUgKyBzdGFtcChmbikgKyAoY29udGV4dCA/ICdfJyArIHN0YW1wKGNvbnRleHQpIDogJycpO1xyXG5cclxuXHRpZiAob2JqW2V2ZW50c0tleV0gJiYgb2JqW2V2ZW50c0tleV1baWRdKSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG5cdHZhciBoYW5kbGVyID0gZnVuY3Rpb24gKGUpIHtcclxuXHRcdHJldHVybiBmbi5jYWxsKGNvbnRleHQgfHwgb2JqLCBlIHx8IHdpbmRvdy5ldmVudCk7XHJcblx0fTtcclxuXHJcblx0dmFyIG9yaWdpbmFsSGFuZGxlciA9IGhhbmRsZXI7XHJcblxyXG5cdGlmIChwb2ludGVyICYmIHR5cGUuaW5kZXhPZigndG91Y2gnKSA9PT0gMCkge1xyXG5cdFx0Ly8gTmVlZHMgRG9tRXZlbnQuUG9pbnRlci5qc1xyXG5cdFx0YWRkUG9pbnRlckxpc3RlbmVyKG9iaiwgdHlwZSwgaGFuZGxlciwgaWQpO1xyXG5cclxuXHR9IGVsc2UgaWYgKHRvdWNoICYmICh0eXBlID09PSAnZGJsY2xpY2snKSAmJiBhZGREb3VibGVUYXBMaXN0ZW5lciAmJlxyXG5cdCAgICAgICAgICAgIShwb2ludGVyICYmIGNocm9tZSkpIHtcclxuXHRcdC8vIENocm9tZSA+NTUgZG9lcyBub3QgbmVlZCB0aGUgc3ludGhldGljIGRibGNsaWNrcyBmcm9tIGFkZERvdWJsZVRhcExpc3RlbmVyXHJcblx0XHQvLyBTZWUgIzUxODBcclxuXHRcdGFkZERvdWJsZVRhcExpc3RlbmVyKG9iaiwgaGFuZGxlciwgaWQpO1xyXG5cclxuXHR9IGVsc2UgaWYgKCdhZGRFdmVudExpc3RlbmVyJyBpbiBvYmopIHtcclxuXHJcblx0XHRpZiAodHlwZSA9PT0gJ21vdXNld2hlZWwnKSB7XHJcblx0XHRcdG9iai5hZGRFdmVudExpc3RlbmVyKCdvbndoZWVsJyBpbiBvYmogPyAnd2hlZWwnIDogJ21vdXNld2hlZWwnLCBoYW5kbGVyLCBmYWxzZSk7XHJcblxyXG5cdFx0fSBlbHNlIGlmICgodHlwZSA9PT0gJ21vdXNlZW50ZXInKSB8fCAodHlwZSA9PT0gJ21vdXNlbGVhdmUnKSkge1xyXG5cdFx0XHRoYW5kbGVyID0gZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0XHRlID0gZSB8fCB3aW5kb3cuZXZlbnQ7XHJcblx0XHRcdFx0aWYgKGlzRXh0ZXJuYWxUYXJnZXQob2JqLCBlKSkge1xyXG5cdFx0XHRcdFx0b3JpZ2luYWxIYW5kbGVyKGUpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fTtcclxuXHRcdFx0b2JqLmFkZEV2ZW50TGlzdGVuZXIodHlwZSA9PT0gJ21vdXNlZW50ZXInID8gJ21vdXNlb3ZlcicgOiAnbW91c2VvdXQnLCBoYW5kbGVyLCBmYWxzZSk7XHJcblxyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0aWYgKHR5cGUgPT09ICdjbGljaycgJiYgYW5kcm9pZCkge1xyXG5cdFx0XHRcdGhhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdFx0ZmlsdGVyQ2xpY2soZSwgb3JpZ2luYWxIYW5kbGVyKTtcclxuXHRcdFx0XHR9O1xyXG5cdFx0XHR9XHJcblx0XHRcdG9iai5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGhhbmRsZXIsIGZhbHNlKTtcclxuXHRcdH1cclxuXHJcblx0fSBlbHNlIGlmICgnYXR0YWNoRXZlbnQnIGluIG9iaikge1xyXG5cdFx0b2JqLmF0dGFjaEV2ZW50KCdvbicgKyB0eXBlLCBoYW5kbGVyKTtcclxuXHR9XHJcblxyXG5cdG9ialtldmVudHNLZXldID0gb2JqW2V2ZW50c0tleV0gfHwge307XHJcblx0b2JqW2V2ZW50c0tleV1baWRdID0gaGFuZGxlcjtcclxufVxyXG5cclxuZnVuY3Rpb24gcmVtb3ZlT25lKG9iaiwgdHlwZSwgZm4sIGNvbnRleHQpIHtcclxuXHJcblx0dmFyIGlkID0gdHlwZSArIHN0YW1wKGZuKSArIChjb250ZXh0ID8gJ18nICsgc3RhbXAoY29udGV4dCkgOiAnJyksXHJcblx0ICAgIGhhbmRsZXIgPSBvYmpbZXZlbnRzS2V5XSAmJiBvYmpbZXZlbnRzS2V5XVtpZF07XHJcblxyXG5cdGlmICghaGFuZGxlcikgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRpZiAocG9pbnRlciAmJiB0eXBlLmluZGV4T2YoJ3RvdWNoJykgPT09IDApIHtcclxuXHRcdHJlbW92ZVBvaW50ZXJMaXN0ZW5lcihvYmosIHR5cGUsIGlkKTtcclxuXHJcblx0fSBlbHNlIGlmICh0b3VjaCAmJiAodHlwZSA9PT0gJ2RibGNsaWNrJykgJiYgcmVtb3ZlRG91YmxlVGFwTGlzdGVuZXIgJiZcclxuXHQgICAgICAgICAgICEocG9pbnRlciAmJiBjaHJvbWUpKSB7XHJcblx0XHRyZW1vdmVEb3VibGVUYXBMaXN0ZW5lcihvYmosIGlkKTtcclxuXHJcblx0fSBlbHNlIGlmICgncmVtb3ZlRXZlbnRMaXN0ZW5lcicgaW4gb2JqKSB7XHJcblxyXG5cdFx0aWYgKHR5cGUgPT09ICdtb3VzZXdoZWVsJykge1xyXG5cdFx0XHRvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcignb253aGVlbCcgaW4gb2JqID8gJ3doZWVsJyA6ICdtb3VzZXdoZWVsJywgaGFuZGxlciwgZmFsc2UpO1xyXG5cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdG9iai5yZW1vdmVFdmVudExpc3RlbmVyKFxyXG5cdFx0XHRcdHR5cGUgPT09ICdtb3VzZWVudGVyJyA/ICdtb3VzZW92ZXInIDpcclxuXHRcdFx0XHR0eXBlID09PSAnbW91c2VsZWF2ZScgPyAnbW91c2VvdXQnIDogdHlwZSwgaGFuZGxlciwgZmFsc2UpO1xyXG5cdFx0fVxyXG5cclxuXHR9IGVsc2UgaWYgKCdkZXRhY2hFdmVudCcgaW4gb2JqKSB7XHJcblx0XHRvYmouZGV0YWNoRXZlbnQoJ29uJyArIHR5cGUsIGhhbmRsZXIpO1xyXG5cdH1cclxuXHJcblx0b2JqW2V2ZW50c0tleV1baWRdID0gbnVsbDtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHN0b3BQcm9wYWdhdGlvbihldjogRE9NRXZlbnQpOiB0aGlzXHJcbi8vIFN0b3AgdGhlIGdpdmVuIGV2ZW50IGZyb20gcHJvcGFnYXRpb24gdG8gcGFyZW50IGVsZW1lbnRzLiBVc2VkIGluc2lkZSB0aGUgbGlzdGVuZXIgZnVuY3Rpb25zOlxyXG4vLyBgYGBqc1xyXG4vLyBMLkRvbUV2ZW50Lm9uKGRpdiwgJ2NsaWNrJywgZnVuY3Rpb24gKGV2KSB7XHJcbi8vIFx0TC5Eb21FdmVudC5zdG9wUHJvcGFnYXRpb24oZXYpO1xyXG4vLyB9KTtcclxuLy8gYGBgXHJcbmZ1bmN0aW9uIHN0b3BQcm9wYWdhdGlvbihlKSB7XHJcblxyXG5cdGlmIChlLnN0b3BQcm9wYWdhdGlvbikge1xyXG5cdFx0ZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuXHR9IGVsc2UgaWYgKGUub3JpZ2luYWxFdmVudCkgeyAgLy8gSW4gY2FzZSBvZiBMZWFmbGV0IGV2ZW50LlxyXG5cdFx0ZS5vcmlnaW5hbEV2ZW50Ll9zdG9wcGVkID0gdHJ1ZTtcclxuXHR9IGVsc2Uge1xyXG5cdFx0ZS5jYW5jZWxCdWJibGUgPSB0cnVlO1xyXG5cdH1cclxuXHRza2lwcGVkKGUpO1xyXG5cclxuXHRyZXR1cm4gdGhpcztcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGRpc2FibGVTY3JvbGxQcm9wYWdhdGlvbihlbDogSFRNTEVsZW1lbnQpOiB0aGlzXHJcbi8vIEFkZHMgYHN0b3BQcm9wYWdhdGlvbmAgdG8gdGhlIGVsZW1lbnQncyBgJ21vdXNld2hlZWwnYCBldmVudHMgKHBsdXMgYnJvd3NlciB2YXJpYW50cykuXHJcbmZ1bmN0aW9uIGRpc2FibGVTY3JvbGxQcm9wYWdhdGlvbihlbCkge1xyXG5cdGFkZE9uZShlbCwgJ21vdXNld2hlZWwnLCBzdG9wUHJvcGFnYXRpb24pO1xyXG5cdHJldHVybiB0aGlzO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24oZWw6IEhUTUxFbGVtZW50KTogdGhpc1xyXG4vLyBBZGRzIGBzdG9wUHJvcGFnYXRpb25gIHRvIHRoZSBlbGVtZW50J3MgYCdjbGljaydgLCBgJ2RvdWJsZWNsaWNrJ2AsXHJcbi8vIGAnbW91c2Vkb3duJ2AgYW5kIGAndG91Y2hzdGFydCdgIGV2ZW50cyAocGx1cyBicm93c2VyIHZhcmlhbnRzKS5cclxuZnVuY3Rpb24gZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24oZWwpIHtcclxuXHRvbihlbCwgJ21vdXNlZG93biB0b3VjaHN0YXJ0IGRibGNsaWNrJywgc3RvcFByb3BhZ2F0aW9uKTtcclxuXHRhZGRPbmUoZWwsICdjbGljaycsIGZha2VTdG9wKTtcclxuXHRyZXR1cm4gdGhpcztcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHByZXZlbnREZWZhdWx0KGV2OiBET01FdmVudCk6IHRoaXNcclxuLy8gUHJldmVudHMgdGhlIGRlZmF1bHQgYWN0aW9uIG9mIHRoZSBET00gRXZlbnQgYGV2YCBmcm9tIGhhcHBlbmluZyAoc3VjaCBhc1xyXG4vLyBmb2xsb3dpbmcgYSBsaW5rIGluIHRoZSBocmVmIG9mIHRoZSBhIGVsZW1lbnQsIG9yIGRvaW5nIGEgUE9TVCByZXF1ZXN0XHJcbi8vIHdpdGggcGFnZSByZWxvYWQgd2hlbiBhIGA8Zm9ybT5gIGlzIHN1Ym1pdHRlZCkuXHJcbi8vIFVzZSBpdCBpbnNpZGUgbGlzdGVuZXIgZnVuY3Rpb25zLlxyXG5mdW5jdGlvbiBwcmV2ZW50RGVmYXVsdChlKSB7XHJcblx0aWYgKGUucHJldmVudERlZmF1bHQpIHtcclxuXHRcdGUucHJldmVudERlZmF1bHQoKTtcclxuXHR9IGVsc2Uge1xyXG5cdFx0ZS5yZXR1cm5WYWx1ZSA9IGZhbHNlO1xyXG5cdH1cclxuXHRyZXR1cm4gdGhpcztcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHN0b3AoZXY6IERPTUV2ZW50KTogdGhpc1xyXG4vLyBEb2VzIGBzdG9wUHJvcGFnYXRpb25gIGFuZCBgcHJldmVudERlZmF1bHRgIGF0IHRoZSBzYW1lIHRpbWUuXHJcbmZ1bmN0aW9uIHN0b3AoZSkge1xyXG5cdHByZXZlbnREZWZhdWx0KGUpO1xyXG5cdHN0b3BQcm9wYWdhdGlvbihlKTtcclxuXHRyZXR1cm4gdGhpcztcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGdldE1vdXNlUG9zaXRpb24oZXY6IERPTUV2ZW50LCBjb250YWluZXI/OiBIVE1MRWxlbWVudCk6IFBvaW50XHJcbi8vIEdldHMgbm9ybWFsaXplZCBtb3VzZSBwb3NpdGlvbiBmcm9tIGEgRE9NIGV2ZW50IHJlbGF0aXZlIHRvIHRoZVxyXG4vLyBgY29udGFpbmVyYCAoYm9yZGVyIGV4Y2x1ZGVkKSBvciB0byB0aGUgd2hvbGUgcGFnZSBpZiBub3Qgc3BlY2lmaWVkLlxyXG5mdW5jdGlvbiBnZXRNb3VzZVBvc2l0aW9uKGUsIGNvbnRhaW5lcikge1xyXG5cdGlmICghY29udGFpbmVyKSB7XHJcblx0XHRyZXR1cm4gbmV3IFBvaW50KGUuY2xpZW50WCwgZS5jbGllbnRZKTtcclxuXHR9XHJcblxyXG5cdHZhciBzY2FsZSA9IGdldFNjYWxlKGNvbnRhaW5lciksXHJcblx0ICAgIG9mZnNldCA9IHNjYWxlLmJvdW5kaW5nQ2xpZW50UmVjdDsgLy8gbGVmdCBhbmQgdG9wICB2YWx1ZXMgYXJlIGluIHBhZ2Ugc2NhbGUgKGxpa2UgdGhlIGV2ZW50IGNsaWVudFgvWSlcclxuXHJcblx0cmV0dXJuIG5ldyBQb2ludChcclxuXHRcdC8vIG9mZnNldC5sZWZ0L3RvcCB2YWx1ZXMgYXJlIGluIHBhZ2Ugc2NhbGUgKGxpa2UgY2xpZW50WC9ZKSxcclxuXHRcdC8vIHdoZXJlYXMgY2xpZW50TGVmdC9Ub3AgKGJvcmRlciB3aWR0aCkgdmFsdWVzIGFyZSB0aGUgb3JpZ2luYWwgdmFsdWVzIChiZWZvcmUgQ1NTIHNjYWxlIGFwcGxpZXMpLlxyXG5cdFx0KGUuY2xpZW50WCAtIG9mZnNldC5sZWZ0KSAvIHNjYWxlLnggLSBjb250YWluZXIuY2xpZW50TGVmdCxcclxuXHRcdChlLmNsaWVudFkgLSBvZmZzZXQudG9wKSAvIHNjYWxlLnkgLSBjb250YWluZXIuY2xpZW50VG9wXHJcblx0KTtcclxufVxyXG5cclxuLy8gQ2hyb21lIG9uIFdpbiBzY3JvbGxzIGRvdWJsZSB0aGUgcGl4ZWxzIGFzIGluIG90aGVyIHBsYXRmb3JtcyAoc2VlICM0NTM4KSxcclxuLy8gYW5kIEZpcmVmb3ggc2Nyb2xscyBkZXZpY2UgcGl4ZWxzLCBub3QgQ1NTIHBpeGVsc1xyXG52YXIgd2hlZWxQeEZhY3RvciA9XHJcblx0KHdpbiAmJiBjaHJvbWUpID8gMiAqIHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvIDpcclxuXHRnZWNrbyA/IHdpbmRvdy5kZXZpY2VQaXhlbFJhdGlvIDogMTtcclxuXHJcbi8vIEBmdW5jdGlvbiBnZXRXaGVlbERlbHRhKGV2OiBET01FdmVudCk6IE51bWJlclxyXG4vLyBHZXRzIG5vcm1hbGl6ZWQgd2hlZWwgZGVsdGEgZnJvbSBhIG1vdXNld2hlZWwgRE9NIGV2ZW50LCBpbiB2ZXJ0aWNhbFxyXG4vLyBwaXhlbHMgc2Nyb2xsZWQgKG5lZ2F0aXZlIGlmIHNjcm9sbGluZyBkb3duKS5cclxuLy8gRXZlbnRzIGZyb20gcG9pbnRpbmcgZGV2aWNlcyB3aXRob3V0IHByZWNpc2Ugc2Nyb2xsaW5nIGFyZSBtYXBwZWQgdG9cclxuLy8gYSBiZXN0IGd1ZXNzIG9mIDYwIHBpeGVscy5cclxuZnVuY3Rpb24gZ2V0V2hlZWxEZWx0YShlKSB7XHJcblx0cmV0dXJuIChlZGdlKSA/IGUud2hlZWxEZWx0YVkgLyAyIDogLy8gRG9uJ3QgdHJ1c3Qgd2luZG93LWdlb21ldHJ5LWJhc2VkIGRlbHRhXHJcblx0ICAgICAgIChlLmRlbHRhWSAmJiBlLmRlbHRhTW9kZSA9PT0gMCkgPyAtZS5kZWx0YVkgLyB3aGVlbFB4RmFjdG9yIDogLy8gUGl4ZWxzXHJcblx0ICAgICAgIChlLmRlbHRhWSAmJiBlLmRlbHRhTW9kZSA9PT0gMSkgPyAtZS5kZWx0YVkgKiAyMCA6IC8vIExpbmVzXHJcblx0ICAgICAgIChlLmRlbHRhWSAmJiBlLmRlbHRhTW9kZSA9PT0gMikgPyAtZS5kZWx0YVkgKiA2MCA6IC8vIFBhZ2VzXHJcblx0ICAgICAgIChlLmRlbHRhWCB8fCBlLmRlbHRhWikgPyAwIDpcdC8vIFNraXAgaG9yaXpvbnRhbC9kZXB0aCB3aGVlbCBldmVudHNcclxuXHQgICAgICAgZS53aGVlbERlbHRhID8gKGUud2hlZWxEZWx0YVkgfHwgZS53aGVlbERlbHRhKSAvIDIgOiAvLyBMZWdhY3kgSUUgcGl4ZWxzXHJcblx0ICAgICAgIChlLmRldGFpbCAmJiBNYXRoLmFicyhlLmRldGFpbCkgPCAzMjc2NSkgPyAtZS5kZXRhaWwgKiAyMCA6IC8vIExlZ2FjeSBNb3ogbGluZXNcclxuXHQgICAgICAgZS5kZXRhaWwgPyBlLmRldGFpbCAvIC0zMjc2NSAqIDYwIDogLy8gTGVnYWN5IE1veiBwYWdlc1xyXG5cdCAgICAgICAwO1xyXG59XHJcblxyXG52YXIgc2tpcEV2ZW50cyA9IHt9O1xyXG5cclxuZnVuY3Rpb24gZmFrZVN0b3AoZSkge1xyXG5cdC8vIGZha2VzIHN0b3BQcm9wYWdhdGlvbiBieSBzZXR0aW5nIGEgc3BlY2lhbCBldmVudCBmbGFnLCBjaGVja2VkL3Jlc2V0IHdpdGggc2tpcHBlZChlKVxyXG5cdHNraXBFdmVudHNbZS50eXBlXSA9IHRydWU7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHNraXBwZWQoZSkge1xyXG5cdHZhciBldmVudHMgPSBza2lwRXZlbnRzW2UudHlwZV07XHJcblx0Ly8gcmVzZXQgd2hlbiBjaGVja2luZywgYXMgaXQncyBvbmx5IHVzZWQgaW4gbWFwIGNvbnRhaW5lciBhbmQgcHJvcGFnYXRlcyBvdXRzaWRlIG9mIHRoZSBtYXBcclxuXHRza2lwRXZlbnRzW2UudHlwZV0gPSBmYWxzZTtcclxuXHRyZXR1cm4gZXZlbnRzO1xyXG59XHJcblxyXG4vLyBjaGVjayBpZiBlbGVtZW50IHJlYWxseSBsZWZ0L2VudGVyZWQgdGhlIGV2ZW50IHRhcmdldCAoZm9yIG1vdXNlZW50ZXIvbW91c2VsZWF2ZSlcclxuZnVuY3Rpb24gaXNFeHRlcm5hbFRhcmdldChlbCwgZSkge1xyXG5cclxuXHR2YXIgcmVsYXRlZCA9IGUucmVsYXRlZFRhcmdldDtcclxuXHJcblx0aWYgKCFyZWxhdGVkKSB7IHJldHVybiB0cnVlOyB9XHJcblxyXG5cdHRyeSB7XHJcblx0XHR3aGlsZSAocmVsYXRlZCAmJiAocmVsYXRlZCAhPT0gZWwpKSB7XHJcblx0XHRcdHJlbGF0ZWQgPSByZWxhdGVkLnBhcmVudE5vZGU7XHJcblx0XHR9XHJcblx0fSBjYXRjaCAoZXJyKSB7XHJcblx0XHRyZXR1cm4gZmFsc2U7XHJcblx0fVxyXG5cdHJldHVybiAocmVsYXRlZCAhPT0gZWwpO1xyXG59XHJcblxyXG52YXIgbGFzdENsaWNrO1xyXG5cclxuLy8gdGhpcyBpcyBhIGhvcnJpYmxlIHdvcmthcm91bmQgZm9yIGEgYnVnIGluIEFuZHJvaWQgd2hlcmUgYSBzaW5nbGUgdG91Y2ggdHJpZ2dlcnMgdHdvIGNsaWNrIGV2ZW50c1xyXG5mdW5jdGlvbiBmaWx0ZXJDbGljayhlLCBoYW5kbGVyKSB7XHJcblx0dmFyIHRpbWVTdGFtcCA9IChlLnRpbWVTdGFtcCB8fCAoZS5vcmlnaW5hbEV2ZW50ICYmIGUub3JpZ2luYWxFdmVudC50aW1lU3RhbXApKSxcclxuXHQgICAgZWxhcHNlZCA9IGxhc3RDbGljayAmJiAodGltZVN0YW1wIC0gbGFzdENsaWNrKTtcclxuXHJcblx0Ly8gYXJlIHRoZXkgY2xvc2VyIHRvZ2V0aGVyIHRoYW4gNTAwbXMgeWV0IG1vcmUgdGhhbiAxMDBtcz9cclxuXHQvLyBBbmRyb2lkIHR5cGljYWxseSB0cmlnZ2VycyB0aGVtIH4zMDBtcyBhcGFydCB3aGlsZSBtdWx0aXBsZSBsaXN0ZW5lcnNcclxuXHQvLyBvbiB0aGUgc2FtZSBldmVudCBzaG91bGQgYmUgdHJpZ2dlcmVkIGZhciBmYXN0ZXI7XHJcblx0Ly8gb3IgY2hlY2sgaWYgY2xpY2sgaXMgc2ltdWxhdGVkIG9uIHRoZSBlbGVtZW50LCBhbmQgaWYgaXQgaXMsIHJlamVjdCBhbnkgbm9uLXNpbXVsYXRlZCBldmVudHNcclxuXHJcblx0aWYgKChlbGFwc2VkICYmIGVsYXBzZWQgPiAxMDAgJiYgZWxhcHNlZCA8IDUwMCkgfHwgKGUudGFyZ2V0Ll9zaW11bGF0ZWRDbGljayAmJiAhZS5fc2ltdWxhdGVkKSkge1xyXG5cdFx0c3RvcChlKTtcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblx0bGFzdENsaWNrID0gdGltZVN0YW1wO1xyXG5cclxuXHRoYW5kbGVyKGUpO1xyXG59XHJcblxyXG5cclxuXG5cbnZhciBEb21FdmVudCA9IChPYmplY3QuZnJlZXplIHx8IE9iamVjdCkoe1xuXHRvbjogb24sXG5cdG9mZjogb2ZmLFxuXHRzdG9wUHJvcGFnYXRpb246IHN0b3BQcm9wYWdhdGlvbixcblx0ZGlzYWJsZVNjcm9sbFByb3BhZ2F0aW9uOiBkaXNhYmxlU2Nyb2xsUHJvcGFnYXRpb24sXG5cdGRpc2FibGVDbGlja1Byb3BhZ2F0aW9uOiBkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbixcblx0cHJldmVudERlZmF1bHQ6IHByZXZlbnREZWZhdWx0LFxuXHRzdG9wOiBzdG9wLFxuXHRnZXRNb3VzZVBvc2l0aW9uOiBnZXRNb3VzZVBvc2l0aW9uLFxuXHRnZXRXaGVlbERlbHRhOiBnZXRXaGVlbERlbHRhLFxuXHRmYWtlU3RvcDogZmFrZVN0b3AsXG5cdHNraXBwZWQ6IHNraXBwZWQsXG5cdGlzRXh0ZXJuYWxUYXJnZXQ6IGlzRXh0ZXJuYWxUYXJnZXQsXG5cdGFkZExpc3RlbmVyOiBvbixcblx0cmVtb3ZlTGlzdGVuZXI6IG9mZlxufSk7XG5cbi8qXG4gKiBAY2xhc3MgUG9zQW5pbWF0aW9uXG4gKiBAYWthIEwuUG9zQW5pbWF0aW9uXG4gKiBAaW5oZXJpdHMgRXZlbnRlZFxuICogVXNlZCBpbnRlcm5hbGx5IGZvciBwYW5uaW5nIGFuaW1hdGlvbnMsIHV0aWxpemluZyBDU1MzIFRyYW5zaXRpb25zIGZvciBtb2Rlcm4gYnJvd3NlcnMgYW5kIGEgdGltZXIgZmFsbGJhY2sgZm9yIElFNi05LlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqc1xuICogdmFyIGZ4ID0gbmV3IEwuUG9zQW5pbWF0aW9uKCk7XG4gKiBmeC5ydW4oZWwsIFszMDAsIDUwMF0sIDAuNSk7XG4gKiBgYGBcbiAqXG4gKiBAY29uc3RydWN0b3IgTC5Qb3NBbmltYXRpb24oKVxuICogQ3JlYXRlcyBhIGBQb3NBbmltYXRpb25gIG9iamVjdC5cbiAqXG4gKi9cblxudmFyIFBvc0FuaW1hdGlvbiA9IEV2ZW50ZWQuZXh0ZW5kKHtcblxuXHQvLyBAbWV0aG9kIHJ1bihlbDogSFRNTEVsZW1lbnQsIG5ld1BvczogUG9pbnQsIGR1cmF0aW9uPzogTnVtYmVyLCBlYXNlTGluZWFyaXR5PzogTnVtYmVyKVxuXHQvLyBSdW4gYW4gYW5pbWF0aW9uIG9mIGEgZ2l2ZW4gZWxlbWVudCB0byBhIG5ldyBwb3NpdGlvbiwgb3B0aW9uYWxseSBzZXR0aW5nXG5cdC8vIGR1cmF0aW9uIGluIHNlY29uZHMgKGAwLjI1YCBieSBkZWZhdWx0KSBhbmQgZWFzaW5nIGxpbmVhcml0eSBmYWN0b3IgKDNyZFxuXHQvLyBhcmd1bWVudCBvZiB0aGUgW2N1YmljIGJlemllciBjdXJ2ZV0oaHR0cDovL2N1YmljLWJlemllci5jb20vIzAsMCwuNSwxKSxcblx0Ly8gYDAuNWAgYnkgZGVmYXVsdCkuXG5cdHJ1bjogZnVuY3Rpb24gKGVsLCBuZXdQb3MsIGR1cmF0aW9uLCBlYXNlTGluZWFyaXR5KSB7XG5cdFx0dGhpcy5zdG9wKCk7XG5cblx0XHR0aGlzLl9lbCA9IGVsO1xuXHRcdHRoaXMuX2luUHJvZ3Jlc3MgPSB0cnVlO1xuXHRcdHRoaXMuX2R1cmF0aW9uID0gZHVyYXRpb24gfHwgMC4yNTtcblx0XHR0aGlzLl9lYXNlT3V0UG93ZXIgPSAxIC8gTWF0aC5tYXgoZWFzZUxpbmVhcml0eSB8fCAwLjUsIDAuMik7XG5cblx0XHR0aGlzLl9zdGFydFBvcyA9IGdldFBvc2l0aW9uKGVsKTtcblx0XHR0aGlzLl9vZmZzZXQgPSBuZXdQb3Muc3VidHJhY3QodGhpcy5fc3RhcnRQb3MpO1xuXHRcdHRoaXMuX3N0YXJ0VGltZSA9ICtuZXcgRGF0ZSgpO1xuXG5cdFx0Ly8gQGV2ZW50IHN0YXJ0OiBFdmVudFxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIGFuaW1hdGlvbiBzdGFydHNcblx0XHR0aGlzLmZpcmUoJ3N0YXJ0Jyk7XG5cblx0XHR0aGlzLl9hbmltYXRlKCk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBzdG9wKClcblx0Ly8gU3RvcHMgdGhlIGFuaW1hdGlvbiAoaWYgY3VycmVudGx5IHJ1bm5pbmcpLlxuXHRzdG9wOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKCF0aGlzLl9pblByb2dyZXNzKSB7IHJldHVybjsgfVxuXG5cdFx0dGhpcy5fc3RlcCh0cnVlKTtcblx0XHR0aGlzLl9jb21wbGV0ZSgpO1xuXHR9LFxuXG5cdF9hbmltYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0Ly8gYW5pbWF0aW9uIGxvb3Bcblx0XHR0aGlzLl9hbmltSWQgPSByZXF1ZXN0QW5pbUZyYW1lKHRoaXMuX2FuaW1hdGUsIHRoaXMpO1xuXHRcdHRoaXMuX3N0ZXAoKTtcblx0fSxcblxuXHRfc3RlcDogZnVuY3Rpb24gKHJvdW5kKSB7XG5cdFx0dmFyIGVsYXBzZWQgPSAoK25ldyBEYXRlKCkpIC0gdGhpcy5fc3RhcnRUaW1lLFxuXHRcdCAgICBkdXJhdGlvbiA9IHRoaXMuX2R1cmF0aW9uICogMTAwMDtcblxuXHRcdGlmIChlbGFwc2VkIDwgZHVyYXRpb24pIHtcblx0XHRcdHRoaXMuX3J1bkZyYW1lKHRoaXMuX2Vhc2VPdXQoZWxhcHNlZCAvIGR1cmF0aW9uKSwgcm91bmQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLl9ydW5GcmFtZSgxKTtcblx0XHRcdHRoaXMuX2NvbXBsZXRlKCk7XG5cdFx0fVxuXHR9LFxuXG5cdF9ydW5GcmFtZTogZnVuY3Rpb24gKHByb2dyZXNzLCByb3VuZCkge1xuXHRcdHZhciBwb3MgPSB0aGlzLl9zdGFydFBvcy5hZGQodGhpcy5fb2Zmc2V0Lm11bHRpcGx5QnkocHJvZ3Jlc3MpKTtcblx0XHRpZiAocm91bmQpIHtcblx0XHRcdHBvcy5fcm91bmQoKTtcblx0XHR9XG5cdFx0c2V0UG9zaXRpb24odGhpcy5fZWwsIHBvcyk7XG5cblx0XHQvLyBAZXZlbnQgc3RlcDogRXZlbnRcblx0XHQvLyBGaXJlZCBjb250aW51b3VzbHkgZHVyaW5nIHRoZSBhbmltYXRpb24uXG5cdFx0dGhpcy5maXJlKCdzdGVwJyk7XG5cdH0sXG5cblx0X2NvbXBsZXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2FuaW1JZCk7XG5cblx0XHR0aGlzLl9pblByb2dyZXNzID0gZmFsc2U7XG5cdFx0Ly8gQGV2ZW50IGVuZDogRXZlbnRcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSBhbmltYXRpb24gZW5kcy5cblx0XHR0aGlzLmZpcmUoJ2VuZCcpO1xuXHR9LFxuXG5cdF9lYXNlT3V0OiBmdW5jdGlvbiAodCkge1xuXHRcdHJldHVybiAxIC0gTWF0aC5wb3coMSAtIHQsIHRoaXMuX2Vhc2VPdXRQb3dlcik7XG5cdH1cbn0pO1xuXG4vKlxyXG4gKiBAY2xhc3MgTWFwXHJcbiAqIEBha2EgTC5NYXBcclxuICogQGluaGVyaXRzIEV2ZW50ZWRcclxuICpcclxuICogVGhlIGNlbnRyYWwgY2xhc3Mgb2YgdGhlIEFQSSDigJQgaXQgaXMgdXNlZCB0byBjcmVhdGUgYSBtYXAgb24gYSBwYWdlIGFuZCBtYW5pcHVsYXRlIGl0LlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiAvLyBpbml0aWFsaXplIHRoZSBtYXAgb24gdGhlIFwibWFwXCIgZGl2IHdpdGggYSBnaXZlbiBjZW50ZXIgYW5kIHpvb21cclxuICogdmFyIG1hcCA9IEwubWFwKCdtYXAnLCB7XHJcbiAqIFx0Y2VudGVyOiBbNTEuNTA1LCAtMC4wOV0sXHJcbiAqIFx0em9vbTogMTNcclxuICogfSk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKi9cclxuXHJcbnZhciBNYXAgPSBFdmVudGVkLmV4dGVuZCh7XHJcblxyXG5cdG9wdGlvbnM6IHtcclxuXHRcdC8vIEBzZWN0aW9uIE1hcCBTdGF0ZSBPcHRpb25zXHJcblx0XHQvLyBAb3B0aW9uIGNyczogQ1JTID0gTC5DUlMuRVBTRzM4NTdcclxuXHRcdC8vIFRoZSBbQ29vcmRpbmF0ZSBSZWZlcmVuY2UgU3lzdGVtXSgjY3JzKSB0byB1c2UuIERvbid0IGNoYW5nZSB0aGlzIGlmIHlvdSdyZSBub3RcclxuXHRcdC8vIHN1cmUgd2hhdCBpdCBtZWFucy5cclxuXHRcdGNyczogRVBTRzM4NTcsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBjZW50ZXI6IExhdExuZyA9IHVuZGVmaW5lZFxyXG5cdFx0Ly8gSW5pdGlhbCBnZW9ncmFwaGljIGNlbnRlciBvZiB0aGUgbWFwXHJcblx0XHRjZW50ZXI6IHVuZGVmaW5lZCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHpvb206IE51bWJlciA9IHVuZGVmaW5lZFxyXG5cdFx0Ly8gSW5pdGlhbCBtYXAgem9vbSBsZXZlbFxyXG5cdFx0em9vbTogdW5kZWZpbmVkLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gbWluWm9vbTogTnVtYmVyID0gKlxyXG5cdFx0Ly8gTWluaW11bSB6b29tIGxldmVsIG9mIHRoZSBtYXAuXHJcblx0XHQvLyBJZiBub3Qgc3BlY2lmaWVkIGFuZCBhdCBsZWFzdCBvbmUgYEdyaWRMYXllcmAgb3IgYFRpbGVMYXllcmAgaXMgaW4gdGhlIG1hcCxcclxuXHRcdC8vIHRoZSBsb3dlc3Qgb2YgdGhlaXIgYG1pblpvb21gIG9wdGlvbnMgd2lsbCBiZSB1c2VkIGluc3RlYWQuXHJcblx0XHRtaW5ab29tOiB1bmRlZmluZWQsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBtYXhab29tOiBOdW1iZXIgPSAqXHJcblx0XHQvLyBNYXhpbXVtIHpvb20gbGV2ZWwgb2YgdGhlIG1hcC5cclxuXHRcdC8vIElmIG5vdCBzcGVjaWZpZWQgYW5kIGF0IGxlYXN0IG9uZSBgR3JpZExheWVyYCBvciBgVGlsZUxheWVyYCBpcyBpbiB0aGUgbWFwLFxyXG5cdFx0Ly8gdGhlIGhpZ2hlc3Qgb2YgdGhlaXIgYG1heFpvb21gIG9wdGlvbnMgd2lsbCBiZSB1c2VkIGluc3RlYWQuXHJcblx0XHRtYXhab29tOiB1bmRlZmluZWQsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBsYXllcnM6IExheWVyW10gPSBbXVxyXG5cdFx0Ly8gQXJyYXkgb2YgbGF5ZXJzIHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgbWFwIGluaXRpYWxseVxyXG5cdFx0bGF5ZXJzOiBbXSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIG1heEJvdW5kczogTGF0TG5nQm91bmRzID0gbnVsbFxyXG5cdFx0Ly8gV2hlbiB0aGlzIG9wdGlvbiBpcyBzZXQsIHRoZSBtYXAgcmVzdHJpY3RzIHRoZSB2aWV3IHRvIHRoZSBnaXZlblxyXG5cdFx0Ly8gZ2VvZ3JhcGhpY2FsIGJvdW5kcywgYm91bmNpbmcgdGhlIHVzZXIgYmFjayBpZiB0aGUgdXNlciB0cmllcyB0byBwYW5cclxuXHRcdC8vIG91dHNpZGUgdGhlIHZpZXcuIFRvIHNldCB0aGUgcmVzdHJpY3Rpb24gZHluYW1pY2FsbHksIHVzZVxyXG5cdFx0Ly8gW2BzZXRNYXhCb3VuZHNgXSgjbWFwLXNldG1heGJvdW5kcykgbWV0aG9kLlxyXG5cdFx0bWF4Qm91bmRzOiB1bmRlZmluZWQsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiByZW5kZXJlcjogUmVuZGVyZXIgPSAqXHJcblx0XHQvLyBUaGUgZGVmYXVsdCBtZXRob2QgZm9yIGRyYXdpbmcgdmVjdG9yIGxheWVycyBvbiB0aGUgbWFwLiBgTC5TVkdgXHJcblx0XHQvLyBvciBgTC5DYW52YXNgIGJ5IGRlZmF1bHQgZGVwZW5kaW5nIG9uIGJyb3dzZXIgc3VwcG9ydC5cclxuXHRcdHJlbmRlcmVyOiB1bmRlZmluZWQsXHJcblxyXG5cclxuXHRcdC8vIEBzZWN0aW9uIEFuaW1hdGlvbiBPcHRpb25zXHJcblx0XHQvLyBAb3B0aW9uIHpvb21BbmltYXRpb246IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBXaGV0aGVyIHRoZSBtYXAgem9vbSBhbmltYXRpb24gaXMgZW5hYmxlZC4gQnkgZGVmYXVsdCBpdCdzIGVuYWJsZWRcclxuXHRcdC8vIGluIGFsbCBicm93c2VycyB0aGF0IHN1cHBvcnQgQ1NTMyBUcmFuc2l0aW9ucyBleGNlcHQgQW5kcm9pZC5cclxuXHRcdHpvb21BbmltYXRpb246IHRydWUsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB6b29tQW5pbWF0aW9uVGhyZXNob2xkOiBOdW1iZXIgPSA0XHJcblx0XHQvLyBXb24ndCBhbmltYXRlIHpvb20gaWYgdGhlIHpvb20gZGlmZmVyZW5jZSBleGNlZWRzIHRoaXMgdmFsdWUuXHJcblx0XHR6b29tQW5pbWF0aW9uVGhyZXNob2xkOiA0LFxyXG5cclxuXHRcdC8vIEBvcHRpb24gZmFkZUFuaW1hdGlvbjogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIFdoZXRoZXIgdGhlIHRpbGUgZmFkZSBhbmltYXRpb24gaXMgZW5hYmxlZC4gQnkgZGVmYXVsdCBpdCdzIGVuYWJsZWRcclxuXHRcdC8vIGluIGFsbCBicm93c2VycyB0aGF0IHN1cHBvcnQgQ1NTMyBUcmFuc2l0aW9ucyBleGNlcHQgQW5kcm9pZC5cclxuXHRcdGZhZGVBbmltYXRpb246IHRydWUsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBtYXJrZXJab29tQW5pbWF0aW9uOiBCb29sZWFuID0gdHJ1ZVxyXG5cdFx0Ly8gV2hldGhlciBtYXJrZXJzIGFuaW1hdGUgdGhlaXIgem9vbSB3aXRoIHRoZSB6b29tIGFuaW1hdGlvbiwgaWYgZGlzYWJsZWRcclxuXHRcdC8vIHRoZXkgd2lsbCBkaXNhcHBlYXIgZm9yIHRoZSBsZW5ndGggb2YgdGhlIGFuaW1hdGlvbi4gQnkgZGVmYXVsdCBpdCdzXHJcblx0XHQvLyBlbmFibGVkIGluIGFsbCBicm93c2VycyB0aGF0IHN1cHBvcnQgQ1NTMyBUcmFuc2l0aW9ucyBleGNlcHQgQW5kcm9pZC5cclxuXHRcdG1hcmtlclpvb21BbmltYXRpb246IHRydWUsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB0cmFuc2Zvcm0zRExpbWl0OiBOdW1iZXIgPSAyXjIzXHJcblx0XHQvLyBEZWZpbmVzIHRoZSBtYXhpbXVtIHNpemUgb2YgYSBDU1MgdHJhbnNsYXRpb24gdHJhbnNmb3JtLiBUaGUgZGVmYXVsdFxyXG5cdFx0Ly8gdmFsdWUgc2hvdWxkIG5vdCBiZSBjaGFuZ2VkIHVubGVzcyBhIHdlYiBicm93c2VyIHBvc2l0aW9ucyBsYXllcnMgaW5cclxuXHRcdC8vIHRoZSB3cm9uZyBwbGFjZSBhZnRlciBkb2luZyBhIGxhcmdlIGBwYW5CeWAuXHJcblx0XHR0cmFuc2Zvcm0zRExpbWl0OiA4Mzg4NjA4LCAvLyBQcmVjaXNpb24gbGltaXQgb2YgYSAzMi1iaXQgZmxvYXRcclxuXHJcblx0XHQvLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXHJcblx0XHQvLyBAb3B0aW9uIHpvb21TbmFwOiBOdW1iZXIgPSAxXHJcblx0XHQvLyBGb3JjZXMgdGhlIG1hcCdzIHpvb20gbGV2ZWwgdG8gYWx3YXlzIGJlIGEgbXVsdGlwbGUgb2YgdGhpcywgcGFydGljdWxhcmx5XHJcblx0XHQvLyByaWdodCBhZnRlciBhIFtgZml0Qm91bmRzKClgXSgjbWFwLWZpdGJvdW5kcykgb3IgYSBwaW5jaC16b29tLlxyXG5cdFx0Ly8gQnkgZGVmYXVsdCwgdGhlIHpvb20gbGV2ZWwgc25hcHMgdG8gdGhlIG5lYXJlc3QgaW50ZWdlcjsgbG93ZXIgdmFsdWVzXHJcblx0XHQvLyAoZS5nLiBgMC41YCBvciBgMC4xYCkgYWxsb3cgZm9yIGdyZWF0ZXIgZ3JhbnVsYXJpdHkuIEEgdmFsdWUgb2YgYDBgXHJcblx0XHQvLyBtZWFucyB0aGUgem9vbSBsZXZlbCB3aWxsIG5vdCBiZSBzbmFwcGVkIGFmdGVyIGBmaXRCb3VuZHNgIG9yIGEgcGluY2gtem9vbS5cclxuXHRcdHpvb21TbmFwOiAxLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gem9vbURlbHRhOiBOdW1iZXIgPSAxXHJcblx0XHQvLyBDb250cm9scyBob3cgbXVjaCB0aGUgbWFwJ3Mgem9vbSBsZXZlbCB3aWxsIGNoYW5nZSBhZnRlciBhXHJcblx0XHQvLyBbYHpvb21JbigpYF0oI21hcC16b29taW4pLCBbYHpvb21PdXQoKWBdKCNtYXAtem9vbW91dCksIHByZXNzaW5nIGArYFxyXG5cdFx0Ly8gb3IgYC1gIG9uIHRoZSBrZXlib2FyZCwgb3IgdXNpbmcgdGhlIFt6b29tIGNvbnRyb2xzXSgjY29udHJvbC16b29tKS5cclxuXHRcdC8vIFZhbHVlcyBzbWFsbGVyIHRoYW4gYDFgIChlLmcuIGAwLjVgKSBhbGxvdyBmb3IgZ3JlYXRlciBncmFudWxhcml0eS5cclxuXHRcdHpvb21EZWx0YTogMSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHRyYWNrUmVzaXplOiBCb29sZWFuID0gdHJ1ZVxyXG5cdFx0Ly8gV2hldGhlciB0aGUgbWFwIGF1dG9tYXRpY2FsbHkgaGFuZGxlcyBicm93c2VyIHdpbmRvdyByZXNpemUgdG8gdXBkYXRlIGl0c2VsZi5cclxuXHRcdHRyYWNrUmVzaXplOiB0cnVlXHJcblx0fSxcclxuXHJcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGlkLCBvcHRpb25zKSB7IC8vIChIVE1MRWxlbWVudCBvciBTdHJpbmcsIE9iamVjdClcclxuXHRcdG9wdGlvbnMgPSBzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuXHRcdC8vIE1ha2Ugc3VyZSB0byBhc3NpZ24gaW50ZXJuYWwgZmxhZ3MgYXQgdGhlIGJlZ2lubmluZyxcclxuXHRcdC8vIHRvIGF2b2lkIGluY29uc2lzdGVudCBzdGF0ZSBpbiBzb21lIGVkZ2UgY2FzZXMuXHJcblx0XHR0aGlzLl9oYW5kbGVycyA9IFtdO1xyXG5cdFx0dGhpcy5fbGF5ZXJzID0ge307XHJcblx0XHR0aGlzLl96b29tQm91bmRMYXllcnMgPSB7fTtcclxuXHRcdHRoaXMuX3NpemVDaGFuZ2VkID0gdHJ1ZTtcclxuXHJcblx0XHR0aGlzLl9pbml0Q29udGFpbmVyKGlkKTtcclxuXHRcdHRoaXMuX2luaXRMYXlvdXQoKTtcclxuXHJcblx0XHQvLyBoYWNrIGZvciBodHRwczovL2dpdGh1Yi5jb20vTGVhZmxldC9MZWFmbGV0L2lzc3Vlcy8xOTgwXHJcblx0XHR0aGlzLl9vblJlc2l6ZSA9IGJpbmQodGhpcy5fb25SZXNpemUsIHRoaXMpO1xyXG5cclxuXHRcdHRoaXMuX2luaXRFdmVudHMoKTtcclxuXHJcblx0XHRpZiAob3B0aW9ucy5tYXhCb3VuZHMpIHtcclxuXHRcdFx0dGhpcy5zZXRNYXhCb3VuZHMob3B0aW9ucy5tYXhCb3VuZHMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChvcHRpb25zLnpvb20gIT09IHVuZGVmaW5lZCkge1xyXG5cdFx0XHR0aGlzLl96b29tID0gdGhpcy5fbGltaXRab29tKG9wdGlvbnMuem9vbSk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKG9wdGlvbnMuY2VudGVyICYmIG9wdGlvbnMuem9vbSAhPT0gdW5kZWZpbmVkKSB7XHJcblx0XHRcdHRoaXMuc2V0Vmlldyh0b0xhdExuZyhvcHRpb25zLmNlbnRlciksIG9wdGlvbnMuem9vbSwge3Jlc2V0OiB0cnVlfSk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5jYWxsSW5pdEhvb2tzKCk7XHJcblxyXG5cdFx0Ly8gZG9uJ3QgYW5pbWF0ZSBvbiBicm93c2VycyB3aXRob3V0IGhhcmR3YXJlLWFjY2VsZXJhdGVkIHRyYW5zaXRpb25zIG9yIG9sZCBBbmRyb2lkL09wZXJhXHJcblx0XHR0aGlzLl96b29tQW5pbWF0ZWQgPSBUUkFOU0lUSU9OICYmIGFueTNkICYmICFtb2JpbGVPcGVyYSAmJlxyXG5cdFx0XHRcdHRoaXMub3B0aW9ucy56b29tQW5pbWF0aW9uO1xyXG5cclxuXHRcdC8vIHpvb20gdHJhbnNpdGlvbnMgcnVuIHdpdGggdGhlIHNhbWUgZHVyYXRpb24gZm9yIGFsbCBsYXllcnMsIHNvIGlmIG9uZSBvZiB0cmFuc2l0aW9uZW5kIGV2ZW50c1xyXG5cdFx0Ly8gaGFwcGVucyBhZnRlciBzdGFydGluZyB6b29tIGFuaW1hdGlvbiAocHJvcGFnYXRpbmcgdG8gdGhlIG1hcCBwYW5lKSwgd2Uga25vdyB0aGF0IGl0IGVuZGVkIGdsb2JhbGx5XHJcblx0XHRpZiAodGhpcy5fem9vbUFuaW1hdGVkKSB7XHJcblx0XHRcdHRoaXMuX2NyZWF0ZUFuaW1Qcm94eSgpO1xyXG5cdFx0XHRvbih0aGlzLl9wcm94eSwgVFJBTlNJVElPTl9FTkQsIHRoaXMuX2NhdGNoVHJhbnNpdGlvbkVuZCwgdGhpcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fYWRkTGF5ZXJzKHRoaXMub3B0aW9ucy5sYXllcnMpO1xyXG5cdH0sXHJcblxyXG5cclxuXHQvLyBAc2VjdGlvbiBNZXRob2RzIGZvciBtb2RpZnlpbmcgbWFwIHN0YXRlXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0VmlldyhjZW50ZXI6IExhdExuZywgem9vbTogTnVtYmVyLCBvcHRpb25zPzogWm9vbS9wYW4gb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBTZXRzIHRoZSB2aWV3IG9mIHRoZSBtYXAgKGdlb2dyYXBoaWNhbCBjZW50ZXIgYW5kIHpvb20pIHdpdGggdGhlIGdpdmVuXHJcblx0Ly8gYW5pbWF0aW9uIG9wdGlvbnMuXHJcblx0c2V0VmlldzogZnVuY3Rpb24gKGNlbnRlciwgem9vbSwgb3B0aW9ucykge1xyXG5cclxuXHRcdHpvb20gPSB6b29tID09PSB1bmRlZmluZWQgPyB0aGlzLl96b29tIDogdGhpcy5fbGltaXRab29tKHpvb20pO1xyXG5cdFx0Y2VudGVyID0gdGhpcy5fbGltaXRDZW50ZXIodG9MYXRMbmcoY2VudGVyKSwgem9vbSwgdGhpcy5vcHRpb25zLm1heEJvdW5kcyk7XHJcblx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcclxuXHJcblx0XHR0aGlzLl9zdG9wKCk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX2xvYWRlZCAmJiAhb3B0aW9ucy5yZXNldCAmJiBvcHRpb25zICE9PSB0cnVlKSB7XHJcblxyXG5cdFx0XHRpZiAob3B0aW9ucy5hbmltYXRlICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0XHRvcHRpb25zLnpvb20gPSBleHRlbmQoe2FuaW1hdGU6IG9wdGlvbnMuYW5pbWF0ZX0sIG9wdGlvbnMuem9vbSk7XHJcblx0XHRcdFx0b3B0aW9ucy5wYW4gPSBleHRlbmQoe2FuaW1hdGU6IG9wdGlvbnMuYW5pbWF0ZSwgZHVyYXRpb246IG9wdGlvbnMuZHVyYXRpb259LCBvcHRpb25zLnBhbik7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIHRyeSBhbmltYXRpbmcgcGFuIG9yIHpvb21cclxuXHRcdFx0dmFyIG1vdmVkID0gKHRoaXMuX3pvb20gIT09IHpvb20pID9cclxuXHRcdFx0XHR0aGlzLl90cnlBbmltYXRlZFpvb20gJiYgdGhpcy5fdHJ5QW5pbWF0ZWRab29tKGNlbnRlciwgem9vbSwgb3B0aW9ucy56b29tKSA6XHJcblx0XHRcdFx0dGhpcy5fdHJ5QW5pbWF0ZWRQYW4oY2VudGVyLCBvcHRpb25zLnBhbik7XHJcblxyXG5cdFx0XHRpZiAobW92ZWQpIHtcclxuXHRcdFx0XHQvLyBwcmV2ZW50IHJlc2l6ZSBoYW5kbGVyIGNhbGwsIHRoZSB2aWV3IHdpbGwgcmVmcmVzaCBhZnRlciBhbmltYXRpb24gYW55d2F5XHJcblx0XHRcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3NpemVUaW1lcik7XHJcblx0XHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHQvLyBhbmltYXRpb24gZGlkbid0IHN0YXJ0LCBqdXN0IHJlc2V0IHRoZSBtYXAgdmlld1xyXG5cdFx0dGhpcy5fcmVzZXRWaWV3KGNlbnRlciwgem9vbSk7XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRab29tKHpvb206IE51bWJlciwgb3B0aW9ucz86IFpvb20vcGFuIG9wdGlvbnMpOiB0aGlzXHJcblx0Ly8gU2V0cyB0aGUgem9vbSBvZiB0aGUgbWFwLlxyXG5cdHNldFpvb206IGZ1bmN0aW9uICh6b29tLCBvcHRpb25zKSB7XHJcblx0XHRpZiAoIXRoaXMuX2xvYWRlZCkge1xyXG5cdFx0XHR0aGlzLl96b29tID0gem9vbTtcclxuXHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcy5zZXRWaWV3KHRoaXMuZ2V0Q2VudGVyKCksIHpvb20sIHt6b29tOiBvcHRpb25zfSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB6b29tSW4oZGVsdGE/OiBOdW1iZXIsIG9wdGlvbnM/OiBab29tIG9wdGlvbnMpOiB0aGlzXHJcblx0Ly8gSW5jcmVhc2VzIHRoZSB6b29tIG9mIHRoZSBtYXAgYnkgYGRlbHRhYCAoW2B6b29tRGVsdGFgXSgjbWFwLXpvb21kZWx0YSkgYnkgZGVmYXVsdCkuXHJcblx0em9vbUluOiBmdW5jdGlvbiAoZGVsdGEsIG9wdGlvbnMpIHtcclxuXHRcdGRlbHRhID0gZGVsdGEgfHwgKGFueTNkID8gdGhpcy5vcHRpb25zLnpvb21EZWx0YSA6IDEpO1xyXG5cdFx0cmV0dXJuIHRoaXMuc2V0Wm9vbSh0aGlzLl96b29tICsgZGVsdGEsIG9wdGlvbnMpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgem9vbU91dChkZWx0YT86IE51bWJlciwgb3B0aW9ucz86IFpvb20gb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBEZWNyZWFzZXMgdGhlIHpvb20gb2YgdGhlIG1hcCBieSBgZGVsdGFgIChbYHpvb21EZWx0YWBdKCNtYXAtem9vbWRlbHRhKSBieSBkZWZhdWx0KS5cclxuXHR6b29tT3V0OiBmdW5jdGlvbiAoZGVsdGEsIG9wdGlvbnMpIHtcclxuXHRcdGRlbHRhID0gZGVsdGEgfHwgKGFueTNkID8gdGhpcy5vcHRpb25zLnpvb21EZWx0YSA6IDEpO1xyXG5cdFx0cmV0dXJuIHRoaXMuc2V0Wm9vbSh0aGlzLl96b29tIC0gZGVsdGEsIG9wdGlvbnMpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0Wm9vbUFyb3VuZChsYXRsbmc6IExhdExuZywgem9vbTogTnVtYmVyLCBvcHRpb25zOiBab29tIG9wdGlvbnMpOiB0aGlzXHJcblx0Ly8gWm9vbXMgdGhlIG1hcCB3aGlsZSBrZWVwaW5nIGEgc3BlY2lmaWVkIGdlb2dyYXBoaWNhbCBwb2ludCBvbiB0aGUgbWFwXHJcblx0Ly8gc3RhdGlvbmFyeSAoZS5nLiB1c2VkIGludGVybmFsbHkgZm9yIHNjcm9sbCB6b29tIGFuZCBkb3VibGUtY2xpY2sgem9vbSkuXHJcblx0Ly8gQGFsdGVybmF0aXZlXHJcblx0Ly8gQG1ldGhvZCBzZXRab29tQXJvdW5kKG9mZnNldDogUG9pbnQsIHpvb206IE51bWJlciwgb3B0aW9uczogWm9vbSBvcHRpb25zKTogdGhpc1xyXG5cdC8vIFpvb21zIHRoZSBtYXAgd2hpbGUga2VlcGluZyBhIHNwZWNpZmllZCBwaXhlbCBvbiB0aGUgbWFwIChyZWxhdGl2ZSB0byB0aGUgdG9wLWxlZnQgY29ybmVyKSBzdGF0aW9uYXJ5LlxyXG5cdHNldFpvb21Bcm91bmQ6IGZ1bmN0aW9uIChsYXRsbmcsIHpvb20sIG9wdGlvbnMpIHtcclxuXHRcdHZhciBzY2FsZSA9IHRoaXMuZ2V0Wm9vbVNjYWxlKHpvb20pLFxyXG5cdFx0ICAgIHZpZXdIYWxmID0gdGhpcy5nZXRTaXplKCkuZGl2aWRlQnkoMiksXHJcblx0XHQgICAgY29udGFpbmVyUG9pbnQgPSBsYXRsbmcgaW5zdGFuY2VvZiBQb2ludCA/IGxhdGxuZyA6IHRoaXMubGF0TG5nVG9Db250YWluZXJQb2ludChsYXRsbmcpLFxyXG5cclxuXHRcdCAgICBjZW50ZXJPZmZzZXQgPSBjb250YWluZXJQb2ludC5zdWJ0cmFjdCh2aWV3SGFsZikubXVsdGlwbHlCeSgxIC0gMSAvIHNjYWxlKSxcclxuXHRcdCAgICBuZXdDZW50ZXIgPSB0aGlzLmNvbnRhaW5lclBvaW50VG9MYXRMbmcodmlld0hhbGYuYWRkKGNlbnRlck9mZnNldCkpO1xyXG5cclxuXHRcdHJldHVybiB0aGlzLnNldFZpZXcobmV3Q2VudGVyLCB6b29tLCB7em9vbTogb3B0aW9uc30pO1xyXG5cdH0sXHJcblxyXG5cdF9nZXRCb3VuZHNDZW50ZXJab29tOiBmdW5jdGlvbiAoYm91bmRzLCBvcHRpb25zKSB7XHJcblxyXG5cdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XHJcblx0XHRib3VuZHMgPSBib3VuZHMuZ2V0Qm91bmRzID8gYm91bmRzLmdldEJvdW5kcygpIDogdG9MYXRMbmdCb3VuZHMoYm91bmRzKTtcclxuXHJcblx0XHR2YXIgcGFkZGluZ1RMID0gdG9Qb2ludChvcHRpb25zLnBhZGRpbmdUb3BMZWZ0IHx8IG9wdGlvbnMucGFkZGluZyB8fCBbMCwgMF0pLFxyXG5cdFx0ICAgIHBhZGRpbmdCUiA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nQm90dG9tUmlnaHQgfHwgb3B0aW9ucy5wYWRkaW5nIHx8IFswLCAwXSksXHJcblxyXG5cdFx0ICAgIHpvb20gPSB0aGlzLmdldEJvdW5kc1pvb20oYm91bmRzLCBmYWxzZSwgcGFkZGluZ1RMLmFkZChwYWRkaW5nQlIpKTtcclxuXHJcblx0XHR6b29tID0gKHR5cGVvZiBvcHRpb25zLm1heFpvb20gPT09ICdudW1iZXInKSA/IE1hdGgubWluKG9wdGlvbnMubWF4Wm9vbSwgem9vbSkgOiB6b29tO1xyXG5cclxuXHRcdGlmICh6b29tID09PSBJbmZpbml0eSkge1xyXG5cdFx0XHRyZXR1cm4ge1xyXG5cdFx0XHRcdGNlbnRlcjogYm91bmRzLmdldENlbnRlcigpLFxyXG5cdFx0XHRcdHpvb206IHpvb21cclxuXHRcdFx0fTtcclxuXHRcdH1cclxuXHJcblx0XHR2YXIgcGFkZGluZ09mZnNldCA9IHBhZGRpbmdCUi5zdWJ0cmFjdChwYWRkaW5nVEwpLmRpdmlkZUJ5KDIpLFxyXG5cclxuXHRcdCAgICBzd1BvaW50ID0gdGhpcy5wcm9qZWN0KGJvdW5kcy5nZXRTb3V0aFdlc3QoKSwgem9vbSksXHJcblx0XHQgICAgbmVQb2ludCA9IHRoaXMucHJvamVjdChib3VuZHMuZ2V0Tm9ydGhFYXN0KCksIHpvb20pLFxyXG5cdFx0ICAgIGNlbnRlciA9IHRoaXMudW5wcm9qZWN0KHN3UG9pbnQuYWRkKG5lUG9pbnQpLmRpdmlkZUJ5KDIpLmFkZChwYWRkaW5nT2Zmc2V0KSwgem9vbSk7XHJcblxyXG5cdFx0cmV0dXJuIHtcclxuXHRcdFx0Y2VudGVyOiBjZW50ZXIsXHJcblx0XHRcdHpvb206IHpvb21cclxuXHRcdH07XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBmaXRCb3VuZHMoYm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBmaXRCb3VuZHMgb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBTZXRzIGEgbWFwIHZpZXcgdGhhdCBjb250YWlucyB0aGUgZ2l2ZW4gZ2VvZ3JhcGhpY2FsIGJvdW5kcyB3aXRoIHRoZVxyXG5cdC8vIG1heGltdW0gem9vbSBsZXZlbCBwb3NzaWJsZS5cclxuXHRmaXRCb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMsIG9wdGlvbnMpIHtcclxuXHJcblx0XHRib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuXHRcdGlmICghYm91bmRzLmlzVmFsaWQoKSkge1xyXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0JvdW5kcyBhcmUgbm90IHZhbGlkLicpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciB0YXJnZXQgPSB0aGlzLl9nZXRCb3VuZHNDZW50ZXJab29tKGJvdW5kcywgb3B0aW9ucyk7XHJcblx0XHRyZXR1cm4gdGhpcy5zZXRWaWV3KHRhcmdldC5jZW50ZXIsIHRhcmdldC56b29tLCBvcHRpb25zKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGZpdFdvcmxkKG9wdGlvbnM/OiBmaXRCb3VuZHMgb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBTZXRzIGEgbWFwIHZpZXcgdGhhdCBtb3N0bHkgY29udGFpbnMgdGhlIHdob2xlIHdvcmxkIHdpdGggdGhlIG1heGltdW1cclxuXHQvLyB6b29tIGxldmVsIHBvc3NpYmxlLlxyXG5cdGZpdFdvcmxkOiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG5cdFx0cmV0dXJuIHRoaXMuZml0Qm91bmRzKFtbLTkwLCAtMTgwXSwgWzkwLCAxODBdXSwgb3B0aW9ucyk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBwYW5UbyhsYXRsbmc6IExhdExuZywgb3B0aW9ucz86IFBhbiBvcHRpb25zKTogdGhpc1xyXG5cdC8vIFBhbnMgdGhlIG1hcCB0byBhIGdpdmVuIGNlbnRlci5cclxuXHRwYW5UbzogZnVuY3Rpb24gKGNlbnRlciwgb3B0aW9ucykgeyAvLyAoTGF0TG5nKVxyXG5cdFx0cmV0dXJuIHRoaXMuc2V0VmlldyhjZW50ZXIsIHRoaXMuX3pvb20sIHtwYW46IG9wdGlvbnN9KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHBhbkJ5KG9mZnNldDogUG9pbnQsIG9wdGlvbnM/OiBQYW4gb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBQYW5zIHRoZSBtYXAgYnkgYSBnaXZlbiBudW1iZXIgb2YgcGl4ZWxzIChhbmltYXRlZCkuXHJcblx0cGFuQnk6IGZ1bmN0aW9uIChvZmZzZXQsIG9wdGlvbnMpIHtcclxuXHRcdG9mZnNldCA9IHRvUG9pbnQob2Zmc2V0KS5yb3VuZCgpO1xyXG5cdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XHJcblxyXG5cdFx0aWYgKCFvZmZzZXQueCAmJiAhb2Zmc2V0LnkpIHtcclxuXHRcdFx0cmV0dXJuIHRoaXMuZmlyZSgnbW92ZWVuZCcpO1xyXG5cdFx0fVxyXG5cdFx0Ly8gSWYgd2UgcGFuIHRvbyBmYXIsIENocm9tZSBnZXRzIGlzc3VlcyB3aXRoIHRpbGVzXHJcblx0XHQvLyBhbmQgbWFrZXMgdGhlbSBkaXNhcHBlYXIgb3IgYXBwZWFyIGluIHRoZSB3cm9uZyBwbGFjZSAoc2xpZ2h0bHkgb2Zmc2V0KSAjMjYwMlxyXG5cdFx0aWYgKG9wdGlvbnMuYW5pbWF0ZSAhPT0gdHJ1ZSAmJiAhdGhpcy5nZXRTaXplKCkuY29udGFpbnMob2Zmc2V0KSkge1xyXG5cdFx0XHR0aGlzLl9yZXNldFZpZXcodGhpcy51bnByb2plY3QodGhpcy5wcm9qZWN0KHRoaXMuZ2V0Q2VudGVyKCkpLmFkZChvZmZzZXQpKSwgdGhpcy5nZXRab29tKCkpO1xyXG5cdFx0XHRyZXR1cm4gdGhpcztcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIXRoaXMuX3BhbkFuaW0pIHtcclxuXHRcdFx0dGhpcy5fcGFuQW5pbSA9IG5ldyBQb3NBbmltYXRpb24oKTtcclxuXHJcblx0XHRcdHRoaXMuX3BhbkFuaW0ub24oe1xyXG5cdFx0XHRcdCdzdGVwJzogdGhpcy5fb25QYW5UcmFuc2l0aW9uU3RlcCxcclxuXHRcdFx0XHQnZW5kJzogdGhpcy5fb25QYW5UcmFuc2l0aW9uRW5kXHJcblx0XHRcdH0sIHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIGRvbid0IGZpcmUgbW92ZXN0YXJ0IGlmIGFuaW1hdGluZyBpbmVydGlhXHJcblx0XHRpZiAoIW9wdGlvbnMubm9Nb3ZlU3RhcnQpIHtcclxuXHRcdFx0dGhpcy5maXJlKCdtb3Zlc3RhcnQnKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBhbmltYXRlIHBhbiB1bmxlc3MgYW5pbWF0ZTogZmFsc2Ugc3BlY2lmaWVkXHJcblx0XHRpZiAob3B0aW9ucy5hbmltYXRlICE9PSBmYWxzZSkge1xyXG5cdFx0XHRhZGRDbGFzcyh0aGlzLl9tYXBQYW5lLCAnbGVhZmxldC1wYW4tYW5pbScpO1xyXG5cclxuXHRcdFx0dmFyIG5ld1BvcyA9IHRoaXMuX2dldE1hcFBhbmVQb3MoKS5zdWJ0cmFjdChvZmZzZXQpLnJvdW5kKCk7XHJcblx0XHRcdHRoaXMuX3BhbkFuaW0ucnVuKHRoaXMuX21hcFBhbmUsIG5ld1Bvcywgb3B0aW9ucy5kdXJhdGlvbiB8fCAwLjI1LCBvcHRpb25zLmVhc2VMaW5lYXJpdHkpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0dGhpcy5fcmF3UGFuQnkob2Zmc2V0KTtcclxuXHRcdFx0dGhpcy5maXJlKCdtb3ZlJykuZmlyZSgnbW92ZWVuZCcpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZmx5VG8obGF0bG5nOiBMYXRMbmcsIHpvb20/OiBOdW1iZXIsIG9wdGlvbnM/OiBab29tL3BhbiBvcHRpb25zKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIHZpZXcgb2YgdGhlIG1hcCAoZ2VvZ3JhcGhpY2FsIGNlbnRlciBhbmQgem9vbSkgcGVyZm9ybWluZyBhIHNtb290aFxyXG5cdC8vIHBhbi16b29tIGFuaW1hdGlvbi5cclxuXHRmbHlUbzogZnVuY3Rpb24gKHRhcmdldENlbnRlciwgdGFyZ2V0Wm9vbSwgb3B0aW9ucykge1xyXG5cclxuXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xyXG5cdFx0aWYgKG9wdGlvbnMuYW5pbWF0ZSA9PT0gZmFsc2UgfHwgIWFueTNkKSB7XHJcblx0XHRcdHJldHVybiB0aGlzLnNldFZpZXcodGFyZ2V0Q2VudGVyLCB0YXJnZXRab29tLCBvcHRpb25zKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9zdG9wKCk7XHJcblxyXG5cdFx0dmFyIGZyb20gPSB0aGlzLnByb2plY3QodGhpcy5nZXRDZW50ZXIoKSksXHJcblx0XHQgICAgdG8gPSB0aGlzLnByb2plY3QodGFyZ2V0Q2VudGVyKSxcclxuXHRcdCAgICBzaXplID0gdGhpcy5nZXRTaXplKCksXHJcblx0XHQgICAgc3RhcnRab29tID0gdGhpcy5fem9vbTtcclxuXHJcblx0XHR0YXJnZXRDZW50ZXIgPSB0b0xhdExuZyh0YXJnZXRDZW50ZXIpO1xyXG5cdFx0dGFyZ2V0Wm9vbSA9IHRhcmdldFpvb20gPT09IHVuZGVmaW5lZCA/IHN0YXJ0Wm9vbSA6IHRhcmdldFpvb207XHJcblxyXG5cdFx0dmFyIHcwID0gTWF0aC5tYXgoc2l6ZS54LCBzaXplLnkpLFxyXG5cdFx0ICAgIHcxID0gdzAgKiB0aGlzLmdldFpvb21TY2FsZShzdGFydFpvb20sIHRhcmdldFpvb20pLFxyXG5cdFx0ICAgIHUxID0gKHRvLmRpc3RhbmNlVG8oZnJvbSkpIHx8IDEsXHJcblx0XHQgICAgcmhvID0gMS40MixcclxuXHRcdCAgICByaG8yID0gcmhvICogcmhvO1xyXG5cclxuXHRcdGZ1bmN0aW9uIHIoaSkge1xyXG5cdFx0XHR2YXIgczEgPSBpID8gLTEgOiAxLFxyXG5cdFx0XHQgICAgczIgPSBpID8gdzEgOiB3MCxcclxuXHRcdFx0ICAgIHQxID0gdzEgKiB3MSAtIHcwICogdzAgKyBzMSAqIHJobzIgKiByaG8yICogdTEgKiB1MSxcclxuXHRcdFx0ICAgIGIxID0gMiAqIHMyICogcmhvMiAqIHUxLFxyXG5cdFx0XHQgICAgYiA9IHQxIC8gYjEsXHJcblx0XHRcdCAgICBzcSA9IE1hdGguc3FydChiICogYiArIDEpIC0gYjtcclxuXHJcblx0XHRcdCAgICAvLyB3b3JrYXJvdW5kIGZvciBmbG9hdGluZyBwb2ludCBwcmVjaXNpb24gYnVnIHdoZW4gc3EgPSAwLCBsb2cgPSAtSW5maW5pdGUsXHJcblx0XHRcdCAgICAvLyB0aHVzIHRyaWdnZXJpbmcgYW4gaW5maW5pdGUgbG9vcCBpbiBmbHlUb1xyXG5cdFx0XHQgICAgdmFyIGxvZyA9IHNxIDwgMC4wMDAwMDAwMDEgPyAtMTggOiBNYXRoLmxvZyhzcSk7XHJcblxyXG5cdFx0XHRyZXR1cm4gbG9nO1xyXG5cdFx0fVxyXG5cclxuXHRcdGZ1bmN0aW9uIHNpbmgobikgeyByZXR1cm4gKE1hdGguZXhwKG4pIC0gTWF0aC5leHAoLW4pKSAvIDI7IH1cclxuXHRcdGZ1bmN0aW9uIGNvc2gobikgeyByZXR1cm4gKE1hdGguZXhwKG4pICsgTWF0aC5leHAoLW4pKSAvIDI7IH1cclxuXHRcdGZ1bmN0aW9uIHRhbmgobikgeyByZXR1cm4gc2luaChuKSAvIGNvc2gobik7IH1cclxuXHJcblx0XHR2YXIgcjAgPSByKDApO1xyXG5cclxuXHRcdGZ1bmN0aW9uIHcocykgeyByZXR1cm4gdzAgKiAoY29zaChyMCkgLyBjb3NoKHIwICsgcmhvICogcykpOyB9XHJcblx0XHRmdW5jdGlvbiB1KHMpIHsgcmV0dXJuIHcwICogKGNvc2gocjApICogdGFuaChyMCArIHJobyAqIHMpIC0gc2luaChyMCkpIC8gcmhvMjsgfVxyXG5cclxuXHRcdGZ1bmN0aW9uIGVhc2VPdXQodCkgeyByZXR1cm4gMSAtIE1hdGgucG93KDEgLSB0LCAxLjUpOyB9XHJcblxyXG5cdFx0dmFyIHN0YXJ0ID0gRGF0ZS5ub3coKSxcclxuXHRcdCAgICBTID0gKHIoMSkgLSByMCkgLyByaG8sXHJcblx0XHQgICAgZHVyYXRpb24gPSBvcHRpb25zLmR1cmF0aW9uID8gMTAwMCAqIG9wdGlvbnMuZHVyYXRpb24gOiAxMDAwICogUyAqIDAuODtcclxuXHJcblx0XHRmdW5jdGlvbiBmcmFtZSgpIHtcclxuXHRcdFx0dmFyIHQgPSAoRGF0ZS5ub3coKSAtIHN0YXJ0KSAvIGR1cmF0aW9uLFxyXG5cdFx0XHQgICAgcyA9IGVhc2VPdXQodCkgKiBTO1xyXG5cclxuXHRcdFx0aWYgKHQgPD0gMSkge1xyXG5cdFx0XHRcdHRoaXMuX2ZseVRvRnJhbWUgPSByZXF1ZXN0QW5pbUZyYW1lKGZyYW1lLCB0aGlzKTtcclxuXHJcblx0XHRcdFx0dGhpcy5fbW92ZShcclxuXHRcdFx0XHRcdHRoaXMudW5wcm9qZWN0KGZyb20uYWRkKHRvLnN1YnRyYWN0KGZyb20pLm11bHRpcGx5QnkodShzKSAvIHUxKSksIHN0YXJ0Wm9vbSksXHJcblx0XHRcdFx0XHR0aGlzLmdldFNjYWxlWm9vbSh3MCAvIHcocyksIHN0YXJ0Wm9vbSksXHJcblx0XHRcdFx0XHR7Zmx5VG86IHRydWV9KTtcclxuXHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0dGhpc1xyXG5cdFx0XHRcdFx0Ll9tb3ZlKHRhcmdldENlbnRlciwgdGFyZ2V0Wm9vbSlcclxuXHRcdFx0XHRcdC5fbW92ZUVuZCh0cnVlKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX21vdmVTdGFydCh0cnVlLCBvcHRpb25zLm5vTW92ZVN0YXJ0KTtcclxuXHJcblx0XHRmcmFtZS5jYWxsKHRoaXMpO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBmbHlUb0JvdW5kcyhib3VuZHM6IExhdExuZ0JvdW5kcywgb3B0aW9ucz86IGZpdEJvdW5kcyBvcHRpb25zKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIHZpZXcgb2YgdGhlIG1hcCB3aXRoIGEgc21vb3RoIGFuaW1hdGlvbiBsaWtlIFtgZmx5VG9gXSgjbWFwLWZseXRvKSxcclxuXHQvLyBidXQgdGFrZXMgYSBib3VuZHMgcGFyYW1ldGVyIGxpa2UgW2BmaXRCb3VuZHNgXSgjbWFwLWZpdGJvdW5kcykuXHJcblx0Zmx5VG9Cb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMsIG9wdGlvbnMpIHtcclxuXHRcdHZhciB0YXJnZXQgPSB0aGlzLl9nZXRCb3VuZHNDZW50ZXJab29tKGJvdW5kcywgb3B0aW9ucyk7XHJcblx0XHRyZXR1cm4gdGhpcy5mbHlUbyh0YXJnZXQuY2VudGVyLCB0YXJnZXQuem9vbSwgb3B0aW9ucyk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRNYXhCb3VuZHMoYm91bmRzOiBCb3VuZHMpOiB0aGlzXHJcblx0Ly8gUmVzdHJpY3RzIHRoZSBtYXAgdmlldyB0byB0aGUgZ2l2ZW4gYm91bmRzIChzZWUgdGhlIFttYXhCb3VuZHNdKCNtYXAtbWF4Ym91bmRzKSBvcHRpb24pLlxyXG5cdHNldE1heEJvdW5kczogZnVuY3Rpb24gKGJvdW5kcykge1xyXG5cdFx0Ym91bmRzID0gdG9MYXRMbmdCb3VuZHMoYm91bmRzKTtcclxuXHJcblx0XHRpZiAoIWJvdW5kcy5pc1ZhbGlkKCkpIHtcclxuXHRcdFx0dGhpcy5vcHRpb25zLm1heEJvdW5kcyA9IG51bGw7XHJcblx0XHRcdHJldHVybiB0aGlzLm9mZignbW92ZWVuZCcsIHRoaXMuX3Bhbkluc2lkZU1heEJvdW5kcyk7XHJcblx0XHR9IGVsc2UgaWYgKHRoaXMub3B0aW9ucy5tYXhCb3VuZHMpIHtcclxuXHRcdFx0dGhpcy5vZmYoJ21vdmVlbmQnLCB0aGlzLl9wYW5JbnNpZGVNYXhCb3VuZHMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMub3B0aW9ucy5tYXhCb3VuZHMgPSBib3VuZHM7XHJcblxyXG5cdFx0aWYgKHRoaXMuX2xvYWRlZCkge1xyXG5cdFx0XHR0aGlzLl9wYW5JbnNpZGVNYXhCb3VuZHMoKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcy5vbignbW92ZWVuZCcsIHRoaXMuX3Bhbkluc2lkZU1heEJvdW5kcyk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRNaW5ab29tKHpvb206IE51bWJlcik6IHRoaXNcclxuXHQvLyBTZXRzIHRoZSBsb3dlciBsaW1pdCBmb3IgdGhlIGF2YWlsYWJsZSB6b29tIGxldmVscyAoc2VlIHRoZSBbbWluWm9vbV0oI21hcC1taW56b29tKSBvcHRpb24pLlxyXG5cdHNldE1pblpvb206IGZ1bmN0aW9uICh6b29tKSB7XHJcblx0XHR2YXIgb2xkWm9vbSA9IHRoaXMub3B0aW9ucy5taW5ab29tO1xyXG5cdFx0dGhpcy5vcHRpb25zLm1pblpvb20gPSB6b29tO1xyXG5cclxuXHRcdGlmICh0aGlzLl9sb2FkZWQgJiYgb2xkWm9vbSAhPT0gem9vbSkge1xyXG5cdFx0XHR0aGlzLmZpcmUoJ3pvb21sZXZlbHNjaGFuZ2UnKTtcclxuXHJcblx0XHRcdGlmICh0aGlzLmdldFpvb20oKSA8IHRoaXMub3B0aW9ucy5taW5ab29tKSB7XHJcblx0XHRcdFx0cmV0dXJuIHRoaXMuc2V0Wm9vbSh6b29tKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0TWF4Wm9vbSh6b29tOiBOdW1iZXIpOiB0aGlzXHJcblx0Ly8gU2V0cyB0aGUgdXBwZXIgbGltaXQgZm9yIHRoZSBhdmFpbGFibGUgem9vbSBsZXZlbHMgKHNlZSB0aGUgW21heFpvb21dKCNtYXAtbWF4em9vbSkgb3B0aW9uKS5cclxuXHRzZXRNYXhab29tOiBmdW5jdGlvbiAoem9vbSkge1xyXG5cdFx0dmFyIG9sZFpvb20gPSB0aGlzLm9wdGlvbnMubWF4Wm9vbTtcclxuXHRcdHRoaXMub3B0aW9ucy5tYXhab29tID0gem9vbTtcclxuXHJcblx0XHRpZiAodGhpcy5fbG9hZGVkICYmIG9sZFpvb20gIT09IHpvb20pIHtcclxuXHRcdFx0dGhpcy5maXJlKCd6b29tbGV2ZWxzY2hhbmdlJyk7XHJcblxyXG5cdFx0XHRpZiAodGhpcy5nZXRab29tKCkgPiB0aGlzLm9wdGlvbnMubWF4Wm9vbSkge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLnNldFpvb20oem9vbSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHBhbkluc2lkZUJvdW5kcyhib3VuZHM6IExhdExuZ0JvdW5kcywgb3B0aW9ucz86IFBhbiBvcHRpb25zKTogdGhpc1xyXG5cdC8vIFBhbnMgdGhlIG1hcCB0byB0aGUgY2xvc2VzdCB2aWV3IHRoYXQgd291bGQgbGllIGluc2lkZSB0aGUgZ2l2ZW4gYm91bmRzIChpZiBpdCdzIG5vdCBhbHJlYWR5KSwgY29udHJvbGxpbmcgdGhlIGFuaW1hdGlvbiB1c2luZyB0aGUgb3B0aW9ucyBzcGVjaWZpYywgaWYgYW55LlxyXG5cdHBhbkluc2lkZUJvdW5kczogZnVuY3Rpb24gKGJvdW5kcywgb3B0aW9ucykge1xyXG5cdFx0dGhpcy5fZW5mb3JjaW5nQm91bmRzID0gdHJ1ZTtcclxuXHRcdHZhciBjZW50ZXIgPSB0aGlzLmdldENlbnRlcigpLFxyXG5cdFx0ICAgIG5ld0NlbnRlciA9IHRoaXMuX2xpbWl0Q2VudGVyKGNlbnRlciwgdGhpcy5fem9vbSwgdG9MYXRMbmdCb3VuZHMoYm91bmRzKSk7XHJcblxyXG5cdFx0aWYgKCFjZW50ZXIuZXF1YWxzKG5ld0NlbnRlcikpIHtcclxuXHRcdFx0dGhpcy5wYW5UbyhuZXdDZW50ZXIsIG9wdGlvbnMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2VuZm9yY2luZ0JvdW5kcyA9IGZhbHNlO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBwYW5JbnNpZGUobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBvcHRpb25zKTogdGhpc1xyXG5cdC8vIFBhbnMgdGhlIG1hcCB0aGUgbWluaW11bSBhbW91bnQgdG8gbWFrZSB0aGUgYGxhdGxuZ2AgdmlzaWJsZS4gVXNlXHJcblx0Ly8gYHBhZGRpbmdgLCBgcGFkZGluZ1RvcExlZnRgIGFuZCBgcGFkZGluZ1RvcFJpZ2h0YCBvcHRpb25zIHRvIGZpdFxyXG5cdC8vIHRoZSBkaXNwbGF5IHRvIG1vcmUgcmVzdHJpY3RlZCBib3VuZHMsIGxpa2UgW2BmaXRCb3VuZHNgXSgjbWFwLWZpdGJvdW5kcykuXHJcblx0Ly8gSWYgYGxhdGxuZ2AgaXMgYWxyZWFkeSB3aXRoaW4gdGhlIChvcHRpb25hbGx5IHBhZGRlZCkgZGlzcGxheSBib3VuZHMsXHJcblx0Ly8gdGhlIG1hcCB3aWxsIG5vdCBiZSBwYW5uZWQuXHJcblx0cGFuSW5zaWRlOiBmdW5jdGlvbiAobGF0bG5nLCBvcHRpb25zKSB7XHJcblx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcclxuXHJcblx0XHR2YXIgcGFkZGluZ1RMID0gdG9Qb2ludChvcHRpb25zLnBhZGRpbmdUb3BMZWZ0IHx8IG9wdGlvbnMucGFkZGluZyB8fCBbMCwgMF0pLFxyXG5cdFx0ICAgIHBhZGRpbmdCUiA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nQm90dG9tUmlnaHQgfHwgb3B0aW9ucy5wYWRkaW5nIHx8IFswLCAwXSksXHJcblx0XHQgICAgY2VudGVyID0gdGhpcy5nZXRDZW50ZXIoKSxcclxuXHRcdCAgICBwaXhlbENlbnRlciA9IHRoaXMucHJvamVjdChjZW50ZXIpLFxyXG5cdFx0ICAgIHBpeGVsUG9pbnQgPSB0aGlzLnByb2plY3QobGF0bG5nKSxcclxuXHRcdCAgICBwaXhlbEJvdW5kcyA9IHRoaXMuZ2V0UGl4ZWxCb3VuZHMoKSxcclxuXHRcdCAgICBoYWxmUGl4ZWxCb3VuZHMgPSBwaXhlbEJvdW5kcy5nZXRTaXplKCkuZGl2aWRlQnkoMiksXHJcblx0XHQgICAgcGFkZGVkQm91bmRzID0gdG9Cb3VuZHMoW3BpeGVsQm91bmRzLm1pbi5hZGQocGFkZGluZ1RMKSwgcGl4ZWxCb3VuZHMubWF4LnN1YnRyYWN0KHBhZGRpbmdCUildKTtcclxuXHJcblx0XHRpZiAoIXBhZGRlZEJvdW5kcy5jb250YWlucyhwaXhlbFBvaW50KSkge1xyXG5cdFx0XHR0aGlzLl9lbmZvcmNpbmdCb3VuZHMgPSB0cnVlO1xyXG5cdFx0XHR2YXIgZGlmZiA9IHBpeGVsQ2VudGVyLnN1YnRyYWN0KHBpeGVsUG9pbnQpLFxyXG5cdFx0XHQgICAgbmV3Q2VudGVyID0gdG9Qb2ludChwaXhlbFBvaW50LnggKyBkaWZmLngsIHBpeGVsUG9pbnQueSArIGRpZmYueSk7XHJcblxyXG5cdFx0XHRpZiAocGl4ZWxQb2ludC54IDwgcGFkZGVkQm91bmRzLm1pbi54IHx8IHBpeGVsUG9pbnQueCA+IHBhZGRlZEJvdW5kcy5tYXgueCkge1xyXG5cdFx0XHRcdG5ld0NlbnRlci54ID0gcGl4ZWxDZW50ZXIueCAtIGRpZmYueDtcclxuXHRcdFx0XHRpZiAoZGlmZi54ID4gMCkge1xyXG5cdFx0XHRcdFx0bmV3Q2VudGVyLnggKz0gaGFsZlBpeGVsQm91bmRzLnggLSBwYWRkaW5nVEwueDtcclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0bmV3Q2VudGVyLnggLT0gaGFsZlBpeGVsQm91bmRzLnggLSBwYWRkaW5nQlIueDtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKHBpeGVsUG9pbnQueSA8IHBhZGRlZEJvdW5kcy5taW4ueSB8fCBwaXhlbFBvaW50LnkgPiBwYWRkZWRCb3VuZHMubWF4LnkpIHtcclxuXHRcdFx0XHRuZXdDZW50ZXIueSA9IHBpeGVsQ2VudGVyLnkgLSBkaWZmLnk7XHJcblx0XHRcdFx0aWYgKGRpZmYueSA+IDApIHtcclxuXHRcdFx0XHRcdG5ld0NlbnRlci55ICs9IGhhbGZQaXhlbEJvdW5kcy55IC0gcGFkZGluZ1RMLnk7XHJcblx0XHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRcdG5ld0NlbnRlci55IC09IGhhbGZQaXhlbEJvdW5kcy55IC0gcGFkZGluZ0JSLnk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXMucGFuVG8odGhpcy51bnByb2plY3QobmV3Q2VudGVyKSwgb3B0aW9ucyk7XHJcblx0XHRcdHRoaXMuX2VuZm9yY2luZ0JvdW5kcyA9IGZhbHNlO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBpbnZhbGlkYXRlU2l6ZShvcHRpb25zOiBab29tL3BhbiBvcHRpb25zKTogdGhpc1xyXG5cdC8vIENoZWNrcyBpZiB0aGUgbWFwIGNvbnRhaW5lciBzaXplIGNoYW5nZWQgYW5kIHVwZGF0ZXMgdGhlIG1hcCBpZiBzbyDigJRcclxuXHQvLyBjYWxsIGl0IGFmdGVyIHlvdSd2ZSBjaGFuZ2VkIHRoZSBtYXAgc2l6ZSBkeW5hbWljYWxseSwgYWxzbyBhbmltYXRpbmdcclxuXHQvLyBwYW4gYnkgZGVmYXVsdC4gSWYgYG9wdGlvbnMucGFuYCBpcyBgZmFsc2VgLCBwYW5uaW5nIHdpbGwgbm90IG9jY3VyLlxyXG5cdC8vIElmIGBvcHRpb25zLmRlYm91bmNlTW92ZWVuZGAgaXMgYHRydWVgLCBpdCB3aWxsIGRlbGF5IGBtb3ZlZW5kYCBldmVudCBzb1xyXG5cdC8vIHRoYXQgaXQgZG9lc24ndCBoYXBwZW4gb2Z0ZW4gZXZlbiBpZiB0aGUgbWV0aG9kIGlzIGNhbGxlZCBtYW55XHJcblx0Ly8gdGltZXMgaW4gYSByb3cuXHJcblxyXG5cdC8vIEBhbHRlcm5hdGl2ZVxyXG5cdC8vIEBtZXRob2QgaW52YWxpZGF0ZVNpemUoYW5pbWF0ZTogQm9vbGVhbik6IHRoaXNcclxuXHQvLyBDaGVja3MgaWYgdGhlIG1hcCBjb250YWluZXIgc2l6ZSBjaGFuZ2VkIGFuZCB1cGRhdGVzIHRoZSBtYXAgaWYgc28g4oCUXHJcblx0Ly8gY2FsbCBpdCBhZnRlciB5b3UndmUgY2hhbmdlZCB0aGUgbWFwIHNpemUgZHluYW1pY2FsbHksIGFsc28gYW5pbWF0aW5nXHJcblx0Ly8gcGFuIGJ5IGRlZmF1bHQuXHJcblx0aW52YWxpZGF0ZVNpemU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblx0XHRpZiAoIXRoaXMuX2xvYWRlZCkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdG9wdGlvbnMgPSBleHRlbmQoe1xyXG5cdFx0XHRhbmltYXRlOiBmYWxzZSxcclxuXHRcdFx0cGFuOiB0cnVlXHJcblx0XHR9LCBvcHRpb25zID09PSB0cnVlID8ge2FuaW1hdGU6IHRydWV9IDogb3B0aW9ucyk7XHJcblxyXG5cdFx0dmFyIG9sZFNpemUgPSB0aGlzLmdldFNpemUoKTtcclxuXHRcdHRoaXMuX3NpemVDaGFuZ2VkID0gdHJ1ZTtcclxuXHRcdHRoaXMuX2xhc3RDZW50ZXIgPSBudWxsO1xyXG5cclxuXHRcdHZhciBuZXdTaXplID0gdGhpcy5nZXRTaXplKCksXHJcblx0XHQgICAgb2xkQ2VudGVyID0gb2xkU2l6ZS5kaXZpZGVCeSgyKS5yb3VuZCgpLFxyXG5cdFx0ICAgIG5ld0NlbnRlciA9IG5ld1NpemUuZGl2aWRlQnkoMikucm91bmQoKSxcclxuXHRcdCAgICBvZmZzZXQgPSBvbGRDZW50ZXIuc3VidHJhY3QobmV3Q2VudGVyKTtcclxuXHJcblx0XHRpZiAoIW9mZnNldC54ICYmICFvZmZzZXQueSkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdGlmIChvcHRpb25zLmFuaW1hdGUgJiYgb3B0aW9ucy5wYW4pIHtcclxuXHRcdFx0dGhpcy5wYW5CeShvZmZzZXQpO1xyXG5cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGlmIChvcHRpb25zLnBhbikge1xyXG5cdFx0XHRcdHRoaXMuX3Jhd1BhbkJ5KG9mZnNldCk7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHRoaXMuZmlyZSgnbW92ZScpO1xyXG5cclxuXHRcdFx0aWYgKG9wdGlvbnMuZGVib3VuY2VNb3ZlZW5kKSB7XHJcblx0XHRcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3NpemVUaW1lcik7XHJcblx0XHRcdFx0dGhpcy5fc2l6ZVRpbWVyID0gc2V0VGltZW91dChiaW5kKHRoaXMuZmlyZSwgdGhpcywgJ21vdmVlbmQnKSwgMjAwKTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHR0aGlzLmZpcmUoJ21vdmVlbmQnKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIEBzZWN0aW9uIE1hcCBzdGF0ZSBjaGFuZ2UgZXZlbnRzXHJcblx0XHQvLyBAZXZlbnQgcmVzaXplOiBSZXNpemVFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIGlzIHJlc2l6ZWQuXHJcblx0XHRyZXR1cm4gdGhpcy5maXJlKCdyZXNpemUnLCB7XHJcblx0XHRcdG9sZFNpemU6IG9sZFNpemUsXHJcblx0XHRcdG5ld1NpemU6IG5ld1NpemVcclxuXHRcdH0pO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBzZWN0aW9uIE1ldGhvZHMgZm9yIG1vZGlmeWluZyBtYXAgc3RhdGVcclxuXHQvLyBAbWV0aG9kIHN0b3AoKTogdGhpc1xyXG5cdC8vIFN0b3BzIHRoZSBjdXJyZW50bHkgcnVubmluZyBgcGFuVG9gIG9yIGBmbHlUb2AgYW5pbWF0aW9uLCBpZiBhbnkuXHJcblx0c3RvcDogZnVuY3Rpb24gKCkge1xyXG5cdFx0dGhpcy5zZXRab29tKHRoaXMuX2xpbWl0Wm9vbSh0aGlzLl96b29tKSk7XHJcblx0XHRpZiAoIXRoaXMub3B0aW9ucy56b29tU25hcCkge1xyXG5cdFx0XHR0aGlzLmZpcmUoJ3ZpZXdyZXNldCcpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXMuX3N0b3AoKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAc2VjdGlvbiBHZW9sb2NhdGlvbiBtZXRob2RzXHJcblx0Ly8gQG1ldGhvZCBsb2NhdGUob3B0aW9ucz86IExvY2F0ZSBvcHRpb25zKTogdGhpc1xyXG5cdC8vIFRyaWVzIHRvIGxvY2F0ZSB0aGUgdXNlciB1c2luZyB0aGUgR2VvbG9jYXRpb24gQVBJLCBmaXJpbmcgYSBbYGxvY2F0aW9uZm91bmRgXSgjbWFwLWxvY2F0aW9uZm91bmQpXHJcblx0Ly8gZXZlbnQgd2l0aCBsb2NhdGlvbiBkYXRhIG9uIHN1Y2Nlc3Mgb3IgYSBbYGxvY2F0aW9uZXJyb3JgXSgjbWFwLWxvY2F0aW9uZXJyb3IpIGV2ZW50IG9uIGZhaWx1cmUsXHJcblx0Ly8gYW5kIG9wdGlvbmFsbHkgc2V0cyB0aGUgbWFwIHZpZXcgdG8gdGhlIHVzZXIncyBsb2NhdGlvbiB3aXRoIHJlc3BlY3QgdG9cclxuXHQvLyBkZXRlY3Rpb24gYWNjdXJhY3kgKG9yIHRvIHRoZSB3b3JsZCB2aWV3IGlmIGdlb2xvY2F0aW9uIGZhaWxlZCkuXHJcblx0Ly8gTm90ZSB0aGF0LCBpZiB5b3VyIHBhZ2UgZG9lc24ndCB1c2UgSFRUUFMsIHRoaXMgbWV0aG9kIHdpbGwgZmFpbCBpblxyXG5cdC8vIG1vZGVybiBicm93c2VycyAoW0Nocm9tZSA1MCBhbmQgbmV3ZXJdKGh0dHBzOi8vc2l0ZXMuZ29vZ2xlLmNvbS9hL2Nocm9taXVtLm9yZy9kZXYvSG9tZS9jaHJvbWl1bS1zZWN1cml0eS9kZXByZWNhdGluZy1wb3dlcmZ1bC1mZWF0dXJlcy1vbi1pbnNlY3VyZS1vcmlnaW5zKSlcclxuXHQvLyBTZWUgYExvY2F0ZSBvcHRpb25zYCBmb3IgbW9yZSBkZXRhaWxzLlxyXG5cdGxvY2F0ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuXHJcblx0XHRvcHRpb25zID0gdGhpcy5fbG9jYXRlT3B0aW9ucyA9IGV4dGVuZCh7XHJcblx0XHRcdHRpbWVvdXQ6IDEwMDAwLFxyXG5cdFx0XHR3YXRjaDogZmFsc2VcclxuXHRcdFx0Ly8gc2V0VmlldzogZmFsc2VcclxuXHRcdFx0Ly8gbWF4Wm9vbTogPE51bWJlcj5cclxuXHRcdFx0Ly8gbWF4aW11bUFnZTogMFxyXG5cdFx0XHQvLyBlbmFibGVIaWdoQWNjdXJhY3k6IGZhbHNlXHJcblx0XHR9LCBvcHRpb25zKTtcclxuXHJcblx0XHRpZiAoISgnZ2VvbG9jYXRpb24nIGluIG5hdmlnYXRvcikpIHtcclxuXHRcdFx0dGhpcy5faGFuZGxlR2VvbG9jYXRpb25FcnJvcih7XHJcblx0XHRcdFx0Y29kZTogMCxcclxuXHRcdFx0XHRtZXNzYWdlOiAnR2VvbG9jYXRpb24gbm90IHN1cHBvcnRlZC4nXHJcblx0XHRcdH0pO1xyXG5cdFx0XHRyZXR1cm4gdGhpcztcclxuXHRcdH1cclxuXHJcblx0XHR2YXIgb25SZXNwb25zZSA9IGJpbmQodGhpcy5faGFuZGxlR2VvbG9jYXRpb25SZXNwb25zZSwgdGhpcyksXHJcblx0XHQgICAgb25FcnJvciA9IGJpbmQodGhpcy5faGFuZGxlR2VvbG9jYXRpb25FcnJvciwgdGhpcyk7XHJcblxyXG5cdFx0aWYgKG9wdGlvbnMud2F0Y2gpIHtcclxuXHRcdFx0dGhpcy5fbG9jYXRpb25XYXRjaElkID1cclxuXHRcdFx0ICAgICAgICBuYXZpZ2F0b3IuZ2VvbG9jYXRpb24ud2F0Y2hQb3NpdGlvbihvblJlc3BvbnNlLCBvbkVycm9yLCBvcHRpb25zKTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdG5hdmlnYXRvci5nZW9sb2NhdGlvbi5nZXRDdXJyZW50UG9zaXRpb24ob25SZXNwb25zZSwgb25FcnJvciwgb3B0aW9ucyk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHN0b3BMb2NhdGUoKTogdGhpc1xyXG5cdC8vIFN0b3BzIHdhdGNoaW5nIGxvY2F0aW9uIHByZXZpb3VzbHkgaW5pdGlhdGVkIGJ5IGBtYXAubG9jYXRlKHt3YXRjaDogdHJ1ZX0pYFxyXG5cdC8vIGFuZCBhYm9ydHMgcmVzZXR0aW5nIHRoZSBtYXAgdmlldyBpZiBtYXAubG9jYXRlIHdhcyBjYWxsZWQgd2l0aFxyXG5cdC8vIGB7c2V0VmlldzogdHJ1ZX1gLlxyXG5cdHN0b3BMb2NhdGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmIChuYXZpZ2F0b3IuZ2VvbG9jYXRpb24gJiYgbmF2aWdhdG9yLmdlb2xvY2F0aW9uLmNsZWFyV2F0Y2gpIHtcclxuXHRcdFx0bmF2aWdhdG9yLmdlb2xvY2F0aW9uLmNsZWFyV2F0Y2godGhpcy5fbG9jYXRpb25XYXRjaElkKTtcclxuXHRcdH1cclxuXHRcdGlmICh0aGlzLl9sb2NhdGVPcHRpb25zKSB7XHJcblx0XHRcdHRoaXMuX2xvY2F0ZU9wdGlvbnMuc2V0VmlldyA9IGZhbHNlO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0X2hhbmRsZUdlb2xvY2F0aW9uRXJyb3I6IGZ1bmN0aW9uIChlcnJvcikge1xyXG5cdFx0dmFyIGMgPSBlcnJvci5jb2RlLFxyXG5cdFx0ICAgIG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlIHx8XHJcblx0XHQgICAgICAgICAgICAoYyA9PT0gMSA/ICdwZXJtaXNzaW9uIGRlbmllZCcgOlxyXG5cdFx0ICAgICAgICAgICAgKGMgPT09IDIgPyAncG9zaXRpb24gdW5hdmFpbGFibGUnIDogJ3RpbWVvdXQnKSk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX2xvY2F0ZU9wdGlvbnMuc2V0VmlldyAmJiAhdGhpcy5fbG9hZGVkKSB7XHJcblx0XHRcdHRoaXMuZml0V29ybGQoKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBAc2VjdGlvbiBMb2NhdGlvbiBldmVudHNcclxuXHRcdC8vIEBldmVudCBsb2NhdGlvbmVycm9yOiBFcnJvckV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIGdlb2xvY2F0aW9uICh1c2luZyB0aGUgW2Bsb2NhdGVgXSgjbWFwLWxvY2F0ZSkgbWV0aG9kKSBmYWlsZWQuXHJcblx0XHR0aGlzLmZpcmUoJ2xvY2F0aW9uZXJyb3InLCB7XHJcblx0XHRcdGNvZGU6IGMsXHJcblx0XHRcdG1lc3NhZ2U6ICdHZW9sb2NhdGlvbiBlcnJvcjogJyArIG1lc3NhZ2UgKyAnLidcclxuXHRcdH0pO1xyXG5cdH0sXHJcblxyXG5cdF9oYW5kbGVHZW9sb2NhdGlvblJlc3BvbnNlOiBmdW5jdGlvbiAocG9zKSB7XHJcblx0XHR2YXIgbGF0ID0gcG9zLmNvb3Jkcy5sYXRpdHVkZSxcclxuXHRcdCAgICBsbmcgPSBwb3MuY29vcmRzLmxvbmdpdHVkZSxcclxuXHRcdCAgICBsYXRsbmcgPSBuZXcgTGF0TG5nKGxhdCwgbG5nKSxcclxuXHRcdCAgICBib3VuZHMgPSBsYXRsbmcudG9Cb3VuZHMocG9zLmNvb3Jkcy5hY2N1cmFjeSAqIDIpLFxyXG5cdFx0ICAgIG9wdGlvbnMgPSB0aGlzLl9sb2NhdGVPcHRpb25zO1xyXG5cclxuXHRcdGlmIChvcHRpb25zLnNldFZpZXcpIHtcclxuXHRcdFx0dmFyIHpvb20gPSB0aGlzLmdldEJvdW5kc1pvb20oYm91bmRzKTtcclxuXHRcdFx0dGhpcy5zZXRWaWV3KGxhdGxuZywgb3B0aW9ucy5tYXhab29tID8gTWF0aC5taW4oem9vbSwgb3B0aW9ucy5tYXhab29tKSA6IHpvb20pO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBkYXRhID0ge1xyXG5cdFx0XHRsYXRsbmc6IGxhdGxuZyxcclxuXHRcdFx0Ym91bmRzOiBib3VuZHMsXHJcblx0XHRcdHRpbWVzdGFtcDogcG9zLnRpbWVzdGFtcFxyXG5cdFx0fTtcclxuXHJcblx0XHRmb3IgKHZhciBpIGluIHBvcy5jb29yZHMpIHtcclxuXHRcdFx0aWYgKHR5cGVvZiBwb3MuY29vcmRzW2ldID09PSAnbnVtYmVyJykge1xyXG5cdFx0XHRcdGRhdGFbaV0gPSBwb3MuY29vcmRzW2ldO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQGV2ZW50IGxvY2F0aW9uZm91bmQ6IExvY2F0aW9uRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gZ2VvbG9jYXRpb24gKHVzaW5nIHRoZSBbYGxvY2F0ZWBdKCNtYXAtbG9jYXRlKSBtZXRob2QpXHJcblx0XHQvLyB3ZW50IHN1Y2Nlc3NmdWxseS5cclxuXHRcdHRoaXMuZmlyZSgnbG9jYXRpb25mb3VuZCcsIGRhdGEpO1xyXG5cdH0sXHJcblxyXG5cdC8vIFRPRE8gQXBwcm9wcmlhdGUgZG9jcyBzZWN0aW9uP1xyXG5cdC8vIEBzZWN0aW9uIE90aGVyIE1ldGhvZHNcclxuXHQvLyBAbWV0aG9kIGFkZEhhbmRsZXIobmFtZTogU3RyaW5nLCBIYW5kbGVyQ2xhc3M6IEZ1bmN0aW9uKTogdGhpc1xyXG5cdC8vIEFkZHMgYSBuZXcgYEhhbmRsZXJgIHRvIHRoZSBtYXAsIGdpdmVuIGl0cyBuYW1lIGFuZCBjb25zdHJ1Y3RvciBmdW5jdGlvbi5cclxuXHRhZGRIYW5kbGVyOiBmdW5jdGlvbiAobmFtZSwgSGFuZGxlckNsYXNzKSB7XHJcblx0XHRpZiAoIUhhbmRsZXJDbGFzcykgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdHZhciBoYW5kbGVyID0gdGhpc1tuYW1lXSA9IG5ldyBIYW5kbGVyQ2xhc3ModGhpcyk7XHJcblxyXG5cdFx0dGhpcy5faGFuZGxlcnMucHVzaChoYW5kbGVyKTtcclxuXHJcblx0XHRpZiAodGhpcy5vcHRpb25zW25hbWVdKSB7XHJcblx0XHRcdGhhbmRsZXIuZW5hYmxlKCk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCByZW1vdmUoKTogdGhpc1xyXG5cdC8vIERlc3Ryb3lzIHRoZSBtYXAgYW5kIGNsZWFycyBhbGwgcmVsYXRlZCBldmVudCBsaXN0ZW5lcnMuXHJcblx0cmVtb3ZlOiBmdW5jdGlvbiAoKSB7XHJcblxyXG5cdFx0dGhpcy5faW5pdEV2ZW50cyh0cnVlKTtcclxuXHJcblx0XHRpZiAodGhpcy5fY29udGFpbmVySWQgIT09IHRoaXMuX2NvbnRhaW5lci5fbGVhZmxldF9pZCkge1xyXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01hcCBjb250YWluZXIgaXMgYmVpbmcgcmV1c2VkIGJ5IGFub3RoZXIgaW5zdGFuY2UnKTtcclxuXHRcdH1cclxuXHJcblx0XHR0cnkge1xyXG5cdFx0XHQvLyB0aHJvd3MgZXJyb3IgaW4gSUU2LThcclxuXHRcdFx0ZGVsZXRlIHRoaXMuX2NvbnRhaW5lci5fbGVhZmxldF9pZDtcclxuXHRcdFx0ZGVsZXRlIHRoaXMuX2NvbnRhaW5lcklkO1xyXG5cdFx0fSBjYXRjaCAoZSkge1xyXG5cdFx0XHQvKmVzbGludC1kaXNhYmxlICovXHJcblx0XHRcdHRoaXMuX2NvbnRhaW5lci5fbGVhZmxldF9pZCA9IHVuZGVmaW5lZDtcclxuXHRcdFx0LyogZXNsaW50LWVuYWJsZSAqL1xyXG5cdFx0XHR0aGlzLl9jb250YWluZXJJZCA9IHVuZGVmaW5lZDtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAodGhpcy5fbG9jYXRpb25XYXRjaElkICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0dGhpcy5zdG9wTG9jYXRlKCk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fc3RvcCgpO1xyXG5cclxuXHRcdHJlbW92ZSh0aGlzLl9tYXBQYW5lKTtcclxuXHJcblx0XHRpZiAodGhpcy5fY2xlYXJDb250cm9sUG9zKSB7XHJcblx0XHRcdHRoaXMuX2NsZWFyQ29udHJvbFBvcygpO1xyXG5cdFx0fVxyXG5cdFx0aWYgKHRoaXMuX3Jlc2l6ZVJlcXVlc3QpIHtcclxuXHRcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX3Jlc2l6ZVJlcXVlc3QpO1xyXG5cdFx0XHR0aGlzLl9yZXNpemVSZXF1ZXN0ID0gbnVsbDtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9jbGVhckhhbmRsZXJzKCk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX2xvYWRlZCkge1xyXG5cdFx0XHQvLyBAc2VjdGlvbiBNYXAgc3RhdGUgY2hhbmdlIGV2ZW50c1xyXG5cdFx0XHQvLyBAZXZlbnQgdW5sb2FkOiBFdmVudFxyXG5cdFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBtYXAgaXMgZGVzdHJveWVkIHdpdGggW3JlbW92ZV0oI21hcC1yZW1vdmUpIG1ldGhvZC5cclxuXHRcdFx0dGhpcy5maXJlKCd1bmxvYWQnKTtcclxuXHRcdH1cclxuXHJcblx0XHR2YXIgaTtcclxuXHRcdGZvciAoaSBpbiB0aGlzLl9sYXllcnMpIHtcclxuXHRcdFx0dGhpcy5fbGF5ZXJzW2ldLnJlbW92ZSgpO1xyXG5cdFx0fVxyXG5cdFx0Zm9yIChpIGluIHRoaXMuX3BhbmVzKSB7XHJcblx0XHRcdHJlbW92ZSh0aGlzLl9wYW5lc1tpXSk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fbGF5ZXJzID0gW107XHJcblx0XHR0aGlzLl9wYW5lcyA9IFtdO1xyXG5cdFx0ZGVsZXRlIHRoaXMuX21hcFBhbmU7XHJcblx0XHRkZWxldGUgdGhpcy5fcmVuZGVyZXI7XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQHNlY3Rpb24gT3RoZXIgTWV0aG9kc1xyXG5cdC8vIEBtZXRob2QgY3JlYXRlUGFuZShuYW1lOiBTdHJpbmcsIGNvbnRhaW5lcj86IEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuXHQvLyBDcmVhdGVzIGEgbmV3IFttYXAgcGFuZV0oI21hcC1wYW5lKSB3aXRoIHRoZSBnaXZlbiBuYW1lIGlmIGl0IGRvZXNuJ3QgZXhpc3QgYWxyZWFkeSxcclxuXHQvLyB0aGVuIHJldHVybnMgaXQuIFRoZSBwYW5lIGlzIGNyZWF0ZWQgYXMgYSBjaGlsZCBvZiBgY29udGFpbmVyYCwgb3JcclxuXHQvLyBhcyBhIGNoaWxkIG9mIHRoZSBtYWluIG1hcCBwYW5lIGlmIG5vdCBzZXQuXHJcblx0Y3JlYXRlUGFuZTogZnVuY3Rpb24gKG5hbWUsIGNvbnRhaW5lcikge1xyXG5cdFx0dmFyIGNsYXNzTmFtZSA9ICdsZWFmbGV0LXBhbmUnICsgKG5hbWUgPyAnIGxlYWZsZXQtJyArIG5hbWUucmVwbGFjZSgnUGFuZScsICcnKSArICctcGFuZScgOiAnJyksXHJcblx0XHQgICAgcGFuZSA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUsIGNvbnRhaW5lciB8fCB0aGlzLl9tYXBQYW5lKTtcclxuXHJcblx0XHRpZiAobmFtZSkge1xyXG5cdFx0XHR0aGlzLl9wYW5lc1tuYW1lXSA9IHBhbmU7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gcGFuZTtcclxuXHR9LFxyXG5cclxuXHQvLyBAc2VjdGlvbiBNZXRob2RzIGZvciBHZXR0aW5nIE1hcCBTdGF0ZVxyXG5cclxuXHQvLyBAbWV0aG9kIGdldENlbnRlcigpOiBMYXRMbmdcclxuXHQvLyBSZXR1cm5zIHRoZSBnZW9ncmFwaGljYWwgY2VudGVyIG9mIHRoZSBtYXAgdmlld1xyXG5cdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xyXG5cdFx0dGhpcy5fY2hlY2tJZkxvYWRlZCgpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9sYXN0Q2VudGVyICYmICF0aGlzLl9tb3ZlZCgpKSB7XHJcblx0XHRcdHJldHVybiB0aGlzLl9sYXN0Q2VudGVyO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXMubGF5ZXJQb2ludFRvTGF0TG5nKHRoaXMuX2dldENlbnRlckxheWVyUG9pbnQoKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRab29tKCk6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIGN1cnJlbnQgem9vbSBsZXZlbCBvZiB0aGUgbWFwIHZpZXdcclxuXHRnZXRab29tOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fem9vbTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldEJvdW5kcygpOiBMYXRMbmdCb3VuZHNcclxuXHQvLyBSZXR1cm5zIHRoZSBnZW9ncmFwaGljYWwgYm91bmRzIHZpc2libGUgaW4gdGhlIGN1cnJlbnQgbWFwIHZpZXdcclxuXHRnZXRCb3VuZHM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBib3VuZHMgPSB0aGlzLmdldFBpeGVsQm91bmRzKCksXHJcblx0XHQgICAgc3cgPSB0aGlzLnVucHJvamVjdChib3VuZHMuZ2V0Qm90dG9tTGVmdCgpKSxcclxuXHRcdCAgICBuZSA9IHRoaXMudW5wcm9qZWN0KGJvdW5kcy5nZXRUb3BSaWdodCgpKTtcclxuXHJcblx0XHRyZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhzdywgbmUpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0TWluWm9vbSgpOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBtaW5pbXVtIHpvb20gbGV2ZWwgb2YgdGhlIG1hcCAoaWYgc2V0IGluIHRoZSBgbWluWm9vbWAgb3B0aW9uIG9mIHRoZSBtYXAgb3Igb2YgYW55IGxheWVycyksIG9yIGAwYCBieSBkZWZhdWx0LlxyXG5cdGdldE1pblpvb206IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLm9wdGlvbnMubWluWm9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fbGF5ZXJzTWluWm9vbSB8fCAwIDogdGhpcy5vcHRpb25zLm1pblpvb207XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRNYXhab29tKCk6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIG1heGltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwIChpZiBzZXQgaW4gdGhlIGBtYXhab29tYCBvcHRpb24gb2YgdGhlIG1hcCBvciBvZiBhbnkgbGF5ZXJzKS5cclxuXHRnZXRNYXhab29tOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLm1heFpvb20gPT09IHVuZGVmaW5lZCA/XHJcblx0XHRcdCh0aGlzLl9sYXllcnNNYXhab29tID09PSB1bmRlZmluZWQgPyBJbmZpbml0eSA6IHRoaXMuX2xheWVyc01heFpvb20pIDpcclxuXHRcdFx0dGhpcy5vcHRpb25zLm1heFpvb207XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRCb3VuZHNab29tKGJvdW5kczogTGF0TG5nQm91bmRzLCBpbnNpZGU/OiBCb29sZWFuLCBwYWRkaW5nPzogUG9pbnQpOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBtYXhpbXVtIHpvb20gbGV2ZWwgb24gd2hpY2ggdGhlIGdpdmVuIGJvdW5kcyBmaXQgdG8gdGhlIG1hcFxyXG5cdC8vIHZpZXcgaW4gaXRzIGVudGlyZXR5LiBJZiBgaW5zaWRlYCAob3B0aW9uYWwpIGlzIHNldCB0byBgdHJ1ZWAsIHRoZSBtZXRob2RcclxuXHQvLyBpbnN0ZWFkIHJldHVybnMgdGhlIG1pbmltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgbWFwIHZpZXcgZml0cyBpbnRvXHJcblx0Ly8gdGhlIGdpdmVuIGJvdW5kcyBpbiBpdHMgZW50aXJldHkuXHJcblx0Z2V0Qm91bmRzWm9vbTogZnVuY3Rpb24gKGJvdW5kcywgaW5zaWRlLCBwYWRkaW5nKSB7IC8vIChMYXRMbmdCb3VuZHNbLCBCb29sZWFuLCBQb2ludF0pIC0+IE51bWJlclxyXG5cdFx0Ym91bmRzID0gdG9MYXRMbmdCb3VuZHMoYm91bmRzKTtcclxuXHRcdHBhZGRpbmcgPSB0b1BvaW50KHBhZGRpbmcgfHwgWzAsIDBdKTtcclxuXHJcblx0XHR2YXIgem9vbSA9IHRoaXMuZ2V0Wm9vbSgpIHx8IDAsXHJcblx0XHQgICAgbWluID0gdGhpcy5nZXRNaW5ab29tKCksXHJcblx0XHQgICAgbWF4ID0gdGhpcy5nZXRNYXhab29tKCksXHJcblx0XHQgICAgbncgPSBib3VuZHMuZ2V0Tm9ydGhXZXN0KCksXHJcblx0XHQgICAgc2UgPSBib3VuZHMuZ2V0U291dGhFYXN0KCksXHJcblx0XHQgICAgc2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpLnN1YnRyYWN0KHBhZGRpbmcpLFxyXG5cdFx0ICAgIGJvdW5kc1NpemUgPSB0b0JvdW5kcyh0aGlzLnByb2plY3Qoc2UsIHpvb20pLCB0aGlzLnByb2plY3QobncsIHpvb20pKS5nZXRTaXplKCksXHJcblx0XHQgICAgc25hcCA9IGFueTNkID8gdGhpcy5vcHRpb25zLnpvb21TbmFwIDogMSxcclxuXHRcdCAgICBzY2FsZXggPSBzaXplLnggLyBib3VuZHNTaXplLngsXHJcblx0XHQgICAgc2NhbGV5ID0gc2l6ZS55IC8gYm91bmRzU2l6ZS55LFxyXG5cdFx0ICAgIHNjYWxlID0gaW5zaWRlID8gTWF0aC5tYXgoc2NhbGV4LCBzY2FsZXkpIDogTWF0aC5taW4oc2NhbGV4LCBzY2FsZXkpO1xyXG5cclxuXHRcdHpvb20gPSB0aGlzLmdldFNjYWxlWm9vbShzY2FsZSwgem9vbSk7XHJcblxyXG5cdFx0aWYgKHNuYXApIHtcclxuXHRcdFx0em9vbSA9IE1hdGgucm91bmQoem9vbSAvIChzbmFwIC8gMTAwKSkgKiAoc25hcCAvIDEwMCk7IC8vIGRvbid0IGp1bXAgaWYgd2l0aGluIDElIG9mIGEgc25hcCBsZXZlbFxyXG5cdFx0XHR6b29tID0gaW5zaWRlID8gTWF0aC5jZWlsKHpvb20gLyBzbmFwKSAqIHNuYXAgOiBNYXRoLmZsb29yKHpvb20gLyBzbmFwKSAqIHNuYXA7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIE1hdGgubWF4KG1pbiwgTWF0aC5taW4obWF4LCB6b29tKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRTaXplKCk6IFBvaW50XHJcblx0Ly8gUmV0dXJucyB0aGUgY3VycmVudCBzaXplIG9mIHRoZSBtYXAgY29udGFpbmVyIChpbiBwaXhlbHMpLlxyXG5cdGdldFNpemU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICghdGhpcy5fc2l6ZSB8fCB0aGlzLl9zaXplQ2hhbmdlZCkge1xyXG5cdFx0XHR0aGlzLl9zaXplID0gbmV3IFBvaW50KFxyXG5cdFx0XHRcdHRoaXMuX2NvbnRhaW5lci5jbGllbnRXaWR0aCB8fCAwLFxyXG5cdFx0XHRcdHRoaXMuX2NvbnRhaW5lci5jbGllbnRIZWlnaHQgfHwgMCk7XHJcblxyXG5cdFx0XHR0aGlzLl9zaXplQ2hhbmdlZCA9IGZhbHNlO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXMuX3NpemUuY2xvbmUoKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldFBpeGVsQm91bmRzKCk6IEJvdW5kc1xyXG5cdC8vIFJldHVybnMgdGhlIGJvdW5kcyBvZiB0aGUgY3VycmVudCBtYXAgdmlldyBpbiBwcm9qZWN0ZWQgcGl4ZWxcclxuXHQvLyBjb29yZGluYXRlcyAoc29tZXRpbWVzIHVzZWZ1bCBpbiBsYXllciBhbmQgb3ZlcmxheSBpbXBsZW1lbnRhdGlvbnMpLlxyXG5cdGdldFBpeGVsQm91bmRzOiBmdW5jdGlvbiAoY2VudGVyLCB6b29tKSB7XHJcblx0XHR2YXIgdG9wTGVmdFBvaW50ID0gdGhpcy5fZ2V0VG9wTGVmdFBvaW50KGNlbnRlciwgem9vbSk7XHJcblx0XHRyZXR1cm4gbmV3IEJvdW5kcyh0b3BMZWZ0UG9pbnQsIHRvcExlZnRQb2ludC5hZGQodGhpcy5nZXRTaXplKCkpKTtcclxuXHR9LFxyXG5cclxuXHQvLyBUT0RPOiBDaGVjayBzZW1hbnRpY3MgLSBpc24ndCB0aGUgcGl4ZWwgb3JpZ2luIHRoZSAwLDAgY29vcmQgcmVsYXRpdmUgdG9cclxuXHQvLyB0aGUgbWFwIHBhbmU/IFwibGVmdCBwb2ludCBvZiB0aGUgbWFwIGxheWVyXCIgY2FuIGJlIGNvbmZ1c2luZywgc3BlY2lhbGx5XHJcblx0Ly8gc2luY2UgdGhlcmUgY2FuIGJlIG5lZ2F0aXZlIG9mZnNldHMuXHJcblx0Ly8gQG1ldGhvZCBnZXRQaXhlbE9yaWdpbigpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgdGhlIHByb2plY3RlZCBwaXhlbCBjb29yZGluYXRlcyBvZiB0aGUgdG9wIGxlZnQgcG9pbnQgb2ZcclxuXHQvLyB0aGUgbWFwIGxheWVyICh1c2VmdWwgaW4gY3VzdG9tIGxheWVyIGFuZCBvdmVybGF5IGltcGxlbWVudGF0aW9ucykuXHJcblx0Z2V0UGl4ZWxPcmlnaW46IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX2NoZWNrSWZMb2FkZWQoKTtcclxuXHRcdHJldHVybiB0aGlzLl9waXhlbE9yaWdpbjtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldFBpeGVsV29ybGRCb3VuZHMoem9vbT86IE51bWJlcik6IEJvdW5kc1xyXG5cdC8vIFJldHVybnMgdGhlIHdvcmxkJ3MgYm91bmRzIGluIHBpeGVsIGNvb3JkaW5hdGVzIGZvciB6b29tIGxldmVsIGB6b29tYC5cclxuXHQvLyBJZiBgem9vbWAgaXMgb21pdHRlZCwgdGhlIG1hcCdzIGN1cnJlbnQgem9vbSBsZXZlbCBpcyB1c2VkLlxyXG5cdGdldFBpeGVsV29ybGRCb3VuZHM6IGZ1bmN0aW9uICh6b29tKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5nZXRQcm9qZWN0ZWRCb3VuZHMoem9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5nZXRab29tKCkgOiB6b29tKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAc2VjdGlvbiBPdGhlciBNZXRob2RzXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0UGFuZShwYW5lOiBTdHJpbmd8SFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudFxyXG5cdC8vIFJldHVybnMgYSBbbWFwIHBhbmVdKCNtYXAtcGFuZSksIGdpdmVuIGl0cyBuYW1lIG9yIGl0cyBIVE1MIGVsZW1lbnQgKGl0cyBpZGVudGl0eSkuXHJcblx0Z2V0UGFuZTogZnVuY3Rpb24gKHBhbmUpIHtcclxuXHRcdHJldHVybiB0eXBlb2YgcGFuZSA9PT0gJ3N0cmluZycgPyB0aGlzLl9wYW5lc1twYW5lXSA6IHBhbmU7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRQYW5lcygpOiBPYmplY3RcclxuXHQvLyBSZXR1cm5zIGEgcGxhaW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIG5hbWVzIG9mIGFsbCBbcGFuZXNdKCNtYXAtcGFuZSkgYXMga2V5cyBhbmRcclxuXHQvLyB0aGUgcGFuZXMgYXMgdmFsdWVzLlxyXG5cdGdldFBhbmVzOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fcGFuZXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRDb250YWluZXI6IEhUTUxFbGVtZW50XHJcblx0Ly8gUmV0dXJucyB0aGUgSFRNTCBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIG1hcC5cclxuXHRnZXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9jb250YWluZXI7XHJcblx0fSxcclxuXHJcblxyXG5cdC8vIEBzZWN0aW9uIENvbnZlcnNpb24gTWV0aG9kc1xyXG5cclxuXHQvLyBAbWV0aG9kIGdldFpvb21TY2FsZSh0b1pvb206IE51bWJlciwgZnJvbVpvb206IE51bWJlcik6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIHNjYWxlIGZhY3RvciB0byBiZSBhcHBsaWVkIHRvIGEgbWFwIHRyYW5zaXRpb24gZnJvbSB6b29tIGxldmVsXHJcblx0Ly8gYGZyb21ab29tYCB0byBgdG9ab29tYC4gVXNlZCBpbnRlcm5hbGx5IHRvIGhlbHAgd2l0aCB6b29tIGFuaW1hdGlvbnMuXHJcblx0Z2V0Wm9vbVNjYWxlOiBmdW5jdGlvbiAodG9ab29tLCBmcm9tWm9vbSkge1xyXG5cdFx0Ly8gVE9ETyByZXBsYWNlIHdpdGggdW5pdmVyc2FsIGltcGxlbWVudGF0aW9uIGFmdGVyIHJlZmFjdG9yaW5nIHByb2plY3Rpb25zXHJcblx0XHR2YXIgY3JzID0gdGhpcy5vcHRpb25zLmNycztcclxuXHRcdGZyb21ab29tID0gZnJvbVpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuX3pvb20gOiBmcm9tWm9vbTtcclxuXHRcdHJldHVybiBjcnMuc2NhbGUodG9ab29tKSAvIGNycy5zY2FsZShmcm9tWm9vbSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRTY2FsZVpvb20oc2NhbGU6IE51bWJlciwgZnJvbVpvb206IE51bWJlcik6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIHpvb20gbGV2ZWwgdGhhdCB0aGUgbWFwIHdvdWxkIGVuZCB1cCBhdCwgaWYgaXQgaXMgYXQgYGZyb21ab29tYFxyXG5cdC8vIGxldmVsIGFuZCBldmVyeXRoaW5nIGlzIHNjYWxlZCBieSBhIGZhY3RvciBvZiBgc2NhbGVgLiBJbnZlcnNlIG9mXHJcblx0Ly8gW2BnZXRab29tU2NhbGVgXSgjbWFwLWdldFpvb21TY2FsZSkuXHJcblx0Z2V0U2NhbGVab29tOiBmdW5jdGlvbiAoc2NhbGUsIGZyb21ab29tKSB7XHJcblx0XHR2YXIgY3JzID0gdGhpcy5vcHRpb25zLmNycztcclxuXHRcdGZyb21ab29tID0gZnJvbVpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuX3pvb20gOiBmcm9tWm9vbTtcclxuXHRcdHZhciB6b29tID0gY3JzLnpvb20oc2NhbGUgKiBjcnMuc2NhbGUoZnJvbVpvb20pKTtcclxuXHRcdHJldHVybiBpc05hTih6b29tKSA/IEluZmluaXR5IDogem9vbTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHByb2plY3QobGF0bG5nOiBMYXRMbmcsIHpvb206IE51bWJlcik6IFBvaW50XHJcblx0Ly8gUHJvamVjdHMgYSBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZSBgTGF0TG5nYCBhY2NvcmRpbmcgdG8gdGhlIHByb2plY3Rpb25cclxuXHQvLyBvZiB0aGUgbWFwJ3MgQ1JTLCB0aGVuIHNjYWxlcyBpdCBhY2NvcmRpbmcgdG8gYHpvb21gIGFuZCB0aGUgQ1JTJ3NcclxuXHQvLyBgVHJhbnNmb3JtYXRpb25gLiBUaGUgcmVzdWx0IGlzIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG9cclxuXHQvLyB0aGUgQ1JTIG9yaWdpbi5cclxuXHRwcm9qZWN0OiBmdW5jdGlvbiAobGF0bG5nLCB6b29tKSB7XHJcblx0XHR6b29tID0gem9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fem9vbSA6IHpvb207XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5sYXRMbmdUb1BvaW50KHRvTGF0TG5nKGxhdGxuZyksIHpvb20pO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgdW5wcm9qZWN0KHBvaW50OiBQb2ludCwgem9vbTogTnVtYmVyKTogTGF0TG5nXHJcblx0Ly8gSW52ZXJzZSBvZiBbYHByb2plY3RgXSgjbWFwLXByb2plY3QpLlxyXG5cdHVucHJvamVjdDogZnVuY3Rpb24gKHBvaW50LCB6b29tKSB7XHJcblx0XHR6b29tID0gem9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fem9vbSA6IHpvb207XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5wb2ludFRvTGF0TG5nKHRvUG9pbnQocG9pbnQpLCB6b29tKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGxheWVyUG9pbnRUb0xhdExuZyhwb2ludDogUG9pbnQpOiBMYXRMbmdcclxuXHQvLyBHaXZlbiBhIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLFxyXG5cdC8vIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGUgKGZvciB0aGUgY3VycmVudCB6b29tIGxldmVsKS5cclxuXHRsYXllclBvaW50VG9MYXRMbmc6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0dmFyIHByb2plY3RlZFBvaW50ID0gdG9Qb2ludChwb2ludCkuYWRkKHRoaXMuZ2V0UGl4ZWxPcmlnaW4oKSk7XHJcblx0XHRyZXR1cm4gdGhpcy51bnByb2plY3QocHJvamVjdGVkUG9pbnQpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgbGF0TG5nVG9MYXllclBvaW50KGxhdGxuZzogTGF0TG5nKTogUG9pbnRcclxuXHQvLyBHaXZlbiBhIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlLCByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIHBpeGVsIGNvb3JkaW5hdGVcclxuXHQvLyByZWxhdGl2ZSB0byB0aGUgW29yaWdpbiBwaXhlbF0oI21hcC1nZXRwaXhlbG9yaWdpbikuXHJcblx0bGF0TG5nVG9MYXllclBvaW50OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHR2YXIgcHJvamVjdGVkUG9pbnQgPSB0aGlzLnByb2plY3QodG9MYXRMbmcobGF0bG5nKSkuX3JvdW5kKCk7XHJcblx0XHRyZXR1cm4gcHJvamVjdGVkUG9pbnQuX3N1YnRyYWN0KHRoaXMuZ2V0UGl4ZWxPcmlnaW4oKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB3cmFwTGF0TG5nKGxhdGxuZzogTGF0TG5nKTogTGF0TG5nXHJcblx0Ly8gUmV0dXJucyBhIGBMYXRMbmdgIHdoZXJlIGBsYXRgIGFuZCBgbG5nYCBoYXMgYmVlbiB3cmFwcGVkIGFjY29yZGluZyB0byB0aGVcclxuXHQvLyBtYXAncyBDUlMncyBgd3JhcExhdGAgYW5kIGB3cmFwTG5nYCBwcm9wZXJ0aWVzLCBpZiB0aGV5IGFyZSBvdXRzaWRlIHRoZVxyXG5cdC8vIENSUydzIGJvdW5kcy5cclxuXHQvLyBCeSBkZWZhdWx0IHRoaXMgbWVhbnMgbG9uZ2l0dWRlIGlzIHdyYXBwZWQgYXJvdW5kIHRoZSBkYXRlbGluZSBzbyBpdHNcclxuXHQvLyB2YWx1ZSBpcyBiZXR3ZWVuIC0xODAgYW5kICsxODAgZGVncmVlcy5cclxuXHR3cmFwTGF0TG5nOiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy53cmFwTGF0TG5nKHRvTGF0TG5nKGxhdGxuZykpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgd3JhcExhdExuZ0JvdW5kcyhib3VuZHM6IExhdExuZ0JvdW5kcyk6IExhdExuZ0JvdW5kc1xyXG5cdC8vIFJldHVybnMgYSBgTGF0TG5nQm91bmRzYCB3aXRoIHRoZSBzYW1lIHNpemUgYXMgdGhlIGdpdmVuIG9uZSwgZW5zdXJpbmcgdGhhdFxyXG5cdC8vIGl0cyBjZW50ZXIgaXMgd2l0aGluIHRoZSBDUlMncyBib3VuZHMuXHJcblx0Ly8gQnkgZGVmYXVsdCB0aGlzIG1lYW5zIHRoZSBjZW50ZXIgbG9uZ2l0dWRlIGlzIHdyYXBwZWQgYXJvdW5kIHRoZSBkYXRlbGluZSBzbyBpdHNcclxuXHQvLyB2YWx1ZSBpcyBiZXR3ZWVuIC0xODAgYW5kICsxODAgZGVncmVlcywgYW5kIHRoZSBtYWpvcml0eSBvZiB0aGUgYm91bmRzXHJcblx0Ly8gb3ZlcmxhcHMgdGhlIENSUydzIGJvdW5kcy5cclxuXHR3cmFwTGF0TG5nQm91bmRzOiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy53cmFwTGF0TG5nQm91bmRzKHRvTGF0TG5nQm91bmRzKGxhdGxuZykpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZGlzdGFuY2UobGF0bG5nMTogTGF0TG5nLCBsYXRsbmcyOiBMYXRMbmcpOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMgYWNjb3JkaW5nIHRvXHJcblx0Ly8gdGhlIG1hcCdzIENSUy4gQnkgZGVmYXVsdCB0aGlzIG1lYXN1cmVzIGRpc3RhbmNlIGluIG1ldGVycy5cclxuXHRkaXN0YW5jZTogZnVuY3Rpb24gKGxhdGxuZzEsIGxhdGxuZzIpIHtcclxuXHRcdHJldHVybiB0aGlzLm9wdGlvbnMuY3JzLmRpc3RhbmNlKHRvTGF0TG5nKGxhdGxuZzEpLCB0b0xhdExuZyhsYXRsbmcyKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBjb250YWluZXJQb2ludFRvTGF5ZXJQb2ludChwb2ludDogUG9pbnQpOiBQb2ludFxyXG5cdC8vIEdpdmVuIGEgcGl4ZWwgY29vcmRpbmF0ZSByZWxhdGl2ZSB0byB0aGUgbWFwIGNvbnRhaW5lciwgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZ1xyXG5cdC8vIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLlxyXG5cdGNvbnRhaW5lclBvaW50VG9MYXllclBvaW50OiBmdW5jdGlvbiAocG9pbnQpIHsgLy8gKFBvaW50KVxyXG5cdFx0cmV0dXJuIHRvUG9pbnQocG9pbnQpLnN1YnRyYWN0KHRoaXMuX2dldE1hcFBhbmVQb3MoKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBsYXllclBvaW50VG9Db250YWluZXJQb2ludChwb2ludDogUG9pbnQpOiBQb2ludFxyXG5cdC8vIEdpdmVuIGEgcGl4ZWwgY29vcmRpbmF0ZSByZWxhdGl2ZSB0byB0aGUgW29yaWdpbiBwaXhlbF0oI21hcC1nZXRwaXhlbG9yaWdpbiksXHJcblx0Ly8gcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZSBtYXAgY29udGFpbmVyLlxyXG5cdGxheWVyUG9pbnRUb0NvbnRhaW5lclBvaW50OiBmdW5jdGlvbiAocG9pbnQpIHsgLy8gKFBvaW50KVxyXG5cdFx0cmV0dXJuIHRvUG9pbnQocG9pbnQpLmFkZCh0aGlzLl9nZXRNYXBQYW5lUG9zKCkpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY29udGFpbmVyUG9pbnRUb0xhdExuZyhwb2ludDogUG9pbnQpOiBMYXRMbmdcclxuXHQvLyBHaXZlbiBhIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIG1hcCBjb250YWluZXIsIHJldHVybnNcclxuXHQvLyB0aGUgY29ycmVzcG9uZGluZyBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZSAoZm9yIHRoZSBjdXJyZW50IHpvb20gbGV2ZWwpLlxyXG5cdGNvbnRhaW5lclBvaW50VG9MYXRMbmc6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0dmFyIGxheWVyUG9pbnQgPSB0aGlzLmNvbnRhaW5lclBvaW50VG9MYXllclBvaW50KHRvUG9pbnQocG9pbnQpKTtcclxuXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0xhdExuZyhsYXllclBvaW50KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGxhdExuZ1RvQ29udGFpbmVyUG9pbnQobGF0bG5nOiBMYXRMbmcpOiBQb2ludFxyXG5cdC8vIEdpdmVuIGEgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGUsIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgcGl4ZWwgY29vcmRpbmF0ZVxyXG5cdC8vIHJlbGF0aXZlIHRvIHRoZSBtYXAgY29udGFpbmVyLlxyXG5cdGxhdExuZ1RvQ29udGFpbmVyUG9pbnQ6IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0NvbnRhaW5lclBvaW50KHRoaXMubGF0TG5nVG9MYXllclBvaW50KHRvTGF0TG5nKGxhdGxuZykpKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIG1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGV2OiBNb3VzZUV2ZW50KTogUG9pbnRcclxuXHQvLyBHaXZlbiBhIE1vdXNlRXZlbnQgb2JqZWN0LCByZXR1cm5zIHRoZSBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZVxyXG5cdC8vIG1hcCBjb250YWluZXIgd2hlcmUgdGhlIGV2ZW50IHRvb2sgcGxhY2UuXHJcblx0bW91c2VFdmVudFRvQ29udGFpbmVyUG9pbnQ6IGZ1bmN0aW9uIChlKSB7XHJcblx0XHRyZXR1cm4gZ2V0TW91c2VQb3NpdGlvbihlLCB0aGlzLl9jb250YWluZXIpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgbW91c2VFdmVudFRvTGF5ZXJQb2ludChldjogTW91c2VFdmVudCk6IFBvaW50XHJcblx0Ly8gR2l2ZW4gYSBNb3VzZUV2ZW50IG9iamVjdCwgcmV0dXJucyB0aGUgcGl4ZWwgY29vcmRpbmF0ZSByZWxhdGl2ZSB0b1xyXG5cdC8vIHRoZSBbb3JpZ2luIHBpeGVsXSgjbWFwLWdldHBpeGVsb3JpZ2luKSB3aGVyZSB0aGUgZXZlbnQgdG9vayBwbGFjZS5cclxuXHRtb3VzZUV2ZW50VG9MYXllclBvaW50OiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQodGhpcy5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBtb3VzZUV2ZW50VG9MYXRMbmcoZXY6IE1vdXNlRXZlbnQpOiBMYXRMbmdcclxuXHQvLyBHaXZlbiBhIE1vdXNlRXZlbnQgb2JqZWN0LCByZXR1cm5zIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlIHdoZXJlIHRoZVxyXG5cdC8vIGV2ZW50IHRvb2sgcGxhY2UuXHJcblx0bW91c2VFdmVudFRvTGF0TG5nOiBmdW5jdGlvbiAoZSkgeyAvLyAoTW91c2VFdmVudClcclxuXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0xhdExuZyh0aGlzLm1vdXNlRXZlbnRUb0xheWVyUG9pbnQoZSkpO1xyXG5cdH0sXHJcblxyXG5cclxuXHQvLyBtYXAgaW5pdGlhbGl6YXRpb24gbWV0aG9kc1xyXG5cclxuXHRfaW5pdENvbnRhaW5lcjogZnVuY3Rpb24gKGlkKSB7XHJcblx0XHR2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gZ2V0KGlkKTtcclxuXHJcblx0XHRpZiAoIWNvbnRhaW5lcikge1xyXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01hcCBjb250YWluZXIgbm90IGZvdW5kLicpO1xyXG5cdFx0fSBlbHNlIGlmIChjb250YWluZXIuX2xlYWZsZXRfaWQpIHtcclxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdNYXAgY29udGFpbmVyIGlzIGFscmVhZHkgaW5pdGlhbGl6ZWQuJyk7XHJcblx0XHR9XHJcblxyXG5cdFx0b24oY29udGFpbmVyLCAnc2Nyb2xsJywgdGhpcy5fb25TY3JvbGwsIHRoaXMpO1xyXG5cdFx0dGhpcy5fY29udGFpbmVySWQgPSBzdGFtcChjb250YWluZXIpO1xyXG5cdH0sXHJcblxyXG5cdF9pbml0TGF5b3V0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyO1xyXG5cclxuXHRcdHRoaXMuX2ZhZGVBbmltYXRlZCA9IHRoaXMub3B0aW9ucy5mYWRlQW5pbWF0aW9uICYmIGFueTNkO1xyXG5cclxuXHRcdGFkZENsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtY29udGFpbmVyJyArXHJcblx0XHRcdCh0b3VjaCA/ICcgbGVhZmxldC10b3VjaCcgOiAnJykgK1xyXG5cdFx0XHQocmV0aW5hID8gJyBsZWFmbGV0LXJldGluYScgOiAnJykgK1xyXG5cdFx0XHQoaWVsdDkgPyAnIGxlYWZsZXQtb2xkaWUnIDogJycpICtcclxuXHRcdFx0KHNhZmFyaSA/ICcgbGVhZmxldC1zYWZhcmknIDogJycpICtcclxuXHRcdFx0KHRoaXMuX2ZhZGVBbmltYXRlZCA/ICcgbGVhZmxldC1mYWRlLWFuaW0nIDogJycpKTtcclxuXHJcblx0XHR2YXIgcG9zaXRpb24gPSBnZXRTdHlsZShjb250YWluZXIsICdwb3NpdGlvbicpO1xyXG5cclxuXHRcdGlmIChwb3NpdGlvbiAhPT0gJ2Fic29sdXRlJyAmJiBwb3NpdGlvbiAhPT0gJ3JlbGF0aXZlJyAmJiBwb3NpdGlvbiAhPT0gJ2ZpeGVkJykge1xyXG5cdFx0XHRjb250YWluZXIuc3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2luaXRQYW5lcygpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9pbml0Q29udHJvbFBvcykge1xyXG5cdFx0XHR0aGlzLl9pbml0Q29udHJvbFBvcygpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9pbml0UGFuZXM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBwYW5lcyA9IHRoaXMuX3BhbmVzID0ge307XHJcblx0XHR0aGlzLl9wYW5lUmVuZGVyZXJzID0ge307XHJcblxyXG5cdFx0Ly8gQHNlY3Rpb25cclxuXHRcdC8vXHJcblx0XHQvLyBQYW5lcyBhcmUgRE9NIGVsZW1lbnRzIHVzZWQgdG8gY29udHJvbCB0aGUgb3JkZXJpbmcgb2YgbGF5ZXJzIG9uIHRoZSBtYXAuIFlvdVxyXG5cdFx0Ly8gY2FuIGFjY2VzcyBwYW5lcyB3aXRoIFtgbWFwLmdldFBhbmVgXSgjbWFwLWdldHBhbmUpIG9yXHJcblx0XHQvLyBbYG1hcC5nZXRQYW5lc2BdKCNtYXAtZ2V0cGFuZXMpIG1ldGhvZHMuIE5ldyBwYW5lcyBjYW4gYmUgY3JlYXRlZCB3aXRoIHRoZVxyXG5cdFx0Ly8gW2BtYXAuY3JlYXRlUGFuZWBdKCNtYXAtY3JlYXRlcGFuZSkgbWV0aG9kLlxyXG5cdFx0Ly9cclxuXHRcdC8vIEV2ZXJ5IG1hcCBoYXMgdGhlIGZvbGxvd2luZyBkZWZhdWx0IHBhbmVzIHRoYXQgZGlmZmVyIG9ubHkgaW4gekluZGV4LlxyXG5cdFx0Ly9cclxuXHRcdC8vIEBwYW5lIG1hcFBhbmU6IEhUTUxFbGVtZW50ID0gJ2F1dG8nXHJcblx0XHQvLyBQYW5lIHRoYXQgY29udGFpbnMgYWxsIG90aGVyIG1hcCBwYW5lc1xyXG5cclxuXHRcdHRoaXMuX21hcFBhbmUgPSB0aGlzLmNyZWF0ZVBhbmUoJ21hcFBhbmUnLCB0aGlzLl9jb250YWluZXIpO1xyXG5cdFx0c2V0UG9zaXRpb24odGhpcy5fbWFwUGFuZSwgbmV3IFBvaW50KDAsIDApKTtcclxuXHJcblx0XHQvLyBAcGFuZSB0aWxlUGFuZTogSFRNTEVsZW1lbnQgPSAyMDBcclxuXHRcdC8vIFBhbmUgZm9yIGBHcmlkTGF5ZXJgcyBhbmQgYFRpbGVMYXllcmBzXHJcblx0XHR0aGlzLmNyZWF0ZVBhbmUoJ3RpbGVQYW5lJyk7XHJcblx0XHQvLyBAcGFuZSBvdmVybGF5UGFuZTogSFRNTEVsZW1lbnQgPSA0MDBcclxuXHRcdC8vIFBhbmUgZm9yIHZlY3RvcnMgKGBQYXRoYHMsIGxpa2UgYFBvbHlsaW5lYHMgYW5kIGBQb2x5Z29uYHMpLCBgSW1hZ2VPdmVybGF5YHMgYW5kIGBWaWRlb092ZXJsYXlgc1xyXG5cdFx0dGhpcy5jcmVhdGVQYW5lKCdzaGFkb3dQYW5lJyk7XHJcblx0XHQvLyBAcGFuZSBzaGFkb3dQYW5lOiBIVE1MRWxlbWVudCA9IDUwMFxyXG5cdFx0Ly8gUGFuZSBmb3Igb3ZlcmxheSBzaGFkb3dzIChlLmcuIGBNYXJrZXJgIHNoYWRvd3MpXHJcblx0XHR0aGlzLmNyZWF0ZVBhbmUoJ292ZXJsYXlQYW5lJyk7XHJcblx0XHQvLyBAcGFuZSBtYXJrZXJQYW5lOiBIVE1MRWxlbWVudCA9IDYwMFxyXG5cdFx0Ly8gUGFuZSBmb3IgYEljb25gcyBvZiBgTWFya2VyYHNcclxuXHRcdHRoaXMuY3JlYXRlUGFuZSgnbWFya2VyUGFuZScpO1xyXG5cdFx0Ly8gQHBhbmUgdG9vbHRpcFBhbmU6IEhUTUxFbGVtZW50ID0gNjUwXHJcblx0XHQvLyBQYW5lIGZvciBgVG9vbHRpcGBzLlxyXG5cdFx0dGhpcy5jcmVhdGVQYW5lKCd0b29sdGlwUGFuZScpO1xyXG5cdFx0Ly8gQHBhbmUgcG9wdXBQYW5lOiBIVE1MRWxlbWVudCA9IDcwMFxyXG5cdFx0Ly8gUGFuZSBmb3IgYFBvcHVwYHMuXHJcblx0XHR0aGlzLmNyZWF0ZVBhbmUoJ3BvcHVwUGFuZScpO1xyXG5cclxuXHRcdGlmICghdGhpcy5vcHRpb25zLm1hcmtlclpvb21BbmltYXRpb24pIHtcclxuXHRcdFx0YWRkQ2xhc3MocGFuZXMubWFya2VyUGFuZSwgJ2xlYWZsZXQtem9vbS1oaWRlJyk7XHJcblx0XHRcdGFkZENsYXNzKHBhbmVzLnNoYWRvd1BhbmUsICdsZWFmbGV0LXpvb20taGlkZScpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cclxuXHQvLyBwcml2YXRlIG1ldGhvZHMgdGhhdCBtb2RpZnkgbWFwIHN0YXRlXHJcblxyXG5cdC8vIEBzZWN0aW9uIE1hcCBzdGF0ZSBjaGFuZ2UgZXZlbnRzXHJcblx0X3Jlc2V0VmlldzogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xyXG5cdFx0c2V0UG9zaXRpb24odGhpcy5fbWFwUGFuZSwgbmV3IFBvaW50KDAsIDApKTtcclxuXHJcblx0XHR2YXIgbG9hZGluZyA9ICF0aGlzLl9sb2FkZWQ7XHJcblx0XHR0aGlzLl9sb2FkZWQgPSB0cnVlO1xyXG5cdFx0em9vbSA9IHRoaXMuX2xpbWl0Wm9vbSh6b29tKTtcclxuXHJcblx0XHR0aGlzLmZpcmUoJ3ZpZXdwcmVyZXNldCcpO1xyXG5cclxuXHRcdHZhciB6b29tQ2hhbmdlZCA9IHRoaXMuX3pvb20gIT09IHpvb207XHJcblx0XHR0aGlzXHJcblx0XHRcdC5fbW92ZVN0YXJ0KHpvb21DaGFuZ2VkLCBmYWxzZSlcclxuXHRcdFx0Ll9tb3ZlKGNlbnRlciwgem9vbSlcclxuXHRcdFx0Ll9tb3ZlRW5kKHpvb21DaGFuZ2VkKTtcclxuXHJcblx0XHQvLyBAZXZlbnQgdmlld3Jlc2V0OiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIG5lZWRzIHRvIHJlZHJhdyBpdHMgY29udGVudCAodGhpcyB1c3VhbGx5IGhhcHBlbnNcclxuXHRcdC8vIG9uIG1hcCB6b29tIG9yIGxvYWQpLiBWZXJ5IHVzZWZ1bCBmb3IgY3JlYXRpbmcgY3VzdG9tIG92ZXJsYXlzLlxyXG5cdFx0dGhpcy5maXJlKCd2aWV3cmVzZXQnKTtcclxuXHJcblx0XHQvLyBAZXZlbnQgbG9hZDogRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcCBpcyBpbml0aWFsaXplZCAod2hlbiBpdHMgY2VudGVyIGFuZCB6b29tIGFyZSBzZXRcclxuXHRcdC8vIGZvciB0aGUgZmlyc3QgdGltZSkuXHJcblx0XHRpZiAobG9hZGluZykge1xyXG5cdFx0XHR0aGlzLmZpcmUoJ2xvYWQnKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfbW92ZVN0YXJ0OiBmdW5jdGlvbiAoem9vbUNoYW5nZWQsIG5vTW92ZVN0YXJ0KSB7XHJcblx0XHQvLyBAZXZlbnQgem9vbXN0YXJ0OiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIHpvb20gaXMgYWJvdXQgdG8gY2hhbmdlIChlLmcuIGJlZm9yZSB6b29tIGFuaW1hdGlvbikuXHJcblx0XHQvLyBAZXZlbnQgbW92ZXN0YXJ0OiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdmlldyBvZiB0aGUgbWFwIHN0YXJ0cyBjaGFuZ2luZyAoZS5nLiB1c2VyIHN0YXJ0cyBkcmFnZ2luZyB0aGUgbWFwKS5cclxuXHRcdGlmICh6b29tQ2hhbmdlZCkge1xyXG5cdFx0XHR0aGlzLmZpcmUoJ3pvb21zdGFydCcpO1xyXG5cdFx0fVxyXG5cdFx0aWYgKCFub01vdmVTdGFydCkge1xyXG5cdFx0XHR0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0X21vdmU6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIGRhdGEpIHtcclxuXHRcdGlmICh6b29tID09PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0em9vbSA9IHRoaXMuX3pvb207XHJcblx0XHR9XHJcblx0XHR2YXIgem9vbUNoYW5nZWQgPSB0aGlzLl96b29tICE9PSB6b29tO1xyXG5cclxuXHRcdHRoaXMuX3pvb20gPSB6b29tO1xyXG5cdFx0dGhpcy5fbGFzdENlbnRlciA9IGNlbnRlcjtcclxuXHRcdHRoaXMuX3BpeGVsT3JpZ2luID0gdGhpcy5fZ2V0TmV3UGl4ZWxPcmlnaW4oY2VudGVyKTtcclxuXHJcblx0XHQvLyBAZXZlbnQgem9vbTogRXZlbnRcclxuXHRcdC8vIEZpcmVkIHJlcGVhdGVkbHkgZHVyaW5nIGFueSBjaGFuZ2UgaW4gem9vbSBsZXZlbCwgaW5jbHVkaW5nIHpvb21cclxuXHRcdC8vIGFuZCBmbHkgYW5pbWF0aW9ucy5cclxuXHRcdGlmICh6b29tQ2hhbmdlZCB8fCAoZGF0YSAmJiBkYXRhLnBpbmNoKSkge1x0Ly8gQWx3YXlzIGZpcmUgJ3pvb20nIGlmIHBpbmNoaW5nIGJlY2F1c2UgIzM1MzBcclxuXHRcdFx0dGhpcy5maXJlKCd6b29tJywgZGF0YSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQGV2ZW50IG1vdmU6IEV2ZW50XHJcblx0XHQvLyBGaXJlZCByZXBlYXRlZGx5IGR1cmluZyBhbnkgbW92ZW1lbnQgb2YgdGhlIG1hcCwgaW5jbHVkaW5nIHBhbiBhbmRcclxuXHRcdC8vIGZseSBhbmltYXRpb25zLlxyXG5cdFx0cmV0dXJuIHRoaXMuZmlyZSgnbW92ZScsIGRhdGEpO1xyXG5cdH0sXHJcblxyXG5cdF9tb3ZlRW5kOiBmdW5jdGlvbiAoem9vbUNoYW5nZWQpIHtcclxuXHRcdC8vIEBldmVudCB6b29tZW5kOiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIGhhcyBjaGFuZ2VkLCBhZnRlciBhbnkgYW5pbWF0aW9ucy5cclxuXHRcdGlmICh6b29tQ2hhbmdlZCkge1xyXG5cdFx0XHR0aGlzLmZpcmUoJ3pvb21lbmQnKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBAZXZlbnQgbW92ZWVuZDogRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIGNlbnRlciBvZiB0aGUgbWFwIHN0b3BzIGNoYW5naW5nIChlLmcuIHVzZXIgc3RvcHBlZFxyXG5cdFx0Ly8gZHJhZ2dpbmcgdGhlIG1hcCkuXHJcblx0XHRyZXR1cm4gdGhpcy5maXJlKCdtb3ZlZW5kJyk7XHJcblx0fSxcclxuXHJcblx0X3N0b3A6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9mbHlUb0ZyYW1lKTtcclxuXHRcdGlmICh0aGlzLl9wYW5BbmltKSB7XHJcblx0XHRcdHRoaXMuX3BhbkFuaW0uc3RvcCgpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0X3Jhd1BhbkJ5OiBmdW5jdGlvbiAob2Zmc2V0KSB7XHJcblx0XHRzZXRQb3NpdGlvbih0aGlzLl9tYXBQYW5lLCB0aGlzLl9nZXRNYXBQYW5lUG9zKCkuc3VidHJhY3Qob2Zmc2V0KSk7XHJcblx0fSxcclxuXHJcblx0X2dldFpvb21TcGFuOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5nZXRNYXhab29tKCkgLSB0aGlzLmdldE1pblpvb20oKTtcclxuXHR9LFxyXG5cclxuXHRfcGFuSW5zaWRlTWF4Qm91bmRzOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAoIXRoaXMuX2VuZm9yY2luZ0JvdW5kcykge1xyXG5cdFx0XHR0aGlzLnBhbkluc2lkZUJvdW5kcyh0aGlzLm9wdGlvbnMubWF4Qm91bmRzKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfY2hlY2tJZkxvYWRlZDogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKCF0aGlzLl9sb2FkZWQpIHtcclxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdTZXQgbWFwIGNlbnRlciBhbmQgem9vbSBmaXJzdC4nKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHQvLyBET00gZXZlbnQgaGFuZGxpbmdcclxuXHJcblx0Ly8gQHNlY3Rpb24gSW50ZXJhY3Rpb24gZXZlbnRzXHJcblx0X2luaXRFdmVudHM6IGZ1bmN0aW9uIChyZW1vdmUkJDEpIHtcclxuXHRcdHRoaXMuX3RhcmdldHMgPSB7fTtcclxuXHRcdHRoaXMuX3RhcmdldHNbc3RhbXAodGhpcy5fY29udGFpbmVyKV0gPSB0aGlzO1xyXG5cclxuXHRcdHZhciBvbk9mZiA9IHJlbW92ZSQkMSA/IG9mZiA6IG9uO1xyXG5cclxuXHRcdC8vIEBldmVudCBjbGljazogTW91c2VFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBjbGlja3MgKG9yIHRhcHMpIHRoZSBtYXAuXHJcblx0XHQvLyBAZXZlbnQgZGJsY2xpY2s6IE1vdXNlRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgZG91YmxlLWNsaWNrcyAob3IgZG91YmxlLXRhcHMpIHRoZSBtYXAuXHJcblx0XHQvLyBAZXZlbnQgbW91c2Vkb3duOiBNb3VzZUV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSB1c2VyIHB1c2hlcyB0aGUgbW91c2UgYnV0dG9uIG9uIHRoZSBtYXAuXHJcblx0XHQvLyBAZXZlbnQgbW91c2V1cDogTW91c2VFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciByZWxlYXNlcyB0aGUgbW91c2UgYnV0dG9uIG9uIHRoZSBtYXAuXHJcblx0XHQvLyBAZXZlbnQgbW91c2VvdmVyOiBNb3VzZUV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSBtb3VzZSBlbnRlcnMgdGhlIG1hcC5cclxuXHRcdC8vIEBldmVudCBtb3VzZW91dDogTW91c2VFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbW91c2UgbGVhdmVzIHRoZSBtYXAuXHJcblx0XHQvLyBAZXZlbnQgbW91c2Vtb3ZlOiBNb3VzZUV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGlsZSB0aGUgbW91c2UgbW92ZXMgb3ZlciB0aGUgbWFwLlxyXG5cdFx0Ly8gQGV2ZW50IGNvbnRleHRtZW51OiBNb3VzZUV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSB1c2VyIHB1c2hlcyB0aGUgcmlnaHQgbW91c2UgYnV0dG9uIG9uIHRoZSBtYXAsIHByZXZlbnRzXHJcblx0XHQvLyBkZWZhdWx0IGJyb3dzZXIgY29udGV4dCBtZW51IGZyb20gc2hvd2luZyBpZiB0aGVyZSBhcmUgbGlzdGVuZXJzIG9uXHJcblx0XHQvLyB0aGlzIGV2ZW50LiBBbHNvIGZpcmVkIG9uIG1vYmlsZSB3aGVuIHRoZSB1c2VyIGhvbGRzIGEgc2luZ2xlIHRvdWNoXHJcblx0XHQvLyBmb3IgYSBzZWNvbmQgKGFsc28gY2FsbGVkIGxvbmcgcHJlc3MpLlxyXG5cdFx0Ly8gQGV2ZW50IGtleXByZXNzOiBLZXlib2FyZEV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSB1c2VyIHByZXNzZXMgYSBrZXkgZnJvbSB0aGUga2V5Ym9hcmQgdGhhdCBwcm9kdWNlcyBhIGNoYXJhY3RlciB2YWx1ZSB3aGlsZSB0aGUgbWFwIGlzIGZvY3VzZWQuXHJcblx0XHQvLyBAZXZlbnQga2V5ZG93bjogS2V5Ym9hcmRFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBwcmVzc2VzIGEga2V5IGZyb20gdGhlIGtleWJvYXJkIHdoaWxlIHRoZSBtYXAgaXMgZm9jdXNlZC4gVW5saWtlIHRoZSBga2V5cHJlc3NgIGV2ZW50LFxyXG5cdFx0Ly8gdGhlIGBrZXlkb3duYCBldmVudCBpcyBmaXJlZCBmb3Iga2V5cyB0aGF0IHByb2R1Y2UgYSBjaGFyYWN0ZXIgdmFsdWUgYW5kIGZvciBrZXlzXHJcblx0XHQvLyB0aGF0IGRvIG5vdCBwcm9kdWNlIGEgY2hhcmFjdGVyIHZhbHVlLlxyXG5cdFx0Ly8gQGV2ZW50IGtleXVwOiBLZXlib2FyZEV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSB1c2VyIHJlbGVhc2VzIGEga2V5IGZyb20gdGhlIGtleWJvYXJkIHdoaWxlIHRoZSBtYXAgaXMgZm9jdXNlZC5cclxuXHRcdG9uT2ZmKHRoaXMuX2NvbnRhaW5lciwgJ2NsaWNrIGRibGNsaWNrIG1vdXNlZG93biBtb3VzZXVwICcgK1xyXG5cdFx0XHQnbW91c2VvdmVyIG1vdXNlb3V0IG1vdXNlbW92ZSBjb250ZXh0bWVudSBrZXlwcmVzcyBrZXlkb3duIGtleXVwJywgdGhpcy5faGFuZGxlRE9NRXZlbnQsIHRoaXMpO1xyXG5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMudHJhY2tSZXNpemUpIHtcclxuXHRcdFx0b25PZmYod2luZG93LCAncmVzaXplJywgdGhpcy5fb25SZXNpemUsIHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChhbnkzZCAmJiB0aGlzLm9wdGlvbnMudHJhbnNmb3JtM0RMaW1pdCkge1xyXG5cdFx0XHQocmVtb3ZlJCQxID8gdGhpcy5vZmYgOiB0aGlzLm9uKS5jYWxsKHRoaXMsICdtb3ZlZW5kJywgdGhpcy5fb25Nb3ZlRW5kKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfb25SZXNpemU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9yZXNpemVSZXF1ZXN0KTtcclxuXHRcdHRoaXMuX3Jlc2l6ZVJlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lKFxyXG5cdFx0ICAgICAgICBmdW5jdGlvbiAoKSB7IHRoaXMuaW52YWxpZGF0ZVNpemUoe2RlYm91bmNlTW92ZWVuZDogdHJ1ZX0pOyB9LCB0aGlzKTtcclxuXHR9LFxyXG5cclxuXHRfb25TY3JvbGw6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX2NvbnRhaW5lci5zY3JvbGxUb3AgID0gMDtcclxuXHRcdHRoaXMuX2NvbnRhaW5lci5zY3JvbGxMZWZ0ID0gMDtcclxuXHR9LFxyXG5cclxuXHRfb25Nb3ZlRW5kOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgcG9zID0gdGhpcy5fZ2V0TWFwUGFuZVBvcygpO1xyXG5cdFx0aWYgKE1hdGgubWF4KE1hdGguYWJzKHBvcy54KSwgTWF0aC5hYnMocG9zLnkpKSA+PSB0aGlzLm9wdGlvbnMudHJhbnNmb3JtM0RMaW1pdCkge1xyXG5cdFx0XHQvLyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMjAzODczIGJ1dCBXZWJraXQgYWxzbyBoYXZlXHJcblx0XHRcdC8vIGEgcGl4ZWwgb2Zmc2V0IG9uIHZlcnkgaGlnaCB2YWx1ZXMsIHNlZTogaHR0cDovL2pzZmlkZGxlLm5ldC9kZzZyNWhoYi9cclxuXHRcdFx0dGhpcy5fcmVzZXRWaWV3KHRoaXMuZ2V0Q2VudGVyKCksIHRoaXMuZ2V0Wm9vbSgpKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfZmluZEV2ZW50VGFyZ2V0czogZnVuY3Rpb24gKGUsIHR5cGUpIHtcclxuXHRcdHZhciB0YXJnZXRzID0gW10sXHJcblx0XHQgICAgdGFyZ2V0LFxyXG5cdFx0ICAgIGlzSG92ZXIgPSB0eXBlID09PSAnbW91c2VvdXQnIHx8IHR5cGUgPT09ICdtb3VzZW92ZXInLFxyXG5cdFx0ICAgIHNyYyA9IGUudGFyZ2V0IHx8IGUuc3JjRWxlbWVudCxcclxuXHRcdCAgICBkcmFnZ2luZyA9IGZhbHNlO1xyXG5cclxuXHRcdHdoaWxlIChzcmMpIHtcclxuXHRcdFx0dGFyZ2V0ID0gdGhpcy5fdGFyZ2V0c1tzdGFtcChzcmMpXTtcclxuXHRcdFx0aWYgKHRhcmdldCAmJiAodHlwZSA9PT0gJ2NsaWNrJyB8fCB0eXBlID09PSAncHJlY2xpY2snKSAmJiAhZS5fc2ltdWxhdGVkICYmIHRoaXMuX2RyYWdnYWJsZU1vdmVkKHRhcmdldCkpIHtcclxuXHRcdFx0XHQvLyBQcmV2ZW50IGZpcmluZyBjbGljayBhZnRlciB5b3UganVzdCBkcmFnZ2VkIGFuIG9iamVjdC5cclxuXHRcdFx0XHRkcmFnZ2luZyA9IHRydWU7XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKHRhcmdldCAmJiB0YXJnZXQubGlzdGVucyh0eXBlLCB0cnVlKSkge1xyXG5cdFx0XHRcdGlmIChpc0hvdmVyICYmICFpc0V4dGVybmFsVGFyZ2V0KHNyYywgZSkpIHsgYnJlYWs7IH1cclxuXHRcdFx0XHR0YXJnZXRzLnB1c2godGFyZ2V0KTtcclxuXHRcdFx0XHRpZiAoaXNIb3ZlcikgeyBicmVhazsgfVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmIChzcmMgPT09IHRoaXMuX2NvbnRhaW5lcikgeyBicmVhazsgfVxyXG5cdFx0XHRzcmMgPSBzcmMucGFyZW50Tm9kZTtcclxuXHRcdH1cclxuXHRcdGlmICghdGFyZ2V0cy5sZW5ndGggJiYgIWRyYWdnaW5nICYmICFpc0hvdmVyICYmIGlzRXh0ZXJuYWxUYXJnZXQoc3JjLCBlKSkge1xyXG5cdFx0XHR0YXJnZXRzID0gW3RoaXNdO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRhcmdldHM7XHJcblx0fSxcclxuXHJcblx0X2hhbmRsZURPTUV2ZW50OiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0aWYgKCF0aGlzLl9sb2FkZWQgfHwgc2tpcHBlZChlKSkgeyByZXR1cm47IH1cclxuXHJcblx0XHR2YXIgdHlwZSA9IGUudHlwZTtcclxuXHJcblx0XHRpZiAodHlwZSA9PT0gJ21vdXNlZG93bicgfHwgdHlwZSA9PT0gJ2tleXByZXNzJyB8fCB0eXBlID09PSAna2V5dXAnIHx8IHR5cGUgPT09ICdrZXlkb3duJykge1xyXG5cdFx0XHQvLyBwcmV2ZW50cyBvdXRsaW5lIHdoZW4gY2xpY2tpbmcgb24ga2V5Ym9hcmQtZm9jdXNhYmxlIGVsZW1lbnRcclxuXHRcdFx0cHJldmVudE91dGxpbmUoZS50YXJnZXQgfHwgZS5zcmNFbGVtZW50KTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9maXJlRE9NRXZlbnQoZSwgdHlwZSk7XHJcblx0fSxcclxuXHJcblx0X21vdXNlRXZlbnRzOiBbJ2NsaWNrJywgJ2RibGNsaWNrJywgJ21vdXNlb3ZlcicsICdtb3VzZW91dCcsICdjb250ZXh0bWVudSddLFxyXG5cclxuXHRfZmlyZURPTUV2ZW50OiBmdW5jdGlvbiAoZSwgdHlwZSwgdGFyZ2V0cykge1xyXG5cclxuXHRcdGlmIChlLnR5cGUgPT09ICdjbGljaycpIHtcclxuXHRcdFx0Ly8gRmlyZSBhIHN5bnRoZXRpYyAncHJlY2xpY2snIGV2ZW50IHdoaWNoIHByb3BhZ2F0ZXMgdXAgKG1haW5seSBmb3IgY2xvc2luZyBwb3B1cHMpLlxyXG5cdFx0XHQvLyBAZXZlbnQgcHJlY2xpY2s6IE1vdXNlRXZlbnRcclxuXHRcdFx0Ly8gRmlyZWQgYmVmb3JlIG1vdXNlIGNsaWNrIG9uIHRoZSBtYXAgKHNvbWV0aW1lcyB1c2VmdWwgd2hlbiB5b3VcclxuXHRcdFx0Ly8gd2FudCBzb21ldGhpbmcgdG8gaGFwcGVuIG9uIGNsaWNrIGJlZm9yZSBhbnkgZXhpc3RpbmcgY2xpY2tcclxuXHRcdFx0Ly8gaGFuZGxlcnMgc3RhcnQgcnVubmluZykuXHJcblx0XHRcdHZhciBzeW50aCA9IGV4dGVuZCh7fSwgZSk7XHJcblx0XHRcdHN5bnRoLnR5cGUgPSAncHJlY2xpY2snO1xyXG5cdFx0XHR0aGlzLl9maXJlRE9NRXZlbnQoc3ludGgsIHN5bnRoLnR5cGUsIHRhcmdldHMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChlLl9zdG9wcGVkKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdC8vIEZpbmQgdGhlIGxheWVyIHRoZSBldmVudCBpcyBwcm9wYWdhdGluZyBmcm9tIGFuZCBpdHMgcGFyZW50cy5cclxuXHRcdHRhcmdldHMgPSAodGFyZ2V0cyB8fCBbXSkuY29uY2F0KHRoaXMuX2ZpbmRFdmVudFRhcmdldHMoZSwgdHlwZSkpO1xyXG5cclxuXHRcdGlmICghdGFyZ2V0cy5sZW5ndGgpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0dmFyIHRhcmdldCA9IHRhcmdldHNbMF07XHJcblx0XHRpZiAodHlwZSA9PT0gJ2NvbnRleHRtZW51JyAmJiB0YXJnZXQubGlzdGVucyh0eXBlLCB0cnVlKSkge1xyXG5cdFx0XHRwcmV2ZW50RGVmYXVsdChlKTtcclxuXHRcdH1cclxuXHJcblx0XHR2YXIgZGF0YSA9IHtcclxuXHRcdFx0b3JpZ2luYWxFdmVudDogZVxyXG5cdFx0fTtcclxuXHJcblx0XHRpZiAoZS50eXBlICE9PSAna2V5cHJlc3MnICYmIGUudHlwZSAhPT0gJ2tleWRvd24nICYmIGUudHlwZSAhPT0gJ2tleXVwJykge1xyXG5cdFx0XHR2YXIgaXNNYXJrZXIgPSB0YXJnZXQuZ2V0TGF0TG5nICYmICghdGFyZ2V0Ll9yYWRpdXMgfHwgdGFyZ2V0Ll9yYWRpdXMgPD0gMTApO1xyXG5cdFx0XHRkYXRhLmNvbnRhaW5lclBvaW50ID0gaXNNYXJrZXIgP1xyXG5cdFx0XHRcdHRoaXMubGF0TG5nVG9Db250YWluZXJQb2ludCh0YXJnZXQuZ2V0TGF0TG5nKCkpIDogdGhpcy5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKTtcclxuXHRcdFx0ZGF0YS5sYXllclBvaW50ID0gdGhpcy5jb250YWluZXJQb2ludFRvTGF5ZXJQb2ludChkYXRhLmNvbnRhaW5lclBvaW50KTtcclxuXHRcdFx0ZGF0YS5sYXRsbmcgPSBpc01hcmtlciA/IHRhcmdldC5nZXRMYXRMbmcoKSA6IHRoaXMubGF5ZXJQb2ludFRvTGF0TG5nKGRhdGEubGF5ZXJQb2ludCk7XHJcblx0XHR9XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0YXJnZXRzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdHRhcmdldHNbaV0uZmlyZSh0eXBlLCBkYXRhLCB0cnVlKTtcclxuXHRcdFx0aWYgKGRhdGEub3JpZ2luYWxFdmVudC5fc3RvcHBlZCB8fFxyXG5cdFx0XHRcdCh0YXJnZXRzW2ldLm9wdGlvbnMuYnViYmxpbmdNb3VzZUV2ZW50cyA9PT0gZmFsc2UgJiYgaW5kZXhPZih0aGlzLl9tb3VzZUV2ZW50cywgdHlwZSkgIT09IC0xKSkgeyByZXR1cm47IH1cclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfZHJhZ2dhYmxlTW92ZWQ6IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdG9iaiA9IG9iai5kcmFnZ2luZyAmJiBvYmouZHJhZ2dpbmcuZW5hYmxlZCgpID8gb2JqIDogdGhpcztcclxuXHRcdHJldHVybiAob2JqLmRyYWdnaW5nICYmIG9iai5kcmFnZ2luZy5tb3ZlZCgpKSB8fCAodGhpcy5ib3hab29tICYmIHRoaXMuYm94Wm9vbS5tb3ZlZCgpKTtcclxuXHR9LFxyXG5cclxuXHRfY2xlYXJIYW5kbGVyczogZnVuY3Rpb24gKCkge1xyXG5cdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHRoaXMuX2hhbmRsZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdHRoaXMuX2hhbmRsZXJzW2ldLmRpc2FibGUoKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHQvLyBAc2VjdGlvbiBPdGhlciBNZXRob2RzXHJcblxyXG5cdC8vIEBtZXRob2Qgd2hlblJlYWR5KGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuXHQvLyBSdW5zIHRoZSBnaXZlbiBmdW5jdGlvbiBgZm5gIHdoZW4gdGhlIG1hcCBnZXRzIGluaXRpYWxpemVkIHdpdGhcclxuXHQvLyBhIHZpZXcgKGNlbnRlciBhbmQgem9vbSkgYW5kIGF0IGxlYXN0IG9uZSBsYXllciwgb3IgaW1tZWRpYXRlbHlcclxuXHQvLyBpZiBpdCdzIGFscmVhZHkgaW5pdGlhbGl6ZWQsIG9wdGlvbmFsbHkgcGFzc2luZyBhIGZ1bmN0aW9uIGNvbnRleHQuXHJcblx0d2hlblJlYWR5OiBmdW5jdGlvbiAoY2FsbGJhY2ssIGNvbnRleHQpIHtcclxuXHRcdGlmICh0aGlzLl9sb2FkZWQpIHtcclxuXHRcdFx0Y2FsbGJhY2suY2FsbChjb250ZXh0IHx8IHRoaXMsIHt0YXJnZXQ6IHRoaXN9KTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHRoaXMub24oJ2xvYWQnLCBjYWxsYmFjaywgY29udGV4dCk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHJcblx0Ly8gcHJpdmF0ZSBtZXRob2RzIGZvciBnZXR0aW5nIG1hcCBzdGF0ZVxyXG5cclxuXHRfZ2V0TWFwUGFuZVBvczogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIGdldFBvc2l0aW9uKHRoaXMuX21hcFBhbmUpIHx8IG5ldyBQb2ludCgwLCAwKTtcclxuXHR9LFxyXG5cclxuXHRfbW92ZWQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBwb3MgPSB0aGlzLl9nZXRNYXBQYW5lUG9zKCk7XHJcblx0XHRyZXR1cm4gcG9zICYmICFwb3MuZXF1YWxzKFswLCAwXSk7XHJcblx0fSxcclxuXHJcblx0X2dldFRvcExlZnRQb2ludDogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xyXG5cdFx0dmFyIHBpeGVsT3JpZ2luID0gY2VudGVyICYmIHpvb20gIT09IHVuZGVmaW5lZCA/XHJcblx0XHRcdHRoaXMuX2dldE5ld1BpeGVsT3JpZ2luKGNlbnRlciwgem9vbSkgOlxyXG5cdFx0XHR0aGlzLmdldFBpeGVsT3JpZ2luKCk7XHJcblx0XHRyZXR1cm4gcGl4ZWxPcmlnaW4uc3VidHJhY3QodGhpcy5fZ2V0TWFwUGFuZVBvcygpKTtcclxuXHR9LFxyXG5cclxuXHRfZ2V0TmV3UGl4ZWxPcmlnaW46IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20pIHtcclxuXHRcdHZhciB2aWV3SGFsZiA9IHRoaXMuZ2V0U2l6ZSgpLl9kaXZpZGVCeSgyKTtcclxuXHRcdHJldHVybiB0aGlzLnByb2plY3QoY2VudGVyLCB6b29tKS5fc3VidHJhY3Qodmlld0hhbGYpLl9hZGQodGhpcy5fZ2V0TWFwUGFuZVBvcygpKS5fcm91bmQoKTtcclxuXHR9LFxyXG5cclxuXHRfbGF0TG5nVG9OZXdMYXllclBvaW50OiBmdW5jdGlvbiAobGF0bG5nLCB6b29tLCBjZW50ZXIpIHtcclxuXHRcdHZhciB0b3BMZWZ0ID0gdGhpcy5fZ2V0TmV3UGl4ZWxPcmlnaW4oY2VudGVyLCB6b29tKTtcclxuXHRcdHJldHVybiB0aGlzLnByb2plY3QobGF0bG5nLCB6b29tKS5fc3VidHJhY3QodG9wTGVmdCk7XHJcblx0fSxcclxuXHJcblx0X2xhdExuZ0JvdW5kc1RvTmV3TGF5ZXJCb3VuZHM6IGZ1bmN0aW9uIChsYXRMbmdCb3VuZHMsIHpvb20sIGNlbnRlcikge1xyXG5cdFx0dmFyIHRvcExlZnQgPSB0aGlzLl9nZXROZXdQaXhlbE9yaWdpbihjZW50ZXIsIHpvb20pO1xyXG5cdFx0cmV0dXJuIHRvQm91bmRzKFtcclxuXHRcdFx0dGhpcy5wcm9qZWN0KGxhdExuZ0JvdW5kcy5nZXRTb3V0aFdlc3QoKSwgem9vbSkuX3N1YnRyYWN0KHRvcExlZnQpLFxyXG5cdFx0XHR0aGlzLnByb2plY3QobGF0TG5nQm91bmRzLmdldE5vcnRoV2VzdCgpLCB6b29tKS5fc3VidHJhY3QodG9wTGVmdCksXHJcblx0XHRcdHRoaXMucHJvamVjdChsYXRMbmdCb3VuZHMuZ2V0U291dGhFYXN0KCksIHpvb20pLl9zdWJ0cmFjdCh0b3BMZWZ0KSxcclxuXHRcdFx0dGhpcy5wcm9qZWN0KGxhdExuZ0JvdW5kcy5nZXROb3J0aEVhc3QoKSwgem9vbSkuX3N1YnRyYWN0KHRvcExlZnQpXHJcblx0XHRdKTtcclxuXHR9LFxyXG5cclxuXHQvLyBsYXllciBwb2ludCBvZiB0aGUgY3VycmVudCBjZW50ZXJcclxuXHRfZ2V0Q2VudGVyTGF5ZXJQb2ludDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQodGhpcy5nZXRTaXplKCkuX2RpdmlkZUJ5KDIpKTtcclxuXHR9LFxyXG5cclxuXHQvLyBvZmZzZXQgb2YgdGhlIHNwZWNpZmllZCBwbGFjZSB0byB0aGUgY3VycmVudCBjZW50ZXIgaW4gcGl4ZWxzXHJcblx0X2dldENlbnRlck9mZnNldDogZnVuY3Rpb24gKGxhdGxuZykge1xyXG5cdFx0cmV0dXJuIHRoaXMubGF0TG5nVG9MYXllclBvaW50KGxhdGxuZykuc3VidHJhY3QodGhpcy5fZ2V0Q2VudGVyTGF5ZXJQb2ludCgpKTtcclxuXHR9LFxyXG5cclxuXHQvLyBhZGp1c3QgY2VudGVyIGZvciB2aWV3IHRvIGdldCBpbnNpZGUgYm91bmRzXHJcblx0X2xpbWl0Q2VudGVyOiBmdW5jdGlvbiAoY2VudGVyLCB6b29tLCBib3VuZHMpIHtcclxuXHJcblx0XHRpZiAoIWJvdW5kcykgeyByZXR1cm4gY2VudGVyOyB9XHJcblxyXG5cdFx0dmFyIGNlbnRlclBvaW50ID0gdGhpcy5wcm9qZWN0KGNlbnRlciwgem9vbSksXHJcblx0XHQgICAgdmlld0hhbGYgPSB0aGlzLmdldFNpemUoKS5kaXZpZGVCeSgyKSxcclxuXHRcdCAgICB2aWV3Qm91bmRzID0gbmV3IEJvdW5kcyhjZW50ZXJQb2ludC5zdWJ0cmFjdCh2aWV3SGFsZiksIGNlbnRlclBvaW50LmFkZCh2aWV3SGFsZikpLFxyXG5cdFx0ICAgIG9mZnNldCA9IHRoaXMuX2dldEJvdW5kc09mZnNldCh2aWV3Qm91bmRzLCBib3VuZHMsIHpvb20pO1xyXG5cclxuXHRcdC8vIElmIG9mZnNldCBpcyBsZXNzIHRoYW4gYSBwaXhlbCwgaWdub3JlLlxyXG5cdFx0Ly8gVGhpcyBwcmV2ZW50cyB1bnN0YWJsZSBwcm9qZWN0aW9ucyBmcm9tIGdldHRpbmcgaW50b1xyXG5cdFx0Ly8gYW4gaW5maW5pdGUgbG9vcCBvZiB0aW55IG9mZnNldHMuXHJcblx0XHRpZiAob2Zmc2V0LnJvdW5kKCkuZXF1YWxzKFswLCAwXSkpIHtcclxuXHRcdFx0cmV0dXJuIGNlbnRlcjtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcy51bnByb2plY3QoY2VudGVyUG9pbnQuYWRkKG9mZnNldCksIHpvb20pO1xyXG5cdH0sXHJcblxyXG5cdC8vIGFkanVzdCBvZmZzZXQgZm9yIHZpZXcgdG8gZ2V0IGluc2lkZSBib3VuZHNcclxuXHRfbGltaXRPZmZzZXQ6IGZ1bmN0aW9uIChvZmZzZXQsIGJvdW5kcykge1xyXG5cdFx0aWYgKCFib3VuZHMpIHsgcmV0dXJuIG9mZnNldDsgfVxyXG5cclxuXHRcdHZhciB2aWV3Qm91bmRzID0gdGhpcy5nZXRQaXhlbEJvdW5kcygpLFxyXG5cdFx0ICAgIG5ld0JvdW5kcyA9IG5ldyBCb3VuZHModmlld0JvdW5kcy5taW4uYWRkKG9mZnNldCksIHZpZXdCb3VuZHMubWF4LmFkZChvZmZzZXQpKTtcclxuXHJcblx0XHRyZXR1cm4gb2Zmc2V0LmFkZCh0aGlzLl9nZXRCb3VuZHNPZmZzZXQobmV3Qm91bmRzLCBib3VuZHMpKTtcclxuXHR9LFxyXG5cclxuXHQvLyByZXR1cm5zIG9mZnNldCBuZWVkZWQgZm9yIHB4Qm91bmRzIHRvIGdldCBpbnNpZGUgbWF4Qm91bmRzIGF0IGEgc3BlY2lmaWVkIHpvb21cclxuXHRfZ2V0Qm91bmRzT2Zmc2V0OiBmdW5jdGlvbiAocHhCb3VuZHMsIG1heEJvdW5kcywgem9vbSkge1xyXG5cdFx0dmFyIHByb2plY3RlZE1heEJvdW5kcyA9IHRvQm91bmRzKFxyXG5cdFx0ICAgICAgICB0aGlzLnByb2plY3QobWF4Qm91bmRzLmdldE5vcnRoRWFzdCgpLCB6b29tKSxcclxuXHRcdCAgICAgICAgdGhpcy5wcm9qZWN0KG1heEJvdW5kcy5nZXRTb3V0aFdlc3QoKSwgem9vbSlcclxuXHRcdCAgICApLFxyXG5cdFx0ICAgIG1pbk9mZnNldCA9IHByb2plY3RlZE1heEJvdW5kcy5taW4uc3VidHJhY3QocHhCb3VuZHMubWluKSxcclxuXHRcdCAgICBtYXhPZmZzZXQgPSBwcm9qZWN0ZWRNYXhCb3VuZHMubWF4LnN1YnRyYWN0KHB4Qm91bmRzLm1heCksXHJcblxyXG5cdFx0ICAgIGR4ID0gdGhpcy5fcmVib3VuZChtaW5PZmZzZXQueCwgLW1heE9mZnNldC54KSxcclxuXHRcdCAgICBkeSA9IHRoaXMuX3JlYm91bmQobWluT2Zmc2V0LnksIC1tYXhPZmZzZXQueSk7XHJcblxyXG5cdFx0cmV0dXJuIG5ldyBQb2ludChkeCwgZHkpO1xyXG5cdH0sXHJcblxyXG5cdF9yZWJvdW5kOiBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcclxuXHRcdHJldHVybiBsZWZ0ICsgcmlnaHQgPiAwID9cclxuXHRcdFx0TWF0aC5yb3VuZChsZWZ0IC0gcmlnaHQpIC8gMiA6XHJcblx0XHRcdE1hdGgubWF4KDAsIE1hdGguY2VpbChsZWZ0KSkgLSBNYXRoLm1heCgwLCBNYXRoLmZsb29yKHJpZ2h0KSk7XHJcblx0fSxcclxuXHJcblx0X2xpbWl0Wm9vbTogZnVuY3Rpb24gKHpvb20pIHtcclxuXHRcdHZhciBtaW4gPSB0aGlzLmdldE1pblpvb20oKSxcclxuXHRcdCAgICBtYXggPSB0aGlzLmdldE1heFpvb20oKSxcclxuXHRcdCAgICBzbmFwID0gYW55M2QgPyB0aGlzLm9wdGlvbnMuem9vbVNuYXAgOiAxO1xyXG5cdFx0aWYgKHNuYXApIHtcclxuXHRcdFx0em9vbSA9IE1hdGgucm91bmQoem9vbSAvIHNuYXApICogc25hcDtcclxuXHRcdH1cclxuXHRcdHJldHVybiBNYXRoLm1heChtaW4sIE1hdGgubWluKG1heCwgem9vbSkpO1xyXG5cdH0sXHJcblxyXG5cdF9vblBhblRyYW5zaXRpb25TdGVwOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR0aGlzLmZpcmUoJ21vdmUnKTtcclxuXHR9LFxyXG5cclxuXHRfb25QYW5UcmFuc2l0aW9uRW5kOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZW1vdmVDbGFzcyh0aGlzLl9tYXBQYW5lLCAnbGVhZmxldC1wYW4tYW5pbScpO1xyXG5cdFx0dGhpcy5maXJlKCdtb3ZlZW5kJyk7XHJcblx0fSxcclxuXHJcblx0X3RyeUFuaW1hdGVkUGFuOiBmdW5jdGlvbiAoY2VudGVyLCBvcHRpb25zKSB7XHJcblx0XHQvLyBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG5ldyBhbmQgY3VycmVudCBjZW50ZXJzIGluIHBpeGVsc1xyXG5cdFx0dmFyIG9mZnNldCA9IHRoaXMuX2dldENlbnRlck9mZnNldChjZW50ZXIpLl90cnVuYygpO1xyXG5cclxuXHRcdC8vIGRvbid0IGFuaW1hdGUgdG9vIGZhciB1bmxlc3MgYW5pbWF0ZTogdHJ1ZSBzcGVjaWZpZWQgaW4gb3B0aW9uc1xyXG5cdFx0aWYgKChvcHRpb25zICYmIG9wdGlvbnMuYW5pbWF0ZSkgIT09IHRydWUgJiYgIXRoaXMuZ2V0U2l6ZSgpLmNvbnRhaW5zKG9mZnNldCkpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG5cdFx0dGhpcy5wYW5CeShvZmZzZXQsIG9wdGlvbnMpO1xyXG5cclxuXHRcdHJldHVybiB0cnVlO1xyXG5cdH0sXHJcblxyXG5cdF9jcmVhdGVBbmltUHJveHk6IGZ1bmN0aW9uICgpIHtcclxuXHJcblx0XHR2YXIgcHJveHkgPSB0aGlzLl9wcm94eSA9IGNyZWF0ZSQxKCdkaXYnLCAnbGVhZmxldC1wcm94eSBsZWFmbGV0LXpvb20tYW5pbWF0ZWQnKTtcclxuXHRcdHRoaXMuX3BhbmVzLm1hcFBhbmUuYXBwZW5kQ2hpbGQocHJveHkpO1xyXG5cclxuXHRcdHRoaXMub24oJ3pvb21hbmltJywgZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0dmFyIHByb3AgPSBUUkFOU0ZPUk0sXHJcblx0XHRcdCAgICB0cmFuc2Zvcm0gPSB0aGlzLl9wcm94eS5zdHlsZVtwcm9wXTtcclxuXHJcblx0XHRcdHNldFRyYW5zZm9ybSh0aGlzLl9wcm94eSwgdGhpcy5wcm9qZWN0KGUuY2VudGVyLCBlLnpvb20pLCB0aGlzLmdldFpvb21TY2FsZShlLnpvb20sIDEpKTtcclxuXHJcblx0XHRcdC8vIHdvcmthcm91bmQgZm9yIGNhc2Ugd2hlbiB0cmFuc2Zvcm0gaXMgdGhlIHNhbWUgYW5kIHNvIHRyYW5zaXRpb25lbmQgZXZlbnQgaXMgbm90IGZpcmVkXHJcblx0XHRcdGlmICh0cmFuc2Zvcm0gPT09IHRoaXMuX3Byb3h5LnN0eWxlW3Byb3BdICYmIHRoaXMuX2FuaW1hdGluZ1pvb20pIHtcclxuXHRcdFx0XHR0aGlzLl9vblpvb21UcmFuc2l0aW9uRW5kKCk7XHJcblx0XHRcdH1cclxuXHRcdH0sIHRoaXMpO1xyXG5cclxuXHRcdHRoaXMub24oJ2xvYWQgbW92ZWVuZCcsIGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0dmFyIGMgPSB0aGlzLmdldENlbnRlcigpLFxyXG5cdFx0XHQgICAgeiA9IHRoaXMuZ2V0Wm9vbSgpO1xyXG5cdFx0XHRzZXRUcmFuc2Zvcm0odGhpcy5fcHJveHksIHRoaXMucHJvamVjdChjLCB6KSwgdGhpcy5nZXRab29tU2NhbGUoeiwgMSkpO1xyXG5cdFx0fSwgdGhpcyk7XHJcblxyXG5cdFx0dGhpcy5fb24oJ3VubG9hZCcsIHRoaXMuX2Rlc3Ryb3lBbmltUHJveHksIHRoaXMpO1xyXG5cdH0sXHJcblxyXG5cdF9kZXN0cm95QW5pbVByb3h5OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZW1vdmUodGhpcy5fcHJveHkpO1xyXG5cdFx0ZGVsZXRlIHRoaXMuX3Byb3h5O1xyXG5cdH0sXHJcblxyXG5cdF9jYXRjaFRyYW5zaXRpb25FbmQ6IGZ1bmN0aW9uIChlKSB7XHJcblx0XHRpZiAodGhpcy5fYW5pbWF0aW5nWm9vbSAmJiBlLnByb3BlcnR5TmFtZS5pbmRleE9mKCd0cmFuc2Zvcm0nKSA+PSAwKSB7XHJcblx0XHRcdHRoaXMuX29uWm9vbVRyYW5zaXRpb25FbmQoKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfbm90aGluZ1RvQW5pbWF0ZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuICF0aGlzLl9jb250YWluZXIuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgnbGVhZmxldC16b29tLWFuaW1hdGVkJykubGVuZ3RoO1xyXG5cdH0sXHJcblxyXG5cdF90cnlBbmltYXRlZFpvb206IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIG9wdGlvbnMpIHtcclxuXHJcblx0XHRpZiAodGhpcy5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm4gdHJ1ZTsgfVxyXG5cclxuXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xyXG5cclxuXHRcdC8vIGRvbid0IGFuaW1hdGUgaWYgZGlzYWJsZWQsIG5vdCBzdXBwb3J0ZWQgb3Igem9vbSBkaWZmZXJlbmNlIGlzIHRvbyBsYXJnZVxyXG5cdFx0aWYgKCF0aGlzLl96b29tQW5pbWF0ZWQgfHwgb3B0aW9ucy5hbmltYXRlID09PSBmYWxzZSB8fCB0aGlzLl9ub3RoaW5nVG9BbmltYXRlKCkgfHxcclxuXHRcdCAgICAgICAgTWF0aC5hYnMoem9vbSAtIHRoaXMuX3pvb20pID4gdGhpcy5vcHRpb25zLnpvb21BbmltYXRpb25UaHJlc2hvbGQpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG5cdFx0Ly8gb2Zmc2V0IGlzIHRoZSBwaXhlbCBjb29yZHMgb2YgdGhlIHpvb20gb3JpZ2luIHJlbGF0aXZlIHRvIHRoZSBjdXJyZW50IGNlbnRlclxyXG5cdFx0dmFyIHNjYWxlID0gdGhpcy5nZXRab29tU2NhbGUoem9vbSksXHJcblx0XHQgICAgb2Zmc2V0ID0gdGhpcy5fZ2V0Q2VudGVyT2Zmc2V0KGNlbnRlcikuX2RpdmlkZUJ5KDEgLSAxIC8gc2NhbGUpO1xyXG5cclxuXHRcdC8vIGRvbid0IGFuaW1hdGUgaWYgdGhlIHpvb20gb3JpZ2luIGlzbid0IHdpdGhpbiBvbmUgc2NyZWVuIGZyb20gdGhlIGN1cnJlbnQgY2VudGVyLCB1bmxlc3MgZm9yY2VkXHJcblx0XHRpZiAob3B0aW9ucy5hbmltYXRlICE9PSB0cnVlICYmICF0aGlzLmdldFNpemUoKS5jb250YWlucyhvZmZzZXQpKSB7IHJldHVybiBmYWxzZTsgfVxyXG5cclxuXHRcdHJlcXVlc3RBbmltRnJhbWUoZnVuY3Rpb24gKCkge1xyXG5cdFx0XHR0aGlzXHJcblx0XHRcdCAgICAuX21vdmVTdGFydCh0cnVlLCBmYWxzZSlcclxuXHRcdFx0ICAgIC5fYW5pbWF0ZVpvb20oY2VudGVyLCB6b29tLCB0cnVlKTtcclxuXHRcdH0sIHRoaXMpO1xyXG5cclxuXHRcdHJldHVybiB0cnVlO1xyXG5cdH0sXHJcblxyXG5cdF9hbmltYXRlWm9vbTogZnVuY3Rpb24gKGNlbnRlciwgem9vbSwgc3RhcnRBbmltLCBub1VwZGF0ZSkge1xyXG5cdFx0aWYgKCF0aGlzLl9tYXBQYW5lKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdGlmIChzdGFydEFuaW0pIHtcclxuXHRcdFx0dGhpcy5fYW5pbWF0aW5nWm9vbSA9IHRydWU7XHJcblxyXG5cdFx0XHQvLyByZW1lbWJlciB3aGF0IGNlbnRlci96b29tIHRvIHNldCBhZnRlciBhbmltYXRpb25cclxuXHRcdFx0dGhpcy5fYW5pbWF0ZVRvQ2VudGVyID0gY2VudGVyO1xyXG5cdFx0XHR0aGlzLl9hbmltYXRlVG9ab29tID0gem9vbTtcclxuXHJcblx0XHRcdGFkZENsYXNzKHRoaXMuX21hcFBhbmUsICdsZWFmbGV0LXpvb20tYW5pbScpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIEBldmVudCB6b29tYW5pbTogWm9vbUFuaW1FdmVudFxyXG5cdFx0Ly8gRmlyZWQgYXQgbGVhc3Qgb25jZSBwZXIgem9vbSBhbmltYXRpb24uIEZvciBjb250aW51b3VzIHpvb20sIGxpa2UgcGluY2ggem9vbWluZywgZmlyZWQgb25jZSBwZXIgZnJhbWUgZHVyaW5nIHpvb20uXHJcblx0XHR0aGlzLmZpcmUoJ3pvb21hbmltJywge1xyXG5cdFx0XHRjZW50ZXI6IGNlbnRlcixcclxuXHRcdFx0em9vbTogem9vbSxcclxuXHRcdFx0bm9VcGRhdGU6IG5vVXBkYXRlXHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBXb3JrIGFyb3VuZCB3ZWJraXQgbm90IGZpcmluZyAndHJhbnNpdGlvbmVuZCcsIHNlZSBodHRwczovL2dpdGh1Yi5jb20vTGVhZmxldC9MZWFmbGV0L2lzc3Vlcy8zNjg5LCAyNjkzXHJcblx0XHRzZXRUaW1lb3V0KGJpbmQodGhpcy5fb25ab29tVHJhbnNpdGlvbkVuZCwgdGhpcyksIDI1MCk7XHJcblx0fSxcclxuXHJcblx0X29uWm9vbVRyYW5zaXRpb25FbmQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICghdGhpcy5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm47IH1cclxuXHJcblx0XHRpZiAodGhpcy5fbWFwUGFuZSkge1xyXG5cdFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9tYXBQYW5lLCAnbGVhZmxldC16b29tLWFuaW0nKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9hbmltYXRpbmdab29tID0gZmFsc2U7XHJcblxyXG5cdFx0dGhpcy5fbW92ZSh0aGlzLl9hbmltYXRlVG9DZW50ZXIsIHRoaXMuX2FuaW1hdGVUb1pvb20pO1xyXG5cclxuXHRcdC8vIFRoaXMgYW5pbSBmcmFtZSBzaG91bGQgcHJldmVudCBhbiBvYnNjdXJlIGlPUyB3ZWJraXQgdGlsZSBsb2FkaW5nIHJhY2UgY29uZGl0aW9uLlxyXG5cdFx0cmVxdWVzdEFuaW1GcmFtZShmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHRoaXMuX21vdmVFbmQodHJ1ZSk7XHJcblx0XHR9LCB0aGlzKTtcclxuXHR9XHJcbn0pO1xyXG5cclxuLy8gQHNlY3Rpb25cclxuXHJcbi8vIEBmYWN0b3J5IEwubWFwKGlkOiBTdHJpbmcsIG9wdGlvbnM/OiBNYXAgb3B0aW9ucylcclxuLy8gSW5zdGFudGlhdGVzIGEgbWFwIG9iamVjdCBnaXZlbiB0aGUgRE9NIElEIG9mIGEgYDxkaXY+YCBlbGVtZW50XHJcbi8vIGFuZCBvcHRpb25hbGx5IGFuIG9iamVjdCBsaXRlcmFsIHdpdGggYE1hcCBvcHRpb25zYC5cclxuLy9cclxuLy8gQGFsdGVybmF0aXZlXHJcbi8vIEBmYWN0b3J5IEwubWFwKGVsOiBIVE1MRWxlbWVudCwgb3B0aW9ucz86IE1hcCBvcHRpb25zKVxyXG4vLyBJbnN0YW50aWF0ZXMgYSBtYXAgb2JqZWN0IGdpdmVuIGFuIGluc3RhbmNlIG9mIGEgYDxkaXY+YCBIVE1MIGVsZW1lbnRcclxuLy8gYW5kIG9wdGlvbmFsbHkgYW4gb2JqZWN0IGxpdGVyYWwgd2l0aCBgTWFwIG9wdGlvbnNgLlxyXG5mdW5jdGlvbiBjcmVhdGVNYXAoaWQsIG9wdGlvbnMpIHtcclxuXHRyZXR1cm4gbmV3IE1hcChpZCwgb3B0aW9ucyk7XHJcbn1cblxuLypcclxuICogQGNsYXNzIENvbnRyb2xcclxuICogQGFrYSBMLkNvbnRyb2xcclxuICogQGluaGVyaXRzIENsYXNzXHJcbiAqXHJcbiAqIEwuQ29udHJvbCBpcyBhIGJhc2UgY2xhc3MgZm9yIGltcGxlbWVudGluZyBtYXAgY29udHJvbHMuIEhhbmRsZXMgcG9zaXRpb25pbmcuXHJcbiAqIEFsbCBvdGhlciBjb250cm9scyBleHRlbmQgZnJvbSB0aGlzIGNsYXNzLlxyXG4gKi9cclxuXHJcbnZhciBDb250cm9sID0gQ2xhc3MuZXh0ZW5kKHtcclxuXHQvLyBAc2VjdGlvblxyXG5cdC8vIEBha2EgQ29udHJvbCBvcHRpb25zXHJcblx0b3B0aW9uczoge1xyXG5cdFx0Ly8gQG9wdGlvbiBwb3NpdGlvbjogU3RyaW5nID0gJ3RvcHJpZ2h0J1xyXG5cdFx0Ly8gVGhlIHBvc2l0aW9uIG9mIHRoZSBjb250cm9sIChvbmUgb2YgdGhlIG1hcCBjb3JuZXJzKS4gUG9zc2libGUgdmFsdWVzIGFyZSBgJ3RvcGxlZnQnYCxcclxuXHRcdC8vIGAndG9wcmlnaHQnYCwgYCdib3R0b21sZWZ0J2Agb3IgYCdib3R0b21yaWdodCdgXHJcblx0XHRwb3NpdGlvbjogJ3RvcHJpZ2h0J1xyXG5cdH0sXHJcblxyXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cdH0sXHJcblxyXG5cdC8qIEBzZWN0aW9uXHJcblx0ICogQ2xhc3NlcyBleHRlbmRpbmcgTC5Db250cm9sIHdpbGwgaW5oZXJpdCB0aGUgZm9sbG93aW5nIG1ldGhvZHM6XHJcblx0ICpcclxuXHQgKiBAbWV0aG9kIGdldFBvc2l0aW9uOiBzdHJpbmdcclxuXHQgKiBSZXR1cm5zIHRoZSBwb3NpdGlvbiBvZiB0aGUgY29udHJvbC5cclxuXHQgKi9cclxuXHRnZXRQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5wb3NpdGlvbjtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNldFBvc2l0aW9uKHBvc2l0aW9uOiBzdHJpbmcpOiB0aGlzXHJcblx0Ly8gU2V0cyB0aGUgcG9zaXRpb24gb2YgdGhlIGNvbnRyb2wuXHJcblx0c2V0UG9zaXRpb246IGZ1bmN0aW9uIChwb3NpdGlvbikge1xyXG5cdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcclxuXHJcblx0XHRpZiAobWFwKSB7XHJcblx0XHRcdG1hcC5yZW1vdmVDb250cm9sKHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMub3B0aW9ucy5wb3NpdGlvbiA9IHBvc2l0aW9uO1xyXG5cclxuXHRcdGlmIChtYXApIHtcclxuXHRcdFx0bWFwLmFkZENvbnRyb2wodGhpcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRDb250YWluZXI6IEhUTUxFbGVtZW50XHJcblx0Ly8gUmV0dXJucyB0aGUgSFRNTEVsZW1lbnQgdGhhdCBjb250YWlucyB0aGUgY29udHJvbC5cclxuXHRnZXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9jb250YWluZXI7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBhZGRUbyhtYXA6IE1hcCk6IHRoaXNcclxuXHQvLyBBZGRzIHRoZSBjb250cm9sIHRvIHRoZSBnaXZlbiBtYXAuXHJcblx0YWRkVG86IGZ1bmN0aW9uIChtYXApIHtcclxuXHRcdHRoaXMucmVtb3ZlKCk7XHJcblx0XHR0aGlzLl9tYXAgPSBtYXA7XHJcblxyXG5cdFx0dmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lciA9IHRoaXMub25BZGQobWFwKSxcclxuXHRcdCAgICBwb3MgPSB0aGlzLmdldFBvc2l0aW9uKCksXHJcblx0XHQgICAgY29ybmVyID0gbWFwLl9jb250cm9sQ29ybmVyc1twb3NdO1xyXG5cclxuXHRcdGFkZENsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtY29udHJvbCcpO1xyXG5cclxuXHRcdGlmIChwb3MuaW5kZXhPZignYm90dG9tJykgIT09IC0xKSB7XHJcblx0XHRcdGNvcm5lci5pbnNlcnRCZWZvcmUoY29udGFpbmVyLCBjb3JuZXIuZmlyc3RDaGlsZCk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRjb3JuZXIuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9tYXAub24oJ3VubG9hZCcsIHRoaXMucmVtb3ZlLCB0aGlzKTtcclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHJlbW92ZTogdGhpc1xyXG5cdC8vIFJlbW92ZXMgdGhlIGNvbnRyb2wgZnJvbSB0aGUgbWFwIGl0IGlzIGN1cnJlbnRseSBhY3RpdmUgb24uXHJcblx0cmVtb3ZlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAoIXRoaXMuX21hcCkge1xyXG5cdFx0XHRyZXR1cm4gdGhpcztcclxuXHRcdH1cclxuXHJcblx0XHRyZW1vdmUodGhpcy5fY29udGFpbmVyKTtcclxuXHJcblx0XHRpZiAodGhpcy5vblJlbW92ZSkge1xyXG5cdFx0XHR0aGlzLm9uUmVtb3ZlKHRoaXMuX21hcCk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fbWFwLm9mZigndW5sb2FkJywgdGhpcy5yZW1vdmUsIHRoaXMpO1xyXG5cdFx0dGhpcy5fbWFwID0gbnVsbDtcclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRfcmVmb2N1c09uTWFwOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0Ly8gaWYgbWFwIGV4aXN0cyBhbmQgZXZlbnQgaXMgbm90IGEga2V5Ym9hcmQgZXZlbnRcclxuXHRcdGlmICh0aGlzLl9tYXAgJiYgZSAmJiBlLnNjcmVlblggPiAwICYmIGUuc2NyZWVuWSA+IDApIHtcclxuXHRcdFx0dGhpcy5fbWFwLmdldENvbnRhaW5lcigpLmZvY3VzKCk7XHJcblx0XHR9XHJcblx0fVxyXG59KTtcclxuXHJcbnZhciBjb250cm9sID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuXHRyZXR1cm4gbmV3IENvbnRyb2wob3B0aW9ucyk7XHJcbn07XHJcblxyXG4vKiBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xyXG4gKiBAdW5pbmhlcml0YWJsZVxyXG4gKlxyXG4gKiBFdmVyeSBjb250cm9sIHNob3VsZCBleHRlbmQgZnJvbSBgTC5Db250cm9sYCBhbmQgKHJlLSlpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBtZXRob2RzLlxyXG4gKlxyXG4gKiBAbWV0aG9kIG9uQWRkKG1hcDogTWFwKTogSFRNTEVsZW1lbnRcclxuICogU2hvdWxkIHJldHVybiB0aGUgY29udGFpbmVyIERPTSBlbGVtZW50IGZvciB0aGUgY29udHJvbCBhbmQgYWRkIGxpc3RlbmVycyBvbiByZWxldmFudCBtYXAgZXZlbnRzLiBDYWxsZWQgb24gW2Bjb250cm9sLmFkZFRvKG1hcClgXSgjY29udHJvbC1hZGRUbykuXHJcbiAqXHJcbiAqIEBtZXRob2Qgb25SZW1vdmUobWFwOiBNYXApXHJcbiAqIE9wdGlvbmFsIG1ldGhvZC4gU2hvdWxkIGNvbnRhaW4gYWxsIGNsZWFuIHVwIGNvZGUgdGhhdCByZW1vdmVzIHRoZSBsaXN0ZW5lcnMgcHJldmlvdXNseSBhZGRlZCBpbiBbYG9uQWRkYF0oI2NvbnRyb2wtb25hZGQpLiBDYWxsZWQgb24gW2Bjb250cm9sLnJlbW92ZSgpYF0oI2NvbnRyb2wtcmVtb3ZlKS5cclxuICovXHJcblxyXG4vKiBAbmFtZXNwYWNlIE1hcFxyXG4gKiBAc2VjdGlvbiBNZXRob2RzIGZvciBMYXllcnMgYW5kIENvbnRyb2xzXHJcbiAqL1xyXG5NYXAuaW5jbHVkZSh7XHJcblx0Ly8gQG1ldGhvZCBhZGRDb250cm9sKGNvbnRyb2w6IENvbnRyb2wpOiB0aGlzXHJcblx0Ly8gQWRkcyB0aGUgZ2l2ZW4gY29udHJvbCB0byB0aGUgbWFwXHJcblx0YWRkQ29udHJvbDogZnVuY3Rpb24gKGNvbnRyb2wpIHtcclxuXHRcdGNvbnRyb2wuYWRkVG8odGhpcyk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHJlbW92ZUNvbnRyb2woY29udHJvbDogQ29udHJvbCk6IHRoaXNcclxuXHQvLyBSZW1vdmVzIHRoZSBnaXZlbiBjb250cm9sIGZyb20gdGhlIG1hcFxyXG5cdHJlbW92ZUNvbnRyb2w6IGZ1bmN0aW9uIChjb250cm9sKSB7XHJcblx0XHRjb250cm9sLnJlbW92ZSgpO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0X2luaXRDb250cm9sUG9zOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgY29ybmVycyA9IHRoaXMuX2NvbnRyb2xDb3JuZXJzID0ge30sXHJcblx0XHQgICAgbCA9ICdsZWFmbGV0LScsXHJcblx0XHQgICAgY29udGFpbmVyID0gdGhpcy5fY29udHJvbENvbnRhaW5lciA9XHJcblx0XHQgICAgICAgICAgICBjcmVhdGUkMSgnZGl2JywgbCArICdjb250cm9sLWNvbnRhaW5lcicsIHRoaXMuX2NvbnRhaW5lcik7XHJcblxyXG5cdFx0ZnVuY3Rpb24gY3JlYXRlQ29ybmVyKHZTaWRlLCBoU2lkZSkge1xyXG5cdFx0XHR2YXIgY2xhc3NOYW1lID0gbCArIHZTaWRlICsgJyAnICsgbCArIGhTaWRlO1xyXG5cclxuXHRcdFx0Y29ybmVyc1t2U2lkZSArIGhTaWRlXSA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUsIGNvbnRhaW5lcik7XHJcblx0XHR9XHJcblxyXG5cdFx0Y3JlYXRlQ29ybmVyKCd0b3AnLCAnbGVmdCcpO1xyXG5cdFx0Y3JlYXRlQ29ybmVyKCd0b3AnLCAncmlnaHQnKTtcclxuXHRcdGNyZWF0ZUNvcm5lcignYm90dG9tJywgJ2xlZnQnKTtcclxuXHRcdGNyZWF0ZUNvcm5lcignYm90dG9tJywgJ3JpZ2h0Jyk7XHJcblx0fSxcclxuXHJcblx0X2NsZWFyQ29udHJvbFBvczogZnVuY3Rpb24gKCkge1xyXG5cdFx0Zm9yICh2YXIgaSBpbiB0aGlzLl9jb250cm9sQ29ybmVycykge1xyXG5cdFx0XHRyZW1vdmUodGhpcy5fY29udHJvbENvcm5lcnNbaV0pO1xyXG5cdFx0fVxyXG5cdFx0cmVtb3ZlKHRoaXMuX2NvbnRyb2xDb250YWluZXIpO1xyXG5cdFx0ZGVsZXRlIHRoaXMuX2NvbnRyb2xDb3JuZXJzO1xyXG5cdFx0ZGVsZXRlIHRoaXMuX2NvbnRyb2xDb250YWluZXI7XHJcblx0fVxyXG59KTtcblxuLypcclxuICogQGNsYXNzIENvbnRyb2wuTGF5ZXJzXHJcbiAqIEBha2EgTC5Db250cm9sLkxheWVyc1xyXG4gKiBAaW5oZXJpdHMgQ29udHJvbFxyXG4gKlxyXG4gKiBUaGUgbGF5ZXJzIGNvbnRyb2wgZ2l2ZXMgdXNlcnMgdGhlIGFiaWxpdHkgdG8gc3dpdGNoIGJldHdlZW4gZGlmZmVyZW50IGJhc2UgbGF5ZXJzIGFuZCBzd2l0Y2ggb3ZlcmxheXMgb24vb2ZmIChjaGVjayBvdXQgdGhlIFtkZXRhaWxlZCBleGFtcGxlXShodHRwOi8vbGVhZmxldGpzLmNvbS9leGFtcGxlcy9sYXllcnMtY29udHJvbC8pKS4gRXh0ZW5kcyBgQ29udHJvbGAuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBiYXNlTGF5ZXJzID0ge1xyXG4gKiBcdFwiTWFwYm94XCI6IG1hcGJveCxcclxuICogXHRcIk9wZW5TdHJlZXRNYXBcIjogb3NtXHJcbiAqIH07XHJcbiAqXHJcbiAqIHZhciBvdmVybGF5cyA9IHtcclxuICogXHRcIk1hcmtlclwiOiBtYXJrZXIsXHJcbiAqIFx0XCJSb2Fkc1wiOiByb2Fkc0xheWVyXHJcbiAqIH07XHJcbiAqXHJcbiAqIEwuY29udHJvbC5sYXllcnMoYmFzZUxheWVycywgb3ZlcmxheXMpLmFkZFRvKG1hcCk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBUaGUgYGJhc2VMYXllcnNgIGFuZCBgb3ZlcmxheXNgIHBhcmFtZXRlcnMgYXJlIG9iamVjdCBsaXRlcmFscyB3aXRoIGxheWVyIG5hbWVzIGFzIGtleXMgYW5kIGBMYXllcmAgb2JqZWN0cyBhcyB2YWx1ZXM6XHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHtcclxuICogICAgIFwiPHNvbWVOYW1lMT5cIjogbGF5ZXIxLFxyXG4gKiAgICAgXCI8c29tZU5hbWUyPlwiOiBsYXllcjJcclxuICogfVxyXG4gKiBgYGBcclxuICpcclxuICogVGhlIGxheWVyIG5hbWVzIGNhbiBjb250YWluIEhUTUwsIHdoaWNoIGFsbG93cyB5b3UgdG8gYWRkIGFkZGl0aW9uYWwgc3R5bGluZyB0byB0aGUgaXRlbXM6XHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHtcIjxpbWcgc3JjPSdteS1sYXllci1pY29uJyAvPiA8c3BhbiBjbGFzcz0nbXktbGF5ZXItaXRlbSc+TXkgTGF5ZXI8L3NwYW4+XCI6IG15TGF5ZXJ9XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBMYXllcnMgPSBDb250cm9sLmV4dGVuZCh7XHJcblx0Ly8gQHNlY3Rpb25cclxuXHQvLyBAYWthIENvbnRyb2wuTGF5ZXJzIG9wdGlvbnNcclxuXHRvcHRpb25zOiB7XHJcblx0XHQvLyBAb3B0aW9uIGNvbGxhcHNlZDogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIElmIGB0cnVlYCwgdGhlIGNvbnRyb2wgd2lsbCBiZSBjb2xsYXBzZWQgaW50byBhbiBpY29uIGFuZCBleHBhbmRlZCBvbiBtb3VzZSBob3ZlciBvciB0b3VjaC5cclxuXHRcdGNvbGxhcHNlZDogdHJ1ZSxcclxuXHRcdHBvc2l0aW9uOiAndG9wcmlnaHQnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gYXV0b1pJbmRleDogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIElmIGB0cnVlYCwgdGhlIGNvbnRyb2wgd2lsbCBhc3NpZ24gekluZGV4ZXMgaW4gaW5jcmVhc2luZyBvcmRlciB0byBhbGwgb2YgaXRzIGxheWVycyBzbyB0aGF0IHRoZSBvcmRlciBpcyBwcmVzZXJ2ZWQgd2hlbiBzd2l0Y2hpbmcgdGhlbSBvbi9vZmYuXHJcblx0XHRhdXRvWkluZGV4OiB0cnVlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gaGlkZVNpbmdsZUJhc2U6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gSWYgYHRydWVgLCB0aGUgYmFzZSBsYXllcnMgaW4gdGhlIGNvbnRyb2wgd2lsbCBiZSBoaWRkZW4gd2hlbiB0aGVyZSBpcyBvbmx5IG9uZS5cclxuXHRcdGhpZGVTaW5nbGVCYXNlOiBmYWxzZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHNvcnRMYXllcnM6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gV2hldGhlciB0byBzb3J0IHRoZSBsYXllcnMuIFdoZW4gYGZhbHNlYCwgbGF5ZXJzIHdpbGwga2VlcCB0aGUgb3JkZXJcclxuXHRcdC8vIGluIHdoaWNoIHRoZXkgd2VyZSBhZGRlZCB0byB0aGUgY29udHJvbC5cclxuXHRcdHNvcnRMYXllcnM6IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gc29ydEZ1bmN0aW9uOiBGdW5jdGlvbiA9ICpcclxuXHRcdC8vIEEgW2NvbXBhcmUgZnVuY3Rpb25dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L3NvcnQpXHJcblx0XHQvLyB0aGF0IHdpbGwgYmUgdXNlZCBmb3Igc29ydGluZyB0aGUgbGF5ZXJzLCB3aGVuIGBzb3J0TGF5ZXJzYCBpcyBgdHJ1ZWAuXHJcblx0XHQvLyBUaGUgZnVuY3Rpb24gcmVjZWl2ZXMgYm90aCB0aGUgYEwuTGF5ZXJgIGluc3RhbmNlcyBhbmQgdGhlaXIgbmFtZXMsIGFzIGluXHJcblx0XHQvLyBgc29ydEZ1bmN0aW9uKGxheWVyQSwgbGF5ZXJCLCBuYW1lQSwgbmFtZUIpYC5cclxuXHRcdC8vIEJ5IGRlZmF1bHQsIGl0IHNvcnRzIGxheWVycyBhbHBoYWJldGljYWxseSBieSB0aGVpciBuYW1lLlxyXG5cdFx0c29ydEZ1bmN0aW9uOiBmdW5jdGlvbiAobGF5ZXJBLCBsYXllckIsIG5hbWVBLCBuYW1lQikge1xyXG5cdFx0XHRyZXR1cm4gbmFtZUEgPCBuYW1lQiA/IC0xIDogKG5hbWVCIDwgbmFtZUEgPyAxIDogMCk7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGJhc2VMYXllcnMsIG92ZXJsYXlzLCBvcHRpb25zKSB7XHJcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuXHRcdHRoaXMuX2xheWVyQ29udHJvbElucHV0cyA9IFtdO1xyXG5cdFx0dGhpcy5fbGF5ZXJzID0gW107XHJcblx0XHR0aGlzLl9sYXN0WkluZGV4ID0gMDtcclxuXHRcdHRoaXMuX2hhbmRsaW5nQ2xpY2sgPSBmYWxzZTtcclxuXHJcblx0XHRmb3IgKHZhciBpIGluIGJhc2VMYXllcnMpIHtcclxuXHRcdFx0dGhpcy5fYWRkTGF5ZXIoYmFzZUxheWVyc1tpXSwgaSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Zm9yIChpIGluIG92ZXJsYXlzKSB7XHJcblx0XHRcdHRoaXMuX2FkZExheWVyKG92ZXJsYXlzW2ldLCBpLCB0cnVlKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0dGhpcy5faW5pdExheW91dCgpO1xyXG5cdFx0dGhpcy5fdXBkYXRlKCk7XHJcblxyXG5cdFx0dGhpcy5fbWFwID0gbWFwO1xyXG5cdFx0bWFwLm9uKCd6b29tZW5kJywgdGhpcy5fY2hlY2tEaXNhYmxlZExheWVycywgdGhpcyk7XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9sYXllcnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0dGhpcy5fbGF5ZXJzW2ldLmxheWVyLm9uKCdhZGQgcmVtb3ZlJywgdGhpcy5fb25MYXllckNoYW5nZSwgdGhpcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXMuX2NvbnRhaW5lcjtcclxuXHR9LFxyXG5cclxuXHRhZGRUbzogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0Q29udHJvbC5wcm90b3R5cGUuYWRkVG8uY2FsbCh0aGlzLCBtYXApO1xyXG5cdFx0Ly8gVHJpZ2dlciBleHBhbmQgYWZ0ZXIgTGF5ZXJzIENvbnRyb2wgaGFzIGJlZW4gaW5zZXJ0ZWQgaW50byBET00gc28gdGhhdCBpcyBub3cgaGFzIGFuIGFjdHVhbCBoZWlnaHQuXHJcblx0XHRyZXR1cm4gdGhpcy5fZXhwYW5kSWZOb3RDb2xsYXBzZWQoKTtcclxuXHR9LFxyXG5cclxuXHRvblJlbW92ZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0dGhpcy5fbWFwLm9mZignem9vbWVuZCcsIHRoaXMuX2NoZWNrRGlzYWJsZWRMYXllcnMsIHRoaXMpO1xyXG5cclxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdHRoaXMuX2xheWVyc1tpXS5sYXllci5vZmYoJ2FkZCByZW1vdmUnLCB0aGlzLl9vbkxheWVyQ2hhbmdlLCB0aGlzKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGFkZEJhc2VMYXllcihsYXllcjogTGF5ZXIsIG5hbWU6IFN0cmluZyk6IHRoaXNcclxuXHQvLyBBZGRzIGEgYmFzZSBsYXllciAocmFkaW8gYnV0dG9uIGVudHJ5KSB3aXRoIHRoZSBnaXZlbiBuYW1lIHRvIHRoZSBjb250cm9sLlxyXG5cdGFkZEJhc2VMYXllcjogZnVuY3Rpb24gKGxheWVyLCBuYW1lKSB7XHJcblx0XHR0aGlzLl9hZGRMYXllcihsYXllciwgbmFtZSk7XHJcblx0XHRyZXR1cm4gKHRoaXMuX21hcCkgPyB0aGlzLl91cGRhdGUoKSA6IHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBhZGRPdmVybGF5KGxheWVyOiBMYXllciwgbmFtZTogU3RyaW5nKTogdGhpc1xyXG5cdC8vIEFkZHMgYW4gb3ZlcmxheSAoY2hlY2tib3ggZW50cnkpIHdpdGggdGhlIGdpdmVuIG5hbWUgdG8gdGhlIGNvbnRyb2wuXHJcblx0YWRkT3ZlcmxheTogZnVuY3Rpb24gKGxheWVyLCBuYW1lKSB7XHJcblx0XHR0aGlzLl9hZGRMYXllcihsYXllciwgbmFtZSwgdHJ1ZSk7XHJcblx0XHRyZXR1cm4gKHRoaXMuX21hcCkgPyB0aGlzLl91cGRhdGUoKSA6IHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCByZW1vdmVMYXllcihsYXllcjogTGF5ZXIpOiB0aGlzXHJcblx0Ly8gUmVtb3ZlIHRoZSBnaXZlbiBsYXllciBmcm9tIHRoZSBjb250cm9sLlxyXG5cdHJlbW92ZUxheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHRcdGxheWVyLm9mZignYWRkIHJlbW92ZScsIHRoaXMuX29uTGF5ZXJDaGFuZ2UsIHRoaXMpO1xyXG5cclxuXHRcdHZhciBvYmogPSB0aGlzLl9nZXRMYXllcihzdGFtcChsYXllcikpO1xyXG5cdFx0aWYgKG9iaikge1xyXG5cdFx0XHR0aGlzLl9sYXllcnMuc3BsaWNlKHRoaXMuX2xheWVycy5pbmRleE9mKG9iaiksIDEpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuICh0aGlzLl9tYXApID8gdGhpcy5fdXBkYXRlKCkgOiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZXhwYW5kKCk6IHRoaXNcclxuXHQvLyBFeHBhbmQgdGhlIGNvbnRyb2wgY29udGFpbmVyIGlmIGNvbGxhcHNlZC5cclxuXHRleHBhbmQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGFkZENsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtZXhwYW5kZWQnKTtcclxuXHRcdHRoaXMuX3NlY3Rpb24uc3R5bGUuaGVpZ2h0ID0gbnVsbDtcclxuXHRcdHZhciBhY2NlcHRhYmxlSGVpZ2h0ID0gdGhpcy5fbWFwLmdldFNpemUoKS55IC0gKHRoaXMuX2NvbnRhaW5lci5vZmZzZXRUb3AgKyA1MCk7XHJcblx0XHRpZiAoYWNjZXB0YWJsZUhlaWdodCA8IHRoaXMuX3NlY3Rpb24uY2xpZW50SGVpZ2h0KSB7XHJcblx0XHRcdGFkZENsYXNzKHRoaXMuX3NlY3Rpb24sICdsZWFmbGV0LWNvbnRyb2wtbGF5ZXJzLXNjcm9sbGJhcicpO1xyXG5cdFx0XHR0aGlzLl9zZWN0aW9uLnN0eWxlLmhlaWdodCA9IGFjY2VwdGFibGVIZWlnaHQgKyAncHgnO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fc2VjdGlvbiwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtc2Nyb2xsYmFyJyk7XHJcblx0XHR9XHJcblx0XHR0aGlzLl9jaGVja0Rpc2FibGVkTGF5ZXJzKCk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGNvbGxhcHNlKCk6IHRoaXNcclxuXHQvLyBDb2xsYXBzZSB0aGUgY29udHJvbCBjb250YWluZXIgaWYgZXhwYW5kZWQuXHJcblx0Y29sbGFwc2U6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJlbW92ZUNsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtZXhwYW5kZWQnKTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdF9pbml0TGF5b3V0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgY2xhc3NOYW1lID0gJ2xlYWZsZXQtY29udHJvbC1sYXllcnMnLFxyXG5cdFx0ICAgIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUpLFxyXG5cdFx0ICAgIGNvbGxhcHNlZCA9IHRoaXMub3B0aW9ucy5jb2xsYXBzZWQ7XHJcblxyXG5cdFx0Ly8gbWFrZXMgdGhpcyB3b3JrIG9uIElFIHRvdWNoIGRldmljZXMgYnkgc3RvcHBpbmcgaXQgZnJvbSBmaXJpbmcgYSBtb3VzZW91dCBldmVudCB3aGVuIHRoZSB0b3VjaCBpcyByZWxlYXNlZFxyXG5cdFx0Y29udGFpbmVyLnNldEF0dHJpYnV0ZSgnYXJpYS1oYXNwb3B1cCcsIHRydWUpO1xyXG5cclxuXHRcdGRpc2FibGVDbGlja1Byb3BhZ2F0aW9uKGNvbnRhaW5lcik7XHJcblx0XHRkaXNhYmxlU2Nyb2xsUHJvcGFnYXRpb24oY29udGFpbmVyKTtcclxuXHJcblx0XHR2YXIgc2VjdGlvbiA9IHRoaXMuX3NlY3Rpb24gPSBjcmVhdGUkMSgnc2VjdGlvbicsIGNsYXNzTmFtZSArICctbGlzdCcpO1xyXG5cclxuXHRcdGlmIChjb2xsYXBzZWQpIHtcclxuXHRcdFx0dGhpcy5fbWFwLm9uKCdjbGljaycsIHRoaXMuY29sbGFwc2UsIHRoaXMpO1xyXG5cclxuXHRcdFx0aWYgKCFhbmRyb2lkKSB7XHJcblx0XHRcdFx0b24oY29udGFpbmVyLCB7XHJcblx0XHRcdFx0XHRtb3VzZWVudGVyOiB0aGlzLmV4cGFuZCxcclxuXHRcdFx0XHRcdG1vdXNlbGVhdmU6IHRoaXMuY29sbGFwc2VcclxuXHRcdFx0XHR9LCB0aGlzKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBsaW5rID0gdGhpcy5fbGF5ZXJzTGluayA9IGNyZWF0ZSQxKCdhJywgY2xhc3NOYW1lICsgJy10b2dnbGUnLCBjb250YWluZXIpO1xyXG5cdFx0bGluay5ocmVmID0gJyMnO1xyXG5cdFx0bGluay50aXRsZSA9ICdMYXllcnMnO1xyXG5cclxuXHRcdGlmICh0b3VjaCkge1xyXG5cdFx0XHRvbihsaW5rLCAnY2xpY2snLCBzdG9wKTtcclxuXHRcdFx0b24obGluaywgJ2NsaWNrJywgdGhpcy5leHBhbmQsIHRoaXMpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0b24obGluaywgJ2ZvY3VzJywgdGhpcy5leHBhbmQsIHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICghY29sbGFwc2VkKSB7XHJcblx0XHRcdHRoaXMuZXhwYW5kKCk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fYmFzZUxheWVyc0xpc3QgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lICsgJy1iYXNlJywgc2VjdGlvbik7XHJcblx0XHR0aGlzLl9zZXBhcmF0b3IgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lICsgJy1zZXBhcmF0b3InLCBzZWN0aW9uKTtcclxuXHRcdHRoaXMuX292ZXJsYXlzTGlzdCA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUgKyAnLW92ZXJsYXlzJywgc2VjdGlvbik7XHJcblxyXG5cdFx0Y29udGFpbmVyLmFwcGVuZENoaWxkKHNlY3Rpb24pO1xyXG5cdH0sXHJcblxyXG5cdF9nZXRMYXllcjogZnVuY3Rpb24gKGlkKSB7XHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2xheWVycy5sZW5ndGg7IGkrKykge1xyXG5cclxuXHRcdFx0aWYgKHRoaXMuX2xheWVyc1tpXSAmJiBzdGFtcCh0aGlzLl9sYXllcnNbaV0ubGF5ZXIpID09PSBpZCkge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLl9sYXllcnNbaV07XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfYWRkTGF5ZXI6IGZ1bmN0aW9uIChsYXllciwgbmFtZSwgb3ZlcmxheSkge1xyXG5cdFx0aWYgKHRoaXMuX21hcCkge1xyXG5cdFx0XHRsYXllci5vbignYWRkIHJlbW92ZScsIHRoaXMuX29uTGF5ZXJDaGFuZ2UsIHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2xheWVycy5wdXNoKHtcclxuXHRcdFx0bGF5ZXI6IGxheWVyLFxyXG5cdFx0XHRuYW1lOiBuYW1lLFxyXG5cdFx0XHRvdmVybGF5OiBvdmVybGF5XHJcblx0XHR9KTtcclxuXHJcblx0XHRpZiAodGhpcy5vcHRpb25zLnNvcnRMYXllcnMpIHtcclxuXHRcdFx0dGhpcy5fbGF5ZXJzLnNvcnQoYmluZChmdW5jdGlvbiAoYSwgYikge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLm9wdGlvbnMuc29ydEZ1bmN0aW9uKGEubGF5ZXIsIGIubGF5ZXIsIGEubmFtZSwgYi5uYW1lKTtcclxuXHRcdFx0fSwgdGhpcykpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuYXV0b1pJbmRleCAmJiBsYXllci5zZXRaSW5kZXgpIHtcclxuXHRcdFx0dGhpcy5fbGFzdFpJbmRleCsrO1xyXG5cdFx0XHRsYXllci5zZXRaSW5kZXgodGhpcy5fbGFzdFpJbmRleCk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fZXhwYW5kSWZOb3RDb2xsYXBzZWQoKTtcclxuXHR9LFxyXG5cclxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAoIXRoaXMuX2NvbnRhaW5lcikgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdGVtcHR5KHRoaXMuX2Jhc2VMYXllcnNMaXN0KTtcclxuXHRcdGVtcHR5KHRoaXMuX292ZXJsYXlzTGlzdCk7XHJcblxyXG5cdFx0dGhpcy5fbGF5ZXJDb250cm9sSW5wdXRzID0gW107XHJcblx0XHR2YXIgYmFzZUxheWVyc1ByZXNlbnQsIG92ZXJsYXlzUHJlc2VudCwgaSwgb2JqLCBiYXNlTGF5ZXJzQ291bnQgPSAwO1xyXG5cclxuXHRcdGZvciAoaSA9IDA7IGkgPCB0aGlzLl9sYXllcnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0b2JqID0gdGhpcy5fbGF5ZXJzW2ldO1xyXG5cdFx0XHR0aGlzLl9hZGRJdGVtKG9iaik7XHJcblx0XHRcdG92ZXJsYXlzUHJlc2VudCA9IG92ZXJsYXlzUHJlc2VudCB8fCBvYmoub3ZlcmxheTtcclxuXHRcdFx0YmFzZUxheWVyc1ByZXNlbnQgPSBiYXNlTGF5ZXJzUHJlc2VudCB8fCAhb2JqLm92ZXJsYXk7XHJcblx0XHRcdGJhc2VMYXllcnNDb3VudCArPSAhb2JqLm92ZXJsYXkgPyAxIDogMDtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBIaWRlIGJhc2UgbGF5ZXJzIHNlY3Rpb24gaWYgdGhlcmUncyBvbmx5IG9uZSBsYXllci5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuaGlkZVNpbmdsZUJhc2UpIHtcclxuXHRcdFx0YmFzZUxheWVyc1ByZXNlbnQgPSBiYXNlTGF5ZXJzUHJlc2VudCAmJiBiYXNlTGF5ZXJzQ291bnQgPiAxO1xyXG5cdFx0XHR0aGlzLl9iYXNlTGF5ZXJzTGlzdC5zdHlsZS5kaXNwbGF5ID0gYmFzZUxheWVyc1ByZXNlbnQgPyAnJyA6ICdub25lJztcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9zZXBhcmF0b3Iuc3R5bGUuZGlzcGxheSA9IG92ZXJsYXlzUHJlc2VudCAmJiBiYXNlTGF5ZXJzUHJlc2VudCA/ICcnIDogJ25vbmUnO1xyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdF9vbkxheWVyQ2hhbmdlOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0aWYgKCF0aGlzLl9oYW5kbGluZ0NsaWNrKSB7XHJcblx0XHRcdHRoaXMuX3VwZGF0ZSgpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBvYmogPSB0aGlzLl9nZXRMYXllcihzdGFtcChlLnRhcmdldCkpO1xyXG5cclxuXHRcdC8vIEBuYW1lc3BhY2UgTWFwXHJcblx0XHQvLyBAc2VjdGlvbiBMYXllciBldmVudHNcclxuXHRcdC8vIEBldmVudCBiYXNlbGF5ZXJjaGFuZ2U6IExheWVyc0NvbnRyb2xFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgYmFzZSBsYXllciBpcyBjaGFuZ2VkIHRocm91Z2ggdGhlIFtsYXllciBjb250cm9sXSgjY29udHJvbC1sYXllcnMpLlxyXG5cdFx0Ly8gQGV2ZW50IG92ZXJsYXlhZGQ6IExheWVyc0NvbnRyb2xFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiBhbiBvdmVybGF5IGlzIHNlbGVjdGVkIHRocm91Z2ggdGhlIFtsYXllciBjb250cm9sXSgjY29udHJvbC1sYXllcnMpLlxyXG5cdFx0Ly8gQGV2ZW50IG92ZXJsYXlyZW1vdmU6IExheWVyc0NvbnRyb2xFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiBhbiBvdmVybGF5IGlzIGRlc2VsZWN0ZWQgdGhyb3VnaCB0aGUgW2xheWVyIGNvbnRyb2xdKCNjb250cm9sLWxheWVycykuXHJcblx0XHQvLyBAbmFtZXNwYWNlIENvbnRyb2wuTGF5ZXJzXHJcblx0XHR2YXIgdHlwZSA9IG9iai5vdmVybGF5ID9cclxuXHRcdFx0KGUudHlwZSA9PT0gJ2FkZCcgPyAnb3ZlcmxheWFkZCcgOiAnb3ZlcmxheXJlbW92ZScpIDpcclxuXHRcdFx0KGUudHlwZSA9PT0gJ2FkZCcgPyAnYmFzZWxheWVyY2hhbmdlJyA6IG51bGwpO1xyXG5cclxuXHRcdGlmICh0eXBlKSB7XHJcblx0XHRcdHRoaXMuX21hcC5maXJlKHR5cGUsIG9iaik7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0Ly8gSUU3IGJ1Z3Mgb3V0IGlmIHlvdSBjcmVhdGUgYSByYWRpbyBkeW5hbWljYWxseSwgc28geW91IGhhdmUgdG8gZG8gaXQgdGhpcyBoYWNreSB3YXkgKHNlZSBodHRwOi8vYml0Lmx5L1BxWUxCZSlcclxuXHRfY3JlYXRlUmFkaW9FbGVtZW50OiBmdW5jdGlvbiAobmFtZSwgY2hlY2tlZCkge1xyXG5cclxuXHRcdHZhciByYWRpb0h0bWwgPSAnPGlucHV0IHR5cGU9XCJyYWRpb1wiIGNsYXNzPVwibGVhZmxldC1jb250cm9sLWxheWVycy1zZWxlY3RvclwiIG5hbWU9XCInICtcclxuXHRcdFx0XHRuYW1lICsgJ1wiJyArIChjaGVja2VkID8gJyBjaGVja2VkPVwiY2hlY2tlZFwiJyA6ICcnKSArICcvPic7XHJcblxyXG5cdFx0dmFyIHJhZGlvRnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuXHRcdHJhZGlvRnJhZ21lbnQuaW5uZXJIVE1MID0gcmFkaW9IdG1sO1xyXG5cclxuXHRcdHJldHVybiByYWRpb0ZyYWdtZW50LmZpcnN0Q2hpbGQ7XHJcblx0fSxcclxuXHJcblx0X2FkZEl0ZW06IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdHZhciBsYWJlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xhYmVsJyksXHJcblx0XHQgICAgY2hlY2tlZCA9IHRoaXMuX21hcC5oYXNMYXllcihvYmoubGF5ZXIpLFxyXG5cdFx0ICAgIGlucHV0O1xyXG5cclxuXHRcdGlmIChvYmoub3ZlcmxheSkge1xyXG5cdFx0XHRpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0Jyk7XHJcblx0XHRcdGlucHV0LnR5cGUgPSAnY2hlY2tib3gnO1xyXG5cdFx0XHRpbnB1dC5jbGFzc05hbWUgPSAnbGVhZmxldC1jb250cm9sLWxheWVycy1zZWxlY3Rvcic7XHJcblx0XHRcdGlucHV0LmRlZmF1bHRDaGVja2VkID0gY2hlY2tlZDtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGlucHV0ID0gdGhpcy5fY3JlYXRlUmFkaW9FbGVtZW50KCdsZWFmbGV0LWJhc2UtbGF5ZXJzXycgKyBzdGFtcCh0aGlzKSwgY2hlY2tlZCk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fbGF5ZXJDb250cm9sSW5wdXRzLnB1c2goaW5wdXQpO1xyXG5cdFx0aW5wdXQubGF5ZXJJZCA9IHN0YW1wKG9iai5sYXllcik7XHJcblxyXG5cdFx0b24oaW5wdXQsICdjbGljaycsIHRoaXMuX29uSW5wdXRDbGljaywgdGhpcyk7XHJcblxyXG5cdFx0dmFyIG5hbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XHJcblx0XHRuYW1lLmlubmVySFRNTCA9ICcgJyArIG9iai5uYW1lO1xyXG5cclxuXHRcdC8vIEhlbHBzIGZyb20gcHJldmVudGluZyBsYXllciBjb250cm9sIGZsaWNrZXIgd2hlbiBjaGVja2JveGVzIGFyZSBkaXNhYmxlZFxyXG5cdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMjc3MVxyXG5cdFx0dmFyIGhvbGRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG5cclxuXHRcdGxhYmVsLmFwcGVuZENoaWxkKGhvbGRlcik7XHJcblx0XHRob2xkZXIuYXBwZW5kQ2hpbGQoaW5wdXQpO1xyXG5cdFx0aG9sZGVyLmFwcGVuZENoaWxkKG5hbWUpO1xyXG5cclxuXHRcdHZhciBjb250YWluZXIgPSBvYmoub3ZlcmxheSA/IHRoaXMuX292ZXJsYXlzTGlzdCA6IHRoaXMuX2Jhc2VMYXllcnNMaXN0O1xyXG5cdFx0Y29udGFpbmVyLmFwcGVuZENoaWxkKGxhYmVsKTtcclxuXHJcblx0XHR0aGlzLl9jaGVja0Rpc2FibGVkTGF5ZXJzKCk7XHJcblx0XHRyZXR1cm4gbGFiZWw7XHJcblx0fSxcclxuXHJcblx0X29uSW5wdXRDbGljazogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGlucHV0cyA9IHRoaXMuX2xheWVyQ29udHJvbElucHV0cyxcclxuXHRcdCAgICBpbnB1dCwgbGF5ZXI7XHJcblx0XHR2YXIgYWRkZWRMYXllcnMgPSBbXSxcclxuXHRcdCAgICByZW1vdmVkTGF5ZXJzID0gW107XHJcblxyXG5cdFx0dGhpcy5faGFuZGxpbmdDbGljayA9IHRydWU7XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IGlucHV0cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG5cdFx0XHRpbnB1dCA9IGlucHV0c1tpXTtcclxuXHRcdFx0bGF5ZXIgPSB0aGlzLl9nZXRMYXllcihpbnB1dC5sYXllcklkKS5sYXllcjtcclxuXHJcblx0XHRcdGlmIChpbnB1dC5jaGVja2VkKSB7XHJcblx0XHRcdFx0YWRkZWRMYXllcnMucHVzaChsYXllcik7XHJcblx0XHRcdH0gZWxzZSBpZiAoIWlucHV0LmNoZWNrZWQpIHtcclxuXHRcdFx0XHRyZW1vdmVkTGF5ZXJzLnB1c2gobGF5ZXIpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQnVnZml4IGlzc3VlIDIzMTg6IFNob3VsZCByZW1vdmUgYWxsIG9sZCBsYXllcnMgYmVmb3JlIHJlYWRkaW5nIG5ldyBvbmVzXHJcblx0XHRmb3IgKGkgPSAwOyBpIDwgcmVtb3ZlZExheWVycy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRpZiAodGhpcy5fbWFwLmhhc0xheWVyKHJlbW92ZWRMYXllcnNbaV0pKSB7XHJcblx0XHRcdFx0dGhpcy5fbWFwLnJlbW92ZUxheWVyKHJlbW92ZWRMYXllcnNbaV0pO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRmb3IgKGkgPSAwOyBpIDwgYWRkZWRMYXllcnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0aWYgKCF0aGlzLl9tYXAuaGFzTGF5ZXIoYWRkZWRMYXllcnNbaV0pKSB7XHJcblx0XHRcdFx0dGhpcy5fbWFwLmFkZExheWVyKGFkZGVkTGF5ZXJzW2ldKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2hhbmRsaW5nQ2xpY2sgPSBmYWxzZTtcclxuXHJcblx0XHR0aGlzLl9yZWZvY3VzT25NYXAoKTtcclxuXHR9LFxyXG5cclxuXHRfY2hlY2tEaXNhYmxlZExheWVyczogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGlucHV0cyA9IHRoaXMuX2xheWVyQ29udHJvbElucHV0cyxcclxuXHRcdCAgICBpbnB1dCxcclxuXHRcdCAgICBsYXllcixcclxuXHRcdCAgICB6b29tID0gdGhpcy5fbWFwLmdldFpvb20oKTtcclxuXHJcblx0XHRmb3IgKHZhciBpID0gaW5wdXRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcblx0XHRcdGlucHV0ID0gaW5wdXRzW2ldO1xyXG5cdFx0XHRsYXllciA9IHRoaXMuX2dldExheWVyKGlucHV0LmxheWVySWQpLmxheWVyO1xyXG5cdFx0XHRpbnB1dC5kaXNhYmxlZCA9IChsYXllci5vcHRpb25zLm1pblpvb20gIT09IHVuZGVmaW5lZCAmJiB6b29tIDwgbGF5ZXIub3B0aW9ucy5taW5ab29tKSB8fFxyXG5cdFx0XHQgICAgICAgICAgICAgICAgIChsYXllci5vcHRpb25zLm1heFpvb20gIT09IHVuZGVmaW5lZCAmJiB6b29tID4gbGF5ZXIub3B0aW9ucy5tYXhab29tKTtcclxuXHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X2V4cGFuZElmTm90Q29sbGFwc2VkOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAodGhpcy5fbWFwICYmICF0aGlzLm9wdGlvbnMuY29sbGFwc2VkKSB7XHJcblx0XHRcdHRoaXMuZXhwYW5kKCk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRfZXhwYW5kOiBmdW5jdGlvbiAoKSB7XHJcblx0XHQvLyBCYWNrd2FyZCBjb21wYXRpYmlsaXR5LCByZW1vdmUgbWUgaW4gMS4xLlxyXG5cdFx0cmV0dXJuIHRoaXMuZXhwYW5kKCk7XHJcblx0fSxcclxuXHJcblx0X2NvbGxhcHNlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHQvLyBCYWNrd2FyZCBjb21wYXRpYmlsaXR5LCByZW1vdmUgbWUgaW4gMS4xLlxyXG5cdFx0cmV0dXJuIHRoaXMuY29sbGFwc2UoKTtcclxuXHR9XHJcblxyXG59KTtcclxuXHJcblxyXG4vLyBAZmFjdG9yeSBMLmNvbnRyb2wubGF5ZXJzKGJhc2VsYXllcnM/OiBPYmplY3QsIG92ZXJsYXlzPzogT2JqZWN0LCBvcHRpb25zPzogQ29udHJvbC5MYXllcnMgb3B0aW9ucylcclxuLy8gQ3JlYXRlcyBhbiBhdHRyaWJ1dGlvbiBjb250cm9sIHdpdGggdGhlIGdpdmVuIGxheWVycy4gQmFzZSBsYXllcnMgd2lsbCBiZSBzd2l0Y2hlZCB3aXRoIHJhZGlvIGJ1dHRvbnMsIHdoaWxlIG92ZXJsYXlzIHdpbGwgYmUgc3dpdGNoZWQgd2l0aCBjaGVja2JveGVzLiBOb3RlIHRoYXQgYWxsIGJhc2UgbGF5ZXJzIHNob3VsZCBiZSBwYXNzZWQgaW4gdGhlIGJhc2UgbGF5ZXJzIG9iamVjdCwgYnV0IG9ubHkgb25lIHNob3VsZCBiZSBhZGRlZCB0byB0aGUgbWFwIGR1cmluZyBtYXAgaW5zdGFudGlhdGlvbi5cclxudmFyIGxheWVycyA9IGZ1bmN0aW9uIChiYXNlTGF5ZXJzLCBvdmVybGF5cywgb3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgTGF5ZXJzKGJhc2VMYXllcnMsIG92ZXJsYXlzLCBvcHRpb25zKTtcclxufTtcblxuLypcclxuICogQGNsYXNzIENvbnRyb2wuWm9vbVxyXG4gKiBAYWthIEwuQ29udHJvbC5ab29tXHJcbiAqIEBpbmhlcml0cyBDb250cm9sXHJcbiAqXHJcbiAqIEEgYmFzaWMgem9vbSBjb250cm9sIHdpdGggdHdvIGJ1dHRvbnMgKHpvb20gaW4gYW5kIHpvb20gb3V0KS4gSXQgaXMgcHV0IG9uIHRoZSBtYXAgYnkgZGVmYXVsdCB1bmxlc3MgeW91IHNldCBpdHMgW2B6b29tQ29udHJvbGAgb3B0aW9uXSgjbWFwLXpvb21jb250cm9sKSB0byBgZmFsc2VgLiBFeHRlbmRzIGBDb250cm9sYC5cclxuICovXHJcblxyXG52YXIgWm9vbSA9IENvbnRyb2wuZXh0ZW5kKHtcclxuXHQvLyBAc2VjdGlvblxyXG5cdC8vIEBha2EgQ29udHJvbC5ab29tIG9wdGlvbnNcclxuXHRvcHRpb25zOiB7XHJcblx0XHRwb3NpdGlvbjogJ3RvcGxlZnQnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gem9vbUluVGV4dDogU3RyaW5nID0gJysnXHJcblx0XHQvLyBUaGUgdGV4dCBzZXQgb24gdGhlICd6b29tIGluJyBidXR0b24uXHJcblx0XHR6b29tSW5UZXh0OiAnKycsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB6b29tSW5UaXRsZTogU3RyaW5nID0gJ1pvb20gaW4nXHJcblx0XHQvLyBUaGUgdGl0bGUgc2V0IG9uIHRoZSAnem9vbSBpbicgYnV0dG9uLlxyXG5cdFx0em9vbUluVGl0bGU6ICdab29tIGluJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHpvb21PdXRUZXh0OiBTdHJpbmcgPSAnJiN4MjIxMjsnXHJcblx0XHQvLyBUaGUgdGV4dCBzZXQgb24gdGhlICd6b29tIG91dCcgYnV0dG9uLlxyXG5cdFx0em9vbU91dFRleHQ6ICcmI3gyMjEyOycsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB6b29tT3V0VGl0bGU6IFN0cmluZyA9ICdab29tIG91dCdcclxuXHRcdC8vIFRoZSB0aXRsZSBzZXQgb24gdGhlICd6b29tIG91dCcgYnV0dG9uLlxyXG5cdFx0em9vbU91dFRpdGxlOiAnWm9vbSBvdXQnXHJcblx0fSxcclxuXHJcblx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuXHRcdHZhciB6b29tTmFtZSA9ICdsZWFmbGV0LWNvbnRyb2wtem9vbScsXHJcblx0XHQgICAgY29udGFpbmVyID0gY3JlYXRlJDEoJ2RpdicsIHpvb21OYW1lICsgJyBsZWFmbGV0LWJhcicpLFxyXG5cdFx0ICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XHJcblxyXG5cdFx0dGhpcy5fem9vbUluQnV0dG9uICA9IHRoaXMuX2NyZWF0ZUJ1dHRvbihvcHRpb25zLnpvb21JblRleHQsIG9wdGlvbnMuem9vbUluVGl0bGUsXHJcblx0XHQgICAgICAgIHpvb21OYW1lICsgJy1pbicsICBjb250YWluZXIsIHRoaXMuX3pvb21Jbik7XHJcblx0XHR0aGlzLl96b29tT3V0QnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKG9wdGlvbnMuem9vbU91dFRleHQsIG9wdGlvbnMuem9vbU91dFRpdGxlLFxyXG5cdFx0ICAgICAgICB6b29tTmFtZSArICctb3V0JywgY29udGFpbmVyLCB0aGlzLl96b29tT3V0KTtcclxuXHJcblx0XHR0aGlzLl91cGRhdGVEaXNhYmxlZCgpO1xyXG5cdFx0bWFwLm9uKCd6b29tZW5kIHpvb21sZXZlbHNjaGFuZ2UnLCB0aGlzLl91cGRhdGVEaXNhYmxlZCwgdGhpcyk7XHJcblxyXG5cdFx0cmV0dXJuIGNvbnRhaW5lcjtcclxuXHR9LFxyXG5cclxuXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0bWFwLm9mZignem9vbWVuZCB6b29tbGV2ZWxzY2hhbmdlJywgdGhpcy5fdXBkYXRlRGlzYWJsZWQsIHRoaXMpO1xyXG5cdH0sXHJcblxyXG5cdGRpc2FibGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX2Rpc2FibGVkID0gdHJ1ZTtcclxuXHRcdHRoaXMuX3VwZGF0ZURpc2FibGVkKCk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRlbmFibGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX2Rpc2FibGVkID0gZmFsc2U7XHJcblx0XHR0aGlzLl91cGRhdGVEaXNhYmxlZCgpO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0X3pvb21JbjogZnVuY3Rpb24gKGUpIHtcclxuXHRcdGlmICghdGhpcy5fZGlzYWJsZWQgJiYgdGhpcy5fbWFwLl96b29tIDwgdGhpcy5fbWFwLmdldE1heFpvb20oKSkge1xyXG5cdFx0XHR0aGlzLl9tYXAuem9vbUluKHRoaXMuX21hcC5vcHRpb25zLnpvb21EZWx0YSAqIChlLnNoaWZ0S2V5ID8gMyA6IDEpKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfem9vbU91dDogZnVuY3Rpb24gKGUpIHtcclxuXHRcdGlmICghdGhpcy5fZGlzYWJsZWQgJiYgdGhpcy5fbWFwLl96b29tID4gdGhpcy5fbWFwLmdldE1pblpvb20oKSkge1xyXG5cdFx0XHR0aGlzLl9tYXAuem9vbU91dCh0aGlzLl9tYXAub3B0aW9ucy56b29tRGVsdGEgKiAoZS5zaGlmdEtleSA/IDMgOiAxKSk7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X2NyZWF0ZUJ1dHRvbjogZnVuY3Rpb24gKGh0bWwsIHRpdGxlLCBjbGFzc05hbWUsIGNvbnRhaW5lciwgZm4pIHtcclxuXHRcdHZhciBsaW5rID0gY3JlYXRlJDEoJ2EnLCBjbGFzc05hbWUsIGNvbnRhaW5lcik7XHJcblx0XHRsaW5rLmlubmVySFRNTCA9IGh0bWw7XHJcblx0XHRsaW5rLmhyZWYgPSAnIyc7XHJcblx0XHRsaW5rLnRpdGxlID0gdGl0bGU7XHJcblxyXG5cdFx0LypcclxuXHRcdCAqIFdpbGwgZm9yY2Ugc2NyZWVuIHJlYWRlcnMgbGlrZSBWb2ljZU92ZXIgdG8gcmVhZCB0aGlzIGFzIFwiWm9vbSBpbiAtIGJ1dHRvblwiXHJcblx0XHQgKi9cclxuXHRcdGxpbmsuc2V0QXR0cmlidXRlKCdyb2xlJywgJ2J1dHRvbicpO1xyXG5cdFx0bGluay5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCB0aXRsZSk7XHJcblxyXG5cdFx0ZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24obGluayk7XHJcblx0XHRvbihsaW5rLCAnY2xpY2snLCBzdG9wKTtcclxuXHRcdG9uKGxpbmssICdjbGljaycsIGZuLCB0aGlzKTtcclxuXHRcdG9uKGxpbmssICdjbGljaycsIHRoaXMuX3JlZm9jdXNPbk1hcCwgdGhpcyk7XHJcblxyXG5cdFx0cmV0dXJuIGxpbms7XHJcblx0fSxcclxuXHJcblx0X3VwZGF0ZURpc2FibGVkOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxyXG5cdFx0ICAgIGNsYXNzTmFtZSA9ICdsZWFmbGV0LWRpc2FibGVkJztcclxuXHJcblx0XHRyZW1vdmVDbGFzcyh0aGlzLl96b29tSW5CdXR0b24sIGNsYXNzTmFtZSk7XHJcblx0XHRyZW1vdmVDbGFzcyh0aGlzLl96b29tT3V0QnV0dG9uLCBjbGFzc05hbWUpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9kaXNhYmxlZCB8fCBtYXAuX3pvb20gPT09IG1hcC5nZXRNaW5ab29tKCkpIHtcclxuXHRcdFx0YWRkQ2xhc3ModGhpcy5fem9vbU91dEJ1dHRvbiwgY2xhc3NOYW1lKTtcclxuXHRcdH1cclxuXHRcdGlmICh0aGlzLl9kaXNhYmxlZCB8fCBtYXAuX3pvb20gPT09IG1hcC5nZXRNYXhab29tKCkpIHtcclxuXHRcdFx0YWRkQ2xhc3ModGhpcy5fem9vbUluQnV0dG9uLCBjbGFzc05hbWUpO1xyXG5cdFx0fVxyXG5cdH1cclxufSk7XHJcblxyXG4vLyBAbmFtZXNwYWNlIE1hcFxyXG4vLyBAc2VjdGlvbiBDb250cm9sIG9wdGlvbnNcclxuLy8gQG9wdGlvbiB6b29tQ29udHJvbDogQm9vbGVhbiA9IHRydWVcclxuLy8gV2hldGhlciBhIFt6b29tIGNvbnRyb2xdKCNjb250cm9sLXpvb20pIGlzIGFkZGVkIHRvIHRoZSBtYXAgYnkgZGVmYXVsdC5cclxuTWFwLm1lcmdlT3B0aW9ucyh7XHJcblx0em9vbUNvbnRyb2w6IHRydWVcclxufSk7XHJcblxyXG5NYXAuYWRkSW5pdEhvb2soZnVuY3Rpb24gKCkge1xyXG5cdGlmICh0aGlzLm9wdGlvbnMuem9vbUNvbnRyb2wpIHtcclxuXHRcdC8vIEBzZWN0aW9uIENvbnRyb2xzXHJcblx0XHQvLyBAcHJvcGVydHkgem9vbUNvbnRyb2w6IENvbnRyb2wuWm9vbVxyXG5cdFx0Ly8gVGhlIGRlZmF1bHQgem9vbSBjb250cm9sIChvbmx5IGF2YWlsYWJsZSBpZiB0aGVcclxuXHRcdC8vIFtgem9vbUNvbnRyb2xgIG9wdGlvbl0oI21hcC16b29tY29udHJvbCkgd2FzIGB0cnVlYCB3aGVuIGNyZWF0aW5nIHRoZSBtYXApLlxyXG5cdFx0dGhpcy56b29tQ29udHJvbCA9IG5ldyBab29tKCk7XHJcblx0XHR0aGlzLmFkZENvbnRyb2wodGhpcy56b29tQ29udHJvbCk7XHJcblx0fVxyXG59KTtcclxuXHJcbi8vIEBuYW1lc3BhY2UgQ29udHJvbC5ab29tXHJcbi8vIEBmYWN0b3J5IEwuY29udHJvbC56b29tKG9wdGlvbnM6IENvbnRyb2wuWm9vbSBvcHRpb25zKVxyXG4vLyBDcmVhdGVzIGEgem9vbSBjb250cm9sXHJcbnZhciB6b29tID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuXHRyZXR1cm4gbmV3IFpvb20ob3B0aW9ucyk7XHJcbn07XG5cbi8qXG4gKiBAY2xhc3MgQ29udHJvbC5TY2FsZVxuICogQGFrYSBMLkNvbnRyb2wuU2NhbGVcbiAqIEBpbmhlcml0cyBDb250cm9sXG4gKlxuICogQSBzaW1wbGUgc2NhbGUgY29udHJvbCB0aGF0IHNob3dzIHRoZSBzY2FsZSBvZiB0aGUgY3VycmVudCBjZW50ZXIgb2Ygc2NyZWVuIGluIG1ldHJpYyAobS9rbSkgYW5kIGltcGVyaWFsIChtaS9mdCkgc3lzdGVtcy4gRXh0ZW5kcyBgQ29udHJvbGAuXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGBqc1xuICogTC5jb250cm9sLnNjYWxlKCkuYWRkVG8obWFwKTtcbiAqIGBgYFxuICovXG5cbnZhciBTY2FsZSA9IENvbnRyb2wuZXh0ZW5kKHtcblx0Ly8gQHNlY3Rpb25cblx0Ly8gQGFrYSBDb250cm9sLlNjYWxlIG9wdGlvbnNcblx0b3B0aW9uczoge1xuXHRcdHBvc2l0aW9uOiAnYm90dG9tbGVmdCcsXG5cblx0XHQvLyBAb3B0aW9uIG1heFdpZHRoOiBOdW1iZXIgPSAxMDBcblx0XHQvLyBNYXhpbXVtIHdpZHRoIG9mIHRoZSBjb250cm9sIGluIHBpeGVscy4gVGhlIHdpZHRoIGlzIHNldCBkeW5hbWljYWxseSB0byBzaG93IHJvdW5kIHZhbHVlcyAoZS5nLiAxMDAsIDIwMCwgNTAwKS5cblx0XHRtYXhXaWR0aDogMTAwLFxuXG5cdFx0Ly8gQG9wdGlvbiBtZXRyaWM6IEJvb2xlYW4gPSBUcnVlXG5cdFx0Ly8gV2hldGhlciB0byBzaG93IHRoZSBtZXRyaWMgc2NhbGUgbGluZSAobS9rbSkuXG5cdFx0bWV0cmljOiB0cnVlLFxuXG5cdFx0Ly8gQG9wdGlvbiBpbXBlcmlhbDogQm9vbGVhbiA9IFRydWVcblx0XHQvLyBXaGV0aGVyIHRvIHNob3cgdGhlIGltcGVyaWFsIHNjYWxlIGxpbmUgKG1pL2Z0KS5cblx0XHRpbXBlcmlhbDogdHJ1ZVxuXG5cdFx0Ly8gQG9wdGlvbiB1cGRhdGVXaGVuSWRsZTogQm9vbGVhbiA9IGZhbHNlXG5cdFx0Ly8gSWYgYHRydWVgLCB0aGUgY29udHJvbCBpcyB1cGRhdGVkIG9uIFtgbW92ZWVuZGBdKCNtYXAtbW92ZWVuZCksIG90aGVyd2lzZSBpdCdzIGFsd2F5cyB1cC10by1kYXRlICh1cGRhdGVkIG9uIFtgbW92ZWBdKCNtYXAtbW92ZSkpLlxuXHR9LFxuXG5cdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XG5cdFx0dmFyIGNsYXNzTmFtZSA9ICdsZWFmbGV0LWNvbnRyb2wtc2NhbGUnLFxuXHRcdCAgICBjb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lKSxcblx0XHQgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcblxuXHRcdHRoaXMuX2FkZFNjYWxlcyhvcHRpb25zLCBjbGFzc05hbWUgKyAnLWxpbmUnLCBjb250YWluZXIpO1xuXG5cdFx0bWFwLm9uKG9wdGlvbnMudXBkYXRlV2hlbklkbGUgPyAnbW92ZWVuZCcgOiAnbW92ZScsIHRoaXMuX3VwZGF0ZSwgdGhpcyk7XG5cdFx0bWFwLndoZW5SZWFkeSh0aGlzLl91cGRhdGUsIHRoaXMpO1xuXG5cdFx0cmV0dXJuIGNvbnRhaW5lcjtcblx0fSxcblxuXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xuXHRcdG1hcC5vZmYodGhpcy5vcHRpb25zLnVwZGF0ZVdoZW5JZGxlID8gJ21vdmVlbmQnIDogJ21vdmUnLCB0aGlzLl91cGRhdGUsIHRoaXMpO1xuXHR9LFxuXG5cdF9hZGRTY2FsZXM6IGZ1bmN0aW9uIChvcHRpb25zLCBjbGFzc05hbWUsIGNvbnRhaW5lcikge1xuXHRcdGlmIChvcHRpb25zLm1ldHJpYykge1xuXHRcdFx0dGhpcy5fbVNjYWxlID0gY3JlYXRlJDEoJ2RpdicsIGNsYXNzTmFtZSwgY29udGFpbmVyKTtcblx0XHR9XG5cdFx0aWYgKG9wdGlvbnMuaW1wZXJpYWwpIHtcblx0XHRcdHRoaXMuX2lTY2FsZSA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUsIGNvbnRhaW5lcik7XG5cdFx0fVxuXHR9LFxuXG5cdF91cGRhdGU6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuXHRcdCAgICB5ID0gbWFwLmdldFNpemUoKS55IC8gMjtcblxuXHRcdHZhciBtYXhNZXRlcnMgPSBtYXAuZGlzdGFuY2UoXG5cdFx0XHRtYXAuY29udGFpbmVyUG9pbnRUb0xhdExuZyhbMCwgeV0pLFxuXHRcdFx0bWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcoW3RoaXMub3B0aW9ucy5tYXhXaWR0aCwgeV0pKTtcblxuXHRcdHRoaXMuX3VwZGF0ZVNjYWxlcyhtYXhNZXRlcnMpO1xuXHR9LFxuXG5cdF91cGRhdGVTY2FsZXM6IGZ1bmN0aW9uIChtYXhNZXRlcnMpIHtcblx0XHRpZiAodGhpcy5vcHRpb25zLm1ldHJpYyAmJiBtYXhNZXRlcnMpIHtcblx0XHRcdHRoaXMuX3VwZGF0ZU1ldHJpYyhtYXhNZXRlcnMpO1xuXHRcdH1cblx0XHRpZiAodGhpcy5vcHRpb25zLmltcGVyaWFsICYmIG1heE1ldGVycykge1xuXHRcdFx0dGhpcy5fdXBkYXRlSW1wZXJpYWwobWF4TWV0ZXJzKTtcblx0XHR9XG5cdH0sXG5cblx0X3VwZGF0ZU1ldHJpYzogZnVuY3Rpb24gKG1heE1ldGVycykge1xuXHRcdHZhciBtZXRlcnMgPSB0aGlzLl9nZXRSb3VuZE51bShtYXhNZXRlcnMpLFxuXHRcdCAgICBsYWJlbCA9IG1ldGVycyA8IDEwMDAgPyBtZXRlcnMgKyAnIG0nIDogKG1ldGVycyAvIDEwMDApICsgJyBrbSc7XG5cblx0XHR0aGlzLl91cGRhdGVTY2FsZSh0aGlzLl9tU2NhbGUsIGxhYmVsLCBtZXRlcnMgLyBtYXhNZXRlcnMpO1xuXHR9LFxuXG5cdF91cGRhdGVJbXBlcmlhbDogZnVuY3Rpb24gKG1heE1ldGVycykge1xuXHRcdHZhciBtYXhGZWV0ID0gbWF4TWV0ZXJzICogMy4yODA4Mzk5LFxuXHRcdCAgICBtYXhNaWxlcywgbWlsZXMsIGZlZXQ7XG5cblx0XHRpZiAobWF4RmVldCA+IDUyODApIHtcblx0XHRcdG1heE1pbGVzID0gbWF4RmVldCAvIDUyODA7XG5cdFx0XHRtaWxlcyA9IHRoaXMuX2dldFJvdW5kTnVtKG1heE1pbGVzKTtcblx0XHRcdHRoaXMuX3VwZGF0ZVNjYWxlKHRoaXMuX2lTY2FsZSwgbWlsZXMgKyAnIG1pJywgbWlsZXMgLyBtYXhNaWxlcyk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0ZmVldCA9IHRoaXMuX2dldFJvdW5kTnVtKG1heEZlZXQpO1xuXHRcdFx0dGhpcy5fdXBkYXRlU2NhbGUodGhpcy5faVNjYWxlLCBmZWV0ICsgJyBmdCcsIGZlZXQgLyBtYXhGZWV0KTtcblx0XHR9XG5cdH0sXG5cblx0X3VwZGF0ZVNjYWxlOiBmdW5jdGlvbiAoc2NhbGUsIHRleHQsIHJhdGlvKSB7XG5cdFx0c2NhbGUuc3R5bGUud2lkdGggPSBNYXRoLnJvdW5kKHRoaXMub3B0aW9ucy5tYXhXaWR0aCAqIHJhdGlvKSArICdweCc7XG5cdFx0c2NhbGUuaW5uZXJIVE1MID0gdGV4dDtcblx0fSxcblxuXHRfZ2V0Um91bmROdW06IGZ1bmN0aW9uIChudW0pIHtcblx0XHR2YXIgcG93MTAgPSBNYXRoLnBvdygxMCwgKE1hdGguZmxvb3IobnVtKSArICcnKS5sZW5ndGggLSAxKSxcblx0XHQgICAgZCA9IG51bSAvIHBvdzEwO1xuXG5cdFx0ZCA9IGQgPj0gMTAgPyAxMCA6XG5cdFx0ICAgIGQgPj0gNSA/IDUgOlxuXHRcdCAgICBkID49IDMgPyAzIDpcblx0XHQgICAgZCA+PSAyID8gMiA6IDE7XG5cblx0XHRyZXR1cm4gcG93MTAgKiBkO1xuXHR9XG59KTtcblxuXG4vLyBAZmFjdG9yeSBMLmNvbnRyb2wuc2NhbGUob3B0aW9ucz86IENvbnRyb2wuU2NhbGUgb3B0aW9ucylcbi8vIENyZWF0ZXMgYW4gc2NhbGUgY29udHJvbCB3aXRoIHRoZSBnaXZlbiBvcHRpb25zLlxudmFyIHNjYWxlID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcblx0cmV0dXJuIG5ldyBTY2FsZShvcHRpb25zKTtcbn07XG5cbi8qXHJcbiAqIEBjbGFzcyBDb250cm9sLkF0dHJpYnV0aW9uXHJcbiAqIEBha2EgTC5Db250cm9sLkF0dHJpYnV0aW9uXHJcbiAqIEBpbmhlcml0cyBDb250cm9sXHJcbiAqXHJcbiAqIFRoZSBhdHRyaWJ1dGlvbiBjb250cm9sIGFsbG93cyB5b3UgdG8gZGlzcGxheSBhdHRyaWJ1dGlvbiBkYXRhIGluIGEgc21hbGwgdGV4dCBib3ggb24gYSBtYXAuIEl0IGlzIHB1dCBvbiB0aGUgbWFwIGJ5IGRlZmF1bHQgdW5sZXNzIHlvdSBzZXQgaXRzIFtgYXR0cmlidXRpb25Db250cm9sYCBvcHRpb25dKCNtYXAtYXR0cmlidXRpb25jb250cm9sKSB0byBgZmFsc2VgLCBhbmQgaXQgZmV0Y2hlcyBhdHRyaWJ1dGlvbiB0ZXh0cyBmcm9tIGxheWVycyB3aXRoIHRoZSBbYGdldEF0dHJpYnV0aW9uYCBtZXRob2RdKCNsYXllci1nZXRhdHRyaWJ1dGlvbikgYXV0b21hdGljYWxseS4gRXh0ZW5kcyBDb250cm9sLlxyXG4gKi9cclxuXHJcbnZhciBBdHRyaWJ1dGlvbiA9IENvbnRyb2wuZXh0ZW5kKHtcclxuXHQvLyBAc2VjdGlvblxyXG5cdC8vIEBha2EgQ29udHJvbC5BdHRyaWJ1dGlvbiBvcHRpb25zXHJcblx0b3B0aW9uczoge1xyXG5cdFx0cG9zaXRpb246ICdib3R0b21yaWdodCcsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBwcmVmaXg6IFN0cmluZyA9ICdMZWFmbGV0J1xyXG5cdFx0Ly8gVGhlIEhUTUwgdGV4dCBzaG93biBiZWZvcmUgdGhlIGF0dHJpYnV0aW9ucy4gUGFzcyBgZmFsc2VgIHRvIGRpc2FibGUuXHJcblx0XHRwcmVmaXg6ICc8YSBocmVmPVwiaHR0cHM6Ly9sZWFmbGV0anMuY29tXCIgdGl0bGU9XCJBIEpTIGxpYnJhcnkgZm9yIGludGVyYWN0aXZlIG1hcHNcIj5MZWFmbGV0PC9hPidcclxuXHR9LFxyXG5cclxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcblx0XHR0aGlzLl9hdHRyaWJ1dGlvbnMgPSB7fTtcclxuXHR9LFxyXG5cclxuXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0bWFwLmF0dHJpYnV0aW9uQ29udHJvbCA9IHRoaXM7XHJcblx0XHR0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgJ2xlYWZsZXQtY29udHJvbC1hdHRyaWJ1dGlvbicpO1xyXG5cdFx0ZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24odGhpcy5fY29udGFpbmVyKTtcclxuXHJcblx0XHQvLyBUT0RPIHVnbHksIHJlZmFjdG9yXHJcblx0XHRmb3IgKHZhciBpIGluIG1hcC5fbGF5ZXJzKSB7XHJcblx0XHRcdGlmIChtYXAuX2xheWVyc1tpXS5nZXRBdHRyaWJ1dGlvbikge1xyXG5cdFx0XHRcdHRoaXMuYWRkQXR0cmlidXRpb24obWFwLl9sYXllcnNbaV0uZ2V0QXR0cmlidXRpb24oKSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl91cGRhdGUoKTtcclxuXHJcblx0XHRyZXR1cm4gdGhpcy5fY29udGFpbmVyO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0UHJlZml4KHByZWZpeDogU3RyaW5nKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIHRleHQgYmVmb3JlIHRoZSBhdHRyaWJ1dGlvbnMuXHJcblx0c2V0UHJlZml4OiBmdW5jdGlvbiAocHJlZml4KSB7XHJcblx0XHR0aGlzLm9wdGlvbnMucHJlZml4ID0gcHJlZml4O1xyXG5cdFx0dGhpcy5fdXBkYXRlKCk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGFkZEF0dHJpYnV0aW9uKHRleHQ6IFN0cmluZyk6IHRoaXNcclxuXHQvLyBBZGRzIGFuIGF0dHJpYnV0aW9uIHRleHQgKGUuZy4gYCdWZWN0b3IgZGF0YSAmY29weTsgTWFwYm94J2ApLlxyXG5cdGFkZEF0dHJpYnV0aW9uOiBmdW5jdGlvbiAodGV4dCkge1xyXG5cdFx0aWYgKCF0ZXh0KSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG5cdFx0aWYgKCF0aGlzLl9hdHRyaWJ1dGlvbnNbdGV4dF0pIHtcclxuXHRcdFx0dGhpcy5fYXR0cmlidXRpb25zW3RleHRdID0gMDtcclxuXHRcdH1cclxuXHRcdHRoaXMuX2F0dHJpYnV0aW9uc1t0ZXh0XSsrO1xyXG5cclxuXHRcdHRoaXMuX3VwZGF0ZSgpO1xyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgcmVtb3ZlQXR0cmlidXRpb24odGV4dDogU3RyaW5nKTogdGhpc1xyXG5cdC8vIFJlbW92ZXMgYW4gYXR0cmlidXRpb24gdGV4dC5cclxuXHRyZW1vdmVBdHRyaWJ1dGlvbjogZnVuY3Rpb24gKHRleHQpIHtcclxuXHRcdGlmICghdGV4dCkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdGlmICh0aGlzLl9hdHRyaWJ1dGlvbnNbdGV4dF0pIHtcclxuXHRcdFx0dGhpcy5fYXR0cmlidXRpb25zW3RleHRdLS07XHJcblx0XHRcdHRoaXMuX3VwZGF0ZSgpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdF91cGRhdGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICghdGhpcy5fbWFwKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdHZhciBhdHRyaWJzID0gW107XHJcblxyXG5cdFx0Zm9yICh2YXIgaSBpbiB0aGlzLl9hdHRyaWJ1dGlvbnMpIHtcclxuXHRcdFx0aWYgKHRoaXMuX2F0dHJpYnV0aW9uc1tpXSkge1xyXG5cdFx0XHRcdGF0dHJpYnMucHVzaChpKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBwcmVmaXhBbmRBdHRyaWJzID0gW107XHJcblxyXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5wcmVmaXgpIHtcclxuXHRcdFx0cHJlZml4QW5kQXR0cmlicy5wdXNoKHRoaXMub3B0aW9ucy5wcmVmaXgpO1xyXG5cdFx0fVxyXG5cdFx0aWYgKGF0dHJpYnMubGVuZ3RoKSB7XHJcblx0XHRcdHByZWZpeEFuZEF0dHJpYnMucHVzaChhdHRyaWJzLmpvaW4oJywgJykpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2NvbnRhaW5lci5pbm5lckhUTUwgPSBwcmVmaXhBbmRBdHRyaWJzLmpvaW4oJyB8ICcpO1xyXG5cdH1cclxufSk7XHJcblxyXG4vLyBAbmFtZXNwYWNlIE1hcFxyXG4vLyBAc2VjdGlvbiBDb250cm9sIG9wdGlvbnNcclxuLy8gQG9wdGlvbiBhdHRyaWJ1dGlvbkNvbnRyb2w6IEJvb2xlYW4gPSB0cnVlXHJcbi8vIFdoZXRoZXIgYSBbYXR0cmlidXRpb24gY29udHJvbF0oI2NvbnRyb2wtYXR0cmlidXRpb24pIGlzIGFkZGVkIHRvIHRoZSBtYXAgYnkgZGVmYXVsdC5cclxuTWFwLm1lcmdlT3B0aW9ucyh7XHJcblx0YXR0cmlidXRpb25Db250cm9sOiB0cnVlXHJcbn0pO1xyXG5cclxuTWFwLmFkZEluaXRIb29rKGZ1bmN0aW9uICgpIHtcclxuXHRpZiAodGhpcy5vcHRpb25zLmF0dHJpYnV0aW9uQ29udHJvbCkge1xyXG5cdFx0bmV3IEF0dHJpYnV0aW9uKCkuYWRkVG8odGhpcyk7XHJcblx0fVxyXG59KTtcclxuXHJcbi8vIEBuYW1lc3BhY2UgQ29udHJvbC5BdHRyaWJ1dGlvblxyXG4vLyBAZmFjdG9yeSBMLmNvbnRyb2wuYXR0cmlidXRpb24ob3B0aW9uczogQ29udHJvbC5BdHRyaWJ1dGlvbiBvcHRpb25zKVxyXG4vLyBDcmVhdGVzIGFuIGF0dHJpYnV0aW9uIGNvbnRyb2wuXHJcbnZhciBhdHRyaWJ1dGlvbiA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblx0cmV0dXJuIG5ldyBBdHRyaWJ1dGlvbihvcHRpb25zKTtcclxufTtcblxuQ29udHJvbC5MYXllcnMgPSBMYXllcnM7XG5Db250cm9sLlpvb20gPSBab29tO1xuQ29udHJvbC5TY2FsZSA9IFNjYWxlO1xuQ29udHJvbC5BdHRyaWJ1dGlvbiA9IEF0dHJpYnV0aW9uO1xuXG5jb250cm9sLmxheWVycyA9IGxheWVycztcbmNvbnRyb2wuem9vbSA9IHpvb207XG5jb250cm9sLnNjYWxlID0gc2NhbGU7XG5jb250cm9sLmF0dHJpYnV0aW9uID0gYXR0cmlidXRpb247XG5cbi8qXG5cdEwuSGFuZGxlciBpcyBhIGJhc2UgY2xhc3MgZm9yIGhhbmRsZXIgY2xhc3NlcyB0aGF0IGFyZSB1c2VkIGludGVybmFsbHkgdG8gaW5qZWN0XG5cdGludGVyYWN0aW9uIGZlYXR1cmVzIGxpa2UgZHJhZ2dpbmcgdG8gY2xhc3NlcyBsaWtlIE1hcCBhbmQgTWFya2VyLlxuKi9cblxuLy8gQGNsYXNzIEhhbmRsZXJcbi8vIEBha2EgTC5IYW5kbGVyXG4vLyBBYnN0cmFjdCBjbGFzcyBmb3IgbWFwIGludGVyYWN0aW9uIGhhbmRsZXJzXG5cbnZhciBIYW5kbGVyID0gQ2xhc3MuZXh0ZW5kKHtcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG1hcCkge1xuXHRcdHRoaXMuX21hcCA9IG1hcDtcblx0fSxcblxuXHQvLyBAbWV0aG9kIGVuYWJsZSgpOiB0aGlzXG5cdC8vIEVuYWJsZXMgdGhlIGhhbmRsZXJcblx0ZW5hYmxlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuIHRoaXM7IH1cblxuXHRcdHRoaXMuX2VuYWJsZWQgPSB0cnVlO1xuXHRcdHRoaXMuYWRkSG9va3MoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGRpc2FibGUoKTogdGhpc1xuXHQvLyBEaXNhYmxlcyB0aGUgaGFuZGxlclxuXHRkaXNhYmxlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKCF0aGlzLl9lbmFibGVkKSB7IHJldHVybiB0aGlzOyB9XG5cblx0XHR0aGlzLl9lbmFibGVkID0gZmFsc2U7XG5cdFx0dGhpcy5yZW1vdmVIb29rcygpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgZW5hYmxlZCgpOiBCb29sZWFuXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBoYW5kbGVyIGlzIGVuYWJsZWRcblx0ZW5hYmxlZDogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiAhIXRoaXMuX2VuYWJsZWQ7XG5cdH1cblxuXHQvLyBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xuXHQvLyBDbGFzc2VzIGluaGVyaXRpbmcgZnJvbSBgSGFuZGxlcmAgbXVzdCBpbXBsZW1lbnQgdGhlIHR3byBmb2xsb3dpbmcgbWV0aG9kczpcblx0Ly8gQG1ldGhvZCBhZGRIb29rcygpXG5cdC8vIENhbGxlZCB3aGVuIHRoZSBoYW5kbGVyIGlzIGVuYWJsZWQsIHNob3VsZCBhZGQgZXZlbnQgaG9va3MuXG5cdC8vIEBtZXRob2QgcmVtb3ZlSG9va3MoKVxuXHQvLyBDYWxsZWQgd2hlbiB0aGUgaGFuZGxlciBpcyBkaXNhYmxlZCwgc2hvdWxkIHJlbW92ZSB0aGUgZXZlbnQgaG9va3MgYWRkZWQgcHJldmlvdXNseS5cbn0pO1xuXG4vLyBAc2VjdGlvbiBUaGVyZSBpcyBzdGF0aWMgZnVuY3Rpb24gd2hpY2ggY2FuIGJlIGNhbGxlZCB3aXRob3V0IGluc3RhbnRpYXRpbmcgTC5IYW5kbGVyOlxuLy8gQGZ1bmN0aW9uIGFkZFRvKG1hcDogTWFwLCBuYW1lOiBTdHJpbmcpOiB0aGlzXG4vLyBBZGRzIGEgbmV3IEhhbmRsZXIgdG8gdGhlIGdpdmVuIG1hcCB3aXRoIHRoZSBnaXZlbiBuYW1lLlxuSGFuZGxlci5hZGRUbyA9IGZ1bmN0aW9uIChtYXAsIG5hbWUpIHtcblx0bWFwLmFkZEhhbmRsZXIobmFtZSwgdGhpcyk7XG5cdHJldHVybiB0aGlzO1xufTtcblxudmFyIE1peGluID0ge0V2ZW50czogRXZlbnRzfTtcblxuLypcclxuICogQGNsYXNzIERyYWdnYWJsZVxyXG4gKiBAYWthIEwuRHJhZ2dhYmxlXHJcbiAqIEBpbmhlcml0cyBFdmVudGVkXHJcbiAqXHJcbiAqIEEgY2xhc3MgZm9yIG1ha2luZyBET00gZWxlbWVudHMgZHJhZ2dhYmxlIChpbmNsdWRpbmcgdG91Y2ggc3VwcG9ydCkuXHJcbiAqIFVzZWQgaW50ZXJuYWxseSBmb3IgbWFwIGFuZCBtYXJrZXIgZHJhZ2dpbmcuIE9ubHkgd29ya3MgZm9yIGVsZW1lbnRzXHJcbiAqIHRoYXQgd2VyZSBwb3NpdGlvbmVkIHdpdGggW2BMLkRvbVV0aWwuc2V0UG9zaXRpb25gXSgjZG9tdXRpbC1zZXRwb3NpdGlvbikuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBkcmFnZ2FibGUgPSBuZXcgTC5EcmFnZ2FibGUoZWxlbWVudFRvRHJhZyk7XHJcbiAqIGRyYWdnYWJsZS5lbmFibGUoKTtcclxuICogYGBgXHJcbiAqL1xyXG5cclxudmFyIFNUQVJUID0gdG91Y2ggPyAndG91Y2hzdGFydCBtb3VzZWRvd24nIDogJ21vdXNlZG93bic7XHJcbnZhciBFTkQgPSB7XHJcblx0bW91c2Vkb3duOiAnbW91c2V1cCcsXHJcblx0dG91Y2hzdGFydDogJ3RvdWNoZW5kJyxcclxuXHRwb2ludGVyZG93bjogJ3RvdWNoZW5kJyxcclxuXHRNU1BvaW50ZXJEb3duOiAndG91Y2hlbmQnXHJcbn07XHJcbnZhciBNT1ZFID0ge1xyXG5cdG1vdXNlZG93bjogJ21vdXNlbW92ZScsXHJcblx0dG91Y2hzdGFydDogJ3RvdWNobW92ZScsXHJcblx0cG9pbnRlcmRvd246ICd0b3VjaG1vdmUnLFxyXG5cdE1TUG9pbnRlckRvd246ICd0b3VjaG1vdmUnXHJcbn07XHJcblxyXG5cclxudmFyIERyYWdnYWJsZSA9IEV2ZW50ZWQuZXh0ZW5kKHtcclxuXHJcblx0b3B0aW9uczoge1xyXG5cdFx0Ly8gQHNlY3Rpb25cclxuXHRcdC8vIEBha2EgRHJhZ2dhYmxlIG9wdGlvbnNcclxuXHRcdC8vIEBvcHRpb24gY2xpY2tUb2xlcmFuY2U6IE51bWJlciA9IDNcclxuXHRcdC8vIFRoZSBtYXggbnVtYmVyIG9mIHBpeGVscyBhIHVzZXIgY2FuIHNoaWZ0IHRoZSBtb3VzZSBwb2ludGVyIGR1cmluZyBhIGNsaWNrXHJcblx0XHQvLyBmb3IgaXQgdG8gYmUgY29uc2lkZXJlZCBhIHZhbGlkIGNsaWNrIChhcyBvcHBvc2VkIHRvIGEgbW91c2UgZHJhZykuXHJcblx0XHRjbGlja1RvbGVyYW5jZTogM1xyXG5cdH0sXHJcblxyXG5cdC8vIEBjb25zdHJ1Y3RvciBMLkRyYWdnYWJsZShlbDogSFRNTEVsZW1lbnQsIGRyYWdIYW5kbGU/OiBIVE1MRWxlbWVudCwgcHJldmVudE91dGxpbmU/OiBCb29sZWFuLCBvcHRpb25zPzogRHJhZ2dhYmxlIG9wdGlvbnMpXHJcblx0Ly8gQ3JlYXRlcyBhIGBEcmFnZ2FibGVgIG9iamVjdCBmb3IgbW92aW5nIGBlbGAgd2hlbiB5b3Ugc3RhcnQgZHJhZ2dpbmcgdGhlIGBkcmFnSGFuZGxlYCBlbGVtZW50IChlcXVhbHMgYGVsYCBpdHNlbGYgYnkgZGVmYXVsdCkuXHJcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGVsZW1lbnQsIGRyYWdTdGFydFRhcmdldCwgcHJldmVudE91dGxpbmUkJDEsIG9wdGlvbnMpIHtcclxuXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblxyXG5cdFx0dGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XHJcblx0XHR0aGlzLl9kcmFnU3RhcnRUYXJnZXQgPSBkcmFnU3RhcnRUYXJnZXQgfHwgZWxlbWVudDtcclxuXHRcdHRoaXMuX3ByZXZlbnRPdXRsaW5lID0gcHJldmVudE91dGxpbmUkJDE7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBlbmFibGUoKVxyXG5cdC8vIEVuYWJsZXMgdGhlIGRyYWdnaW5nIGFiaWxpdHlcclxuXHRlbmFibGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh0aGlzLl9lbmFibGVkKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdG9uKHRoaXMuX2RyYWdTdGFydFRhcmdldCwgU1RBUlQsIHRoaXMuX29uRG93biwgdGhpcyk7XHJcblxyXG5cdFx0dGhpcy5fZW5hYmxlZCA9IHRydWU7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBkaXNhYmxlKClcclxuXHQvLyBEaXNhYmxlcyB0aGUgZHJhZ2dpbmcgYWJpbGl0eVxyXG5cdGRpc2FibGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICghdGhpcy5fZW5hYmxlZCkgeyByZXR1cm47IH1cclxuXHJcblx0XHQvLyBJZiB3ZSdyZSBjdXJyZW50bHkgZHJhZ2dpbmcgdGhpcyBkcmFnZ2FibGUsXHJcblx0XHQvLyBkaXNhYmxpbmcgaXQgY291bnRzIGFzIGZpcnN0IGVuZGluZyB0aGUgZHJhZy5cclxuXHRcdGlmIChEcmFnZ2FibGUuX2RyYWdnaW5nID09PSB0aGlzKSB7XHJcblx0XHRcdHRoaXMuZmluaXNoRHJhZygpO1xyXG5cdFx0fVxyXG5cclxuXHRcdG9mZih0aGlzLl9kcmFnU3RhcnRUYXJnZXQsIFNUQVJULCB0aGlzLl9vbkRvd24sIHRoaXMpO1xyXG5cclxuXHRcdHRoaXMuX2VuYWJsZWQgPSBmYWxzZTtcclxuXHRcdHRoaXMuX21vdmVkID0gZmFsc2U7XHJcblx0fSxcclxuXHJcblx0X29uRG93bjogZnVuY3Rpb24gKGUpIHtcclxuXHRcdC8vIElnbm9yZSBzaW11bGF0ZWQgZXZlbnRzLCBzaW5jZSB3ZSBoYW5kbGUgYm90aCB0b3VjaCBhbmRcclxuXHRcdC8vIG1vdXNlIGV4cGxpY2l0bHk7IG90aGVyd2lzZSB3ZSByaXNrIGdldHRpbmcgZHVwbGljYXRlcyBvZlxyXG5cdFx0Ly8gdG91Y2ggZXZlbnRzLCBzZWUgIzQzMTUuXHJcblx0XHQvLyBBbHNvIGlnbm9yZSB0aGUgZXZlbnQgaWYgZGlzYWJsZWQ7IHRoaXMgaGFwcGVucyBpbiBJRTExXHJcblx0XHQvLyB1bmRlciBzb21lIGNpcmN1bXN0YW5jZXMsIHNlZSAjMzY2Ni5cclxuXHRcdGlmIChlLl9zaW11bGF0ZWQgfHwgIXRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0dGhpcy5fbW92ZWQgPSBmYWxzZTtcclxuXHJcblx0XHRpZiAoaGFzQ2xhc3ModGhpcy5fZWxlbWVudCwgJ2xlYWZsZXQtem9vbS1hbmltJykpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0aWYgKERyYWdnYWJsZS5fZHJhZ2dpbmcgfHwgZS5zaGlmdEtleSB8fCAoKGUud2hpY2ggIT09IDEpICYmIChlLmJ1dHRvbiAhPT0gMSkgJiYgIWUudG91Y2hlcykpIHsgcmV0dXJuOyB9XHJcblx0XHREcmFnZ2FibGUuX2RyYWdnaW5nID0gdGhpczsgIC8vIFByZXZlbnQgZHJhZ2dpbmcgbXVsdGlwbGUgb2JqZWN0cyBhdCBvbmNlLlxyXG5cclxuXHRcdGlmICh0aGlzLl9wcmV2ZW50T3V0bGluZSkge1xyXG5cdFx0XHRwcmV2ZW50T3V0bGluZSh0aGlzLl9lbGVtZW50KTtcclxuXHRcdH1cclxuXHJcblx0XHRkaXNhYmxlSW1hZ2VEcmFnKCk7XHJcblx0XHRkaXNhYmxlVGV4dFNlbGVjdGlvbigpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9tb3ZpbmcpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0Ly8gQGV2ZW50IGRvd246IEV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIGEgZHJhZyBpcyBhYm91dCB0byBzdGFydC5cclxuXHRcdHRoaXMuZmlyZSgnZG93bicpO1xyXG5cclxuXHRcdHZhciBmaXJzdCA9IGUudG91Y2hlcyA/IGUudG91Y2hlc1swXSA6IGUsXHJcblx0XHQgICAgc2l6ZWRQYXJlbnQgPSBnZXRTaXplZFBhcmVudE5vZGUodGhpcy5fZWxlbWVudCk7XHJcblxyXG5cdFx0dGhpcy5fc3RhcnRQb2ludCA9IG5ldyBQb2ludChmaXJzdC5jbGllbnRYLCBmaXJzdC5jbGllbnRZKTtcclxuXHJcblx0XHQvLyBDYWNoZSB0aGUgc2NhbGUsIHNvIHRoYXQgd2UgY2FuIGNvbnRpbnVvdXNseSBjb21wZW5zYXRlIGZvciBpdCBkdXJpbmcgZHJhZyAoX29uTW92ZSkuXHJcblx0XHR0aGlzLl9wYXJlbnRTY2FsZSA9IGdldFNjYWxlKHNpemVkUGFyZW50KTtcclxuXHJcblx0XHRvbihkb2N1bWVudCwgTU9WRVtlLnR5cGVdLCB0aGlzLl9vbk1vdmUsIHRoaXMpO1xyXG5cdFx0b24oZG9jdW1lbnQsIEVORFtlLnR5cGVdLCB0aGlzLl9vblVwLCB0aGlzKTtcclxuXHR9LFxyXG5cclxuXHRfb25Nb3ZlOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0Ly8gSWdub3JlIHNpbXVsYXRlZCBldmVudHMsIHNpbmNlIHdlIGhhbmRsZSBib3RoIHRvdWNoIGFuZFxyXG5cdFx0Ly8gbW91c2UgZXhwbGljaXRseTsgb3RoZXJ3aXNlIHdlIHJpc2sgZ2V0dGluZyBkdXBsaWNhdGVzIG9mXHJcblx0XHQvLyB0b3VjaCBldmVudHMsIHNlZSAjNDMxNS5cclxuXHRcdC8vIEFsc28gaWdub3JlIHRoZSBldmVudCBpZiBkaXNhYmxlZDsgdGhpcyBoYXBwZW5zIGluIElFMTFcclxuXHRcdC8vIHVuZGVyIHNvbWUgY2lyY3Vtc3RhbmNlcywgc2VlICMzNjY2LlxyXG5cdFx0aWYgKGUuX3NpbXVsYXRlZCB8fCAhdGhpcy5fZW5hYmxlZCkgeyByZXR1cm47IH1cclxuXHJcblx0XHRpZiAoZS50b3VjaGVzICYmIGUudG91Y2hlcy5sZW5ndGggPiAxKSB7XHJcblx0XHRcdHRoaXMuX21vdmVkID0gdHJ1ZTtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBmaXJzdCA9IChlLnRvdWNoZXMgJiYgZS50b3VjaGVzLmxlbmd0aCA9PT0gMSA/IGUudG91Y2hlc1swXSA6IGUpLFxyXG5cdFx0ICAgIG9mZnNldCA9IG5ldyBQb2ludChmaXJzdC5jbGllbnRYLCBmaXJzdC5jbGllbnRZKS5fc3VidHJhY3QodGhpcy5fc3RhcnRQb2ludCk7XHJcblxyXG5cdFx0aWYgKCFvZmZzZXQueCAmJiAhb2Zmc2V0LnkpIHsgcmV0dXJuOyB9XHJcblx0XHRpZiAoTWF0aC5hYnMob2Zmc2V0LngpICsgTWF0aC5hYnMob2Zmc2V0LnkpIDwgdGhpcy5vcHRpb25zLmNsaWNrVG9sZXJhbmNlKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdC8vIFdlIGFzc3VtZSB0aGF0IHRoZSBwYXJlbnQgY29udGFpbmVyJ3MgcG9zaXRpb24sIGJvcmRlciBhbmQgc2NhbGUgZG8gbm90IGNoYW5nZSBmb3IgdGhlIGR1cmF0aW9uIG9mIHRoZSBkcmFnLlxyXG5cdFx0Ly8gVGhlcmVmb3JlIHRoZXJlIGlzIG5vIG5lZWQgdG8gYWNjb3VudCBmb3IgdGhlIHBvc2l0aW9uIGFuZCBib3JkZXIgKHRoZXkgYXJlIGVsaW1pbmF0ZWQgYnkgdGhlIHN1YnRyYWN0aW9uKVxyXG5cdFx0Ly8gYW5kIHdlIGNhbiB1c2UgdGhlIGNhY2hlZCB2YWx1ZSBmb3IgdGhlIHNjYWxlLlxyXG5cdFx0b2Zmc2V0LnggLz0gdGhpcy5fcGFyZW50U2NhbGUueDtcclxuXHRcdG9mZnNldC55IC89IHRoaXMuX3BhcmVudFNjYWxlLnk7XHJcblxyXG5cdFx0cHJldmVudERlZmF1bHQoZSk7XHJcblxyXG5cdFx0aWYgKCF0aGlzLl9tb3ZlZCkge1xyXG5cdFx0XHQvLyBAZXZlbnQgZHJhZ3N0YXJ0OiBFdmVudFxyXG5cdFx0XHQvLyBGaXJlZCB3aGVuIGEgZHJhZyBzdGFydHNcclxuXHRcdFx0dGhpcy5maXJlKCdkcmFnc3RhcnQnKTtcclxuXHJcblx0XHRcdHRoaXMuX21vdmVkID0gdHJ1ZTtcclxuXHRcdFx0dGhpcy5fc3RhcnRQb3MgPSBnZXRQb3NpdGlvbih0aGlzLl9lbGVtZW50KS5zdWJ0cmFjdChvZmZzZXQpO1xyXG5cclxuXHRcdFx0YWRkQ2xhc3MoZG9jdW1lbnQuYm9keSwgJ2xlYWZsZXQtZHJhZ2dpbmcnKTtcclxuXHJcblx0XHRcdHRoaXMuX2xhc3RUYXJnZXQgPSBlLnRhcmdldCB8fCBlLnNyY0VsZW1lbnQ7XHJcblx0XHRcdC8vIElFIGFuZCBFZGdlIGRvIG5vdCBnaXZlIHRoZSA8dXNlPiBlbGVtZW50LCBzbyBmZXRjaCBpdFxyXG5cdFx0XHQvLyBpZiBuZWNlc3NhcnlcclxuXHRcdFx0aWYgKCh3aW5kb3cuU1ZHRWxlbWVudEluc3RhbmNlKSAmJiAodGhpcy5fbGFzdFRhcmdldCBpbnN0YW5jZW9mIFNWR0VsZW1lbnRJbnN0YW5jZSkpIHtcclxuXHRcdFx0XHR0aGlzLl9sYXN0VGFyZ2V0ID0gdGhpcy5fbGFzdFRhcmdldC5jb3JyZXNwb25kaW5nVXNlRWxlbWVudDtcclxuXHRcdFx0fVxyXG5cdFx0XHRhZGRDbGFzcyh0aGlzLl9sYXN0VGFyZ2V0LCAnbGVhZmxldC1kcmFnLXRhcmdldCcpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX25ld1BvcyA9IHRoaXMuX3N0YXJ0UG9zLmFkZChvZmZzZXQpO1xyXG5cdFx0dGhpcy5fbW92aW5nID0gdHJ1ZTtcclxuXHJcblx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fYW5pbVJlcXVlc3QpO1xyXG5cdFx0dGhpcy5fbGFzdEV2ZW50ID0gZTtcclxuXHRcdHRoaXMuX2FuaW1SZXF1ZXN0ID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl91cGRhdGVQb3NpdGlvbiwgdGhpcywgdHJ1ZSk7XHJcblx0fSxcclxuXHJcblx0X3VwZGF0ZVBvc2l0aW9uOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgZSA9IHtvcmlnaW5hbEV2ZW50OiB0aGlzLl9sYXN0RXZlbnR9O1xyXG5cclxuXHRcdC8vIEBldmVudCBwcmVkcmFnOiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgY29udGludW91c2x5IGR1cmluZyBkcmFnZ2luZyAqYmVmb3JlKiBlYWNoIGNvcnJlc3BvbmRpbmdcclxuXHRcdC8vIHVwZGF0ZSBvZiB0aGUgZWxlbWVudCdzIHBvc2l0aW9uLlxyXG5cdFx0dGhpcy5maXJlKCdwcmVkcmFnJywgZSk7XHJcblx0XHRzZXRQb3NpdGlvbih0aGlzLl9lbGVtZW50LCB0aGlzLl9uZXdQb3MpO1xyXG5cclxuXHRcdC8vIEBldmVudCBkcmFnOiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgY29udGludW91c2x5IGR1cmluZyBkcmFnZ2luZy5cclxuXHRcdHRoaXMuZmlyZSgnZHJhZycsIGUpO1xyXG5cdH0sXHJcblxyXG5cdF9vblVwOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0Ly8gSWdub3JlIHNpbXVsYXRlZCBldmVudHMsIHNpbmNlIHdlIGhhbmRsZSBib3RoIHRvdWNoIGFuZFxyXG5cdFx0Ly8gbW91c2UgZXhwbGljaXRseTsgb3RoZXJ3aXNlIHdlIHJpc2sgZ2V0dGluZyBkdXBsaWNhdGVzIG9mXHJcblx0XHQvLyB0b3VjaCBldmVudHMsIHNlZSAjNDMxNS5cclxuXHRcdC8vIEFsc28gaWdub3JlIHRoZSBldmVudCBpZiBkaXNhYmxlZDsgdGhpcyBoYXBwZW5zIGluIElFMTFcclxuXHRcdC8vIHVuZGVyIHNvbWUgY2lyY3Vtc3RhbmNlcywgc2VlICMzNjY2LlxyXG5cdFx0aWYgKGUuX3NpbXVsYXRlZCB8fCAhdGhpcy5fZW5hYmxlZCkgeyByZXR1cm47IH1cclxuXHRcdHRoaXMuZmluaXNoRHJhZygpO1xyXG5cdH0sXHJcblxyXG5cdGZpbmlzaERyYWc6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJlbW92ZUNsYXNzKGRvY3VtZW50LmJvZHksICdsZWFmbGV0LWRyYWdnaW5nJyk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX2xhc3RUYXJnZXQpIHtcclxuXHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fbGFzdFRhcmdldCwgJ2xlYWZsZXQtZHJhZy10YXJnZXQnKTtcclxuXHRcdFx0dGhpcy5fbGFzdFRhcmdldCA9IG51bGw7XHJcblx0XHR9XHJcblxyXG5cdFx0Zm9yICh2YXIgaSBpbiBNT1ZFKSB7XHJcblx0XHRcdG9mZihkb2N1bWVudCwgTU9WRVtpXSwgdGhpcy5fb25Nb3ZlLCB0aGlzKTtcclxuXHRcdFx0b2ZmKGRvY3VtZW50LCBFTkRbaV0sIHRoaXMuX29uVXAsIHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGVuYWJsZUltYWdlRHJhZygpO1xyXG5cdFx0ZW5hYmxlVGV4dFNlbGVjdGlvbigpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9tb3ZlZCAmJiB0aGlzLl9tb3ZpbmcpIHtcclxuXHRcdFx0Ly8gZW5zdXJlIGRyYWcgaXMgbm90IGZpcmVkIGFmdGVyIGRyYWdlbmRcclxuXHRcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2FuaW1SZXF1ZXN0KTtcclxuXHJcblx0XHRcdC8vIEBldmVudCBkcmFnZW5kOiBEcmFnRW5kRXZlbnRcclxuXHRcdFx0Ly8gRmlyZWQgd2hlbiB0aGUgZHJhZyBlbmRzLlxyXG5cdFx0XHR0aGlzLmZpcmUoJ2RyYWdlbmQnLCB7XHJcblx0XHRcdFx0ZGlzdGFuY2U6IHRoaXMuX25ld1Bvcy5kaXN0YW5jZVRvKHRoaXMuX3N0YXJ0UG9zKVxyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9tb3ZpbmcgPSBmYWxzZTtcclxuXHRcdERyYWdnYWJsZS5fZHJhZ2dpbmcgPSBmYWxzZTtcclxuXHR9XHJcblxyXG59KTtcblxuLypcclxuICogQG5hbWVzcGFjZSBMaW5lVXRpbFxyXG4gKlxyXG4gKiBWYXJpb3VzIHV0aWxpdHkgZnVuY3Rpb25zIGZvciBwb2x5bGluZSBwb2ludHMgcHJvY2Vzc2luZywgdXNlZCBieSBMZWFmbGV0IGludGVybmFsbHkgdG8gbWFrZSBwb2x5bGluZXMgbGlnaHRuaW5nLWZhc3QuXHJcbiAqL1xyXG5cclxuLy8gU2ltcGxpZnkgcG9seWxpbmUgd2l0aCB2ZXJ0ZXggcmVkdWN0aW9uIGFuZCBEb3VnbGFzLVBldWNrZXIgc2ltcGxpZmljYXRpb24uXHJcbi8vIEltcHJvdmVzIHJlbmRlcmluZyBwZXJmb3JtYW5jZSBkcmFtYXRpY2FsbHkgYnkgbGVzc2VuaW5nIHRoZSBudW1iZXIgb2YgcG9pbnRzIHRvIGRyYXcuXHJcblxyXG4vLyBAZnVuY3Rpb24gc2ltcGxpZnkocG9pbnRzOiBQb2ludFtdLCB0b2xlcmFuY2U6IE51bWJlcik6IFBvaW50W11cclxuLy8gRHJhbWF0aWNhbGx5IHJlZHVjZXMgdGhlIG51bWJlciBvZiBwb2ludHMgaW4gYSBwb2x5bGluZSB3aGlsZSByZXRhaW5pbmdcclxuLy8gaXRzIHNoYXBlIGFuZCByZXR1cm5zIGEgbmV3IGFycmF5IG9mIHNpbXBsaWZpZWQgcG9pbnRzLCB1c2luZyB0aGVcclxuLy8gW0RvdWdsYXMtUGV1Y2tlciBhbGdvcml0aG1dKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRG91Z2xhcy1QZXVja2VyX2FsZ29yaXRobSkuXHJcbi8vIFVzZWQgZm9yIGEgaHVnZSBwZXJmb3JtYW5jZSBib29zdCB3aGVuIHByb2Nlc3NpbmcvZGlzcGxheWluZyBMZWFmbGV0IHBvbHlsaW5lcyBmb3JcclxuLy8gZWFjaCB6b29tIGxldmVsIGFuZCBhbHNvIHJlZHVjaW5nIHZpc3VhbCBub2lzZS4gdG9sZXJhbmNlIGFmZmVjdHMgdGhlIGFtb3VudCBvZlxyXG4vLyBzaW1wbGlmaWNhdGlvbiAobGVzc2VyIHZhbHVlIG1lYW5zIGhpZ2hlciBxdWFsaXR5IGJ1dCBzbG93ZXIgYW5kIHdpdGggbW9yZSBwb2ludHMpLlxyXG4vLyBBbHNvIHJlbGVhc2VkIGFzIGEgc2VwYXJhdGVkIG1pY3JvLWxpYnJhcnkgW1NpbXBsaWZ5LmpzXShodHRwOi8vbW91cm5lci5naXRodWIuY29tL3NpbXBsaWZ5LWpzLykuXHJcbmZ1bmN0aW9uIHNpbXBsaWZ5KHBvaW50cywgdG9sZXJhbmNlKSB7XHJcblx0aWYgKCF0b2xlcmFuY2UgfHwgIXBvaW50cy5sZW5ndGgpIHtcclxuXHRcdHJldHVybiBwb2ludHMuc2xpY2UoKTtcclxuXHR9XHJcblxyXG5cdHZhciBzcVRvbGVyYW5jZSA9IHRvbGVyYW5jZSAqIHRvbGVyYW5jZTtcclxuXHJcblx0ICAgIC8vIHN0YWdlIDE6IHZlcnRleCByZWR1Y3Rpb25cclxuXHQgICAgcG9pbnRzID0gX3JlZHVjZVBvaW50cyhwb2ludHMsIHNxVG9sZXJhbmNlKTtcclxuXHJcblx0ICAgIC8vIHN0YWdlIDI6IERvdWdsYXMtUGV1Y2tlciBzaW1wbGlmaWNhdGlvblxyXG5cdCAgICBwb2ludHMgPSBfc2ltcGxpZnlEUChwb2ludHMsIHNxVG9sZXJhbmNlKTtcclxuXHJcblx0cmV0dXJuIHBvaW50cztcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHBvaW50VG9TZWdtZW50RGlzdGFuY2UocDogUG9pbnQsIHAxOiBQb2ludCwgcDI6IFBvaW50KTogTnVtYmVyXHJcbi8vIFJldHVybnMgdGhlIGRpc3RhbmNlIGJldHdlZW4gcG9pbnQgYHBgIGFuZCBzZWdtZW50IGBwMWAgdG8gYHAyYC5cclxuZnVuY3Rpb24gcG9pbnRUb1NlZ21lbnREaXN0YW5jZShwLCBwMSwgcDIpIHtcclxuXHRyZXR1cm4gTWF0aC5zcXJ0KF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudChwLCBwMSwgcDIsIHRydWUpKTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGNsb3Nlc3RQb2ludE9uU2VnbWVudChwOiBQb2ludCwgcDE6IFBvaW50LCBwMjogUG9pbnQpOiBOdW1iZXJcclxuLy8gUmV0dXJucyB0aGUgY2xvc2VzdCBwb2ludCBmcm9tIGEgcG9pbnQgYHBgIG9uIGEgc2VnbWVudCBgcDFgIHRvIGBwMmAuXHJcbmZ1bmN0aW9uIGNsb3Nlc3RQb2ludE9uU2VnbWVudChwLCBwMSwgcDIpIHtcclxuXHRyZXR1cm4gX3NxQ2xvc2VzdFBvaW50T25TZWdtZW50KHAsIHAxLCBwMik7XHJcbn1cclxuXHJcbi8vIERvdWdsYXMtUGV1Y2tlciBzaW1wbGlmaWNhdGlvbiwgc2VlIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRG91Z2xhcy1QZXVja2VyX2FsZ29yaXRobVxyXG5mdW5jdGlvbiBfc2ltcGxpZnlEUChwb2ludHMsIHNxVG9sZXJhbmNlKSB7XHJcblxyXG5cdHZhciBsZW4gPSBwb2ludHMubGVuZ3RoLFxyXG5cdCAgICBBcnJheUNvbnN0cnVjdG9yID0gdHlwZW9mIFVpbnQ4QXJyYXkgIT09IHVuZGVmaW5lZCArICcnID8gVWludDhBcnJheSA6IEFycmF5LFxyXG5cdCAgICBtYXJrZXJzID0gbmV3IEFycmF5Q29uc3RydWN0b3IobGVuKTtcclxuXHJcblx0ICAgIG1hcmtlcnNbMF0gPSBtYXJrZXJzW2xlbiAtIDFdID0gMTtcclxuXHJcblx0X3NpbXBsaWZ5RFBTdGVwKHBvaW50cywgbWFya2Vycywgc3FUb2xlcmFuY2UsIDAsIGxlbiAtIDEpO1xyXG5cclxuXHR2YXIgaSxcclxuXHQgICAgbmV3UG9pbnRzID0gW107XHJcblxyXG5cdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0aWYgKG1hcmtlcnNbaV0pIHtcclxuXHRcdFx0bmV3UG9pbnRzLnB1c2gocG9pbnRzW2ldKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHJldHVybiBuZXdQb2ludHM7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIF9zaW1wbGlmeURQU3RlcChwb2ludHMsIG1hcmtlcnMsIHNxVG9sZXJhbmNlLCBmaXJzdCwgbGFzdCkge1xyXG5cclxuXHR2YXIgbWF4U3FEaXN0ID0gMCxcclxuXHRpbmRleCwgaSwgc3FEaXN0O1xyXG5cclxuXHRmb3IgKGkgPSBmaXJzdCArIDE7IGkgPD0gbGFzdCAtIDE7IGkrKykge1xyXG5cdFx0c3FEaXN0ID0gX3NxQ2xvc2VzdFBvaW50T25TZWdtZW50KHBvaW50c1tpXSwgcG9pbnRzW2ZpcnN0XSwgcG9pbnRzW2xhc3RdLCB0cnVlKTtcclxuXHJcblx0XHRpZiAoc3FEaXN0ID4gbWF4U3FEaXN0KSB7XHJcblx0XHRcdGluZGV4ID0gaTtcclxuXHRcdFx0bWF4U3FEaXN0ID0gc3FEaXN0O1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0aWYgKG1heFNxRGlzdCA+IHNxVG9sZXJhbmNlKSB7XHJcblx0XHRtYXJrZXJzW2luZGV4XSA9IDE7XHJcblxyXG5cdFx0X3NpbXBsaWZ5RFBTdGVwKHBvaW50cywgbWFya2Vycywgc3FUb2xlcmFuY2UsIGZpcnN0LCBpbmRleCk7XHJcblx0XHRfc2ltcGxpZnlEUFN0ZXAocG9pbnRzLCBtYXJrZXJzLCBzcVRvbGVyYW5jZSwgaW5kZXgsIGxhc3QpO1xyXG5cdH1cclxufVxyXG5cclxuLy8gcmVkdWNlIHBvaW50cyB0aGF0IGFyZSB0b28gY2xvc2UgdG8gZWFjaCBvdGhlciB0byBhIHNpbmdsZSBwb2ludFxyXG5mdW5jdGlvbiBfcmVkdWNlUG9pbnRzKHBvaW50cywgc3FUb2xlcmFuY2UpIHtcclxuXHR2YXIgcmVkdWNlZFBvaW50cyA9IFtwb2ludHNbMF1dO1xyXG5cclxuXHRmb3IgKHZhciBpID0gMSwgcHJldiA9IDAsIGxlbiA9IHBvaW50cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0aWYgKF9zcURpc3QocG9pbnRzW2ldLCBwb2ludHNbcHJldl0pID4gc3FUb2xlcmFuY2UpIHtcclxuXHRcdFx0cmVkdWNlZFBvaW50cy5wdXNoKHBvaW50c1tpXSk7XHJcblx0XHRcdHByZXYgPSBpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHRpZiAocHJldiA8IGxlbiAtIDEpIHtcclxuXHRcdHJlZHVjZWRQb2ludHMucHVzaChwb2ludHNbbGVuIC0gMV0pO1xyXG5cdH1cclxuXHRyZXR1cm4gcmVkdWNlZFBvaW50cztcclxufVxyXG5cclxudmFyIF9sYXN0Q29kZTtcclxuXHJcbi8vIEBmdW5jdGlvbiBjbGlwU2VnbWVudChhOiBQb2ludCwgYjogUG9pbnQsIGJvdW5kczogQm91bmRzLCB1c2VMYXN0Q29kZT86IEJvb2xlYW4sIHJvdW5kPzogQm9vbGVhbik6IFBvaW50W118Qm9vbGVhblxyXG4vLyBDbGlwcyB0aGUgc2VnbWVudCBhIHRvIGIgYnkgcmVjdGFuZ3VsYXIgYm91bmRzIHdpdGggdGhlXHJcbi8vIFtDb2hlbi1TdXRoZXJsYW5kIGFsZ29yaXRobV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29oZW4lRTIlODAlOTNTdXRoZXJsYW5kX2FsZ29yaXRobSlcclxuLy8gKG1vZGlmeWluZyB0aGUgc2VnbWVudCBwb2ludHMgZGlyZWN0bHkhKS4gVXNlZCBieSBMZWFmbGV0IHRvIG9ubHkgc2hvdyBwb2x5bGluZVxyXG4vLyBwb2ludHMgdGhhdCBhcmUgb24gdGhlIHNjcmVlbiBvciBuZWFyLCBpbmNyZWFzaW5nIHBlcmZvcm1hbmNlLlxyXG5mdW5jdGlvbiBjbGlwU2VnbWVudChhLCBiLCBib3VuZHMsIHVzZUxhc3RDb2RlLCByb3VuZCkge1xyXG5cdHZhciBjb2RlQSA9IHVzZUxhc3RDb2RlID8gX2xhc3RDb2RlIDogX2dldEJpdENvZGUoYSwgYm91bmRzKSxcclxuXHQgICAgY29kZUIgPSBfZ2V0Qml0Q29kZShiLCBib3VuZHMpLFxyXG5cclxuXHQgICAgY29kZU91dCwgcCwgbmV3Q29kZTtcclxuXHJcblx0ICAgIC8vIHNhdmUgMm5kIGNvZGUgdG8gYXZvaWQgY2FsY3VsYXRpbmcgaXQgb24gdGhlIG5leHQgc2VnbWVudFxyXG5cdCAgICBfbGFzdENvZGUgPSBjb2RlQjtcclxuXHJcblx0d2hpbGUgKHRydWUpIHtcclxuXHRcdC8vIGlmIGEsYiBpcyBpbnNpZGUgdGhlIGNsaXAgd2luZG93ICh0cml2aWFsIGFjY2VwdClcclxuXHRcdGlmICghKGNvZGVBIHwgY29kZUIpKSB7XHJcblx0XHRcdHJldHVybiBbYSwgYl07XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gaWYgYSxiIGlzIG91dHNpZGUgdGhlIGNsaXAgd2luZG93ICh0cml2aWFsIHJlamVjdClcclxuXHRcdGlmIChjb2RlQSAmIGNvZGVCKSB7XHJcblx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBvdGhlciBjYXNlc1xyXG5cdFx0Y29kZU91dCA9IGNvZGVBIHx8IGNvZGVCO1xyXG5cdFx0cCA9IF9nZXRFZGdlSW50ZXJzZWN0aW9uKGEsIGIsIGNvZGVPdXQsIGJvdW5kcywgcm91bmQpO1xyXG5cdFx0bmV3Q29kZSA9IF9nZXRCaXRDb2RlKHAsIGJvdW5kcyk7XHJcblxyXG5cdFx0aWYgKGNvZGVPdXQgPT09IGNvZGVBKSB7XHJcblx0XHRcdGEgPSBwO1xyXG5cdFx0XHRjb2RlQSA9IG5ld0NvZGU7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRiID0gcDtcclxuXHRcdFx0Y29kZUIgPSBuZXdDb2RlO1xyXG5cdFx0fVxyXG5cdH1cclxufVxyXG5cclxuZnVuY3Rpb24gX2dldEVkZ2VJbnRlcnNlY3Rpb24oYSwgYiwgY29kZSwgYm91bmRzLCByb3VuZCkge1xyXG5cdHZhciBkeCA9IGIueCAtIGEueCxcclxuXHQgICAgZHkgPSBiLnkgLSBhLnksXHJcblx0ICAgIG1pbiA9IGJvdW5kcy5taW4sXHJcblx0ICAgIG1heCA9IGJvdW5kcy5tYXgsXHJcblx0ICAgIHgsIHk7XHJcblxyXG5cdGlmIChjb2RlICYgOCkgeyAvLyB0b3BcclxuXHRcdHggPSBhLnggKyBkeCAqIChtYXgueSAtIGEueSkgLyBkeTtcclxuXHRcdHkgPSBtYXgueTtcclxuXHJcblx0fSBlbHNlIGlmIChjb2RlICYgNCkgeyAvLyBib3R0b21cclxuXHRcdHggPSBhLnggKyBkeCAqIChtaW4ueSAtIGEueSkgLyBkeTtcclxuXHRcdHkgPSBtaW4ueTtcclxuXHJcblx0fSBlbHNlIGlmIChjb2RlICYgMikgeyAvLyByaWdodFxyXG5cdFx0eCA9IG1heC54O1xyXG5cdFx0eSA9IGEueSArIGR5ICogKG1heC54IC0gYS54KSAvIGR4O1xyXG5cclxuXHR9IGVsc2UgaWYgKGNvZGUgJiAxKSB7IC8vIGxlZnRcclxuXHRcdHggPSBtaW4ueDtcclxuXHRcdHkgPSBhLnkgKyBkeSAqIChtaW4ueCAtIGEueCkgLyBkeDtcclxuXHR9XHJcblxyXG5cdHJldHVybiBuZXcgUG9pbnQoeCwgeSwgcm91bmQpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBfZ2V0Qml0Q29kZShwLCBib3VuZHMpIHtcclxuXHR2YXIgY29kZSA9IDA7XHJcblxyXG5cdGlmIChwLnggPCBib3VuZHMubWluLngpIHsgLy8gbGVmdFxyXG5cdFx0Y29kZSB8PSAxO1xyXG5cdH0gZWxzZSBpZiAocC54ID4gYm91bmRzLm1heC54KSB7IC8vIHJpZ2h0XHJcblx0XHRjb2RlIHw9IDI7XHJcblx0fVxyXG5cclxuXHRpZiAocC55IDwgYm91bmRzLm1pbi55KSB7IC8vIGJvdHRvbVxyXG5cdFx0Y29kZSB8PSA0O1xyXG5cdH0gZWxzZSBpZiAocC55ID4gYm91bmRzLm1heC55KSB7IC8vIHRvcFxyXG5cdFx0Y29kZSB8PSA4O1xyXG5cdH1cclxuXHJcblx0cmV0dXJuIGNvZGU7XHJcbn1cclxuXHJcbi8vIHNxdWFyZSBkaXN0YW5jZSAodG8gYXZvaWQgdW5uZWNlc3NhcnkgTWF0aC5zcXJ0IGNhbGxzKVxyXG5mdW5jdGlvbiBfc3FEaXN0KHAxLCBwMikge1xyXG5cdHZhciBkeCA9IHAyLnggLSBwMS54LFxyXG5cdCAgICBkeSA9IHAyLnkgLSBwMS55O1xyXG5cdHJldHVybiBkeCAqIGR4ICsgZHkgKiBkeTtcclxufVxyXG5cclxuLy8gcmV0dXJuIGNsb3Nlc3QgcG9pbnQgb24gc2VnbWVudCBvciBkaXN0YW5jZSB0byB0aGF0IHBvaW50XHJcbmZ1bmN0aW9uIF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudChwLCBwMSwgcDIsIHNxRGlzdCkge1xyXG5cdHZhciB4ID0gcDEueCxcclxuXHQgICAgeSA9IHAxLnksXHJcblx0ICAgIGR4ID0gcDIueCAtIHgsXHJcblx0ICAgIGR5ID0gcDIueSAtIHksXHJcblx0ICAgIGRvdCA9IGR4ICogZHggKyBkeSAqIGR5LFxyXG5cdCAgICB0O1xyXG5cclxuXHRpZiAoZG90ID4gMCkge1xyXG5cdFx0dCA9ICgocC54IC0geCkgKiBkeCArIChwLnkgLSB5KSAqIGR5KSAvIGRvdDtcclxuXHJcblx0XHRpZiAodCA+IDEpIHtcclxuXHRcdFx0eCA9IHAyLng7XHJcblx0XHRcdHkgPSBwMi55O1xyXG5cdFx0fSBlbHNlIGlmICh0ID4gMCkge1xyXG5cdFx0XHR4ICs9IGR4ICogdDtcclxuXHRcdFx0eSArPSBkeSAqIHQ7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRkeCA9IHAueCAtIHg7XHJcblx0ZHkgPSBwLnkgLSB5O1xyXG5cclxuXHRyZXR1cm4gc3FEaXN0ID8gZHggKiBkeCArIGR5ICogZHkgOiBuZXcgUG9pbnQoeCwgeSk7XHJcbn1cclxuXHJcblxyXG4vLyBAZnVuY3Rpb24gaXNGbGF0KGxhdGxuZ3M6IExhdExuZ1tdKTogQm9vbGVhblxyXG4vLyBSZXR1cm5zIHRydWUgaWYgYGxhdGxuZ3NgIGlzIGEgZmxhdCBhcnJheSwgZmFsc2UgaXMgbmVzdGVkLlxyXG5mdW5jdGlvbiBpc0ZsYXQobGF0bG5ncykge1xyXG5cdHJldHVybiAhaXNBcnJheShsYXRsbmdzWzBdKSB8fCAodHlwZW9mIGxhdGxuZ3NbMF1bMF0gIT09ICdvYmplY3QnICYmIHR5cGVvZiBsYXRsbmdzWzBdWzBdICE9PSAndW5kZWZpbmVkJyk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIF9mbGF0KGxhdGxuZ3MpIHtcclxuXHRjb25zb2xlLndhcm4oJ0RlcHJlY2F0ZWQgdXNlIG9mIF9mbGF0LCBwbGVhc2UgdXNlIEwuTGluZVV0aWwuaXNGbGF0IGluc3RlYWQuJyk7XHJcblx0cmV0dXJuIGlzRmxhdChsYXRsbmdzKTtcclxufVxyXG5cblxudmFyIExpbmVVdGlsID0gKE9iamVjdC5mcmVlemUgfHwgT2JqZWN0KSh7XG5cdHNpbXBsaWZ5OiBzaW1wbGlmeSxcblx0cG9pbnRUb1NlZ21lbnREaXN0YW5jZTogcG9pbnRUb1NlZ21lbnREaXN0YW5jZSxcblx0Y2xvc2VzdFBvaW50T25TZWdtZW50OiBjbG9zZXN0UG9pbnRPblNlZ21lbnQsXG5cdGNsaXBTZWdtZW50OiBjbGlwU2VnbWVudCxcblx0X2dldEVkZ2VJbnRlcnNlY3Rpb246IF9nZXRFZGdlSW50ZXJzZWN0aW9uLFxuXHRfZ2V0Qml0Q29kZTogX2dldEJpdENvZGUsXG5cdF9zcUNsb3Nlc3RQb2ludE9uU2VnbWVudDogX3NxQ2xvc2VzdFBvaW50T25TZWdtZW50LFxuXHRpc0ZsYXQ6IGlzRmxhdCxcblx0X2ZsYXQ6IF9mbGF0XG59KTtcblxuLypcclxuICogQG5hbWVzcGFjZSBQb2x5VXRpbFxyXG4gKiBWYXJpb3VzIHV0aWxpdHkgZnVuY3Rpb25zIGZvciBwb2x5Z29uIGdlb21ldHJpZXMuXHJcbiAqL1xyXG5cclxuLyogQGZ1bmN0aW9uIGNsaXBQb2x5Z29uKHBvaW50czogUG9pbnRbXSwgYm91bmRzOiBCb3VuZHMsIHJvdW5kPzogQm9vbGVhbik6IFBvaW50W11cclxuICogQ2xpcHMgdGhlIHBvbHlnb24gZ2VvbWV0cnkgZGVmaW5lZCBieSB0aGUgZ2l2ZW4gYHBvaW50c2AgYnkgdGhlIGdpdmVuIGJvdW5kcyAodXNpbmcgdGhlIFtTdXRoZXJsYW5kLUhvZGdtYW4gYWxnb3JpdGhtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TdXRoZXJsYW5kJUUyJTgwJTkzSG9kZ21hbl9hbGdvcml0aG0pKS5cclxuICogVXNlZCBieSBMZWFmbGV0IHRvIG9ubHkgc2hvdyBwb2x5Z29uIHBvaW50cyB0aGF0IGFyZSBvbiB0aGUgc2NyZWVuIG9yIG5lYXIsIGluY3JlYXNpbmdcclxuICogcGVyZm9ybWFuY2UuIE5vdGUgdGhhdCBwb2x5Z29uIHBvaW50cyBuZWVkcyBkaWZmZXJlbnQgYWxnb3JpdGhtIGZvciBjbGlwcGluZ1xyXG4gKiB0aGFuIHBvbHlsaW5lLCBzbyB0aGVyZSdzIGEgc2VwYXJhdGUgbWV0aG9kIGZvciBpdC5cclxuICovXHJcbmZ1bmN0aW9uIGNsaXBQb2x5Z29uKHBvaW50cywgYm91bmRzLCByb3VuZCkge1xyXG5cdHZhciBjbGlwcGVkUG9pbnRzLFxyXG5cdCAgICBlZGdlcyA9IFsxLCA0LCAyLCA4XSxcclxuXHQgICAgaSwgaiwgayxcclxuXHQgICAgYSwgYixcclxuXHQgICAgbGVuLCBlZGdlLCBwO1xyXG5cclxuXHRmb3IgKGkgPSAwLCBsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdHBvaW50c1tpXS5fY29kZSA9IF9nZXRCaXRDb2RlKHBvaW50c1tpXSwgYm91bmRzKTtcclxuXHR9XHJcblxyXG5cdC8vIGZvciBlYWNoIGVkZ2UgKGxlZnQsIGJvdHRvbSwgcmlnaHQsIHRvcClcclxuXHRmb3IgKGsgPSAwOyBrIDwgNDsgaysrKSB7XHJcblx0XHRlZGdlID0gZWRnZXNba107XHJcblx0XHRjbGlwcGVkUG9pbnRzID0gW107XHJcblxyXG5cdFx0Zm9yIChpID0gMCwgbGVuID0gcG9pbnRzLmxlbmd0aCwgaiA9IGxlbiAtIDE7IGkgPCBsZW47IGogPSBpKyspIHtcclxuXHRcdFx0YSA9IHBvaW50c1tpXTtcclxuXHRcdFx0YiA9IHBvaW50c1tqXTtcclxuXHJcblx0XHRcdC8vIGlmIGEgaXMgaW5zaWRlIHRoZSBjbGlwIHdpbmRvd1xyXG5cdFx0XHRpZiAoIShhLl9jb2RlICYgZWRnZSkpIHtcclxuXHRcdFx0XHQvLyBpZiBiIGlzIG91dHNpZGUgdGhlIGNsaXAgd2luZG93IChhLT5iIGdvZXMgb3V0IG9mIHNjcmVlbilcclxuXHRcdFx0XHRpZiAoYi5fY29kZSAmIGVkZ2UpIHtcclxuXHRcdFx0XHRcdHAgPSBfZ2V0RWRnZUludGVyc2VjdGlvbihiLCBhLCBlZGdlLCBib3VuZHMsIHJvdW5kKTtcclxuXHRcdFx0XHRcdHAuX2NvZGUgPSBfZ2V0Qml0Q29kZShwLCBib3VuZHMpO1xyXG5cdFx0XHRcdFx0Y2xpcHBlZFBvaW50cy5wdXNoKHApO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRjbGlwcGVkUG9pbnRzLnB1c2goYSk7XHJcblxyXG5cdFx0XHQvLyBlbHNlIGlmIGIgaXMgaW5zaWRlIHRoZSBjbGlwIHdpbmRvdyAoYS0+YiBlbnRlcnMgdGhlIHNjcmVlbilcclxuXHRcdFx0fSBlbHNlIGlmICghKGIuX2NvZGUgJiBlZGdlKSkge1xyXG5cdFx0XHRcdHAgPSBfZ2V0RWRnZUludGVyc2VjdGlvbihiLCBhLCBlZGdlLCBib3VuZHMsIHJvdW5kKTtcclxuXHRcdFx0XHRwLl9jb2RlID0gX2dldEJpdENvZGUocCwgYm91bmRzKTtcclxuXHRcdFx0XHRjbGlwcGVkUG9pbnRzLnB1c2gocCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdHBvaW50cyA9IGNsaXBwZWRQb2ludHM7XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gcG9pbnRzO1xyXG59XHJcblxuXG52YXIgUG9seVV0aWwgPSAoT2JqZWN0LmZyZWV6ZSB8fCBPYmplY3QpKHtcblx0Y2xpcFBvbHlnb246IGNsaXBQb2x5Z29uXG59KTtcblxuLypcclxuICogQG5hbWVzcGFjZSBQcm9qZWN0aW9uXHJcbiAqIEBzZWN0aW9uXHJcbiAqIExlYWZsZXQgY29tZXMgd2l0aCBhIHNldCBvZiBhbHJlYWR5IGRlZmluZWQgUHJvamVjdGlvbnMgb3V0IG9mIHRoZSBib3g6XHJcbiAqXHJcbiAqIEBwcm9qZWN0aW9uIEwuUHJvamVjdGlvbi5Mb25MYXRcclxuICpcclxuICogRXF1aXJlY3Rhbmd1bGFyLCBvciBQbGF0ZSBDYXJyZWUgcHJvamVjdGlvbiDigJQgdGhlIG1vc3Qgc2ltcGxlIHByb2plY3Rpb24sXHJcbiAqIG1vc3RseSB1c2VkIGJ5IEdJUyBlbnRodXNpYXN0cy4gRGlyZWN0bHkgbWFwcyBgeGAgYXMgbG9uZ2l0dWRlLCBhbmQgYHlgIGFzXHJcbiAqIGxhdGl0dWRlLiBBbHNvIHN1aXRhYmxlIGZvciBmbGF0IHdvcmxkcywgZS5nLiBnYW1lIG1hcHMuIFVzZWQgYnkgdGhlXHJcbiAqIGBFUFNHOjQzMjZgIGFuZCBgU2ltcGxlYCBDUlMuXHJcbiAqL1xyXG5cclxudmFyIExvbkxhdCA9IHtcclxuXHRwcm9qZWN0OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHRyZXR1cm4gbmV3IFBvaW50KGxhdGxuZy5sbmcsIGxhdGxuZy5sYXQpO1xyXG5cdH0sXHJcblxyXG5cdHVucHJvamVjdDogZnVuY3Rpb24gKHBvaW50KSB7XHJcblx0XHRyZXR1cm4gbmV3IExhdExuZyhwb2ludC55LCBwb2ludC54KTtcclxuXHR9LFxyXG5cclxuXHRib3VuZHM6IG5ldyBCb3VuZHMoWy0xODAsIC05MF0sIFsxODAsIDkwXSlcclxufTtcblxuLypcclxuICogQG5hbWVzcGFjZSBQcm9qZWN0aW9uXHJcbiAqIEBwcm9qZWN0aW9uIEwuUHJvamVjdGlvbi5NZXJjYXRvclxyXG4gKlxyXG4gKiBFbGxpcHRpY2FsIE1lcmNhdG9yIHByb2plY3Rpb24g4oCUIG1vcmUgY29tcGxleCB0aGFuIFNwaGVyaWNhbCBNZXJjYXRvci4gQXNzdW1lcyB0aGF0IEVhcnRoIGlzIGFuIGVsbGlwc29pZC4gVXNlZCBieSB0aGUgRVBTRzozMzk1IENSUy5cclxuICovXHJcblxyXG52YXIgTWVyY2F0b3IgPSB7XHJcblx0UjogNjM3ODEzNyxcclxuXHRSX01JTk9SOiA2MzU2NzUyLjMxNDI0NTE3OSxcclxuXHJcblx0Ym91bmRzOiBuZXcgQm91bmRzKFstMjAwMzc1MDguMzQyNzksIC0xNTQ5NjU3MC43Mzk3Ml0sIFsyMDAzNzUwOC4zNDI3OSwgMTg3NjQ2NTYuMjMxMzhdKSxcclxuXHJcblx0cHJvamVjdDogZnVuY3Rpb24gKGxhdGxuZykge1xyXG5cdFx0dmFyIGQgPSBNYXRoLlBJIC8gMTgwLFxyXG5cdFx0ICAgIHIgPSB0aGlzLlIsXHJcblx0XHQgICAgeSA9IGxhdGxuZy5sYXQgKiBkLFxyXG5cdFx0ICAgIHRtcCA9IHRoaXMuUl9NSU5PUiAvIHIsXHJcblx0XHQgICAgZSA9IE1hdGguc3FydCgxIC0gdG1wICogdG1wKSxcclxuXHRcdCAgICBjb24gPSBlICogTWF0aC5zaW4oeSk7XHJcblxyXG5cdFx0dmFyIHRzID0gTWF0aC50YW4oTWF0aC5QSSAvIDQgLSB5IC8gMikgLyBNYXRoLnBvdygoMSAtIGNvbikgLyAoMSArIGNvbiksIGUgLyAyKTtcclxuXHRcdHkgPSAtciAqIE1hdGgubG9nKE1hdGgubWF4KHRzLCAxRS0xMCkpO1xyXG5cclxuXHRcdHJldHVybiBuZXcgUG9pbnQobGF0bG5nLmxuZyAqIGQgKiByLCB5KTtcclxuXHR9LFxyXG5cclxuXHR1bnByb2plY3Q6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0dmFyIGQgPSAxODAgLyBNYXRoLlBJLFxyXG5cdFx0ICAgIHIgPSB0aGlzLlIsXHJcblx0XHQgICAgdG1wID0gdGhpcy5SX01JTk9SIC8gcixcclxuXHRcdCAgICBlID0gTWF0aC5zcXJ0KDEgLSB0bXAgKiB0bXApLFxyXG5cdFx0ICAgIHRzID0gTWF0aC5leHAoLXBvaW50LnkgLyByKSxcclxuXHRcdCAgICBwaGkgPSBNYXRoLlBJIC8gMiAtIDIgKiBNYXRoLmF0YW4odHMpO1xyXG5cclxuXHRcdGZvciAodmFyIGkgPSAwLCBkcGhpID0gMC4xLCBjb247IGkgPCAxNSAmJiBNYXRoLmFicyhkcGhpKSA+IDFlLTc7IGkrKykge1xyXG5cdFx0XHRjb24gPSBlICogTWF0aC5zaW4ocGhpKTtcclxuXHRcdFx0Y29uID0gTWF0aC5wb3coKDEgLSBjb24pIC8gKDEgKyBjb24pLCBlIC8gMik7XHJcblx0XHRcdGRwaGkgPSBNYXRoLlBJIC8gMiAtIDIgKiBNYXRoLmF0YW4odHMgKiBjb24pIC0gcGhpO1xyXG5cdFx0XHRwaGkgKz0gZHBoaTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gbmV3IExhdExuZyhwaGkgKiBkLCBwb2ludC54ICogZCAvIHIpO1xyXG5cdH1cclxufTtcblxuLypcbiAqIEBjbGFzcyBQcm9qZWN0aW9uXG5cbiAqIEFuIG9iamVjdCB3aXRoIG1ldGhvZHMgZm9yIHByb2plY3RpbmcgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIG9mIHRoZSB3b3JsZCBvbnRvXG4gKiBhIGZsYXQgc3VyZmFjZSAoYW5kIGJhY2spLiBTZWUgW01hcCBwcm9qZWN0aW9uXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01hcF9wcm9qZWN0aW9uKS5cblxuICogQHByb3BlcnR5IGJvdW5kczogQm91bmRzXG4gKiBUaGUgYm91bmRzIChzcGVjaWZpZWQgaW4gQ1JTIHVuaXRzKSB3aGVyZSB0aGUgcHJvamVjdGlvbiBpcyB2YWxpZFxuXG4gKiBAbWV0aG9kIHByb2plY3QobGF0bG5nOiBMYXRMbmcpOiBQb2ludFxuICogUHJvamVjdHMgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGludG8gYSAyRCBwb2ludC5cbiAqIE9ubHkgYWNjZXB0cyBhY3R1YWwgYEwuTGF0TG5nYCBpbnN0YW5jZXMsIG5vdCBhcnJheXMuXG5cbiAqIEBtZXRob2QgdW5wcm9qZWN0KHBvaW50OiBQb2ludCk6IExhdExuZ1xuICogVGhlIGludmVyc2Ugb2YgYHByb2plY3RgLiBQcm9qZWN0cyBhIDJEIHBvaW50IGludG8gYSBnZW9ncmFwaGljYWwgbG9jYXRpb24uXG4gKiBPbmx5IGFjY2VwdHMgYWN0dWFsIGBMLlBvaW50YCBpbnN0YW5jZXMsIG5vdCBhcnJheXMuXG5cbiAqIE5vdGUgdGhhdCB0aGUgcHJvamVjdGlvbiBpbnN0YW5jZXMgZG8gbm90IGluaGVyaXQgZnJvbSBMZWFmZXQncyBgQ2xhc3NgIG9iamVjdCxcbiAqIGFuZCBjYW4ndCBiZSBpbnN0YW50aWF0ZWQuIEFsc28sIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSB0aGVtLFxuICogYW5kIG1ldGhvZHMgY2FuJ3QgYmUgYWRkZWQgdG8gdGhlbSB3aXRoIHRoZSBgaW5jbHVkZWAgZnVuY3Rpb24uXG5cbiAqL1xuXG5cblxuXG52YXIgaW5kZXggPSAoT2JqZWN0LmZyZWV6ZSB8fCBPYmplY3QpKHtcblx0TG9uTGF0OiBMb25MYXQsXG5cdE1lcmNhdG9yOiBNZXJjYXRvcixcblx0U3BoZXJpY2FsTWVyY2F0b3I6IFNwaGVyaWNhbE1lcmNhdG9yXG59KTtcblxuLypcclxuICogQG5hbWVzcGFjZSBDUlNcclxuICogQGNycyBMLkNSUy5FUFNHMzM5NVxyXG4gKlxyXG4gKiBSYXJlbHkgdXNlZCBieSBzb21lIGNvbW1lcmNpYWwgdGlsZSBwcm92aWRlcnMuIFVzZXMgRWxsaXB0aWNhbCBNZXJjYXRvciBwcm9qZWN0aW9uLlxyXG4gKi9cclxudmFyIEVQU0czMzk1ID0gZXh0ZW5kKHt9LCBFYXJ0aCwge1xyXG5cdGNvZGU6ICdFUFNHOjMzOTUnLFxyXG5cdHByb2plY3Rpb246IE1lcmNhdG9yLFxyXG5cclxuXHR0cmFuc2Zvcm1hdGlvbjogKGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBzY2FsZSA9IDAuNSAvIChNYXRoLlBJICogTWVyY2F0b3IuUik7XHJcblx0XHRyZXR1cm4gdG9UcmFuc2Zvcm1hdGlvbihzY2FsZSwgMC41LCAtc2NhbGUsIDAuNSk7XHJcblx0fSgpKVxyXG59KTtcblxuLypcclxuICogQG5hbWVzcGFjZSBDUlNcclxuICogQGNycyBMLkNSUy5FUFNHNDMyNlxyXG4gKlxyXG4gKiBBIGNvbW1vbiBDUlMgYW1vbmcgR0lTIGVudGh1c2lhc3RzLiBVc2VzIHNpbXBsZSBFcXVpcmVjdGFuZ3VsYXIgcHJvamVjdGlvbi5cclxuICpcclxuICogTGVhZmxldCAxLjAueCBjb21wbGllcyB3aXRoIHRoZSBbVE1TIGNvb3JkaW5hdGUgc2NoZW1lIGZvciBFUFNHOjQzMjZdKGh0dHBzOi8vd2lraS5vc2dlby5vcmcvd2lraS9UaWxlX01hcF9TZXJ2aWNlX1NwZWNpZmljYXRpb24jZ2xvYmFsLWdlb2RldGljKSxcclxuICogd2hpY2ggaXMgYSBicmVha2luZyBjaGFuZ2UgZnJvbSAwLjcueCBiZWhhdmlvdXIuICBJZiB5b3UgYXJlIHVzaW5nIGEgYFRpbGVMYXllcmBcclxuICogd2l0aCB0aGlzIENSUywgZW5zdXJlIHRoYXQgdGhlcmUgYXJlIHR3byAyNTZ4MjU2IHBpeGVsIHRpbGVzIGNvdmVyaW5nIHRoZVxyXG4gKiB3aG9sZSBlYXJ0aCBhdCB6b29tIGxldmVsIHplcm8sIGFuZCB0aGF0IHRoZSB0aWxlIGNvb3JkaW5hdGUgb3JpZ2luIGlzICgtMTgwLCs5MCksXHJcbiAqIG9yICgtMTgwLC05MCkgZm9yIGBUaWxlTGF5ZXJgcyB3aXRoIFt0aGUgYHRtc2Agb3B0aW9uXSgjdGlsZWxheWVyLXRtcykgc2V0LlxyXG4gKi9cclxuXHJcbnZhciBFUFNHNDMyNiA9IGV4dGVuZCh7fSwgRWFydGgsIHtcclxuXHRjb2RlOiAnRVBTRzo0MzI2JyxcclxuXHRwcm9qZWN0aW9uOiBMb25MYXQsXHJcblx0dHJhbnNmb3JtYXRpb246IHRvVHJhbnNmb3JtYXRpb24oMSAvIDE4MCwgMSwgLTEgLyAxODAsIDAuNSlcclxufSk7XG5cbi8qXG4gKiBAbmFtZXNwYWNlIENSU1xuICogQGNycyBMLkNSUy5TaW1wbGVcbiAqXG4gKiBBIHNpbXBsZSBDUlMgdGhhdCBtYXBzIGxvbmdpdHVkZSBhbmQgbGF0aXR1ZGUgaW50byBgeGAgYW5kIGB5YCBkaXJlY3RseS5cbiAqIE1heSBiZSB1c2VkIGZvciBtYXBzIG9mIGZsYXQgc3VyZmFjZXMgKGUuZy4gZ2FtZSBtYXBzKS4gTm90ZSB0aGF0IHRoZSBgeWBcbiAqIGF4aXMgc2hvdWxkIHN0aWxsIGJlIGludmVydGVkIChnb2luZyBmcm9tIGJvdHRvbSB0byB0b3ApLiBgZGlzdGFuY2UoKWAgcmV0dXJuc1xuICogc2ltcGxlIGV1Y2xpZGVhbiBkaXN0YW5jZS5cbiAqL1xuXG52YXIgU2ltcGxlID0gZXh0ZW5kKHt9LCBDUlMsIHtcblx0cHJvamVjdGlvbjogTG9uTGF0LFxuXHR0cmFuc2Zvcm1hdGlvbjogdG9UcmFuc2Zvcm1hdGlvbigxLCAwLCAtMSwgMCksXG5cblx0c2NhbGU6IGZ1bmN0aW9uICh6b29tKSB7XG5cdFx0cmV0dXJuIE1hdGgucG93KDIsIHpvb20pO1xuXHR9LFxuXG5cdHpvb206IGZ1bmN0aW9uIChzY2FsZSkge1xuXHRcdHJldHVybiBNYXRoLmxvZyhzY2FsZSkgLyBNYXRoLkxOMjtcblx0fSxcblxuXHRkaXN0YW5jZTogZnVuY3Rpb24gKGxhdGxuZzEsIGxhdGxuZzIpIHtcblx0XHR2YXIgZHggPSBsYXRsbmcyLmxuZyAtIGxhdGxuZzEubG5nLFxuXHRcdCAgICBkeSA9IGxhdGxuZzIubGF0IC0gbGF0bG5nMS5sYXQ7XG5cblx0XHRyZXR1cm4gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcblx0fSxcblxuXHRpbmZpbml0ZTogdHJ1ZVxufSk7XG5cbkNSUy5FYXJ0aCA9IEVhcnRoO1xuQ1JTLkVQU0czMzk1ID0gRVBTRzMzOTU7XG5DUlMuRVBTRzM4NTcgPSBFUFNHMzg1NztcbkNSUy5FUFNHOTAwOTEzID0gRVBTRzkwMDkxMztcbkNSUy5FUFNHNDMyNiA9IEVQU0c0MzI2O1xuQ1JTLlNpbXBsZSA9IFNpbXBsZTtcblxuLypcbiAqIEBjbGFzcyBMYXllclxuICogQGluaGVyaXRzIEV2ZW50ZWRcbiAqIEBha2EgTC5MYXllclxuICogQGFrYSBJTGF5ZXJcbiAqXG4gKiBBIHNldCBvZiBtZXRob2RzIGZyb20gdGhlIExheWVyIGJhc2UgY2xhc3MgdGhhdCBhbGwgTGVhZmxldCBsYXllcnMgdXNlLlxuICogSW5oZXJpdHMgYWxsIG1ldGhvZHMsIG9wdGlvbnMgYW5kIGV2ZW50cyBmcm9tIGBMLkV2ZW50ZWRgLlxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBganNcbiAqIHZhciBsYXllciA9IEwubWFya2VyKGxhdGxuZykuYWRkVG8obWFwKTtcbiAqIGxheWVyLmFkZFRvKG1hcCk7XG4gKiBsYXllci5yZW1vdmUoKTtcbiAqIGBgYFxuICpcbiAqIEBldmVudCBhZGQ6IEV2ZW50XG4gKiBGaXJlZCBhZnRlciB0aGUgbGF5ZXIgaXMgYWRkZWQgdG8gYSBtYXBcbiAqXG4gKiBAZXZlbnQgcmVtb3ZlOiBFdmVudFxuICogRmlyZWQgYWZ0ZXIgdGhlIGxheWVyIGlzIHJlbW92ZWQgZnJvbSBhIG1hcFxuICovXG5cblxudmFyIExheWVyID0gRXZlbnRlZC5leHRlbmQoe1xuXG5cdC8vIENsYXNzZXMgZXh0ZW5kaW5nIGBMLkxheWVyYCB3aWxsIGluaGVyaXQgdGhlIGZvbGxvd2luZyBvcHRpb25zOlxuXHRvcHRpb25zOiB7XG5cdFx0Ly8gQG9wdGlvbiBwYW5lOiBTdHJpbmcgPSAnb3ZlcmxheVBhbmUnXG5cdFx0Ly8gQnkgZGVmYXVsdCB0aGUgbGF5ZXIgd2lsbCBiZSBhZGRlZCB0byB0aGUgbWFwJ3MgW292ZXJsYXkgcGFuZV0oI21hcC1vdmVybGF5cGFuZSkuIE92ZXJyaWRpbmcgdGhpcyBvcHRpb24gd2lsbCBjYXVzZSB0aGUgbGF5ZXIgdG8gYmUgcGxhY2VkIG9uIGFub3RoZXIgcGFuZSBieSBkZWZhdWx0LlxuXHRcdHBhbmU6ICdvdmVybGF5UGFuZScsXG5cblx0XHQvLyBAb3B0aW9uIGF0dHJpYnV0aW9uOiBTdHJpbmcgPSBudWxsXG5cdFx0Ly8gU3RyaW5nIHRvIGJlIHNob3duIGluIHRoZSBhdHRyaWJ1dGlvbiBjb250cm9sLCBlLmcuIFwiwqkgT3BlblN0cmVldE1hcCBjb250cmlidXRvcnNcIi4gSXQgZGVzY3JpYmVzIHRoZSBsYXllciBkYXRhIGFuZCBpcyBvZnRlbiBhIGxlZ2FsIG9ibGlnYXRpb24gdG93YXJkcyBjb3B5cmlnaHQgaG9sZGVycyBhbmQgdGlsZSBwcm92aWRlcnMuXG5cdFx0YXR0cmlidXRpb246IG51bGwsXG5cblx0XHRidWJibGluZ01vdXNlRXZlbnRzOiB0cnVlXG5cdH0sXG5cblx0LyogQHNlY3Rpb25cblx0ICogQ2xhc3NlcyBleHRlbmRpbmcgYEwuTGF5ZXJgIHdpbGwgaW5oZXJpdCB0aGUgZm9sbG93aW5nIG1ldGhvZHM6XG5cdCAqXG5cdCAqIEBtZXRob2QgYWRkVG8obWFwOiBNYXB8TGF5ZXJHcm91cCk6IHRoaXNcblx0ICogQWRkcyB0aGUgbGF5ZXIgdG8gdGhlIGdpdmVuIG1hcCBvciBsYXllciBncm91cC5cblx0ICovXG5cdGFkZFRvOiBmdW5jdGlvbiAobWFwKSB7XG5cdFx0bWFwLmFkZExheWVyKHRoaXMpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgcmVtb3ZlOiB0aGlzXG5cdC8vIFJlbW92ZXMgdGhlIGxheWVyIGZyb20gdGhlIG1hcCBpdCBpcyBjdXJyZW50bHkgYWN0aXZlIG9uLlxuXHRyZW1vdmU6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5yZW1vdmVGcm9tKHRoaXMuX21hcCB8fCB0aGlzLl9tYXBUb0FkZCk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCByZW1vdmVGcm9tKG1hcDogTWFwKTogdGhpc1xuXHQvLyBSZW1vdmVzIHRoZSBsYXllciBmcm9tIHRoZSBnaXZlbiBtYXBcblx0cmVtb3ZlRnJvbTogZnVuY3Rpb24gKG9iaikge1xuXHRcdGlmIChvYmopIHtcblx0XHRcdG9iai5yZW1vdmVMYXllcih0aGlzKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBnZXRQYW5lKG5hbWU/IDogU3RyaW5nKTogSFRNTEVsZW1lbnRcblx0Ly8gUmV0dXJucyB0aGUgYEhUTUxFbGVtZW50YCByZXByZXNlbnRpbmcgdGhlIG5hbWVkIHBhbmUgb24gdGhlIG1hcC4gSWYgYG5hbWVgIGlzIG9taXR0ZWQsIHJldHVybnMgdGhlIHBhbmUgZm9yIHRoaXMgbGF5ZXIuXG5cdGdldFBhbmU6IGZ1bmN0aW9uIChuYW1lKSB7XG5cdFx0cmV0dXJuIHRoaXMuX21hcC5nZXRQYW5lKG5hbWUgPyAodGhpcy5vcHRpb25zW25hbWVdIHx8IG5hbWUpIDogdGhpcy5vcHRpb25zLnBhbmUpO1xuXHR9LFxuXG5cdGFkZEludGVyYWN0aXZlVGFyZ2V0OiBmdW5jdGlvbiAodGFyZ2V0RWwpIHtcblx0XHR0aGlzLl9tYXAuX3RhcmdldHNbc3RhbXAodGFyZ2V0RWwpXSA9IHRoaXM7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0cmVtb3ZlSW50ZXJhY3RpdmVUYXJnZXQ6IGZ1bmN0aW9uICh0YXJnZXRFbCkge1xuXHRcdGRlbGV0ZSB0aGlzLl9tYXAuX3RhcmdldHNbc3RhbXAodGFyZ2V0RWwpXTtcblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGdldEF0dHJpYnV0aW9uOiBTdHJpbmdcblx0Ly8gVXNlZCBieSB0aGUgYGF0dHJpYnV0aW9uIGNvbnRyb2xgLCByZXR1cm5zIHRoZSBbYXR0cmlidXRpb24gb3B0aW9uXSgjZ3JpZGxheWVyLWF0dHJpYnV0aW9uKS5cblx0Z2V0QXR0cmlidXRpb246IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmF0dHJpYnV0aW9uO1xuXHR9LFxuXG5cdF9sYXllckFkZDogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgbWFwID0gZS50YXJnZXQ7XG5cblx0XHQvLyBjaGVjayBpbiBjYXNlIGxheWVyIGdldHMgYWRkZWQgYW5kIHRoZW4gcmVtb3ZlZCBiZWZvcmUgdGhlIG1hcCBpcyByZWFkeVxuXHRcdGlmICghbWFwLmhhc0xheWVyKHRoaXMpKSB7IHJldHVybjsgfVxuXG5cdFx0dGhpcy5fbWFwID0gbWFwO1xuXHRcdHRoaXMuX3pvb21BbmltYXRlZCA9IG1hcC5fem9vbUFuaW1hdGVkO1xuXG5cdFx0aWYgKHRoaXMuZ2V0RXZlbnRzKSB7XG5cdFx0XHR2YXIgZXZlbnRzID0gdGhpcy5nZXRFdmVudHMoKTtcblx0XHRcdG1hcC5vbihldmVudHMsIHRoaXMpO1xuXHRcdFx0dGhpcy5vbmNlKCdyZW1vdmUnLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdG1hcC5vZmYoZXZlbnRzLCB0aGlzKTtcblx0XHRcdH0sIHRoaXMpO1xuXHRcdH1cblxuXHRcdHRoaXMub25BZGQobWFwKTtcblxuXHRcdGlmICh0aGlzLmdldEF0dHJpYnV0aW9uICYmIG1hcC5hdHRyaWJ1dGlvbkNvbnRyb2wpIHtcblx0XHRcdG1hcC5hdHRyaWJ1dGlvbkNvbnRyb2wuYWRkQXR0cmlidXRpb24odGhpcy5nZXRBdHRyaWJ1dGlvbigpKTtcblx0XHR9XG5cblx0XHR0aGlzLmZpcmUoJ2FkZCcpO1xuXHRcdG1hcC5maXJlKCdsYXllcmFkZCcsIHtsYXllcjogdGhpc30pO1xuXHR9XG59KTtcblxuLyogQHNlY3Rpb24gRXh0ZW5zaW9uIG1ldGhvZHNcbiAqIEB1bmluaGVyaXRhYmxlXG4gKlxuICogRXZlcnkgbGF5ZXIgc2hvdWxkIGV4dGVuZCBmcm9tIGBMLkxheWVyYCBhbmQgKHJlLSlpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBtZXRob2RzLlxuICpcbiAqIEBtZXRob2Qgb25BZGQobWFwOiBNYXApOiB0aGlzXG4gKiBTaG91bGQgY29udGFpbiBjb2RlIHRoYXQgY3JlYXRlcyBET00gZWxlbWVudHMgZm9yIHRoZSBsYXllciwgYWRkcyB0aGVtIHRvIGBtYXAgcGFuZXNgIHdoZXJlIHRoZXkgc2hvdWxkIGJlbG9uZyBhbmQgcHV0cyBsaXN0ZW5lcnMgb24gcmVsZXZhbnQgbWFwIGV2ZW50cy4gQ2FsbGVkIG9uIFtgbWFwLmFkZExheWVyKGxheWVyKWBdKCNtYXAtYWRkbGF5ZXIpLlxuICpcbiAqIEBtZXRob2Qgb25SZW1vdmUobWFwOiBNYXApOiB0aGlzXG4gKiBTaG91bGQgY29udGFpbiBhbGwgY2xlYW4gdXAgY29kZSB0aGF0IHJlbW92ZXMgdGhlIGxheWVyJ3MgZWxlbWVudHMgZnJvbSB0aGUgRE9NIGFuZCByZW1vdmVzIGxpc3RlbmVycyBwcmV2aW91c2x5IGFkZGVkIGluIFtgb25BZGRgXSgjbGF5ZXItb25hZGQpLiBDYWxsZWQgb24gW2BtYXAucmVtb3ZlTGF5ZXIobGF5ZXIpYF0oI21hcC1yZW1vdmVsYXllcikuXG4gKlxuICogQG1ldGhvZCBnZXRFdmVudHMoKTogT2JqZWN0XG4gKiBUaGlzIG9wdGlvbmFsIG1ldGhvZCBzaG91bGQgcmV0dXJuIGFuIG9iamVjdCBsaWtlIGB7IHZpZXdyZXNldDogdGhpcy5fcmVzZXQgfWAgZm9yIFtgYWRkRXZlbnRMaXN0ZW5lcmBdKCNldmVudGVkLWFkZGV2ZW50bGlzdGVuZXIpLiBUaGUgZXZlbnQgaGFuZGxlcnMgaW4gdGhpcyBvYmplY3Qgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGFkZGVkIGFuZCByZW1vdmVkIGZyb20gdGhlIG1hcCB3aXRoIHlvdXIgbGF5ZXIuXG4gKlxuICogQG1ldGhvZCBnZXRBdHRyaWJ1dGlvbigpOiBTdHJpbmdcbiAqIFRoaXMgb3B0aW9uYWwgbWV0aG9kIHNob3VsZCByZXR1cm4gYSBzdHJpbmcgY29udGFpbmluZyBIVE1MIHRvIGJlIHNob3duIG9uIHRoZSBgQXR0cmlidXRpb24gY29udHJvbGAgd2hlbmV2ZXIgdGhlIGxheWVyIGlzIHZpc2libGUuXG4gKlxuICogQG1ldGhvZCBiZWZvcmVBZGQobWFwOiBNYXApOiB0aGlzXG4gKiBPcHRpb25hbCBtZXRob2QuIENhbGxlZCBvbiBbYG1hcC5hZGRMYXllcihsYXllcilgXSgjbWFwLWFkZGxheWVyKSwgYmVmb3JlIHRoZSBsYXllciBpcyBhZGRlZCB0byB0aGUgbWFwLCBiZWZvcmUgZXZlbnRzIGFyZSBpbml0aWFsaXplZCwgd2l0aG91dCB3YWl0aW5nIHVudGlsIHRoZSBtYXAgaXMgaW4gYSB1c2FibGUgc3RhdGUuIFVzZSBmb3IgZWFybHkgaW5pdGlhbGl6YXRpb24gb25seS5cbiAqL1xuXG5cbi8qIEBuYW1lc3BhY2UgTWFwXG4gKiBAc2VjdGlvbiBMYXllciBldmVudHNcbiAqXG4gKiBAZXZlbnQgbGF5ZXJhZGQ6IExheWVyRXZlbnRcbiAqIEZpcmVkIHdoZW4gYSBuZXcgbGF5ZXIgaXMgYWRkZWQgdG8gdGhlIG1hcC5cbiAqXG4gKiBAZXZlbnQgbGF5ZXJyZW1vdmU6IExheWVyRXZlbnRcbiAqIEZpcmVkIHdoZW4gc29tZSBsYXllciBpcyByZW1vdmVkIGZyb20gdGhlIG1hcFxuICpcbiAqIEBzZWN0aW9uIE1ldGhvZHMgZm9yIExheWVycyBhbmQgQ29udHJvbHNcbiAqL1xuTWFwLmluY2x1ZGUoe1xuXHQvLyBAbWV0aG9kIGFkZExheWVyKGxheWVyOiBMYXllcik6IHRoaXNcblx0Ly8gQWRkcyB0aGUgZ2l2ZW4gbGF5ZXIgdG8gdGhlIG1hcFxuXHRhZGRMYXllcjogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0aWYgKCFsYXllci5fbGF5ZXJBZGQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignVGhlIHByb3ZpZGVkIG9iamVjdCBpcyBub3QgYSBMYXllci4nKTtcblx0XHR9XG5cblx0XHR2YXIgaWQgPSBzdGFtcChsYXllcik7XG5cdFx0aWYgKHRoaXMuX2xheWVyc1tpZF0pIHsgcmV0dXJuIHRoaXM7IH1cblx0XHR0aGlzLl9sYXllcnNbaWRdID0gbGF5ZXI7XG5cblx0XHRsYXllci5fbWFwVG9BZGQgPSB0aGlzO1xuXG5cdFx0aWYgKGxheWVyLmJlZm9yZUFkZCkge1xuXHRcdFx0bGF5ZXIuYmVmb3JlQWRkKHRoaXMpO1xuXHRcdH1cblxuXHRcdHRoaXMud2hlblJlYWR5KGxheWVyLl9sYXllckFkZCwgbGF5ZXIpO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCByZW1vdmVMYXllcihsYXllcjogTGF5ZXIpOiB0aGlzXG5cdC8vIFJlbW92ZXMgdGhlIGdpdmVuIGxheWVyIGZyb20gdGhlIG1hcC5cblx0cmVtb3ZlTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHZhciBpZCA9IHN0YW1wKGxheWVyKTtcblxuXHRcdGlmICghdGhpcy5fbGF5ZXJzW2lkXSkgeyByZXR1cm4gdGhpczsgfVxuXG5cdFx0aWYgKHRoaXMuX2xvYWRlZCkge1xuXHRcdFx0bGF5ZXIub25SZW1vdmUodGhpcyk7XG5cdFx0fVxuXG5cdFx0aWYgKGxheWVyLmdldEF0dHJpYnV0aW9uICYmIHRoaXMuYXR0cmlidXRpb25Db250cm9sKSB7XG5cdFx0XHR0aGlzLmF0dHJpYnV0aW9uQ29udHJvbC5yZW1vdmVBdHRyaWJ1dGlvbihsYXllci5nZXRBdHRyaWJ1dGlvbigpKTtcblx0XHR9XG5cblx0XHRkZWxldGUgdGhpcy5fbGF5ZXJzW2lkXTtcblxuXHRcdGlmICh0aGlzLl9sb2FkZWQpIHtcblx0XHRcdHRoaXMuZmlyZSgnbGF5ZXJyZW1vdmUnLCB7bGF5ZXI6IGxheWVyfSk7XG5cdFx0XHRsYXllci5maXJlKCdyZW1vdmUnKTtcblx0XHR9XG5cblx0XHRsYXllci5fbWFwID0gbGF5ZXIuX21hcFRvQWRkID0gbnVsbDtcblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgaGFzTGF5ZXIobGF5ZXI6IExheWVyKTogQm9vbGVhblxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gbGF5ZXIgaXMgY3VycmVudGx5IGFkZGVkIHRvIHRoZSBtYXBcblx0aGFzTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHJldHVybiAhIWxheWVyICYmIChzdGFtcChsYXllcikgaW4gdGhpcy5fbGF5ZXJzKTtcblx0fSxcblxuXHQvKiBAbWV0aG9kIGVhY2hMYXllcihmbjogRnVuY3Rpb24sIGNvbnRleHQ/OiBPYmplY3QpOiB0aGlzXG5cdCAqIEl0ZXJhdGVzIG92ZXIgdGhlIGxheWVycyBvZiB0aGUgbWFwLCBvcHRpb25hbGx5IHNwZWNpZnlpbmcgY29udGV4dCBvZiB0aGUgaXRlcmF0b3IgZnVuY3Rpb24uXG5cdCAqIGBgYFxuXHQgKiBtYXAuZWFjaExheWVyKGZ1bmN0aW9uKGxheWVyKXtcblx0ICogICAgIGxheWVyLmJpbmRQb3B1cCgnSGVsbG8nKTtcblx0ICogfSk7XG5cdCAqIGBgYFxuXHQgKi9cblx0ZWFjaExheWVyOiBmdW5jdGlvbiAobWV0aG9kLCBjb250ZXh0KSB7XG5cdFx0Zm9yICh2YXIgaSBpbiB0aGlzLl9sYXllcnMpIHtcblx0XHRcdG1ldGhvZC5jYWxsKGNvbnRleHQsIHRoaXMuX2xheWVyc1tpXSk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdF9hZGRMYXllcnM6IGZ1bmN0aW9uIChsYXllcnMpIHtcblx0XHRsYXllcnMgPSBsYXllcnMgPyAoaXNBcnJheShsYXllcnMpID8gbGF5ZXJzIDogW2xheWVyc10pIDogW107XG5cblx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gbGF5ZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHR0aGlzLmFkZExheWVyKGxheWVyc1tpXSk7XG5cdFx0fVxuXHR9LFxuXG5cdF9hZGRab29tTGltaXQ6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdGlmIChpc05hTihsYXllci5vcHRpb25zLm1heFpvb20pIHx8ICFpc05hTihsYXllci5vcHRpb25zLm1pblpvb20pKSB7XG5cdFx0XHR0aGlzLl96b29tQm91bmRMYXllcnNbc3RhbXAobGF5ZXIpXSA9IGxheWVyO1xuXHRcdFx0dGhpcy5fdXBkYXRlWm9vbUxldmVscygpO1xuXHRcdH1cblx0fSxcblxuXHRfcmVtb3ZlWm9vbUxpbWl0OiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR2YXIgaWQgPSBzdGFtcChsYXllcik7XG5cblx0XHRpZiAodGhpcy5fem9vbUJvdW5kTGF5ZXJzW2lkXSkge1xuXHRcdFx0ZGVsZXRlIHRoaXMuX3pvb21Cb3VuZExheWVyc1tpZF07XG5cdFx0XHR0aGlzLl91cGRhdGVab29tTGV2ZWxzKCk7XG5cdFx0fVxuXHR9LFxuXG5cdF91cGRhdGVab29tTGV2ZWxzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG1pblpvb20gPSBJbmZpbml0eSxcblx0XHQgICAgbWF4Wm9vbSA9IC1JbmZpbml0eSxcblx0XHQgICAgb2xkWm9vbVNwYW4gPSB0aGlzLl9nZXRab29tU3BhbigpO1xuXG5cdFx0Zm9yICh2YXIgaSBpbiB0aGlzLl96b29tQm91bmRMYXllcnMpIHtcblx0XHRcdHZhciBvcHRpb25zID0gdGhpcy5fem9vbUJvdW5kTGF5ZXJzW2ldLm9wdGlvbnM7XG5cblx0XHRcdG1pblpvb20gPSBvcHRpb25zLm1pblpvb20gPT09IHVuZGVmaW5lZCA/IG1pblpvb20gOiBNYXRoLm1pbihtaW5ab29tLCBvcHRpb25zLm1pblpvb20pO1xuXHRcdFx0bWF4Wm9vbSA9IG9wdGlvbnMubWF4Wm9vbSA9PT0gdW5kZWZpbmVkID8gbWF4Wm9vbSA6IE1hdGgubWF4KG1heFpvb20sIG9wdGlvbnMubWF4Wm9vbSk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fbGF5ZXJzTWF4Wm9vbSA9IG1heFpvb20gPT09IC1JbmZpbml0eSA/IHVuZGVmaW5lZCA6IG1heFpvb207XG5cdFx0dGhpcy5fbGF5ZXJzTWluWm9vbSA9IG1pblpvb20gPT09IEluZmluaXR5ID8gdW5kZWZpbmVkIDogbWluWm9vbTtcblxuXHRcdC8vIEBzZWN0aW9uIE1hcCBzdGF0ZSBjaGFuZ2UgZXZlbnRzXG5cdFx0Ly8gQGV2ZW50IHpvb21sZXZlbHNjaGFuZ2U6IEV2ZW50XG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbnVtYmVyIG9mIHpvb21sZXZlbHMgb24gdGhlIG1hcCBpcyBjaGFuZ2VkIGR1ZVxuXHRcdC8vIHRvIGFkZGluZyBvciByZW1vdmluZyBhIGxheWVyLlxuXHRcdGlmIChvbGRab29tU3BhbiAhPT0gdGhpcy5fZ2V0Wm9vbVNwYW4oKSkge1xuXHRcdFx0dGhpcy5maXJlKCd6b29tbGV2ZWxzY2hhbmdlJyk7XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5tYXhab29tID09PSB1bmRlZmluZWQgJiYgdGhpcy5fbGF5ZXJzTWF4Wm9vbSAmJiB0aGlzLmdldFpvb20oKSA+IHRoaXMuX2xheWVyc01heFpvb20pIHtcblx0XHRcdHRoaXMuc2V0Wm9vbSh0aGlzLl9sYXllcnNNYXhab29tKTtcblx0XHR9XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5taW5ab29tID09PSB1bmRlZmluZWQgJiYgdGhpcy5fbGF5ZXJzTWluWm9vbSAmJiB0aGlzLmdldFpvb20oKSA8IHRoaXMuX2xheWVyc01pblpvb20pIHtcblx0XHRcdHRoaXMuc2V0Wm9vbSh0aGlzLl9sYXllcnNNaW5ab29tKTtcblx0XHR9XG5cdH1cbn0pO1xuXG4vKlxyXG4gKiBAY2xhc3MgTGF5ZXJHcm91cFxyXG4gKiBAYWthIEwuTGF5ZXJHcm91cFxyXG4gKiBAaW5oZXJpdHMgTGF5ZXJcclxuICpcclxuICogVXNlZCB0byBncm91cCBzZXZlcmFsIGxheWVycyBhbmQgaGFuZGxlIHRoZW0gYXMgb25lLiBJZiB5b3UgYWRkIGl0IHRvIHRoZSBtYXAsXHJcbiAqIGFueSBsYXllcnMgYWRkZWQgb3IgcmVtb3ZlZCBmcm9tIHRoZSBncm91cCB3aWxsIGJlIGFkZGVkL3JlbW92ZWQgb24gdGhlIG1hcCBhc1xyXG4gKiB3ZWxsLiBFeHRlbmRzIGBMYXllcmAuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIEwubGF5ZXJHcm91cChbbWFya2VyMSwgbWFya2VyMl0pXHJcbiAqIFx0LmFkZExheWVyKHBvbHlsaW5lKVxyXG4gKiBcdC5hZGRUbyhtYXApO1xyXG4gKiBgYGBcclxuICovXHJcblxyXG52YXIgTGF5ZXJHcm91cCA9IExheWVyLmV4dGVuZCh7XHJcblxyXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChsYXllcnMsIG9wdGlvbnMpIHtcclxuXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblxyXG5cdFx0dGhpcy5fbGF5ZXJzID0ge307XHJcblxyXG5cdFx0dmFyIGksIGxlbjtcclxuXHJcblx0XHRpZiAobGF5ZXJzKSB7XHJcblx0XHRcdGZvciAoaSA9IDAsIGxlbiA9IGxheWVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0XHRcdHRoaXMuYWRkTGF5ZXIobGF5ZXJzW2ldKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgYWRkTGF5ZXIobGF5ZXI6IExheWVyKTogdGhpc1xyXG5cdC8vIEFkZHMgdGhlIGdpdmVuIGxheWVyIHRvIHRoZSBncm91cC5cclxuXHRhZGRMYXllcjogZnVuY3Rpb24gKGxheWVyKSB7XHJcblx0XHR2YXIgaWQgPSB0aGlzLmdldExheWVySWQobGF5ZXIpO1xyXG5cclxuXHRcdHRoaXMuX2xheWVyc1tpZF0gPSBsYXllcjtcclxuXHJcblx0XHRpZiAodGhpcy5fbWFwKSB7XHJcblx0XHRcdHRoaXMuX21hcC5hZGRMYXllcihsYXllcik7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCByZW1vdmVMYXllcihsYXllcjogTGF5ZXIpOiB0aGlzXHJcblx0Ly8gUmVtb3ZlcyB0aGUgZ2l2ZW4gbGF5ZXIgZnJvbSB0aGUgZ3JvdXAuXHJcblx0Ly8gQGFsdGVybmF0aXZlXHJcblx0Ly8gQG1ldGhvZCByZW1vdmVMYXllcihpZDogTnVtYmVyKTogdGhpc1xyXG5cdC8vIFJlbW92ZXMgdGhlIGxheWVyIHdpdGggdGhlIGdpdmVuIGludGVybmFsIElEIGZyb20gdGhlIGdyb3VwLlxyXG5cdHJlbW92ZUxheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHRcdHZhciBpZCA9IGxheWVyIGluIHRoaXMuX2xheWVycyA/IGxheWVyIDogdGhpcy5nZXRMYXllcklkKGxheWVyKTtcclxuXHJcblx0XHRpZiAodGhpcy5fbWFwICYmIHRoaXMuX2xheWVyc1tpZF0pIHtcclxuXHRcdFx0dGhpcy5fbWFwLnJlbW92ZUxheWVyKHRoaXMuX2xheWVyc1tpZF0pO1xyXG5cdFx0fVxyXG5cclxuXHRcdGRlbGV0ZSB0aGlzLl9sYXllcnNbaWRdO1xyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgaGFzTGF5ZXIobGF5ZXI6IExheWVyKTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiBsYXllciBpcyBjdXJyZW50bHkgYWRkZWQgdG8gdGhlIGdyb3VwLlxyXG5cdC8vIEBhbHRlcm5hdGl2ZVxyXG5cdC8vIEBtZXRob2QgaGFzTGF5ZXIoaWQ6IE51bWJlcik6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gaW50ZXJuYWwgSUQgaXMgY3VycmVudGx5IGFkZGVkIHRvIHRoZSBncm91cC5cclxuXHRoYXNMYXllcjogZnVuY3Rpb24gKGxheWVyKSB7XHJcblx0XHRyZXR1cm4gISFsYXllciAmJiAobGF5ZXIgaW4gdGhpcy5fbGF5ZXJzIHx8IHRoaXMuZ2V0TGF5ZXJJZChsYXllcikgaW4gdGhpcy5fbGF5ZXJzKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGNsZWFyTGF5ZXJzKCk6IHRoaXNcclxuXHQvLyBSZW1vdmVzIGFsbCB0aGUgbGF5ZXJzIGZyb20gdGhlIGdyb3VwLlxyXG5cdGNsZWFyTGF5ZXJzOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5lYWNoTGF5ZXIodGhpcy5yZW1vdmVMYXllciwgdGhpcyk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBpbnZva2UobWV0aG9kTmFtZTogU3RyaW5nLCDigKYpOiB0aGlzXHJcblx0Ly8gQ2FsbHMgYG1ldGhvZE5hbWVgIG9uIGV2ZXJ5IGxheWVyIGNvbnRhaW5lZCBpbiB0aGlzIGdyb3VwLCBwYXNzaW5nIGFueVxyXG5cdC8vIGFkZGl0aW9uYWwgcGFyYW1ldGVycy4gSGFzIG5vIGVmZmVjdCBpZiB0aGUgbGF5ZXJzIGNvbnRhaW5lZCBkbyBub3RcclxuXHQvLyBpbXBsZW1lbnQgYG1ldGhvZE5hbWVgLlxyXG5cdGludm9rZTogZnVuY3Rpb24gKG1ldGhvZE5hbWUpIHtcclxuXHRcdHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcclxuXHRcdCAgICBpLCBsYXllcjtcclxuXHJcblx0XHRmb3IgKGkgaW4gdGhpcy5fbGF5ZXJzKSB7XHJcblx0XHRcdGxheWVyID0gdGhpcy5fbGF5ZXJzW2ldO1xyXG5cclxuXHRcdFx0aWYgKGxheWVyW21ldGhvZE5hbWVdKSB7XHJcblx0XHRcdFx0bGF5ZXJbbWV0aG9kTmFtZV0uYXBwbHkobGF5ZXIsIGFyZ3MpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuXHRcdHRoaXMuZWFjaExheWVyKG1hcC5hZGRMYXllciwgbWFwKTtcclxuXHR9LFxyXG5cclxuXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0dGhpcy5lYWNoTGF5ZXIobWFwLnJlbW92ZUxheWVyLCBtYXApO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZWFjaExheWVyKGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuXHQvLyBJdGVyYXRlcyBvdmVyIHRoZSBsYXllcnMgb2YgdGhlIGdyb3VwLCBvcHRpb25hbGx5IHNwZWNpZnlpbmcgY29udGV4dCBvZiB0aGUgaXRlcmF0b3IgZnVuY3Rpb24uXHJcblx0Ly8gYGBganNcclxuXHQvLyBncm91cC5lYWNoTGF5ZXIoZnVuY3Rpb24gKGxheWVyKSB7XHJcblx0Ly8gXHRsYXllci5iaW5kUG9wdXAoJ0hlbGxvJyk7XHJcblx0Ly8gfSk7XHJcblx0Ly8gYGBgXHJcblx0ZWFjaExheWVyOiBmdW5jdGlvbiAobWV0aG9kLCBjb250ZXh0KSB7XHJcblx0XHRmb3IgKHZhciBpIGluIHRoaXMuX2xheWVycykge1xyXG5cdFx0XHRtZXRob2QuY2FsbChjb250ZXh0LCB0aGlzLl9sYXllcnNbaV0pO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRMYXllcihpZDogTnVtYmVyKTogTGF5ZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBsYXllciB3aXRoIHRoZSBnaXZlbiBpbnRlcm5hbCBJRC5cclxuXHRnZXRMYXllcjogZnVuY3Rpb24gKGlkKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fbGF5ZXJzW2lkXTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldExheWVycygpOiBMYXllcltdXHJcblx0Ly8gUmV0dXJucyBhbiBhcnJheSBvZiBhbGwgdGhlIGxheWVycyBhZGRlZCB0byB0aGUgZ3JvdXAuXHJcblx0Z2V0TGF5ZXJzOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgbGF5ZXJzID0gW107XHJcblx0XHR0aGlzLmVhY2hMYXllcihsYXllcnMucHVzaCwgbGF5ZXJzKTtcclxuXHRcdHJldHVybiBsYXllcnM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRaSW5kZXgoekluZGV4OiBOdW1iZXIpOiB0aGlzXHJcblx0Ly8gQ2FsbHMgYHNldFpJbmRleGAgb24gZXZlcnkgbGF5ZXIgY29udGFpbmVkIGluIHRoaXMgZ3JvdXAsIHBhc3NpbmcgdGhlIHotaW5kZXguXHJcblx0c2V0WkluZGV4OiBmdW5jdGlvbiAoekluZGV4KSB7XHJcblx0XHRyZXR1cm4gdGhpcy5pbnZva2UoJ3NldFpJbmRleCcsIHpJbmRleCk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRMYXllcklkKGxheWVyOiBMYXllcik6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIGludGVybmFsIElEIGZvciBhIGxheWVyXHJcblx0Z2V0TGF5ZXJJZDogZnVuY3Rpb24gKGxheWVyKSB7XHJcblx0XHRyZXR1cm4gc3RhbXAobGF5ZXIpO1xyXG5cdH1cclxufSk7XHJcblxyXG5cclxuLy8gQGZhY3RvcnkgTC5sYXllckdyb3VwKGxheWVycz86IExheWVyW10sIG9wdGlvbnM/OiBPYmplY3QpXHJcbi8vIENyZWF0ZSBhIGxheWVyIGdyb3VwLCBvcHRpb25hbGx5IGdpdmVuIGFuIGluaXRpYWwgc2V0IG9mIGxheWVycyBhbmQgYW4gYG9wdGlvbnNgIG9iamVjdC5cclxudmFyIGxheWVyR3JvdXAgPSBmdW5jdGlvbiAobGF5ZXJzLCBvcHRpb25zKSB7XHJcblx0cmV0dXJuIG5ldyBMYXllckdyb3VwKGxheWVycywgb3B0aW9ucyk7XHJcbn07XG5cbi8qXHJcbiAqIEBjbGFzcyBGZWF0dXJlR3JvdXBcclxuICogQGFrYSBMLkZlYXR1cmVHcm91cFxyXG4gKiBAaW5oZXJpdHMgTGF5ZXJHcm91cFxyXG4gKlxyXG4gKiBFeHRlbmRlZCBgTGF5ZXJHcm91cGAgdGhhdCBtYWtlcyBpdCBlYXNpZXIgdG8gZG8gdGhlIHNhbWUgdGhpbmcgdG8gYWxsIGl0cyBtZW1iZXIgbGF5ZXJzOlxyXG4gKiAgKiBbYGJpbmRQb3B1cGBdKCNsYXllci1iaW5kcG9wdXApIGJpbmRzIGEgcG9wdXAgdG8gYWxsIG9mIHRoZSBsYXllcnMgYXQgb25jZSAobGlrZXdpc2Ugd2l0aCBbYGJpbmRUb29sdGlwYF0oI2xheWVyLWJpbmR0b29sdGlwKSlcclxuICogICogRXZlbnRzIGFyZSBwcm9wYWdhdGVkIHRvIHRoZSBgRmVhdHVyZUdyb3VwYCwgc28gaWYgdGhlIGdyb3VwIGhhcyBhbiBldmVudFxyXG4gKiBoYW5kbGVyLCBpdCB3aWxsIGhhbmRsZSBldmVudHMgZnJvbSBhbnkgb2YgdGhlIGxheWVycy4gVGhpcyBpbmNsdWRlcyBtb3VzZSBldmVudHNcclxuICogYW5kIGN1c3RvbSBldmVudHMuXHJcbiAqICAqIEhhcyBgbGF5ZXJhZGRgIGFuZCBgbGF5ZXJyZW1vdmVgIGV2ZW50c1xyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiBMLmZlYXR1cmVHcm91cChbbWFya2VyMSwgbWFya2VyMiwgcG9seWxpbmVdKVxyXG4gKiBcdC5iaW5kUG9wdXAoJ0hlbGxvIHdvcmxkIScpXHJcbiAqIFx0Lm9uKCdjbGljaycsIGZ1bmN0aW9uKCkgeyBhbGVydCgnQ2xpY2tlZCBvbiBhIG1lbWJlciBvZiB0aGUgZ3JvdXAhJyk7IH0pXHJcbiAqIFx0LmFkZFRvKG1hcCk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBGZWF0dXJlR3JvdXAgPSBMYXllckdyb3VwLmV4dGVuZCh7XHJcblxyXG5cdGFkZExheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHRcdGlmICh0aGlzLmhhc0xheWVyKGxheWVyKSkge1xyXG5cdFx0XHRyZXR1cm4gdGhpcztcclxuXHRcdH1cclxuXHJcblx0XHRsYXllci5hZGRFdmVudFBhcmVudCh0aGlzKTtcclxuXHJcblx0XHRMYXllckdyb3VwLnByb3RvdHlwZS5hZGRMYXllci5jYWxsKHRoaXMsIGxheWVyKTtcclxuXHJcblx0XHQvLyBAZXZlbnQgbGF5ZXJhZGQ6IExheWVyRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gYSBsYXllciBpcyBhZGRlZCB0byB0aGlzIGBGZWF0dXJlR3JvdXBgXHJcblx0XHRyZXR1cm4gdGhpcy5maXJlKCdsYXllcmFkZCcsIHtsYXllcjogbGF5ZXJ9KTtcclxuXHR9LFxyXG5cclxuXHRyZW1vdmVMYXllcjogZnVuY3Rpb24gKGxheWVyKSB7XHJcblx0XHRpZiAoIXRoaXMuaGFzTGF5ZXIobGF5ZXIpKSB7XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fVxyXG5cdFx0aWYgKGxheWVyIGluIHRoaXMuX2xheWVycykge1xyXG5cdFx0XHRsYXllciA9IHRoaXMuX2xheWVyc1tsYXllcl07XHJcblx0XHR9XHJcblxyXG5cdFx0bGF5ZXIucmVtb3ZlRXZlbnRQYXJlbnQodGhpcyk7XHJcblxyXG5cdFx0TGF5ZXJHcm91cC5wcm90b3R5cGUucmVtb3ZlTGF5ZXIuY2FsbCh0aGlzLCBsYXllcik7XHJcblxyXG5cdFx0Ly8gQGV2ZW50IGxheWVycmVtb3ZlOiBMYXllckV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIGEgbGF5ZXIgaXMgcmVtb3ZlZCBmcm9tIHRoaXMgYEZlYXR1cmVHcm91cGBcclxuXHRcdHJldHVybiB0aGlzLmZpcmUoJ2xheWVycmVtb3ZlJywge2xheWVyOiBsYXllcn0pO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0U3R5bGUoc3R5bGU6IFBhdGggb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBTZXRzIHRoZSBnaXZlbiBwYXRoIG9wdGlvbnMgdG8gZWFjaCBsYXllciBvZiB0aGUgZ3JvdXAgdGhhdCBoYXMgYSBgc2V0U3R5bGVgIG1ldGhvZC5cclxuXHRzZXRTdHlsZTogZnVuY3Rpb24gKHN0eWxlKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5pbnZva2UoJ3NldFN0eWxlJywgc3R5bGUpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgYnJpbmdUb0Zyb250KCk6IHRoaXNcclxuXHQvLyBCcmluZ3MgdGhlIGxheWVyIGdyb3VwIHRvIHRoZSB0b3Agb2YgYWxsIG90aGVyIGxheWVyc1xyXG5cdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuaW52b2tlKCdicmluZ1RvRnJvbnQnKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGJyaW5nVG9CYWNrKCk6IHRoaXNcclxuXHQvLyBCcmluZ3MgdGhlIGxheWVyIGdyb3VwIHRvIHRoZSBiYWNrIG9mIGFsbCBvdGhlciBsYXllcnNcclxuXHRicmluZ1RvQmFjazogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuaW52b2tlKCdicmluZ1RvQmFjaycpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0Qm91bmRzKCk6IExhdExuZ0JvdW5kc1xyXG5cdC8vIFJldHVybnMgdGhlIExhdExuZ0JvdW5kcyBvZiB0aGUgRmVhdHVyZSBHcm91cCAoY3JlYXRlZCBmcm9tIGJvdW5kcyBhbmQgY29vcmRpbmF0ZXMgb2YgaXRzIGNoaWxkcmVuKS5cclxuXHRnZXRCb3VuZHM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBib3VuZHMgPSBuZXcgTGF0TG5nQm91bmRzKCk7XHJcblxyXG5cdFx0Zm9yICh2YXIgaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XHJcblx0XHRcdHZhciBsYXllciA9IHRoaXMuX2xheWVyc1tpZF07XHJcblx0XHRcdGJvdW5kcy5leHRlbmQobGF5ZXIuZ2V0Qm91bmRzID8gbGF5ZXIuZ2V0Qm91bmRzKCkgOiBsYXllci5nZXRMYXRMbmcoKSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gYm91bmRzO1xyXG5cdH1cclxufSk7XHJcblxyXG4vLyBAZmFjdG9yeSBMLmZlYXR1cmVHcm91cChsYXllcnM6IExheWVyW10pXHJcbi8vIENyZWF0ZSBhIGZlYXR1cmUgZ3JvdXAsIG9wdGlvbmFsbHkgZ2l2ZW4gYW4gaW5pdGlhbCBzZXQgb2YgbGF5ZXJzLlxyXG52YXIgZmVhdHVyZUdyb3VwID0gZnVuY3Rpb24gKGxheWVycykge1xyXG5cdHJldHVybiBuZXcgRmVhdHVyZUdyb3VwKGxheWVycyk7XHJcbn07XG5cbi8qXHJcbiAqIEBjbGFzcyBJY29uXHJcbiAqIEBha2EgTC5JY29uXHJcbiAqXHJcbiAqIFJlcHJlc2VudHMgYW4gaWNvbiB0byBwcm92aWRlIHdoZW4gY3JlYXRpbmcgYSBtYXJrZXIuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBteUljb24gPSBMLmljb24oe1xyXG4gKiAgICAgaWNvblVybDogJ215LWljb24ucG5nJyxcclxuICogICAgIGljb25SZXRpbmFVcmw6ICdteS1pY29uQDJ4LnBuZycsXHJcbiAqICAgICBpY29uU2l6ZTogWzM4LCA5NV0sXHJcbiAqICAgICBpY29uQW5jaG9yOiBbMjIsIDk0XSxcclxuICogICAgIHBvcHVwQW5jaG9yOiBbLTMsIC03Nl0sXHJcbiAqICAgICBzaGFkb3dVcmw6ICdteS1pY29uLXNoYWRvdy5wbmcnLFxyXG4gKiAgICAgc2hhZG93UmV0aW5hVXJsOiAnbXktaWNvbi1zaGFkb3dAMngucG5nJyxcclxuICogICAgIHNoYWRvd1NpemU6IFs2OCwgOTVdLFxyXG4gKiAgICAgc2hhZG93QW5jaG9yOiBbMjIsIDk0XVxyXG4gKiB9KTtcclxuICpcclxuICogTC5tYXJrZXIoWzUwLjUwNSwgMzAuNTddLCB7aWNvbjogbXlJY29ufSkuYWRkVG8obWFwKTtcclxuICogYGBgXHJcbiAqXHJcbiAqIGBMLkljb24uRGVmYXVsdGAgZXh0ZW5kcyBgTC5JY29uYCBhbmQgaXMgdGhlIGJsdWUgaWNvbiBMZWFmbGV0IHVzZXMgZm9yIG1hcmtlcnMgYnkgZGVmYXVsdC5cclxuICpcclxuICovXHJcblxyXG52YXIgSWNvbiA9IENsYXNzLmV4dGVuZCh7XHJcblxyXG5cdC8qIEBzZWN0aW9uXHJcblx0ICogQGFrYSBJY29uIG9wdGlvbnNcclxuXHQgKlxyXG5cdCAqIEBvcHRpb24gaWNvblVybDogU3RyaW5nID0gbnVsbFxyXG5cdCAqICoqKHJlcXVpcmVkKSoqIFRoZSBVUkwgdG8gdGhlIGljb24gaW1hZ2UgKGFic29sdXRlIG9yIHJlbGF0aXZlIHRvIHlvdXIgc2NyaXB0IHBhdGgpLlxyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBpY29uUmV0aW5hVXJsOiBTdHJpbmcgPSBudWxsXHJcblx0ICogVGhlIFVSTCB0byBhIHJldGluYSBzaXplZCB2ZXJzaW9uIG9mIHRoZSBpY29uIGltYWdlIChhYnNvbHV0ZSBvciByZWxhdGl2ZSB0byB5b3VyXHJcblx0ICogc2NyaXB0IHBhdGgpLiBVc2VkIGZvciBSZXRpbmEgc2NyZWVuIGRldmljZXMuXHJcblx0ICpcclxuXHQgKiBAb3B0aW9uIGljb25TaXplOiBQb2ludCA9IG51bGxcclxuXHQgKiBTaXplIG9mIHRoZSBpY29uIGltYWdlIGluIHBpeGVscy5cclxuXHQgKlxyXG5cdCAqIEBvcHRpb24gaWNvbkFuY2hvcjogUG9pbnQgPSBudWxsXHJcblx0ICogVGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBcInRpcFwiIG9mIHRoZSBpY29uIChyZWxhdGl2ZSB0byBpdHMgdG9wIGxlZnQgY29ybmVyKS4gVGhlIGljb25cclxuXHQgKiB3aWxsIGJlIGFsaWduZWQgc28gdGhhdCB0aGlzIHBvaW50IGlzIGF0IHRoZSBtYXJrZXIncyBnZW9ncmFwaGljYWwgbG9jYXRpb24uIENlbnRlcmVkXHJcblx0ICogYnkgZGVmYXVsdCBpZiBzaXplIGlzIHNwZWNpZmllZCwgYWxzbyBjYW4gYmUgc2V0IGluIENTUyB3aXRoIG5lZ2F0aXZlIG1hcmdpbnMuXHJcblx0ICpcclxuXHQgKiBAb3B0aW9uIHBvcHVwQW5jaG9yOiBQb2ludCA9IFswLCAwXVxyXG5cdCAqIFRoZSBjb29yZGluYXRlcyBvZiB0aGUgcG9pbnQgZnJvbSB3aGljaCBwb3B1cHMgd2lsbCBcIm9wZW5cIiwgcmVsYXRpdmUgdG8gdGhlIGljb24gYW5jaG9yLlxyXG5cdCAqXHJcblx0ICogQG9wdGlvbiB0b29sdGlwQW5jaG9yOiBQb2ludCA9IFswLCAwXVxyXG5cdCAqIFRoZSBjb29yZGluYXRlcyBvZiB0aGUgcG9pbnQgZnJvbSB3aGljaCB0b29sdGlwcyB3aWxsIFwib3BlblwiLCByZWxhdGl2ZSB0byB0aGUgaWNvbiBhbmNob3IuXHJcblx0ICpcclxuXHQgKiBAb3B0aW9uIHNoYWRvd1VybDogU3RyaW5nID0gbnVsbFxyXG5cdCAqIFRoZSBVUkwgdG8gdGhlIGljb24gc2hhZG93IGltYWdlLiBJZiBub3Qgc3BlY2lmaWVkLCBubyBzaGFkb3cgaW1hZ2Ugd2lsbCBiZSBjcmVhdGVkLlxyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBzaGFkb3dSZXRpbmFVcmw6IFN0cmluZyA9IG51bGxcclxuXHQgKlxyXG5cdCAqIEBvcHRpb24gc2hhZG93U2l6ZTogUG9pbnQgPSBudWxsXHJcblx0ICogU2l6ZSBvZiB0aGUgc2hhZG93IGltYWdlIGluIHBpeGVscy5cclxuXHQgKlxyXG5cdCAqIEBvcHRpb24gc2hhZG93QW5jaG9yOiBQb2ludCA9IG51bGxcclxuXHQgKiBUaGUgY29vcmRpbmF0ZXMgb2YgdGhlIFwidGlwXCIgb2YgdGhlIHNoYWRvdyAocmVsYXRpdmUgdG8gaXRzIHRvcCBsZWZ0IGNvcm5lcikgKHRoZSBzYW1lXHJcblx0ICogYXMgaWNvbkFuY2hvciBpZiBub3Qgc3BlY2lmaWVkKS5cclxuXHQgKlxyXG5cdCAqIEBvcHRpb24gY2xhc3NOYW1lOiBTdHJpbmcgPSAnJ1xyXG5cdCAqIEEgY3VzdG9tIGNsYXNzIG5hbWUgdG8gYXNzaWduIHRvIGJvdGggaWNvbiBhbmQgc2hhZG93IGltYWdlcy4gRW1wdHkgYnkgZGVmYXVsdC5cclxuXHQgKi9cclxuXHJcblx0b3B0aW9uczoge1xyXG5cdFx0cG9wdXBBbmNob3I6IFswLCAwXSxcclxuXHRcdHRvb2x0aXBBbmNob3I6IFswLCAwXVxyXG5cdH0sXHJcblxyXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY3JlYXRlSWNvbihvbGRJY29uPzogSFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudFxyXG5cdC8vIENhbGxlZCBpbnRlcm5hbGx5IHdoZW4gdGhlIGljb24gaGFzIHRvIGJlIHNob3duLCByZXR1cm5zIGEgYDxpbWc+YCBIVE1MIGVsZW1lbnRcclxuXHQvLyBzdHlsZWQgYWNjb3JkaW5nIHRvIHRoZSBvcHRpb25zLlxyXG5cdGNyZWF0ZUljb246IGZ1bmN0aW9uIChvbGRJY29uKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fY3JlYXRlSWNvbignaWNvbicsIG9sZEljb24pO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY3JlYXRlU2hhZG93KG9sZEljb24/OiBIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50XHJcblx0Ly8gQXMgYGNyZWF0ZUljb25gLCBidXQgZm9yIHRoZSBzaGFkb3cgYmVuZWF0aCBpdC5cclxuXHRjcmVhdGVTaGFkb3c6IGZ1bmN0aW9uIChvbGRJY29uKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fY3JlYXRlSWNvbignc2hhZG93Jywgb2xkSWNvbik7XHJcblx0fSxcclxuXHJcblx0X2NyZWF0ZUljb246IGZ1bmN0aW9uIChuYW1lLCBvbGRJY29uKSB7XHJcblx0XHR2YXIgc3JjID0gdGhpcy5fZ2V0SWNvblVybChuYW1lKTtcclxuXHJcblx0XHRpZiAoIXNyYykge1xyXG5cdFx0XHRpZiAobmFtZSA9PT0gJ2ljb24nKSB7XHJcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCdpY29uVXJsIG5vdCBzZXQgaW4gSWNvbiBvcHRpb25zIChzZWUgdGhlIGRvY3MpLicpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiBudWxsO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBpbWcgPSB0aGlzLl9jcmVhdGVJbWcoc3JjLCBvbGRJY29uICYmIG9sZEljb24udGFnTmFtZSA9PT0gJ0lNRycgPyBvbGRJY29uIDogbnVsbCk7XHJcblx0XHR0aGlzLl9zZXRJY29uU3R5bGVzKGltZywgbmFtZSk7XHJcblxyXG5cdFx0cmV0dXJuIGltZztcclxuXHR9LFxyXG5cclxuXHRfc2V0SWNvblN0eWxlczogZnVuY3Rpb24gKGltZywgbmFtZSkge1xyXG5cdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XHJcblx0XHR2YXIgc2l6ZU9wdGlvbiA9IG9wdGlvbnNbbmFtZSArICdTaXplJ107XHJcblxyXG5cdFx0aWYgKHR5cGVvZiBzaXplT3B0aW9uID09PSAnbnVtYmVyJykge1xyXG5cdFx0XHRzaXplT3B0aW9uID0gW3NpemVPcHRpb24sIHNpemVPcHRpb25dO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBzaXplID0gdG9Qb2ludChzaXplT3B0aW9uKSxcclxuXHRcdCAgICBhbmNob3IgPSB0b1BvaW50KG5hbWUgPT09ICdzaGFkb3cnICYmIG9wdGlvbnMuc2hhZG93QW5jaG9yIHx8IG9wdGlvbnMuaWNvbkFuY2hvciB8fFxyXG5cdFx0ICAgICAgICAgICAgc2l6ZSAmJiBzaXplLmRpdmlkZUJ5KDIsIHRydWUpKTtcclxuXHJcblx0XHRpbWcuY2xhc3NOYW1lID0gJ2xlYWZsZXQtbWFya2VyLScgKyBuYW1lICsgJyAnICsgKG9wdGlvbnMuY2xhc3NOYW1lIHx8ICcnKTtcclxuXHJcblx0XHRpZiAoYW5jaG9yKSB7XHJcblx0XHRcdGltZy5zdHlsZS5tYXJnaW5MZWZ0ID0gKC1hbmNob3IueCkgKyAncHgnO1xyXG5cdFx0XHRpbWcuc3R5bGUubWFyZ2luVG9wICA9ICgtYW5jaG9yLnkpICsgJ3B4JztcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoc2l6ZSkge1xyXG5cdFx0XHRpbWcuc3R5bGUud2lkdGggID0gc2l6ZS54ICsgJ3B4JztcclxuXHRcdFx0aW1nLnN0eWxlLmhlaWdodCA9IHNpemUueSArICdweCc7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X2NyZWF0ZUltZzogZnVuY3Rpb24gKHNyYywgZWwpIHtcclxuXHRcdGVsID0gZWwgfHwgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyk7XHJcblx0XHRlbC5zcmMgPSBzcmM7XHJcblx0XHRyZXR1cm4gZWw7XHJcblx0fSxcclxuXHJcblx0X2dldEljb25Vcmw6IGZ1bmN0aW9uIChuYW1lKSB7XHJcblx0XHRyZXR1cm4gcmV0aW5hICYmIHRoaXMub3B0aW9uc1tuYW1lICsgJ1JldGluYVVybCddIHx8IHRoaXMub3B0aW9uc1tuYW1lICsgJ1VybCddO1xyXG5cdH1cclxufSk7XHJcblxyXG5cclxuLy8gQGZhY3RvcnkgTC5pY29uKG9wdGlvbnM6IEljb24gb3B0aW9ucylcclxuLy8gQ3JlYXRlcyBhbiBpY29uIGluc3RhbmNlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXHJcbmZ1bmN0aW9uIGljb24ob3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgSWNvbihvcHRpb25zKTtcclxufVxuXG4vKlxuICogQG1pbmljbGFzcyBJY29uLkRlZmF1bHQgKEljb24pXG4gKiBAYWthIEwuSWNvbi5EZWZhdWx0XG4gKiBAc2VjdGlvblxuICpcbiAqIEEgdHJpdmlhbCBzdWJjbGFzcyBvZiBgSWNvbmAsIHJlcHJlc2VudHMgdGhlIGljb24gdG8gdXNlIGluIGBNYXJrZXJgcyB3aGVuXG4gKiBubyBpY29uIGlzIHNwZWNpZmllZC4gUG9pbnRzIHRvIHRoZSBibHVlIG1hcmtlciBpbWFnZSBkaXN0cmlidXRlZCB3aXRoIExlYWZsZXRcbiAqIHJlbGVhc2VzLlxuICpcbiAqIEluIG9yZGVyIHRvIGN1c3RvbWl6ZSB0aGUgZGVmYXVsdCBpY29uLCBqdXN0IGNoYW5nZSB0aGUgcHJvcGVydGllcyBvZiBgTC5JY29uLkRlZmF1bHQucHJvdG90eXBlLm9wdGlvbnNgXG4gKiAod2hpY2ggaXMgYSBzZXQgb2YgYEljb24gb3B0aW9uc2ApLlxuICpcbiAqIElmIHlvdSB3YW50IHRvIF9jb21wbGV0ZWx5XyByZXBsYWNlIHRoZSBkZWZhdWx0IGljb24sIG92ZXJyaWRlIHRoZVxuICogYEwuTWFya2VyLnByb3RvdHlwZS5vcHRpb25zLmljb25gIHdpdGggeW91ciBvd24gaWNvbiBpbnN0ZWFkLlxuICovXG5cbnZhciBJY29uRGVmYXVsdCA9IEljb24uZXh0ZW5kKHtcblxuXHRvcHRpb25zOiB7XG5cdFx0aWNvblVybDogICAgICAgJ21hcmtlci1pY29uLnBuZycsXG5cdFx0aWNvblJldGluYVVybDogJ21hcmtlci1pY29uLTJ4LnBuZycsXG5cdFx0c2hhZG93VXJsOiAgICAgJ21hcmtlci1zaGFkb3cucG5nJyxcblx0XHRpY29uU2l6ZTogICAgWzI1LCA0MV0sXG5cdFx0aWNvbkFuY2hvcjogIFsxMiwgNDFdLFxuXHRcdHBvcHVwQW5jaG9yOiBbMSwgLTM0XSxcblx0XHR0b29sdGlwQW5jaG9yOiBbMTYsIC0yOF0sXG5cdFx0c2hhZG93U2l6ZTogIFs0MSwgNDFdXG5cdH0sXG5cblx0X2dldEljb25Vcmw6IGZ1bmN0aW9uIChuYW1lKSB7XG5cdFx0aWYgKCFJY29uRGVmYXVsdC5pbWFnZVBhdGgpIHtcdC8vIERlcHJlY2F0ZWQsIGJhY2t3YXJkcy1jb21wYXRpYmlsaXR5IG9ubHlcblx0XHRcdEljb25EZWZhdWx0LmltYWdlUGF0aCA9IHRoaXMuX2RldGVjdEljb25QYXRoKCk7XG5cdFx0fVxuXG5cdFx0Ly8gQG9wdGlvbiBpbWFnZVBhdGg6IFN0cmluZ1xuXHRcdC8vIGBJY29uLkRlZmF1bHRgIHdpbGwgdHJ5IHRvIGF1dG8tZGV0ZWN0IHRoZSBsb2NhdGlvbiBvZiB0aGVcblx0XHQvLyBibHVlIGljb24gaW1hZ2VzLiBJZiB5b3UgYXJlIHBsYWNpbmcgdGhlc2UgaW1hZ2VzIGluIGEgbm9uLXN0YW5kYXJkXG5cdFx0Ly8gd2F5LCBzZXQgdGhpcyBvcHRpb24gdG8gcG9pbnQgdG8gdGhlIHJpZ2h0IHBhdGguXG5cdFx0cmV0dXJuICh0aGlzLm9wdGlvbnMuaW1hZ2VQYXRoIHx8IEljb25EZWZhdWx0LmltYWdlUGF0aCkgKyBJY29uLnByb3RvdHlwZS5fZ2V0SWNvblVybC5jYWxsKHRoaXMsIG5hbWUpO1xuXHR9LFxuXG5cdF9kZXRlY3RJY29uUGF0aDogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBlbCA9IGNyZWF0ZSQxKCdkaXYnLCAgJ2xlYWZsZXQtZGVmYXVsdC1pY29uLXBhdGgnLCBkb2N1bWVudC5ib2R5KTtcblx0XHR2YXIgcGF0aCA9IGdldFN0eWxlKGVsLCAnYmFja2dyb3VuZC1pbWFnZScpIHx8XG5cdFx0ICAgICAgICAgICBnZXRTdHlsZShlbCwgJ2JhY2tncm91bmRJbWFnZScpO1x0Ly8gSUU4XG5cblx0XHRkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGVsKTtcblxuXHRcdGlmIChwYXRoID09PSBudWxsIHx8IHBhdGguaW5kZXhPZigndXJsJykgIT09IDApIHtcblx0XHRcdHBhdGggPSAnJztcblx0XHR9IGVsc2Uge1xuXHRcdFx0cGF0aCA9IHBhdGgucmVwbGFjZSgvXnVybFxcKFtcIiddPy8sICcnKS5yZXBsYWNlKC9tYXJrZXItaWNvblxcLnBuZ1tcIiddP1xcKSQvLCAnJyk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHBhdGg7XG5cdH1cbn0pO1xuXG4vKlxuICogTC5IYW5kbGVyLk1hcmtlckRyYWcgaXMgdXNlZCBpbnRlcm5hbGx5IGJ5IEwuTWFya2VyIHRvIG1ha2UgdGhlIG1hcmtlcnMgZHJhZ2dhYmxlLlxuICovXG5cblxuLyogQG5hbWVzcGFjZSBNYXJrZXJcbiAqIEBzZWN0aW9uIEludGVyYWN0aW9uIGhhbmRsZXJzXG4gKlxuICogSW50ZXJhY3Rpb24gaGFuZGxlcnMgYXJlIHByb3BlcnRpZXMgb2YgYSBtYXJrZXIgaW5zdGFuY2UgdGhhdCBhbGxvdyB5b3UgdG8gY29udHJvbCBpbnRlcmFjdGlvbiBiZWhhdmlvciBpbiBydW50aW1lLCBlbmFibGluZyBvciBkaXNhYmxpbmcgY2VydGFpbiBmZWF0dXJlcyBzdWNoIGFzIGRyYWdnaW5nIChzZWUgYEhhbmRsZXJgIG1ldGhvZHMpLiBFeGFtcGxlOlxuICpcbiAqIGBgYGpzXG4gKiBtYXJrZXIuZHJhZ2dpbmcuZGlzYWJsZSgpO1xuICogYGBgXG4gKlxuICogQHByb3BlcnR5IGRyYWdnaW5nOiBIYW5kbGVyXG4gKiBNYXJrZXIgZHJhZ2dpbmcgaGFuZGxlciAoYnkgYm90aCBtb3VzZSBhbmQgdG91Y2gpLiBPbmx5IHZhbGlkIHdoZW4gdGhlIG1hcmtlciBpcyBvbiB0aGUgbWFwIChPdGhlcndpc2Ugc2V0IFtgbWFya2VyLm9wdGlvbnMuZHJhZ2dhYmxlYF0oI21hcmtlci1kcmFnZ2FibGUpKS5cbiAqL1xuXG52YXIgTWFya2VyRHJhZyA9IEhhbmRsZXIuZXh0ZW5kKHtcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG1hcmtlcikge1xuXHRcdHRoaXMuX21hcmtlciA9IG1hcmtlcjtcblx0fSxcblxuXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBpY29uID0gdGhpcy5fbWFya2VyLl9pY29uO1xuXG5cdFx0aWYgKCF0aGlzLl9kcmFnZ2FibGUpIHtcblx0XHRcdHRoaXMuX2RyYWdnYWJsZSA9IG5ldyBEcmFnZ2FibGUoaWNvbiwgaWNvbiwgdHJ1ZSk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fZHJhZ2dhYmxlLm9uKHtcblx0XHRcdGRyYWdzdGFydDogdGhpcy5fb25EcmFnU3RhcnQsXG5cdFx0XHRwcmVkcmFnOiB0aGlzLl9vblByZURyYWcsXG5cdFx0XHRkcmFnOiB0aGlzLl9vbkRyYWcsXG5cdFx0XHRkcmFnZW5kOiB0aGlzLl9vbkRyYWdFbmRcblx0XHR9LCB0aGlzKS5lbmFibGUoKTtcblxuXHRcdGFkZENsYXNzKGljb24sICdsZWFmbGV0LW1hcmtlci1kcmFnZ2FibGUnKTtcblx0fSxcblxuXHRyZW1vdmVIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX2RyYWdnYWJsZS5vZmYoe1xuXHRcdFx0ZHJhZ3N0YXJ0OiB0aGlzLl9vbkRyYWdTdGFydCxcblx0XHRcdHByZWRyYWc6IHRoaXMuX29uUHJlRHJhZyxcblx0XHRcdGRyYWc6IHRoaXMuX29uRHJhZyxcblx0XHRcdGRyYWdlbmQ6IHRoaXMuX29uRHJhZ0VuZFxuXHRcdH0sIHRoaXMpLmRpc2FibGUoKTtcblxuXHRcdGlmICh0aGlzLl9tYXJrZXIuX2ljb24pIHtcblx0XHRcdHJlbW92ZUNsYXNzKHRoaXMuX21hcmtlci5faWNvbiwgJ2xlYWZsZXQtbWFya2VyLWRyYWdnYWJsZScpO1xuXHRcdH1cblx0fSxcblxuXHRtb3ZlZDogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLl9kcmFnZ2FibGUgJiYgdGhpcy5fZHJhZ2dhYmxlLl9tb3ZlZDtcblx0fSxcblxuXHRfYWRqdXN0UGFuOiBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBtYXJrZXIgPSB0aGlzLl9tYXJrZXIsXG5cdFx0ICAgIG1hcCA9IG1hcmtlci5fbWFwLFxuXHRcdCAgICBzcGVlZCA9IHRoaXMuX21hcmtlci5vcHRpb25zLmF1dG9QYW5TcGVlZCxcblx0XHQgICAgcGFkZGluZyA9IHRoaXMuX21hcmtlci5vcHRpb25zLmF1dG9QYW5QYWRkaW5nLFxuXHRcdCAgICBpY29uUG9zID0gZ2V0UG9zaXRpb24obWFya2VyLl9pY29uKSxcblx0XHQgICAgYm91bmRzID0gbWFwLmdldFBpeGVsQm91bmRzKCksXG5cdFx0ICAgIG9yaWdpbiA9IG1hcC5nZXRQaXhlbE9yaWdpbigpO1xuXG5cdFx0dmFyIHBhbkJvdW5kcyA9IHRvQm91bmRzKFxuXHRcdFx0Ym91bmRzLm1pbi5fc3VidHJhY3Qob3JpZ2luKS5hZGQocGFkZGluZyksXG5cdFx0XHRib3VuZHMubWF4Ll9zdWJ0cmFjdChvcmlnaW4pLnN1YnRyYWN0KHBhZGRpbmcpXG5cdFx0KTtcblxuXHRcdGlmICghcGFuQm91bmRzLmNvbnRhaW5zKGljb25Qb3MpKSB7XG5cdFx0XHQvLyBDb21wdXRlIGluY3JlbWVudGFsIG1vdmVtZW50XG5cdFx0XHR2YXIgbW92ZW1lbnQgPSB0b1BvaW50KFxuXHRcdFx0XHQoTWF0aC5tYXgocGFuQm91bmRzLm1heC54LCBpY29uUG9zLngpIC0gcGFuQm91bmRzLm1heC54KSAvIChib3VuZHMubWF4LnggLSBwYW5Cb3VuZHMubWF4LngpIC1cblx0XHRcdFx0KE1hdGgubWluKHBhbkJvdW5kcy5taW4ueCwgaWNvblBvcy54KSAtIHBhbkJvdW5kcy5taW4ueCkgLyAoYm91bmRzLm1pbi54IC0gcGFuQm91bmRzLm1pbi54KSxcblxuXHRcdFx0XHQoTWF0aC5tYXgocGFuQm91bmRzLm1heC55LCBpY29uUG9zLnkpIC0gcGFuQm91bmRzLm1heC55KSAvIChib3VuZHMubWF4LnkgLSBwYW5Cb3VuZHMubWF4LnkpIC1cblx0XHRcdFx0KE1hdGgubWluKHBhbkJvdW5kcy5taW4ueSwgaWNvblBvcy55KSAtIHBhbkJvdW5kcy5taW4ueSkgLyAoYm91bmRzLm1pbi55IC0gcGFuQm91bmRzLm1pbi55KVxuXHRcdFx0KS5tdWx0aXBseUJ5KHNwZWVkKTtcblxuXHRcdFx0bWFwLnBhbkJ5KG1vdmVtZW50LCB7YW5pbWF0ZTogZmFsc2V9KTtcblxuXHRcdFx0dGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3MuX2FkZChtb3ZlbWVudCk7XG5cdFx0XHR0aGlzLl9kcmFnZ2FibGUuX3N0YXJ0UG9zLl9hZGQobW92ZW1lbnQpO1xuXG5cdFx0XHRzZXRQb3NpdGlvbihtYXJrZXIuX2ljb24sIHRoaXMuX2RyYWdnYWJsZS5fbmV3UG9zKTtcblx0XHRcdHRoaXMuX29uRHJhZyhlKTtcblxuXHRcdFx0dGhpcy5fcGFuUmVxdWVzdCA9IHJlcXVlc3RBbmltRnJhbWUodGhpcy5fYWRqdXN0UGFuLmJpbmQodGhpcywgZSkpO1xuXHRcdH1cblx0fSxcblxuXHRfb25EcmFnU3RhcnQ6IGZ1bmN0aW9uICgpIHtcblx0XHQvLyBAc2VjdGlvbiBEcmFnZ2luZyBldmVudHNcblx0XHQvLyBAZXZlbnQgZHJhZ3N0YXJ0OiBFdmVudFxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgc3RhcnRzIGRyYWdnaW5nIHRoZSBtYXJrZXIuXG5cblx0XHQvLyBAZXZlbnQgbW92ZXN0YXJ0OiBFdmVudFxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcmtlciBzdGFydHMgbW92aW5nIChiZWNhdXNlIG9mIGRyYWdnaW5nKS5cblxuXHRcdHRoaXMuX29sZExhdExuZyA9IHRoaXMuX21hcmtlci5nZXRMYXRMbmcoKTtcblx0XHR0aGlzLl9tYXJrZXJcblx0XHQgICAgLmNsb3NlUG9wdXAoKVxuXHRcdCAgICAuZmlyZSgnbW92ZXN0YXJ0Jylcblx0XHQgICAgLmZpcmUoJ2RyYWdzdGFydCcpO1xuXHR9LFxuXG5cdF9vblByZURyYWc6IGZ1bmN0aW9uIChlKSB7XG5cdFx0aWYgKHRoaXMuX21hcmtlci5vcHRpb25zLmF1dG9QYW4pIHtcblx0XHRcdGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9wYW5SZXF1ZXN0KTtcblx0XHRcdHRoaXMuX3BhblJlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lKHRoaXMuX2FkanVzdFBhbi5iaW5kKHRoaXMsIGUpKTtcblx0XHR9XG5cdH0sXG5cblx0X29uRHJhZzogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgbWFya2VyID0gdGhpcy5fbWFya2VyLFxuXHRcdCAgICBzaGFkb3cgPSBtYXJrZXIuX3NoYWRvdyxcblx0XHQgICAgaWNvblBvcyA9IGdldFBvc2l0aW9uKG1hcmtlci5faWNvbiksXG5cdFx0ICAgIGxhdGxuZyA9IG1hcmtlci5fbWFwLmxheWVyUG9pbnRUb0xhdExuZyhpY29uUG9zKTtcblxuXHRcdC8vIHVwZGF0ZSBzaGFkb3cgcG9zaXRpb25cblx0XHRpZiAoc2hhZG93KSB7XG5cdFx0XHRzZXRQb3NpdGlvbihzaGFkb3csIGljb25Qb3MpO1xuXHRcdH1cblxuXHRcdG1hcmtlci5fbGF0bG5nID0gbGF0bG5nO1xuXHRcdGUubGF0bG5nID0gbGF0bG5nO1xuXHRcdGUub2xkTGF0TG5nID0gdGhpcy5fb2xkTGF0TG5nO1xuXG5cdFx0Ly8gQGV2ZW50IGRyYWc6IEV2ZW50XG5cdFx0Ly8gRmlyZWQgcmVwZWF0ZWRseSB3aGlsZSB0aGUgdXNlciBkcmFncyB0aGUgbWFya2VyLlxuXHRcdG1hcmtlclxuXHRcdCAgICAuZmlyZSgnbW92ZScsIGUpXG5cdFx0ICAgIC5maXJlKCdkcmFnJywgZSk7XG5cdH0sXG5cblx0X29uRHJhZ0VuZDogZnVuY3Rpb24gKGUpIHtcblx0XHQvLyBAZXZlbnQgZHJhZ2VuZDogRHJhZ0VuZEV2ZW50XG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBzdG9wcyBkcmFnZ2luZyB0aGUgbWFya2VyLlxuXG5cdFx0IGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9wYW5SZXF1ZXN0KTtcblxuXHRcdC8vIEBldmVudCBtb3ZlZW5kOiBFdmVudFxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcmtlciBzdG9wcyBtb3ZpbmcgKGJlY2F1c2Ugb2YgZHJhZ2dpbmcpLlxuXHRcdGRlbGV0ZSB0aGlzLl9vbGRMYXRMbmc7XG5cdFx0dGhpcy5fbWFya2VyXG5cdFx0ICAgIC5maXJlKCdtb3ZlZW5kJylcblx0XHQgICAgLmZpcmUoJ2RyYWdlbmQnLCBlKTtcblx0fVxufSk7XG5cbi8qXHJcbiAqIEBjbGFzcyBNYXJrZXJcclxuICogQGluaGVyaXRzIEludGVyYWN0aXZlIGxheWVyXHJcbiAqIEBha2EgTC5NYXJrZXJcclxuICogTC5NYXJrZXIgaXMgdXNlZCB0byBkaXNwbGF5IGNsaWNrYWJsZS9kcmFnZ2FibGUgaWNvbnMgb24gdGhlIG1hcC4gRXh0ZW5kcyBgTGF5ZXJgLlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiBMLm1hcmtlcihbNTAuNSwgMzAuNV0pLmFkZFRvKG1hcCk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBNYXJrZXIgPSBMYXllci5leHRlbmQoe1xyXG5cclxuXHQvLyBAc2VjdGlvblxyXG5cdC8vIEBha2EgTWFya2VyIG9wdGlvbnNcclxuXHRvcHRpb25zOiB7XHJcblx0XHQvLyBAb3B0aW9uIGljb246IEljb24gPSAqXHJcblx0XHQvLyBJY29uIGluc3RhbmNlIHRvIHVzZSBmb3IgcmVuZGVyaW5nIHRoZSBtYXJrZXIuXHJcblx0XHQvLyBTZWUgW0ljb24gZG9jdW1lbnRhdGlvbl0oI0wuSWNvbikgZm9yIGRldGFpbHMgb24gaG93IHRvIGN1c3RvbWl6ZSB0aGUgbWFya2VyIGljb24uXHJcblx0XHQvLyBJZiBub3Qgc3BlY2lmaWVkLCBhIGNvbW1vbiBpbnN0YW5jZSBvZiBgTC5JY29uLkRlZmF1bHRgIGlzIHVzZWQuXHJcblx0XHRpY29uOiBuZXcgSWNvbkRlZmF1bHQoKSxcclxuXHJcblx0XHQvLyBPcHRpb24gaW5oZXJpdGVkIGZyb20gXCJJbnRlcmFjdGl2ZSBsYXllclwiIGFic3RyYWN0IGNsYXNzXHJcblx0XHRpbnRlcmFjdGl2ZTogdHJ1ZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGtleWJvYXJkOiBCb29sZWFuID0gdHJ1ZVxyXG5cdFx0Ly8gV2hldGhlciB0aGUgbWFya2VyIGNhbiBiZSB0YWJiZWQgdG8gd2l0aCBhIGtleWJvYXJkIGFuZCBjbGlja2VkIGJ5IHByZXNzaW5nIGVudGVyLlxyXG5cdFx0a2V5Ym9hcmQ6IHRydWUsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB0aXRsZTogU3RyaW5nID0gJydcclxuXHRcdC8vIFRleHQgZm9yIHRoZSBicm93c2VyIHRvb2x0aXAgdGhhdCBhcHBlYXIgb24gbWFya2VyIGhvdmVyIChubyB0b29sdGlwIGJ5IGRlZmF1bHQpLlxyXG5cdFx0dGl0bGU6ICcnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gYWx0OiBTdHJpbmcgPSAnJ1xyXG5cdFx0Ly8gVGV4dCBmb3IgdGhlIGBhbHRgIGF0dHJpYnV0ZSBvZiB0aGUgaWNvbiBpbWFnZSAodXNlZnVsIGZvciBhY2Nlc3NpYmlsaXR5KS5cclxuXHRcdGFsdDogJycsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB6SW5kZXhPZmZzZXQ6IE51bWJlciA9IDBcclxuXHRcdC8vIEJ5IGRlZmF1bHQsIG1hcmtlciBpbWFnZXMgekluZGV4IGlzIHNldCBhdXRvbWF0aWNhbGx5IGJhc2VkIG9uIGl0cyBsYXRpdHVkZS4gVXNlIHRoaXMgb3B0aW9uIGlmIHlvdSB3YW50IHRvIHB1dCB0aGUgbWFya2VyIG9uIHRvcCBvZiBhbGwgb3RoZXJzIChvciBiZWxvdyksIHNwZWNpZnlpbmcgYSBoaWdoIHZhbHVlIGxpa2UgYDEwMDBgIChvciBoaWdoIG5lZ2F0aXZlIHZhbHVlLCByZXNwZWN0aXZlbHkpLlxyXG5cdFx0ekluZGV4T2Zmc2V0OiAwLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMS4wXHJcblx0XHQvLyBUaGUgb3BhY2l0eSBvZiB0aGUgbWFya2VyLlxyXG5cdFx0b3BhY2l0eTogMSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHJpc2VPbkhvdmVyOiBCb29sZWFuID0gZmFsc2VcclxuXHRcdC8vIElmIGB0cnVlYCwgdGhlIG1hcmtlciB3aWxsIGdldCBvbiB0b3Agb2Ygb3RoZXJzIHdoZW4geW91IGhvdmVyIHRoZSBtb3VzZSBvdmVyIGl0LlxyXG5cdFx0cmlzZU9uSG92ZXI6IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gcmlzZU9mZnNldDogTnVtYmVyID0gMjUwXHJcblx0XHQvLyBUaGUgei1pbmRleCBvZmZzZXQgdXNlZCBmb3IgdGhlIGByaXNlT25Ib3ZlcmAgZmVhdHVyZS5cclxuXHRcdHJpc2VPZmZzZXQ6IDI1MCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHBhbmU6IFN0cmluZyA9ICdtYXJrZXJQYW5lJ1xyXG5cdFx0Ly8gYE1hcCBwYW5lYCB3aGVyZSB0aGUgbWFya2VycyBpY29uIHdpbGwgYmUgYWRkZWQuXHJcblx0XHRwYW5lOiAnbWFya2VyUGFuZScsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBwYW5lOiBTdHJpbmcgPSAnc2hhZG93UGFuZSdcclxuXHRcdC8vIGBNYXAgcGFuZWAgd2hlcmUgdGhlIG1hcmtlcnMgc2hhZG93IHdpbGwgYmUgYWRkZWQuXHJcblx0XHRzaGFkb3dQYW5lOiAnc2hhZG93UGFuZScsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBidWJibGluZ01vdXNlRXZlbnRzOiBCb29sZWFuID0gZmFsc2VcclxuXHRcdC8vIFdoZW4gYHRydWVgLCBhIG1vdXNlIGV2ZW50IG9uIHRoaXMgbWFya2VyIHdpbGwgdHJpZ2dlciB0aGUgc2FtZSBldmVudCBvbiB0aGUgbWFwXHJcblx0XHQvLyAodW5sZXNzIFtgTC5Eb21FdmVudC5zdG9wUHJvcGFnYXRpb25gXSgjZG9tZXZlbnQtc3RvcHByb3BhZ2F0aW9uKSBpcyB1c2VkKS5cclxuXHRcdGJ1YmJsaW5nTW91c2VFdmVudHM6IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBzZWN0aW9uIERyYWdnYWJsZSBtYXJrZXIgb3B0aW9uc1xyXG5cdFx0Ly8gQG9wdGlvbiBkcmFnZ2FibGU6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gV2hldGhlciB0aGUgbWFya2VyIGlzIGRyYWdnYWJsZSB3aXRoIG1vdXNlL3RvdWNoIG9yIG5vdC5cclxuXHRcdGRyYWdnYWJsZTogZmFsc2UsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBhdXRvUGFuOiBCb29sZWFuID0gZmFsc2VcclxuXHRcdC8vIFdoZXRoZXIgdG8gcGFuIHRoZSBtYXAgd2hlbiBkcmFnZ2luZyB0aGlzIG1hcmtlciBuZWFyIGl0cyBlZGdlIG9yIG5vdC5cclxuXHRcdGF1dG9QYW46IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gYXV0b1BhblBhZGRpbmc6IFBvaW50ID0gUG9pbnQoNTAsIDUwKVxyXG5cdFx0Ly8gRGlzdGFuY2UgKGluIHBpeGVscyB0byB0aGUgbGVmdC9yaWdodCBhbmQgdG8gdGhlIHRvcC9ib3R0b20pIG9mIHRoZVxyXG5cdFx0Ly8gbWFwIGVkZ2UgdG8gc3RhcnQgcGFubmluZyB0aGUgbWFwLlxyXG5cdFx0YXV0b1BhblBhZGRpbmc6IFs1MCwgNTBdLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gYXV0b1BhblNwZWVkOiBOdW1iZXIgPSAxMFxyXG5cdFx0Ly8gTnVtYmVyIG9mIHBpeGVscyB0aGUgbWFwIHNob3VsZCBwYW4gYnkuXHJcblx0XHRhdXRvUGFuU3BlZWQ6IDEwXHJcblx0fSxcclxuXHJcblx0LyogQHNlY3Rpb25cclxuXHQgKlxyXG5cdCAqIEluIGFkZGl0aW9uIHRvIFtzaGFyZWQgbGF5ZXIgbWV0aG9kc10oI0xheWVyKSBsaWtlIGBhZGRUbygpYCBhbmQgYHJlbW92ZSgpYCBhbmQgW3BvcHVwIG1ldGhvZHNdKCNQb3B1cCkgbGlrZSBiaW5kUG9wdXAoKSB5b3UgY2FuIGFsc28gdXNlIHRoZSBmb2xsb3dpbmcgbWV0aG9kczpcclxuXHQgKi9cclxuXHJcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxhdGxuZywgb3B0aW9ucykge1xyXG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHRcdHRoaXMuX2xhdGxuZyA9IHRvTGF0TG5nKGxhdGxuZyk7XHJcblx0fSxcclxuXHJcblx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuXHRcdHRoaXMuX3pvb21BbmltYXRlZCA9IHRoaXMuX3pvb21BbmltYXRlZCAmJiBtYXAub3B0aW9ucy5tYXJrZXJab29tQW5pbWF0aW9uO1xyXG5cclxuXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuXHRcdFx0bWFwLm9uKCd6b29tYW5pbScsIHRoaXMuX2FuaW1hdGVab29tLCB0aGlzKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9pbml0SWNvbigpO1xyXG5cdFx0dGhpcy51cGRhdGUoKTtcclxuXHR9LFxyXG5cclxuXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0aWYgKHRoaXMuZHJhZ2dpbmcgJiYgdGhpcy5kcmFnZ2luZy5lbmFibGVkKCkpIHtcclxuXHRcdFx0dGhpcy5vcHRpb25zLmRyYWdnYWJsZSA9IHRydWU7XHJcblx0XHRcdHRoaXMuZHJhZ2dpbmcucmVtb3ZlSG9va3MoKTtcclxuXHRcdH1cclxuXHRcdGRlbGV0ZSB0aGlzLmRyYWdnaW5nO1xyXG5cclxuXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuXHRcdFx0bWFwLm9mZignem9vbWFuaW0nLCB0aGlzLl9hbmltYXRlWm9vbSwgdGhpcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fcmVtb3ZlSWNvbigpO1xyXG5cdFx0dGhpcy5fcmVtb3ZlU2hhZG93KCk7XHJcblx0fSxcclxuXHJcblx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4ge1xyXG5cdFx0XHR6b29tOiB0aGlzLnVwZGF0ZSxcclxuXHRcdFx0dmlld3Jlc2V0OiB0aGlzLnVwZGF0ZVxyXG5cdFx0fTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldExhdExuZzogTGF0TG5nXHJcblx0Ly8gUmV0dXJucyB0aGUgY3VycmVudCBnZW9ncmFwaGljYWwgcG9zaXRpb24gb2YgdGhlIG1hcmtlci5cclxuXHRnZXRMYXRMbmc6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9sYXRsbmc7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRMYXRMbmcobGF0bG5nOiBMYXRMbmcpOiB0aGlzXHJcblx0Ly8gQ2hhbmdlcyB0aGUgbWFya2VyIHBvc2l0aW9uIHRvIHRoZSBnaXZlbiBwb2ludC5cclxuXHRzZXRMYXRMbmc6IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuXHRcdHZhciBvbGRMYXRMbmcgPSB0aGlzLl9sYXRsbmc7XHJcblx0XHR0aGlzLl9sYXRsbmcgPSB0b0xhdExuZyhsYXRsbmcpO1xyXG5cdFx0dGhpcy51cGRhdGUoKTtcclxuXHJcblx0XHQvLyBAZXZlbnQgbW92ZTogRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcmtlciBpcyBtb3ZlZCB2aWEgW2BzZXRMYXRMbmdgXSgjbWFya2VyLXNldGxhdGxuZykgb3IgYnkgW2RyYWdnaW5nXSgjbWFya2VyLWRyYWdnaW5nKS4gT2xkIGFuZCBuZXcgY29vcmRpbmF0ZXMgYXJlIGluY2x1ZGVkIGluIGV2ZW50IGFyZ3VtZW50cyBhcyBgb2xkTGF0TG5nYCwgYGxhdGxuZ2AuXHJcblx0XHRyZXR1cm4gdGhpcy5maXJlKCdtb3ZlJywge29sZExhdExuZzogb2xkTGF0TG5nLCBsYXRsbmc6IHRoaXMuX2xhdGxuZ30pO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0WkluZGV4T2Zmc2V0KG9mZnNldDogTnVtYmVyKTogdGhpc1xyXG5cdC8vIENoYW5nZXMgdGhlIFt6SW5kZXggb2Zmc2V0XSgjbWFya2VyLXppbmRleG9mZnNldCkgb2YgdGhlIG1hcmtlci5cclxuXHRzZXRaSW5kZXhPZmZzZXQ6IGZ1bmN0aW9uIChvZmZzZXQpIHtcclxuXHRcdHRoaXMub3B0aW9ucy56SW5kZXhPZmZzZXQgPSBvZmZzZXQ7XHJcblx0XHRyZXR1cm4gdGhpcy51cGRhdGUoKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldEljb246IEljb25cclxuXHQvLyBSZXR1cm5zIHRoZSBjdXJyZW50IGljb24gdXNlZCBieSB0aGUgbWFya2VyXHJcblx0Z2V0SWNvbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5pY29uO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0SWNvbihpY29uOiBJY29uKTogdGhpc1xyXG5cdC8vIENoYW5nZXMgdGhlIG1hcmtlciBpY29uLlxyXG5cdHNldEljb246IGZ1bmN0aW9uIChpY29uKSB7XHJcblxyXG5cdFx0dGhpcy5vcHRpb25zLmljb24gPSBpY29uO1xyXG5cclxuXHRcdGlmICh0aGlzLl9tYXApIHtcclxuXHRcdFx0dGhpcy5faW5pdEljb24oKTtcclxuXHRcdFx0dGhpcy51cGRhdGUoKTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAodGhpcy5fcG9wdXApIHtcclxuXHRcdFx0dGhpcy5iaW5kUG9wdXAodGhpcy5fcG9wdXAsIHRoaXMuX3BvcHVwLm9wdGlvbnMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdGdldEVsZW1lbnQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9pY29uO1xyXG5cdH0sXHJcblxyXG5cdHVwZGF0ZTogZnVuY3Rpb24gKCkge1xyXG5cclxuXHRcdGlmICh0aGlzLl9pY29uICYmIHRoaXMuX21hcCkge1xyXG5cdFx0XHR2YXIgcG9zID0gdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcpLnJvdW5kKCk7XHJcblx0XHRcdHRoaXMuX3NldFBvcyhwb3MpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdF9pbml0SWNvbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXHJcblx0XHQgICAgY2xhc3NUb0FkZCA9ICdsZWFmbGV0LXpvb20tJyArICh0aGlzLl96b29tQW5pbWF0ZWQgPyAnYW5pbWF0ZWQnIDogJ2hpZGUnKTtcclxuXHJcblx0XHR2YXIgaWNvbiA9IG9wdGlvbnMuaWNvbi5jcmVhdGVJY29uKHRoaXMuX2ljb24pLFxyXG5cdFx0ICAgIGFkZEljb24gPSBmYWxzZTtcclxuXHJcblx0XHQvLyBpZiB3ZSdyZSBub3QgcmV1c2luZyB0aGUgaWNvbiwgcmVtb3ZlIHRoZSBvbGQgb25lIGFuZCBpbml0IG5ldyBvbmVcclxuXHRcdGlmIChpY29uICE9PSB0aGlzLl9pY29uKSB7XHJcblx0XHRcdGlmICh0aGlzLl9pY29uKSB7XHJcblx0XHRcdFx0dGhpcy5fcmVtb3ZlSWNvbigpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGFkZEljb24gPSB0cnVlO1xyXG5cclxuXHRcdFx0aWYgKG9wdGlvbnMudGl0bGUpIHtcclxuXHRcdFx0XHRpY29uLnRpdGxlID0gb3B0aW9ucy50aXRsZTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKGljb24udGFnTmFtZSA9PT0gJ0lNRycpIHtcclxuXHRcdFx0XHRpY29uLmFsdCA9IG9wdGlvbnMuYWx0IHx8ICcnO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0YWRkQ2xhc3MoaWNvbiwgY2xhc3NUb0FkZCk7XHJcblxyXG5cdFx0aWYgKG9wdGlvbnMua2V5Ym9hcmQpIHtcclxuXHRcdFx0aWNvbi50YWJJbmRleCA9ICcwJztcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9pY29uID0gaWNvbjtcclxuXHJcblx0XHRpZiAob3B0aW9ucy5yaXNlT25Ib3Zlcikge1xyXG5cdFx0XHR0aGlzLm9uKHtcclxuXHRcdFx0XHRtb3VzZW92ZXI6IHRoaXMuX2JyaW5nVG9Gcm9udCxcclxuXHRcdFx0XHRtb3VzZW91dDogdGhpcy5fcmVzZXRaSW5kZXhcclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIG5ld1NoYWRvdyA9IG9wdGlvbnMuaWNvbi5jcmVhdGVTaGFkb3codGhpcy5fc2hhZG93KSxcclxuXHRcdCAgICBhZGRTaGFkb3cgPSBmYWxzZTtcclxuXHJcblx0XHRpZiAobmV3U2hhZG93ICE9PSB0aGlzLl9zaGFkb3cpIHtcclxuXHRcdFx0dGhpcy5fcmVtb3ZlU2hhZG93KCk7XHJcblx0XHRcdGFkZFNoYWRvdyA9IHRydWU7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKG5ld1NoYWRvdykge1xyXG5cdFx0XHRhZGRDbGFzcyhuZXdTaGFkb3csIGNsYXNzVG9BZGQpO1xyXG5cdFx0XHRuZXdTaGFkb3cuYWx0ID0gJyc7XHJcblx0XHR9XHJcblx0XHR0aGlzLl9zaGFkb3cgPSBuZXdTaGFkb3c7XHJcblxyXG5cclxuXHRcdGlmIChvcHRpb25zLm9wYWNpdHkgPCAxKSB7XHJcblx0XHRcdHRoaXMuX3VwZGF0ZU9wYWNpdHkoKTtcclxuXHRcdH1cclxuXHJcblxyXG5cdFx0aWYgKGFkZEljb24pIHtcclxuXHRcdFx0dGhpcy5nZXRQYW5lKCkuYXBwZW5kQ2hpbGQodGhpcy5faWNvbik7XHJcblx0XHR9XHJcblx0XHR0aGlzLl9pbml0SW50ZXJhY3Rpb24oKTtcclxuXHRcdGlmIChuZXdTaGFkb3cgJiYgYWRkU2hhZG93KSB7XHJcblx0XHRcdHRoaXMuZ2V0UGFuZShvcHRpb25zLnNoYWRvd1BhbmUpLmFwcGVuZENoaWxkKHRoaXMuX3NoYWRvdyk7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X3JlbW92ZUljb246IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh0aGlzLm9wdGlvbnMucmlzZU9uSG92ZXIpIHtcclxuXHRcdFx0dGhpcy5vZmYoe1xyXG5cdFx0XHRcdG1vdXNlb3ZlcjogdGhpcy5fYnJpbmdUb0Zyb250LFxyXG5cdFx0XHRcdG1vdXNlb3V0OiB0aGlzLl9yZXNldFpJbmRleFxyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHJcblx0XHRyZW1vdmUodGhpcy5faWNvbik7XHJcblx0XHR0aGlzLnJlbW92ZUludGVyYWN0aXZlVGFyZ2V0KHRoaXMuX2ljb24pO1xyXG5cclxuXHRcdHRoaXMuX2ljb24gPSBudWxsO1xyXG5cdH0sXHJcblxyXG5cdF9yZW1vdmVTaGFkb3c6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh0aGlzLl9zaGFkb3cpIHtcclxuXHRcdFx0cmVtb3ZlKHRoaXMuX3NoYWRvdyk7XHJcblx0XHR9XHJcblx0XHR0aGlzLl9zaGFkb3cgPSBudWxsO1xyXG5cdH0sXHJcblxyXG5cdF9zZXRQb3M6IGZ1bmN0aW9uIChwb3MpIHtcclxuXHRcdHNldFBvc2l0aW9uKHRoaXMuX2ljb24sIHBvcyk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX3NoYWRvdykge1xyXG5cdFx0XHRzZXRQb3NpdGlvbih0aGlzLl9zaGFkb3csIHBvcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fekluZGV4ID0gcG9zLnkgKyB0aGlzLm9wdGlvbnMuekluZGV4T2Zmc2V0O1xyXG5cclxuXHRcdHRoaXMuX3Jlc2V0WkluZGV4KCk7XHJcblx0fSxcclxuXHJcblx0X3VwZGF0ZVpJbmRleDogZnVuY3Rpb24gKG9mZnNldCkge1xyXG5cdFx0dGhpcy5faWNvbi5zdHlsZS56SW5kZXggPSB0aGlzLl96SW5kZXggKyBvZmZzZXQ7XHJcblx0fSxcclxuXHJcblx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAob3B0KSB7XHJcblx0XHR2YXIgcG9zID0gdGhpcy5fbWFwLl9sYXRMbmdUb05ld0xheWVyUG9pbnQodGhpcy5fbGF0bG5nLCBvcHQuem9vbSwgb3B0LmNlbnRlcikucm91bmQoKTtcclxuXHJcblx0XHR0aGlzLl9zZXRQb3MocG9zKTtcclxuXHR9LFxyXG5cclxuXHRfaW5pdEludGVyYWN0aW9uOiBmdW5jdGlvbiAoKSB7XHJcblxyXG5cdFx0aWYgKCF0aGlzLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0YWRkQ2xhc3ModGhpcy5faWNvbiwgJ2xlYWZsZXQtaW50ZXJhY3RpdmUnKTtcclxuXHJcblx0XHR0aGlzLmFkZEludGVyYWN0aXZlVGFyZ2V0KHRoaXMuX2ljb24pO1xyXG5cclxuXHRcdGlmIChNYXJrZXJEcmFnKSB7XHJcblx0XHRcdHZhciBkcmFnZ2FibGUgPSB0aGlzLm9wdGlvbnMuZHJhZ2dhYmxlO1xyXG5cdFx0XHRpZiAodGhpcy5kcmFnZ2luZykge1xyXG5cdFx0XHRcdGRyYWdnYWJsZSA9IHRoaXMuZHJhZ2dpbmcuZW5hYmxlZCgpO1xyXG5cdFx0XHRcdHRoaXMuZHJhZ2dpbmcuZGlzYWJsZSgpO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR0aGlzLmRyYWdnaW5nID0gbmV3IE1hcmtlckRyYWcodGhpcyk7XHJcblxyXG5cdFx0XHRpZiAoZHJhZ2dhYmxlKSB7XHJcblx0XHRcdFx0dGhpcy5kcmFnZ2luZy5lbmFibGUoKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0T3BhY2l0eShvcGFjaXR5OiBOdW1iZXIpOiB0aGlzXHJcblx0Ly8gQ2hhbmdlcyB0aGUgb3BhY2l0eSBvZiB0aGUgbWFya2VyLlxyXG5cdHNldE9wYWNpdHk6IGZ1bmN0aW9uIChvcGFjaXR5KSB7XHJcblx0XHR0aGlzLm9wdGlvbnMub3BhY2l0eSA9IG9wYWNpdHk7XHJcblx0XHRpZiAodGhpcy5fbWFwKSB7XHJcblx0XHRcdHRoaXMuX3VwZGF0ZU9wYWNpdHkoKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRfdXBkYXRlT3BhY2l0eTogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIG9wYWNpdHkgPSB0aGlzLm9wdGlvbnMub3BhY2l0eTtcclxuXHJcblx0XHRpZiAodGhpcy5faWNvbikge1xyXG5cdFx0XHRzZXRPcGFjaXR5KHRoaXMuX2ljb24sIG9wYWNpdHkpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLl9zaGFkb3cpIHtcclxuXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9zaGFkb3csIG9wYWNpdHkpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9icmluZ1RvRnJvbnQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX3VwZGF0ZVpJbmRleCh0aGlzLm9wdGlvbnMucmlzZU9mZnNldCk7XHJcblx0fSxcclxuXHJcblx0X3Jlc2V0WkluZGV4OiBmdW5jdGlvbiAoKSB7XHJcblx0XHR0aGlzLl91cGRhdGVaSW5kZXgoMCk7XHJcblx0fSxcclxuXHJcblx0X2dldFBvcHVwQW5jaG9yOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmljb24ub3B0aW9ucy5wb3B1cEFuY2hvcjtcclxuXHR9LFxyXG5cclxuXHRfZ2V0VG9vbHRpcEFuY2hvcjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5pY29uLm9wdGlvbnMudG9vbHRpcEFuY2hvcjtcclxuXHR9XHJcbn0pO1xyXG5cclxuXHJcbi8vIGZhY3RvcnkgTC5tYXJrZXIobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/IDogTWFya2VyIG9wdGlvbnMpXHJcblxyXG4vLyBAZmFjdG9yeSBMLm1hcmtlcihsYXRsbmc6IExhdExuZywgb3B0aW9ucz8gOiBNYXJrZXIgb3B0aW9ucylcclxuLy8gSW5zdGFudGlhdGVzIGEgTWFya2VyIG9iamVjdCBnaXZlbiBhIGdlb2dyYXBoaWNhbCBwb2ludCBhbmQgb3B0aW9uYWxseSBhbiBvcHRpb25zIG9iamVjdC5cclxuZnVuY3Rpb24gbWFya2VyKGxhdGxuZywgb3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgTWFya2VyKGxhdGxuZywgb3B0aW9ucyk7XHJcbn1cblxuLypcbiAqIEBjbGFzcyBQYXRoXG4gKiBAYWthIEwuUGF0aFxuICogQGluaGVyaXRzIEludGVyYWN0aXZlIGxheWVyXG4gKlxuICogQW4gYWJzdHJhY3QgY2xhc3MgdGhhdCBjb250YWlucyBvcHRpb25zIGFuZCBjb25zdGFudHMgc2hhcmVkIGJldHdlZW4gdmVjdG9yXG4gKiBvdmVybGF5cyAoUG9seWdvbiwgUG9seWxpbmUsIENpcmNsZSkuIERvIG5vdCB1c2UgaXQgZGlyZWN0bHkuIEV4dGVuZHMgYExheWVyYC5cbiAqL1xuXG52YXIgUGF0aCA9IExheWVyLmV4dGVuZCh7XG5cblx0Ly8gQHNlY3Rpb25cblx0Ly8gQGFrYSBQYXRoIG9wdGlvbnNcblx0b3B0aW9uczoge1xuXHRcdC8vIEBvcHRpb24gc3Ryb2tlOiBCb29sZWFuID0gdHJ1ZVxuXHRcdC8vIFdoZXRoZXIgdG8gZHJhdyBzdHJva2UgYWxvbmcgdGhlIHBhdGguIFNldCBpdCB0byBgZmFsc2VgIHRvIGRpc2FibGUgYm9yZGVycyBvbiBwb2x5Z29ucyBvciBjaXJjbGVzLlxuXHRcdHN0cm9rZTogdHJ1ZSxcblxuXHRcdC8vIEBvcHRpb24gY29sb3I6IFN0cmluZyA9ICcjMzM4OGZmJ1xuXHRcdC8vIFN0cm9rZSBjb2xvclxuXHRcdGNvbG9yOiAnIzMzODhmZicsXG5cblx0XHQvLyBAb3B0aW9uIHdlaWdodDogTnVtYmVyID0gM1xuXHRcdC8vIFN0cm9rZSB3aWR0aCBpbiBwaXhlbHNcblx0XHR3ZWlnaHQ6IDMsXG5cblx0XHQvLyBAb3B0aW9uIG9wYWNpdHk6IE51bWJlciA9IDEuMFxuXHRcdC8vIFN0cm9rZSBvcGFjaXR5XG5cdFx0b3BhY2l0eTogMSxcblxuXHRcdC8vIEBvcHRpb24gbGluZUNhcDogU3RyaW5nPSAncm91bmQnXG5cdFx0Ly8gQSBzdHJpbmcgdGhhdCBkZWZpbmVzIFtzaGFwZSB0byBiZSB1c2VkIGF0IHRoZSBlbmRdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL1NWRy9BdHRyaWJ1dGUvc3Ryb2tlLWxpbmVjYXApIG9mIHRoZSBzdHJva2UuXG5cdFx0bGluZUNhcDogJ3JvdW5kJyxcblxuXHRcdC8vIEBvcHRpb24gbGluZUpvaW46IFN0cmluZyA9ICdyb3VuZCdcblx0XHQvLyBBIHN0cmluZyB0aGF0IGRlZmluZXMgW3NoYXBlIHRvIGJlIHVzZWQgYXQgdGhlIGNvcm5lcnNdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL1NWRy9BdHRyaWJ1dGUvc3Ryb2tlLWxpbmVqb2luKSBvZiB0aGUgc3Ryb2tlLlxuXHRcdGxpbmVKb2luOiAncm91bmQnLFxuXG5cdFx0Ly8gQG9wdGlvbiBkYXNoQXJyYXk6IFN0cmluZyA9IG51bGxcblx0XHQvLyBBIHN0cmluZyB0aGF0IGRlZmluZXMgdGhlIHN0cm9rZSBbZGFzaCBwYXR0ZXJuXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlL3N0cm9rZS1kYXNoYXJyYXkpLiBEb2Vzbid0IHdvcmsgb24gYENhbnZhc2AtcG93ZXJlZCBsYXllcnMgaW4gW3NvbWUgb2xkIGJyb3dzZXJzXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEL3NldExpbmVEYXNoI0Jyb3dzZXJfY29tcGF0aWJpbGl0eSkuXG5cdFx0ZGFzaEFycmF5OiBudWxsLFxuXG5cdFx0Ly8gQG9wdGlvbiBkYXNoT2Zmc2V0OiBTdHJpbmcgPSBudWxsXG5cdFx0Ly8gQSBzdHJpbmcgdGhhdCBkZWZpbmVzIHRoZSBbZGlzdGFuY2UgaW50byB0aGUgZGFzaCBwYXR0ZXJuIHRvIHN0YXJ0IHRoZSBkYXNoXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlL3N0cm9rZS1kYXNob2Zmc2V0KS4gRG9lc24ndCB3b3JrIG9uIGBDYW52YXNgLXBvd2VyZWQgbGF5ZXJzIGluIFtzb21lIG9sZCBicm93c2Vyc10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC9zZXRMaW5lRGFzaCNCcm93c2VyX2NvbXBhdGliaWxpdHkpLlxuXHRcdGRhc2hPZmZzZXQ6IG51bGwsXG5cblx0XHQvLyBAb3B0aW9uIGZpbGw6IEJvb2xlYW4gPSBkZXBlbmRzXG5cdFx0Ly8gV2hldGhlciB0byBmaWxsIHRoZSBwYXRoIHdpdGggY29sb3IuIFNldCBpdCB0byBgZmFsc2VgIHRvIGRpc2FibGUgZmlsbGluZyBvbiBwb2x5Z29ucyBvciBjaXJjbGVzLlxuXHRcdGZpbGw6IGZhbHNlLFxuXG5cdFx0Ly8gQG9wdGlvbiBmaWxsQ29sb3I6IFN0cmluZyA9ICpcblx0XHQvLyBGaWxsIGNvbG9yLiBEZWZhdWx0cyB0byB0aGUgdmFsdWUgb2YgdGhlIFtgY29sb3JgXSgjcGF0aC1jb2xvcikgb3B0aW9uXG5cdFx0ZmlsbENvbG9yOiBudWxsLFxuXG5cdFx0Ly8gQG9wdGlvbiBmaWxsT3BhY2l0eTogTnVtYmVyID0gMC4yXG5cdFx0Ly8gRmlsbCBvcGFjaXR5LlxuXHRcdGZpbGxPcGFjaXR5OiAwLjIsXG5cblx0XHQvLyBAb3B0aW9uIGZpbGxSdWxlOiBTdHJpbmcgPSAnZXZlbm9kZCdcblx0XHQvLyBBIHN0cmluZyB0aGF0IGRlZmluZXMgW2hvdyB0aGUgaW5zaWRlIG9mIGEgc2hhcGVdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL1NWRy9BdHRyaWJ1dGUvZmlsbC1ydWxlKSBpcyBkZXRlcm1pbmVkLlxuXHRcdGZpbGxSdWxlOiAnZXZlbm9kZCcsXG5cblx0XHQvLyBjbGFzc05hbWU6ICcnLFxuXG5cdFx0Ly8gT3B0aW9uIGluaGVyaXRlZCBmcm9tIFwiSW50ZXJhY3RpdmUgbGF5ZXJcIiBhYnN0cmFjdCBjbGFzc1xuXHRcdGludGVyYWN0aXZlOiB0cnVlLFxuXG5cdFx0Ly8gQG9wdGlvbiBidWJibGluZ01vdXNlRXZlbnRzOiBCb29sZWFuID0gdHJ1ZVxuXHRcdC8vIFdoZW4gYHRydWVgLCBhIG1vdXNlIGV2ZW50IG9uIHRoaXMgcGF0aCB3aWxsIHRyaWdnZXIgdGhlIHNhbWUgZXZlbnQgb24gdGhlIG1hcFxuXHRcdC8vICh1bmxlc3MgW2BMLkRvbUV2ZW50LnN0b3BQcm9wYWdhdGlvbmBdKCNkb21ldmVudC1zdG9wcHJvcGFnYXRpb24pIGlzIHVzZWQpLlxuXHRcdGJ1YmJsaW5nTW91c2VFdmVudHM6IHRydWVcblx0fSxcblxuXHRiZWZvcmVBZGQ6IGZ1bmN0aW9uIChtYXApIHtcblx0XHQvLyBSZW5kZXJlciBpcyBzZXQgaGVyZSBiZWNhdXNlIHdlIG5lZWQgdG8gY2FsbCByZW5kZXJlci5nZXRFdmVudHNcblx0XHQvLyBiZWZvcmUgdGhpcy5nZXRFdmVudHMuXG5cdFx0dGhpcy5fcmVuZGVyZXIgPSBtYXAuZ2V0UmVuZGVyZXIodGhpcyk7XG5cdH0sXG5cblx0b25BZGQ6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9yZW5kZXJlci5faW5pdFBhdGgodGhpcyk7XG5cdFx0dGhpcy5fcmVzZXQoKTtcblx0XHR0aGlzLl9yZW5kZXJlci5fYWRkUGF0aCh0aGlzKTtcblx0fSxcblxuXHRvblJlbW92ZTogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3JlbmRlcmVyLl9yZW1vdmVQYXRoKHRoaXMpO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgcmVkcmF3KCk6IHRoaXNcblx0Ly8gUmVkcmF3cyB0aGUgbGF5ZXIuIFNvbWV0aW1lcyB1c2VmdWwgYWZ0ZXIgeW91IGNoYW5nZWQgdGhlIGNvb3JkaW5hdGVzIHRoYXQgdGhlIHBhdGggdXNlcy5cblx0cmVkcmF3OiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcCkge1xuXHRcdFx0dGhpcy5fcmVuZGVyZXIuX3VwZGF0ZVBhdGgodGhpcyk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2Qgc2V0U3R5bGUoc3R5bGU6IFBhdGggb3B0aW9ucyk6IHRoaXNcblx0Ly8gQ2hhbmdlcyB0aGUgYXBwZWFyYW5jZSBvZiBhIFBhdGggYmFzZWQgb24gdGhlIG9wdGlvbnMgaW4gdGhlIGBQYXRoIG9wdGlvbnNgIG9iamVjdC5cblx0c2V0U3R5bGU6IGZ1bmN0aW9uIChzdHlsZSkge1xuXHRcdHNldE9wdGlvbnModGhpcywgc3R5bGUpO1xuXHRcdGlmICh0aGlzLl9yZW5kZXJlcikge1xuXHRcdFx0dGhpcy5fcmVuZGVyZXIuX3VwZGF0ZVN0eWxlKHRoaXMpO1xuXHRcdFx0aWYgKHRoaXMub3B0aW9ucy5zdHJva2UgJiYgc3R5bGUuaGFzT3duUHJvcGVydHkoJ3dlaWdodCcpKSB7XG5cdFx0XHRcdHRoaXMuX3VwZGF0ZUJvdW5kcygpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udCgpOiB0aGlzXG5cdC8vIEJyaW5ncyB0aGUgbGF5ZXIgdG8gdGhlIHRvcCBvZiBhbGwgcGF0aCBsYXllcnMuXG5cdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9yZW5kZXJlcikge1xuXHRcdFx0dGhpcy5fcmVuZGVyZXIuX2JyaW5nVG9Gcm9udCh0aGlzKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBicmluZ1RvQmFjaygpOiB0aGlzXG5cdC8vIEJyaW5ncyB0aGUgbGF5ZXIgdG8gdGhlIGJvdHRvbSBvZiBhbGwgcGF0aCBsYXllcnMuXG5cdGJyaW5nVG9CYWNrOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX3JlbmRlcmVyKSB7XG5cdFx0XHR0aGlzLl9yZW5kZXJlci5fYnJpbmdUb0JhY2sodGhpcyk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdGdldEVsZW1lbnQ6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fcGF0aDtcblx0fSxcblxuXHRfcmVzZXQ6IGZ1bmN0aW9uICgpIHtcblx0XHQvLyBkZWZpbmVkIGluIGNoaWxkIGNsYXNzZXNcblx0XHR0aGlzLl9wcm9qZWN0KCk7XG5cdFx0dGhpcy5fdXBkYXRlKCk7XG5cdH0sXG5cblx0X2NsaWNrVG9sZXJhbmNlOiBmdW5jdGlvbiAoKSB7XG5cdFx0Ly8gdXNlZCB3aGVuIGRvaW5nIGhpdCBkZXRlY3Rpb24gZm9yIENhbnZhcyBsYXllcnNcblx0XHRyZXR1cm4gKHRoaXMub3B0aW9ucy5zdHJva2UgPyB0aGlzLm9wdGlvbnMud2VpZ2h0IC8gMiA6IDApICsgdGhpcy5fcmVuZGVyZXIub3B0aW9ucy50b2xlcmFuY2U7XG5cdH1cbn0pO1xuXG4vKlxuICogQGNsYXNzIENpcmNsZU1hcmtlclxuICogQGFrYSBMLkNpcmNsZU1hcmtlclxuICogQGluaGVyaXRzIFBhdGhcbiAqXG4gKiBBIGNpcmNsZSBvZiBhIGZpeGVkIHNpemUgd2l0aCByYWRpdXMgc3BlY2lmaWVkIGluIHBpeGVscy4gRXh0ZW5kcyBgUGF0aGAuXG4gKi9cblxudmFyIENpcmNsZU1hcmtlciA9IFBhdGguZXh0ZW5kKHtcblxuXHQvLyBAc2VjdGlvblxuXHQvLyBAYWthIENpcmNsZU1hcmtlciBvcHRpb25zXG5cdG9wdGlvbnM6IHtcblx0XHRmaWxsOiB0cnVlLFxuXG5cdFx0Ly8gQG9wdGlvbiByYWRpdXM6IE51bWJlciA9IDEwXG5cdFx0Ly8gUmFkaXVzIG9mIHRoZSBjaXJjbGUgbWFya2VyLCBpbiBwaXhlbHNcblx0XHRyYWRpdXM6IDEwXG5cdH0sXG5cblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxhdGxuZywgb3B0aW9ucykge1xuXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XG5cdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcblx0XHR0aGlzLl9yYWRpdXMgPSB0aGlzLm9wdGlvbnMucmFkaXVzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2Qgc2V0TGF0TG5nKGxhdExuZzogTGF0TG5nKTogdGhpc1xuXHQvLyBTZXRzIHRoZSBwb3NpdGlvbiBvZiBhIGNpcmNsZSBtYXJrZXIgdG8gYSBuZXcgbG9jYXRpb24uXG5cdHNldExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xuXHRcdHRoaXMuX2xhdGxuZyA9IHRvTGF0TG5nKGxhdGxuZyk7XG5cdFx0dGhpcy5yZWRyYXcoKTtcblx0XHRyZXR1cm4gdGhpcy5maXJlKCdtb3ZlJywge2xhdGxuZzogdGhpcy5fbGF0bG5nfSk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBnZXRMYXRMbmcoKTogTGF0TG5nXG5cdC8vIFJldHVybnMgdGhlIGN1cnJlbnQgZ2VvZ3JhcGhpY2FsIHBvc2l0aW9uIG9mIHRoZSBjaXJjbGUgbWFya2VyXG5cdGdldExhdExuZzogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLl9sYXRsbmc7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBzZXRSYWRpdXMocmFkaXVzOiBOdW1iZXIpOiB0aGlzXG5cdC8vIFNldHMgdGhlIHJhZGl1cyBvZiBhIGNpcmNsZSBtYXJrZXIuIFVuaXRzIGFyZSBpbiBwaXhlbHMuXG5cdHNldFJhZGl1czogZnVuY3Rpb24gKHJhZGl1cykge1xuXHRcdHRoaXMub3B0aW9ucy5yYWRpdXMgPSB0aGlzLl9yYWRpdXMgPSByYWRpdXM7XG5cdFx0cmV0dXJuIHRoaXMucmVkcmF3KCk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBnZXRSYWRpdXMoKTogTnVtYmVyXG5cdC8vIFJldHVybnMgdGhlIGN1cnJlbnQgcmFkaXVzIG9mIHRoZSBjaXJjbGVcblx0Z2V0UmFkaXVzOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3JhZGl1cztcblx0fSxcblxuXHRzZXRTdHlsZSA6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG5cdFx0dmFyIHJhZGl1cyA9IG9wdGlvbnMgJiYgb3B0aW9ucy5yYWRpdXMgfHwgdGhpcy5fcmFkaXVzO1xuXHRcdFBhdGgucHJvdG90eXBlLnNldFN0eWxlLmNhbGwodGhpcywgb3B0aW9ucyk7XG5cdFx0dGhpcy5zZXRSYWRpdXMocmFkaXVzKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRfcHJvamVjdDogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3BvaW50ID0gdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcpO1xuXHRcdHRoaXMuX3VwZGF0ZUJvdW5kcygpO1xuXHR9LFxuXG5cdF91cGRhdGVCb3VuZHM6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgciA9IHRoaXMuX3JhZGl1cyxcblx0XHQgICAgcjIgPSB0aGlzLl9yYWRpdXNZIHx8IHIsXG5cdFx0ICAgIHcgPSB0aGlzLl9jbGlja1RvbGVyYW5jZSgpLFxuXHRcdCAgICBwID0gW3IgKyB3LCByMiArIHddO1xuXHRcdHRoaXMuX3B4Qm91bmRzID0gbmV3IEJvdW5kcyh0aGlzLl9wb2ludC5zdWJ0cmFjdChwKSwgdGhpcy5fcG9pbnQuYWRkKHApKTtcblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcCkge1xuXHRcdFx0dGhpcy5fdXBkYXRlUGF0aCgpO1xuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlUGF0aDogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3JlbmRlcmVyLl91cGRhdGVDaXJjbGUodGhpcyk7XG5cdH0sXG5cblx0X2VtcHR5OiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3JhZGl1cyAmJiAhdGhpcy5fcmVuZGVyZXIuX2JvdW5kcy5pbnRlcnNlY3RzKHRoaXMuX3B4Qm91bmRzKTtcblx0fSxcblxuXHQvLyBOZWVkZWQgYnkgdGhlIGBDYW52YXNgIHJlbmRlcmVyIGZvciBpbnRlcmFjdGl2aXR5XG5cdF9jb250YWluc1BvaW50OiBmdW5jdGlvbiAocCkge1xuXHRcdHJldHVybiBwLmRpc3RhbmNlVG8odGhpcy5fcG9pbnQpIDw9IHRoaXMuX3JhZGl1cyArIHRoaXMuX2NsaWNrVG9sZXJhbmNlKCk7XG5cdH1cbn0pO1xuXG5cbi8vIEBmYWN0b3J5IEwuY2lyY2xlTWFya2VyKGxhdGxuZzogTGF0TG5nLCBvcHRpb25zPzogQ2lyY2xlTWFya2VyIG9wdGlvbnMpXG4vLyBJbnN0YW50aWF0ZXMgYSBjaXJjbGUgbWFya2VyIG9iamVjdCBnaXZlbiBhIGdlb2dyYXBoaWNhbCBwb2ludCwgYW5kIGFuIG9wdGlvbmFsIG9wdGlvbnMgb2JqZWN0LlxuZnVuY3Rpb24gY2lyY2xlTWFya2VyKGxhdGxuZywgb3B0aW9ucykge1xuXHRyZXR1cm4gbmV3IENpcmNsZU1hcmtlcihsYXRsbmcsIG9wdGlvbnMpO1xufVxuXG4vKlxuICogQGNsYXNzIENpcmNsZVxuICogQGFrYSBMLkNpcmNsZVxuICogQGluaGVyaXRzIENpcmNsZU1hcmtlclxuICpcbiAqIEEgY2xhc3MgZm9yIGRyYXdpbmcgY2lyY2xlIG92ZXJsYXlzIG9uIGEgbWFwLiBFeHRlbmRzIGBDaXJjbGVNYXJrZXJgLlxuICpcbiAqIEl0J3MgYW4gYXBwcm94aW1hdGlvbiBhbmQgc3RhcnRzIHRvIGRpdmVyZ2UgZnJvbSBhIHJlYWwgY2lyY2xlIGNsb3NlciB0byBwb2xlcyAoZHVlIHRvIHByb2plY3Rpb24gZGlzdG9ydGlvbikuXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGBqc1xuICogTC5jaXJjbGUoWzUwLjUsIDMwLjVdLCB7cmFkaXVzOiAyMDB9KS5hZGRUbyhtYXApO1xuICogYGBgXG4gKi9cblxudmFyIENpcmNsZSA9IENpcmNsZU1hcmtlci5leHRlbmQoe1xuXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChsYXRsbmcsIG9wdGlvbnMsIGxlZ2FjeU9wdGlvbnMpIHtcblx0XHRpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdudW1iZXInKSB7XG5cdFx0XHQvLyBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eSB3aXRoIDAuNy54IGZhY3RvcnkgKGxhdGxuZywgcmFkaXVzLCBvcHRpb25zPylcblx0XHRcdG9wdGlvbnMgPSBleHRlbmQoe30sIGxlZ2FjeU9wdGlvbnMsIHtyYWRpdXM6IG9wdGlvbnN9KTtcblx0XHR9XG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcblx0XHR0aGlzLl9sYXRsbmcgPSB0b0xhdExuZyhsYXRsbmcpO1xuXG5cdFx0aWYgKGlzTmFOKHRoaXMub3B0aW9ucy5yYWRpdXMpKSB7IHRocm93IG5ldyBFcnJvcignQ2lyY2xlIHJhZGl1cyBjYW5ub3QgYmUgTmFOJyk7IH1cblxuXHRcdC8vIEBzZWN0aW9uXG5cdFx0Ly8gQGFrYSBDaXJjbGUgb3B0aW9uc1xuXHRcdC8vIEBvcHRpb24gcmFkaXVzOiBOdW1iZXI7IFJhZGl1cyBvZiB0aGUgY2lyY2xlLCBpbiBtZXRlcnMuXG5cdFx0dGhpcy5fbVJhZGl1cyA9IHRoaXMub3B0aW9ucy5yYWRpdXM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBzZXRSYWRpdXMocmFkaXVzOiBOdW1iZXIpOiB0aGlzXG5cdC8vIFNldHMgdGhlIHJhZGl1cyBvZiBhIGNpcmNsZS4gVW5pdHMgYXJlIGluIG1ldGVycy5cblx0c2V0UmFkaXVzOiBmdW5jdGlvbiAocmFkaXVzKSB7XG5cdFx0dGhpcy5fbVJhZGl1cyA9IHJhZGl1cztcblx0XHRyZXR1cm4gdGhpcy5yZWRyYXcoKTtcblx0fSxcblxuXHQvLyBAbWV0aG9kIGdldFJhZGl1cygpOiBOdW1iZXJcblx0Ly8gUmV0dXJucyB0aGUgY3VycmVudCByYWRpdXMgb2YgYSBjaXJjbGUuIFVuaXRzIGFyZSBpbiBtZXRlcnMuXG5cdGdldFJhZGl1czogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLl9tUmFkaXVzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgZ2V0Qm91bmRzKCk6IExhdExuZ0JvdW5kc1xuXHQvLyBSZXR1cm5zIHRoZSBgTGF0TG5nQm91bmRzYCBvZiB0aGUgcGF0aC5cblx0Z2V0Qm91bmRzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGhhbGYgPSBbdGhpcy5fcmFkaXVzLCB0aGlzLl9yYWRpdXNZIHx8IHRoaXMuX3JhZGl1c107XG5cblx0XHRyZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhcblx0XHRcdHRoaXMuX21hcC5sYXllclBvaW50VG9MYXRMbmcodGhpcy5fcG9pbnQuc3VidHJhY3QoaGFsZikpLFxuXHRcdFx0dGhpcy5fbWFwLmxheWVyUG9pbnRUb0xhdExuZyh0aGlzLl9wb2ludC5hZGQoaGFsZikpKTtcblx0fSxcblxuXHRzZXRTdHlsZTogUGF0aC5wcm90b3R5cGUuc2V0U3R5bGUsXG5cblx0X3Byb2plY3Q6IGZ1bmN0aW9uICgpIHtcblxuXHRcdHZhciBsbmcgPSB0aGlzLl9sYXRsbmcubG5nLFxuXHRcdCAgICBsYXQgPSB0aGlzLl9sYXRsbmcubGF0LFxuXHRcdCAgICBtYXAgPSB0aGlzLl9tYXAsXG5cdFx0ICAgIGNycyA9IG1hcC5vcHRpb25zLmNycztcblxuXHRcdGlmIChjcnMuZGlzdGFuY2UgPT09IEVhcnRoLmRpc3RhbmNlKSB7XG5cdFx0XHR2YXIgZCA9IE1hdGguUEkgLyAxODAsXG5cdFx0XHQgICAgbGF0UiA9ICh0aGlzLl9tUmFkaXVzIC8gRWFydGguUikgLyBkLFxuXHRcdFx0ICAgIHRvcCA9IG1hcC5wcm9qZWN0KFtsYXQgKyBsYXRSLCBsbmddKSxcblx0XHRcdCAgICBib3R0b20gPSBtYXAucHJvamVjdChbbGF0IC0gbGF0UiwgbG5nXSksXG5cdFx0XHQgICAgcCA9IHRvcC5hZGQoYm90dG9tKS5kaXZpZGVCeSgyKSxcblx0XHRcdCAgICBsYXQyID0gbWFwLnVucHJvamVjdChwKS5sYXQsXG5cdFx0XHQgICAgbG5nUiA9IE1hdGguYWNvcygoTWF0aC5jb3MobGF0UiAqIGQpIC0gTWF0aC5zaW4obGF0ICogZCkgKiBNYXRoLnNpbihsYXQyICogZCkpIC9cblx0XHRcdCAgICAgICAgICAgIChNYXRoLmNvcyhsYXQgKiBkKSAqIE1hdGguY29zKGxhdDIgKiBkKSkpIC8gZDtcblxuXHRcdFx0aWYgKGlzTmFOKGxuZ1IpIHx8IGxuZ1IgPT09IDApIHtcblx0XHRcdFx0bG5nUiA9IGxhdFIgLyBNYXRoLmNvcyhNYXRoLlBJIC8gMTgwICogbGF0KTsgLy8gRmFsbGJhY2sgZm9yIGVkZ2UgY2FzZSwgIzI0MjVcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5fcG9pbnQgPSBwLnN1YnRyYWN0KG1hcC5nZXRQaXhlbE9yaWdpbigpKTtcblx0XHRcdHRoaXMuX3JhZGl1cyA9IGlzTmFOKGxuZ1IpID8gMCA6IHAueCAtIG1hcC5wcm9qZWN0KFtsYXQyLCBsbmcgLSBsbmdSXSkueDtcblx0XHRcdHRoaXMuX3JhZGl1c1kgPSBwLnkgLSB0b3AueTtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgbGF0bG5nMiA9IGNycy51bnByb2plY3QoY3JzLnByb2plY3QodGhpcy5fbGF0bG5nKS5zdWJ0cmFjdChbdGhpcy5fbVJhZGl1cywgMF0pKTtcblxuXHRcdFx0dGhpcy5fcG9pbnQgPSBtYXAubGF0TG5nVG9MYXllclBvaW50KHRoaXMuX2xhdGxuZyk7XG5cdFx0XHR0aGlzLl9yYWRpdXMgPSB0aGlzLl9wb2ludC54IC0gbWFwLmxhdExuZ1RvTGF5ZXJQb2ludChsYXRsbmcyKS54O1xuXHRcdH1cblxuXHRcdHRoaXMuX3VwZGF0ZUJvdW5kcygpO1xuXHR9XG59KTtcblxuLy8gQGZhY3RvcnkgTC5jaXJjbGUobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBDaXJjbGUgb3B0aW9ucylcbi8vIEluc3RhbnRpYXRlcyBhIGNpcmNsZSBvYmplY3QgZ2l2ZW4gYSBnZW9ncmFwaGljYWwgcG9pbnQsIGFuZCBhbiBvcHRpb25zIG9iamVjdFxuLy8gd2hpY2ggY29udGFpbnMgdGhlIGNpcmNsZSByYWRpdXMuXG4vLyBAYWx0ZXJuYXRpdmVcbi8vIEBmYWN0b3J5IEwuY2lyY2xlKGxhdGxuZzogTGF0TG5nLCByYWRpdXM6IE51bWJlciwgb3B0aW9ucz86IENpcmNsZSBvcHRpb25zKVxuLy8gT2Jzb2xldGUgd2F5IG9mIGluc3RhbnRpYXRpbmcgYSBjaXJjbGUsIGZvciBjb21wYXRpYmlsaXR5IHdpdGggMC43LnggY29kZS5cbi8vIERvIG5vdCB1c2UgaW4gbmV3IGFwcGxpY2F0aW9ucyBvciBwbHVnaW5zLlxuZnVuY3Rpb24gY2lyY2xlKGxhdGxuZywgb3B0aW9ucywgbGVnYWN5T3B0aW9ucykge1xuXHRyZXR1cm4gbmV3IENpcmNsZShsYXRsbmcsIG9wdGlvbnMsIGxlZ2FjeU9wdGlvbnMpO1xufVxuXG4vKlxuICogQGNsYXNzIFBvbHlsaW5lXG4gKiBAYWthIEwuUG9seWxpbmVcbiAqIEBpbmhlcml0cyBQYXRoXG4gKlxuICogQSBjbGFzcyBmb3IgZHJhd2luZyBwb2x5bGluZSBvdmVybGF5cyBvbiBhIG1hcC4gRXh0ZW5kcyBgUGF0aGAuXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGBqc1xuICogLy8gY3JlYXRlIGEgcmVkIHBvbHlsaW5lIGZyb20gYW4gYXJyYXkgb2YgTGF0TG5nIHBvaW50c1xuICogdmFyIGxhdGxuZ3MgPSBbXG4gKiBcdFs0NS41MSwgLTEyMi42OF0sXG4gKiBcdFszNy43NywgLTEyMi40M10sXG4gKiBcdFszNC4wNCwgLTExOC4yXVxuICogXTtcbiAqXG4gKiB2YXIgcG9seWxpbmUgPSBMLnBvbHlsaW5lKGxhdGxuZ3MsIHtjb2xvcjogJ3JlZCd9KS5hZGRUbyhtYXApO1xuICpcbiAqIC8vIHpvb20gdGhlIG1hcCB0byB0aGUgcG9seWxpbmVcbiAqIG1hcC5maXRCb3VuZHMocG9seWxpbmUuZ2V0Qm91bmRzKCkpO1xuICogYGBgXG4gKlxuICogWW91IGNhbiBhbHNvIHBhc3MgYSBtdWx0aS1kaW1lbnNpb25hbCBhcnJheSB0byByZXByZXNlbnQgYSBgTXVsdGlQb2x5bGluZWAgc2hhcGU6XG4gKlxuICogYGBganNcbiAqIC8vIGNyZWF0ZSBhIHJlZCBwb2x5bGluZSBmcm9tIGFuIGFycmF5IG9mIGFycmF5cyBvZiBMYXRMbmcgcG9pbnRzXG4gKiB2YXIgbGF0bG5ncyA9IFtcbiAqIFx0W1s0NS41MSwgLTEyMi42OF0sXG4gKiBcdCBbMzcuNzcsIC0xMjIuNDNdLFxuICogXHQgWzM0LjA0LCAtMTE4LjJdXSxcbiAqIFx0W1s0MC43OCwgLTczLjkxXSxcbiAqIFx0IFs0MS44MywgLTg3LjYyXSxcbiAqIFx0IFszMi43NiwgLTk2LjcyXV1cbiAqIF07XG4gKiBgYGBcbiAqL1xuXG5cbnZhciBQb2x5bGluZSA9IFBhdGguZXh0ZW5kKHtcblxuXHQvLyBAc2VjdGlvblxuXHQvLyBAYWthIFBvbHlsaW5lIG9wdGlvbnNcblx0b3B0aW9uczoge1xuXHRcdC8vIEBvcHRpb24gc21vb3RoRmFjdG9yOiBOdW1iZXIgPSAxLjBcblx0XHQvLyBIb3cgbXVjaCB0byBzaW1wbGlmeSB0aGUgcG9seWxpbmUgb24gZWFjaCB6b29tIGxldmVsLiBNb3JlIG1lYW5zXG5cdFx0Ly8gYmV0dGVyIHBlcmZvcm1hbmNlIGFuZCBzbW9vdGhlciBsb29rLCBhbmQgbGVzcyBtZWFucyBtb3JlIGFjY3VyYXRlIHJlcHJlc2VudGF0aW9uLlxuXHRcdHNtb290aEZhY3RvcjogMS4wLFxuXG5cdFx0Ly8gQG9wdGlvbiBub0NsaXA6IEJvb2xlYW4gPSBmYWxzZVxuXHRcdC8vIERpc2FibGUgcG9seWxpbmUgY2xpcHBpbmcuXG5cdFx0bm9DbGlwOiBmYWxzZVxuXHR9LFxuXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChsYXRsbmdzLCBvcHRpb25zKSB7XG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcblx0XHR0aGlzLl9zZXRMYXRMbmdzKGxhdGxuZ3MpO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgZ2V0TGF0TG5ncygpOiBMYXRMbmdbXVxuXHQvLyBSZXR1cm5zIGFuIGFycmF5IG9mIHRoZSBwb2ludHMgaW4gdGhlIHBhdGgsIG9yIG5lc3RlZCBhcnJheXMgb2YgcG9pbnRzIGluIGNhc2Ugb2YgbXVsdGktcG9seWxpbmUuXG5cdGdldExhdExuZ3M6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fbGF0bG5ncztcblx0fSxcblxuXHQvLyBAbWV0aG9kIHNldExhdExuZ3MobGF0bG5nczogTGF0TG5nW10pOiB0aGlzXG5cdC8vIFJlcGxhY2VzIGFsbCB0aGUgcG9pbnRzIGluIHRoZSBwb2x5bGluZSB3aXRoIHRoZSBnaXZlbiBhcnJheSBvZiBnZW9ncmFwaGljYWwgcG9pbnRzLlxuXHRzZXRMYXRMbmdzOiBmdW5jdGlvbiAobGF0bG5ncykge1xuXHRcdHRoaXMuX3NldExhdExuZ3MobGF0bG5ncyk7XG5cdFx0cmV0dXJuIHRoaXMucmVkcmF3KCk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBpc0VtcHR5KCk6IEJvb2xlYW5cblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIFBvbHlsaW5lIGhhcyBubyBMYXRMbmdzLlxuXHRpc0VtcHR5OiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuICF0aGlzLl9sYXRsbmdzLmxlbmd0aDtcblx0fSxcblxuXHQvLyBAbWV0aG9kIGNsb3Nlc3RMYXllclBvaW50KHA6IFBvaW50KTogUG9pbnRcblx0Ly8gUmV0dXJucyB0aGUgcG9pbnQgY2xvc2VzdCB0byBgcGAgb24gdGhlIFBvbHlsaW5lLlxuXHRjbG9zZXN0TGF5ZXJQb2ludDogZnVuY3Rpb24gKHApIHtcblx0XHR2YXIgbWluRGlzdGFuY2UgPSBJbmZpbml0eSxcblx0XHQgICAgbWluUG9pbnQgPSBudWxsLFxuXHRcdCAgICBjbG9zZXN0ID0gX3NxQ2xvc2VzdFBvaW50T25TZWdtZW50LFxuXHRcdCAgICBwMSwgcDI7XG5cblx0XHRmb3IgKHZhciBqID0gMCwgakxlbiA9IHRoaXMuX3BhcnRzLmxlbmd0aDsgaiA8IGpMZW47IGorKykge1xuXHRcdFx0dmFyIHBvaW50cyA9IHRoaXMuX3BhcnRzW2pdO1xuXG5cdFx0XHRmb3IgKHZhciBpID0gMSwgbGVuID0gcG9pbnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRcdHAxID0gcG9pbnRzW2kgLSAxXTtcblx0XHRcdFx0cDIgPSBwb2ludHNbaV07XG5cblx0XHRcdFx0dmFyIHNxRGlzdCA9IGNsb3Nlc3QocCwgcDEsIHAyLCB0cnVlKTtcblxuXHRcdFx0XHRpZiAoc3FEaXN0IDwgbWluRGlzdGFuY2UpIHtcblx0XHRcdFx0XHRtaW5EaXN0YW5jZSA9IHNxRGlzdDtcblx0XHRcdFx0XHRtaW5Qb2ludCA9IGNsb3Nlc3QocCwgcDEsIHAyKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAobWluUG9pbnQpIHtcblx0XHRcdG1pblBvaW50LmRpc3RhbmNlID0gTWF0aC5zcXJ0KG1pbkRpc3RhbmNlKTtcblx0XHR9XG5cdFx0cmV0dXJuIG1pblBvaW50O1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgZ2V0Q2VudGVyKCk6IExhdExuZ1xuXHQvLyBSZXR1cm5zIHRoZSBjZW50ZXIgKFtjZW50cm9pZF0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DZW50cm9pZCkpIG9mIHRoZSBwb2x5bGluZS5cblx0Z2V0Q2VudGVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0Ly8gdGhyb3dzIGVycm9yIHdoZW4gbm90IHlldCBhZGRlZCB0byBtYXAgYXMgdGhpcyBjZW50ZXIgY2FsY3VsYXRpb24gcmVxdWlyZXMgcHJvamVjdGVkIGNvb3JkaW5hdGVzXG5cdFx0aWYgKCF0aGlzLl9tYXApIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignTXVzdCBhZGQgbGF5ZXIgdG8gbWFwIGJlZm9yZSB1c2luZyBnZXRDZW50ZXIoKScpO1xuXHRcdH1cblxuXHRcdHZhciBpLCBoYWxmRGlzdCwgc2VnRGlzdCwgZGlzdCwgcDEsIHAyLCByYXRpbyxcblx0XHQgICAgcG9pbnRzID0gdGhpcy5fcmluZ3NbMF0sXG5cdFx0ICAgIGxlbiA9IHBvaW50cy5sZW5ndGg7XG5cblx0XHRpZiAoIWxlbikgeyByZXR1cm4gbnVsbDsgfVxuXG5cdFx0Ly8gcG9seWxpbmUgY2VudHJvaWQgYWxnb3JpdGhtOyBvbmx5IHVzZXMgdGhlIGZpcnN0IHJpbmcgaWYgdGhlcmUgYXJlIG11bHRpcGxlXG5cblx0XHRmb3IgKGkgPSAwLCBoYWxmRGlzdCA9IDA7IGkgPCBsZW4gLSAxOyBpKyspIHtcblx0XHRcdGhhbGZEaXN0ICs9IHBvaW50c1tpXS5kaXN0YW5jZVRvKHBvaW50c1tpICsgMV0pIC8gMjtcblx0XHR9XG5cblx0XHQvLyBUaGUgbGluZSBpcyBzbyBzbWFsbCBpbiB0aGUgY3VycmVudCB2aWV3IHRoYXQgYWxsIHBvaW50cyBhcmUgb24gdGhlIHNhbWUgcGl4ZWwuXG5cdFx0aWYgKGhhbGZEaXN0ID09PSAwKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fbWFwLmxheWVyUG9pbnRUb0xhdExuZyhwb2ludHNbMF0pO1xuXHRcdH1cblxuXHRcdGZvciAoaSA9IDAsIGRpc3QgPSAwOyBpIDwgbGVuIC0gMTsgaSsrKSB7XG5cdFx0XHRwMSA9IHBvaW50c1tpXTtcblx0XHRcdHAyID0gcG9pbnRzW2kgKyAxXTtcblx0XHRcdHNlZ0Rpc3QgPSBwMS5kaXN0YW5jZVRvKHAyKTtcblx0XHRcdGRpc3QgKz0gc2VnRGlzdDtcblxuXHRcdFx0aWYgKGRpc3QgPiBoYWxmRGlzdCkge1xuXHRcdFx0XHRyYXRpbyA9IChkaXN0IC0gaGFsZkRpc3QpIC8gc2VnRGlzdDtcblx0XHRcdFx0cmV0dXJuIHRoaXMuX21hcC5sYXllclBvaW50VG9MYXRMbmcoW1xuXHRcdFx0XHRcdHAyLnggLSByYXRpbyAqIChwMi54IC0gcDEueCksXG5cdFx0XHRcdFx0cDIueSAtIHJhdGlvICogKHAyLnkgLSBwMS55KVxuXHRcdFx0XHRdKTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBnZXRCb3VuZHMoKTogTGF0TG5nQm91bmRzXG5cdC8vIFJldHVybnMgdGhlIGBMYXRMbmdCb3VuZHNgIG9mIHRoZSBwYXRoLlxuXHRnZXRCb3VuZHM6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fYm91bmRzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgYWRkTGF0TG5nKGxhdGxuZzogTGF0TG5nLCBsYXRsbmdzPyBMYXRMbmdbXSk6IHRoaXNcblx0Ly8gQWRkcyBhIGdpdmVuIHBvaW50IHRvIHRoZSBwb2x5bGluZS4gQnkgZGVmYXVsdCwgYWRkcyB0byB0aGUgZmlyc3QgcmluZyBvZlxuXHQvLyB0aGUgcG9seWxpbmUgaW4gY2FzZSBvZiBhIG11bHRpLXBvbHlsaW5lLCBidXQgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZ1xuXHQvLyBhIHNwZWNpZmljIHJpbmcgYXMgYSBMYXRMbmcgYXJyYXkgKHRoYXQgeW91IGNhbiBlYXJsaWVyIGFjY2VzcyB3aXRoIFtgZ2V0TGF0TG5nc2BdKCNwb2x5bGluZS1nZXRsYXRsbmdzKSkuXG5cdGFkZExhdExuZzogZnVuY3Rpb24gKGxhdGxuZywgbGF0bG5ncykge1xuXHRcdGxhdGxuZ3MgPSBsYXRsbmdzIHx8IHRoaXMuX2RlZmF1bHRTaGFwZSgpO1xuXHRcdGxhdGxuZyA9IHRvTGF0TG5nKGxhdGxuZyk7XG5cdFx0bGF0bG5ncy5wdXNoKGxhdGxuZyk7XG5cdFx0dGhpcy5fYm91bmRzLmV4dGVuZChsYXRsbmcpO1xuXHRcdHJldHVybiB0aGlzLnJlZHJhdygpO1xuXHR9LFxuXG5cdF9zZXRMYXRMbmdzOiBmdW5jdGlvbiAobGF0bG5ncykge1xuXHRcdHRoaXMuX2JvdW5kcyA9IG5ldyBMYXRMbmdCb3VuZHMoKTtcblx0XHR0aGlzLl9sYXRsbmdzID0gdGhpcy5fY29udmVydExhdExuZ3MobGF0bG5ncyk7XG5cdH0sXG5cblx0X2RlZmF1bHRTaGFwZTogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiBpc0ZsYXQodGhpcy5fbGF0bG5ncykgPyB0aGlzLl9sYXRsbmdzIDogdGhpcy5fbGF0bG5nc1swXTtcblx0fSxcblxuXHQvLyByZWN1cnNpdmVseSBjb252ZXJ0IGxhdGxuZ3MgaW5wdXQgaW50byBhY3R1YWwgTGF0TG5nIGluc3RhbmNlczsgY2FsY3VsYXRlIGJvdW5kcyBhbG9uZyB0aGUgd2F5XG5cdF9jb252ZXJ0TGF0TG5nczogZnVuY3Rpb24gKGxhdGxuZ3MpIHtcblx0XHR2YXIgcmVzdWx0ID0gW10sXG5cdFx0ICAgIGZsYXQgPSBpc0ZsYXQobGF0bG5ncyk7XG5cblx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gbGF0bG5ncy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0aWYgKGZsYXQpIHtcblx0XHRcdFx0cmVzdWx0W2ldID0gdG9MYXRMbmcobGF0bG5nc1tpXSk7XG5cdFx0XHRcdHRoaXMuX2JvdW5kcy5leHRlbmQocmVzdWx0W2ldKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJlc3VsdFtpXSA9IHRoaXMuX2NvbnZlcnRMYXRMbmdzKGxhdGxuZ3NbaV0pO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH0sXG5cblx0X3Byb2plY3Q6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgcHhCb3VuZHMgPSBuZXcgQm91bmRzKCk7XG5cdFx0dGhpcy5fcmluZ3MgPSBbXTtcblx0XHR0aGlzLl9wcm9qZWN0TGF0bG5ncyh0aGlzLl9sYXRsbmdzLCB0aGlzLl9yaW5ncywgcHhCb3VuZHMpO1xuXG5cdFx0aWYgKHRoaXMuX2JvdW5kcy5pc1ZhbGlkKCkgJiYgcHhCb3VuZHMuaXNWYWxpZCgpKSB7XG5cdFx0XHR0aGlzLl9yYXdQeEJvdW5kcyA9IHB4Qm91bmRzO1xuXHRcdFx0dGhpcy5fdXBkYXRlQm91bmRzKCk7XG5cdFx0fVxuXHR9LFxuXG5cdF91cGRhdGVCb3VuZHM6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgdyA9IHRoaXMuX2NsaWNrVG9sZXJhbmNlKCksXG5cdFx0ICAgIHAgPSBuZXcgUG9pbnQodywgdyk7XG5cdFx0dGhpcy5fcHhCb3VuZHMgPSBuZXcgQm91bmRzKFtcblx0XHRcdHRoaXMuX3Jhd1B4Qm91bmRzLm1pbi5zdWJ0cmFjdChwKSxcblx0XHRcdHRoaXMuX3Jhd1B4Qm91bmRzLm1heC5hZGQocClcblx0XHRdKTtcblx0fSxcblxuXHQvLyByZWN1cnNpdmVseSB0dXJucyBsYXRsbmdzIGludG8gYSBzZXQgb2YgcmluZ3Mgd2l0aCBwcm9qZWN0ZWQgY29vcmRpbmF0ZXNcblx0X3Byb2plY3RMYXRsbmdzOiBmdW5jdGlvbiAobGF0bG5ncywgcmVzdWx0LCBwcm9qZWN0ZWRCb3VuZHMpIHtcblx0XHR2YXIgZmxhdCA9IGxhdGxuZ3NbMF0gaW5zdGFuY2VvZiBMYXRMbmcsXG5cdFx0ICAgIGxlbiA9IGxhdGxuZ3MubGVuZ3RoLFxuXHRcdCAgICBpLCByaW5nO1xuXG5cdFx0aWYgKGZsYXQpIHtcblx0XHRcdHJpbmcgPSBbXTtcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0XHRyaW5nW2ldID0gdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludChsYXRsbmdzW2ldKTtcblx0XHRcdFx0cHJvamVjdGVkQm91bmRzLmV4dGVuZChyaW5nW2ldKTtcblx0XHRcdH1cblx0XHRcdHJlc3VsdC5wdXNoKHJpbmcpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdFx0dGhpcy5fcHJvamVjdExhdGxuZ3MobGF0bG5nc1tpXSwgcmVzdWx0LCBwcm9qZWN0ZWRCb3VuZHMpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHQvLyBjbGlwIHBvbHlsaW5lIGJ5IHJlbmRlcmVyIGJvdW5kcyBzbyB0aGF0IHdlIGhhdmUgbGVzcyB0byByZW5kZXIgZm9yIHBlcmZvcm1hbmNlXG5cdF9jbGlwUG9pbnRzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGJvdW5kcyA9IHRoaXMuX3JlbmRlcmVyLl9ib3VuZHM7XG5cblx0XHR0aGlzLl9wYXJ0cyA9IFtdO1xuXHRcdGlmICghdGhpcy5fcHhCb3VuZHMgfHwgIXRoaXMuX3B4Qm91bmRzLmludGVyc2VjdHMoYm91bmRzKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLm9wdGlvbnMubm9DbGlwKSB7XG5cdFx0XHR0aGlzLl9wYXJ0cyA9IHRoaXMuX3JpbmdzO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBwYXJ0cyA9IHRoaXMuX3BhcnRzLFxuXHRcdCAgICBpLCBqLCBrLCBsZW4sIGxlbjIsIHNlZ21lbnQsIHBvaW50cztcblxuXHRcdGZvciAoaSA9IDAsIGsgPSAwLCBsZW4gPSB0aGlzLl9yaW5ncy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0cG9pbnRzID0gdGhpcy5fcmluZ3NbaV07XG5cblx0XHRcdGZvciAoaiA9IDAsIGxlbjIgPSBwb2ludHMubGVuZ3RoOyBqIDwgbGVuMiAtIDE7IGorKykge1xuXHRcdFx0XHRzZWdtZW50ID0gY2xpcFNlZ21lbnQocG9pbnRzW2pdLCBwb2ludHNbaiArIDFdLCBib3VuZHMsIGosIHRydWUpO1xuXG5cdFx0XHRcdGlmICghc2VnbWVudCkgeyBjb250aW51ZTsgfVxuXG5cdFx0XHRcdHBhcnRzW2tdID0gcGFydHNba10gfHwgW107XG5cdFx0XHRcdHBhcnRzW2tdLnB1c2goc2VnbWVudFswXSk7XG5cblx0XHRcdFx0Ly8gaWYgc2VnbWVudCBnb2VzIG91dCBvZiBzY3JlZW4sIG9yIGl0J3MgdGhlIGxhc3Qgb25lLCBpdCdzIHRoZSBlbmQgb2YgdGhlIGxpbmUgcGFydFxuXHRcdFx0XHRpZiAoKHNlZ21lbnRbMV0gIT09IHBvaW50c1tqICsgMV0pIHx8IChqID09PSBsZW4yIC0gMikpIHtcblx0XHRcdFx0XHRwYXJ0c1trXS5wdXNoKHNlZ21lbnRbMV0pO1xuXHRcdFx0XHRcdGsrKztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHQvLyBzaW1wbGlmeSBlYWNoIGNsaXBwZWQgcGFydCBvZiB0aGUgcG9seWxpbmUgZm9yIHBlcmZvcm1hbmNlXG5cdF9zaW1wbGlmeVBvaW50czogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBwYXJ0cyA9IHRoaXMuX3BhcnRzLFxuXHRcdCAgICB0b2xlcmFuY2UgPSB0aGlzLm9wdGlvbnMuc21vb3RoRmFjdG9yO1xuXG5cdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHBhcnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRwYXJ0c1tpXSA9IHNpbXBsaWZ5KHBhcnRzW2ldLCB0b2xlcmFuY2UpO1xuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cblx0XHR0aGlzLl9jbGlwUG9pbnRzKCk7XG5cdFx0dGhpcy5fc2ltcGxpZnlQb2ludHMoKTtcblx0XHR0aGlzLl91cGRhdGVQYXRoKCk7XG5cdH0sXG5cblx0X3VwZGF0ZVBhdGg6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9yZW5kZXJlci5fdXBkYXRlUG9seSh0aGlzKTtcblx0fSxcblxuXHQvLyBOZWVkZWQgYnkgdGhlIGBDYW52YXNgIHJlbmRlcmVyIGZvciBpbnRlcmFjdGl2aXR5XG5cdF9jb250YWluc1BvaW50OiBmdW5jdGlvbiAocCwgY2xvc2VkKSB7XG5cdFx0dmFyIGksIGosIGssIGxlbiwgbGVuMiwgcGFydCxcblx0XHQgICAgdyA9IHRoaXMuX2NsaWNrVG9sZXJhbmNlKCk7XG5cblx0XHRpZiAoIXRoaXMuX3B4Qm91bmRzIHx8ICF0aGlzLl9weEJvdW5kcy5jb250YWlucyhwKSkgeyByZXR1cm4gZmFsc2U7IH1cblxuXHRcdC8vIGhpdCBkZXRlY3Rpb24gZm9yIHBvbHlsaW5lc1xuXHRcdGZvciAoaSA9IDAsIGxlbiA9IHRoaXMuX3BhcnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRwYXJ0ID0gdGhpcy5fcGFydHNbaV07XG5cblx0XHRcdGZvciAoaiA9IDAsIGxlbjIgPSBwYXJ0Lmxlbmd0aCwgayA9IGxlbjIgLSAxOyBqIDwgbGVuMjsgayA9IGorKykge1xuXHRcdFx0XHRpZiAoIWNsb3NlZCAmJiAoaiA9PT0gMCkpIHsgY29udGludWU7IH1cblxuXHRcdFx0XHRpZiAocG9pbnRUb1NlZ21lbnREaXN0YW5jZShwLCBwYXJ0W2tdLCBwYXJ0W2pdKSA8PSB3KSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59KTtcblxuLy8gQGZhY3RvcnkgTC5wb2x5bGluZShsYXRsbmdzOiBMYXRMbmdbXSwgb3B0aW9ucz86IFBvbHlsaW5lIG9wdGlvbnMpXG4vLyBJbnN0YW50aWF0ZXMgYSBwb2x5bGluZSBvYmplY3QgZ2l2ZW4gYW4gYXJyYXkgb2YgZ2VvZ3JhcGhpY2FsIHBvaW50cyBhbmRcbi8vIG9wdGlvbmFsbHkgYW4gb3B0aW9ucyBvYmplY3QuIFlvdSBjYW4gY3JlYXRlIGEgYFBvbHlsaW5lYCBvYmplY3Qgd2l0aFxuLy8gbXVsdGlwbGUgc2VwYXJhdGUgbGluZXMgKGBNdWx0aVBvbHlsaW5lYCkgYnkgcGFzc2luZyBhbiBhcnJheSBvZiBhcnJheXNcbi8vIG9mIGdlb2dyYXBoaWMgcG9pbnRzLlxuZnVuY3Rpb24gcG9seWxpbmUobGF0bG5ncywgb3B0aW9ucykge1xuXHRyZXR1cm4gbmV3IFBvbHlsaW5lKGxhdGxuZ3MsIG9wdGlvbnMpO1xufVxuXG4vLyBSZXRyb2NvbXBhdC4gQWxsb3cgcGx1Z2lucyB0byBzdXBwb3J0IExlYWZsZXQgdmVyc2lvbnMgYmVmb3JlIGFuZCBhZnRlciAxLjEuXG5Qb2x5bGluZS5fZmxhdCA9IF9mbGF0O1xuXG4vKlxuICogQGNsYXNzIFBvbHlnb25cbiAqIEBha2EgTC5Qb2x5Z29uXG4gKiBAaW5oZXJpdHMgUG9seWxpbmVcbiAqXG4gKiBBIGNsYXNzIGZvciBkcmF3aW5nIHBvbHlnb24gb3ZlcmxheXMgb24gYSBtYXAuIEV4dGVuZHMgYFBvbHlsaW5lYC5cbiAqXG4gKiBOb3RlIHRoYXQgcG9pbnRzIHlvdSBwYXNzIHdoZW4gY3JlYXRpbmcgYSBwb2x5Z29uIHNob3VsZG4ndCBoYXZlIGFuIGFkZGl0aW9uYWwgbGFzdCBwb2ludCBlcXVhbCB0byB0aGUgZmlyc3Qgb25lIOKAlCBpdCdzIGJldHRlciB0byBmaWx0ZXIgb3V0IHN1Y2ggcG9pbnRzLlxuICpcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIGBgYGpzXG4gKiAvLyBjcmVhdGUgYSByZWQgcG9seWdvbiBmcm9tIGFuIGFycmF5IG9mIExhdExuZyBwb2ludHNcbiAqIHZhciBsYXRsbmdzID0gW1szNywgLTEwOS4wNV0sWzQxLCAtMTA5LjAzXSxbNDEsIC0xMDIuMDVdLFszNywgLTEwMi4wNF1dO1xuICpcbiAqIHZhciBwb2x5Z29uID0gTC5wb2x5Z29uKGxhdGxuZ3MsIHtjb2xvcjogJ3JlZCd9KS5hZGRUbyhtYXApO1xuICpcbiAqIC8vIHpvb20gdGhlIG1hcCB0byB0aGUgcG9seWdvblxuICogbWFwLmZpdEJvdW5kcyhwb2x5Z29uLmdldEJvdW5kcygpKTtcbiAqIGBgYFxuICpcbiAqIFlvdSBjYW4gYWxzbyBwYXNzIGFuIGFycmF5IG9mIGFycmF5cyBvZiBsYXRsbmdzLCB3aXRoIHRoZSBmaXJzdCBhcnJheSByZXByZXNlbnRpbmcgdGhlIG91dGVyIHNoYXBlIGFuZCB0aGUgb3RoZXIgYXJyYXlzIHJlcHJlc2VudGluZyBob2xlcyBpbiB0aGUgb3V0ZXIgc2hhcGU6XG4gKlxuICogYGBganNcbiAqIHZhciBsYXRsbmdzID0gW1xuICogICBbWzM3LCAtMTA5LjA1XSxbNDEsIC0xMDkuMDNdLFs0MSwgLTEwMi4wNV0sWzM3LCAtMTAyLjA0XV0sIC8vIG91dGVyIHJpbmdcbiAqICAgW1szNy4yOSwgLTEwOC41OF0sWzQwLjcxLCAtMTA4LjU4XSxbNDAuNzEsIC0xMDIuNTBdLFszNy4yOSwgLTEwMi41MF1dIC8vIGhvbGVcbiAqIF07XG4gKiBgYGBcbiAqXG4gKiBBZGRpdGlvbmFsbHksIHlvdSBjYW4gcGFzcyBhIG11bHRpLWRpbWVuc2lvbmFsIGFycmF5IHRvIHJlcHJlc2VudCBhIE11bHRpUG9seWdvbiBzaGFwZS5cbiAqXG4gKiBgYGBqc1xuICogdmFyIGxhdGxuZ3MgPSBbXG4gKiAgIFsgLy8gZmlyc3QgcG9seWdvblxuICogICAgIFtbMzcsIC0xMDkuMDVdLFs0MSwgLTEwOS4wM10sWzQxLCAtMTAyLjA1XSxbMzcsIC0xMDIuMDRdXSwgLy8gb3V0ZXIgcmluZ1xuICogICAgIFtbMzcuMjksIC0xMDguNThdLFs0MC43MSwgLTEwOC41OF0sWzQwLjcxLCAtMTAyLjUwXSxbMzcuMjksIC0xMDIuNTBdXSAvLyBob2xlXG4gKiAgIF0sXG4gKiAgIFsgLy8gc2Vjb25kIHBvbHlnb25cbiAqICAgICBbWzQxLCAtMTExLjAzXSxbNDUsIC0xMTEuMDRdLFs0NSwgLTEwNC4wNV0sWzQxLCAtMTA0LjA1XV1cbiAqICAgXVxuICogXTtcbiAqIGBgYFxuICovXG5cbnZhciBQb2x5Z29uID0gUG9seWxpbmUuZXh0ZW5kKHtcblxuXHRvcHRpb25zOiB7XG5cdFx0ZmlsbDogdHJ1ZVxuXHR9LFxuXG5cdGlzRW1wdHk6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gIXRoaXMuX2xhdGxuZ3MubGVuZ3RoIHx8ICF0aGlzLl9sYXRsbmdzWzBdLmxlbmd0aDtcblx0fSxcblxuXHRnZXRDZW50ZXI6IGZ1bmN0aW9uICgpIHtcblx0XHQvLyB0aHJvd3MgZXJyb3Igd2hlbiBub3QgeWV0IGFkZGVkIHRvIG1hcCBhcyB0aGlzIGNlbnRlciBjYWxjdWxhdGlvbiByZXF1aXJlcyBwcm9qZWN0ZWQgY29vcmRpbmF0ZXNcblx0XHRpZiAoIXRoaXMuX21hcCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdNdXN0IGFkZCBsYXllciB0byBtYXAgYmVmb3JlIHVzaW5nIGdldENlbnRlcigpJyk7XG5cdFx0fVxuXG5cdFx0dmFyIGksIGosIHAxLCBwMiwgZiwgYXJlYSwgeCwgeSwgY2VudGVyLFxuXHRcdCAgICBwb2ludHMgPSB0aGlzLl9yaW5nc1swXSxcblx0XHQgICAgbGVuID0gcG9pbnRzLmxlbmd0aDtcblxuXHRcdGlmICghbGVuKSB7IHJldHVybiBudWxsOyB9XG5cblx0XHQvLyBwb2x5Z29uIGNlbnRyb2lkIGFsZ29yaXRobTsgb25seSB1c2VzIHRoZSBmaXJzdCByaW5nIGlmIHRoZXJlIGFyZSBtdWx0aXBsZVxuXG5cdFx0YXJlYSA9IHggPSB5ID0gMDtcblxuXHRcdGZvciAoaSA9IDAsIGogPSBsZW4gLSAxOyBpIDwgbGVuOyBqID0gaSsrKSB7XG5cdFx0XHRwMSA9IHBvaW50c1tpXTtcblx0XHRcdHAyID0gcG9pbnRzW2pdO1xuXG5cdFx0XHRmID0gcDEueSAqIHAyLnggLSBwMi55ICogcDEueDtcblx0XHRcdHggKz0gKHAxLnggKyBwMi54KSAqIGY7XG5cdFx0XHR5ICs9IChwMS55ICsgcDIueSkgKiBmO1xuXHRcdFx0YXJlYSArPSBmICogMztcblx0XHR9XG5cblx0XHRpZiAoYXJlYSA9PT0gMCkge1xuXHRcdFx0Ly8gUG9seWdvbiBpcyBzbyBzbWFsbCB0aGF0IGFsbCBwb2ludHMgYXJlIG9uIHNhbWUgcGl4ZWwuXG5cdFx0XHRjZW50ZXIgPSBwb2ludHNbMF07XG5cdFx0fSBlbHNlIHtcblx0XHRcdGNlbnRlciA9IFt4IC8gYXJlYSwgeSAvIGFyZWFdO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5fbWFwLmxheWVyUG9pbnRUb0xhdExuZyhjZW50ZXIpO1xuXHR9LFxuXG5cdF9jb252ZXJ0TGF0TG5nczogZnVuY3Rpb24gKGxhdGxuZ3MpIHtcblx0XHR2YXIgcmVzdWx0ID0gUG9seWxpbmUucHJvdG90eXBlLl9jb252ZXJ0TGF0TG5ncy5jYWxsKHRoaXMsIGxhdGxuZ3MpLFxuXHRcdCAgICBsZW4gPSByZXN1bHQubGVuZ3RoO1xuXG5cdFx0Ly8gcmVtb3ZlIGxhc3QgcG9pbnQgaWYgaXQgZXF1YWxzIGZpcnN0IG9uZVxuXHRcdGlmIChsZW4gPj0gMiAmJiByZXN1bHRbMF0gaW5zdGFuY2VvZiBMYXRMbmcgJiYgcmVzdWx0WzBdLmVxdWFscyhyZXN1bHRbbGVuIC0gMV0pKSB7XG5cdFx0XHRyZXN1bHQucG9wKCk7XG5cdFx0fVxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH0sXG5cblx0X3NldExhdExuZ3M6IGZ1bmN0aW9uIChsYXRsbmdzKSB7XG5cdFx0UG9seWxpbmUucHJvdG90eXBlLl9zZXRMYXRMbmdzLmNhbGwodGhpcywgbGF0bG5ncyk7XG5cdFx0aWYgKGlzRmxhdCh0aGlzLl9sYXRsbmdzKSkge1xuXHRcdFx0dGhpcy5fbGF0bG5ncyA9IFt0aGlzLl9sYXRsbmdzXTtcblx0XHR9XG5cdH0sXG5cblx0X2RlZmF1bHRTaGFwZTogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiBpc0ZsYXQodGhpcy5fbGF0bG5nc1swXSkgPyB0aGlzLl9sYXRsbmdzWzBdIDogdGhpcy5fbGF0bG5nc1swXVswXTtcblx0fSxcblxuXHRfY2xpcFBvaW50czogZnVuY3Rpb24gKCkge1xuXHRcdC8vIHBvbHlnb25zIG5lZWQgYSBkaWZmZXJlbnQgY2xpcHBpbmcgYWxnb3JpdGhtIHNvIHdlIHJlZGVmaW5lIHRoYXRcblxuXHRcdHZhciBib3VuZHMgPSB0aGlzLl9yZW5kZXJlci5fYm91bmRzLFxuXHRcdCAgICB3ID0gdGhpcy5vcHRpb25zLndlaWdodCxcblx0XHQgICAgcCA9IG5ldyBQb2ludCh3LCB3KTtcblxuXHRcdC8vIGluY3JlYXNlIGNsaXAgcGFkZGluZyBieSBzdHJva2Ugd2lkdGggdG8gYXZvaWQgc3Ryb2tlIG9uIGNsaXAgZWRnZXNcblx0XHRib3VuZHMgPSBuZXcgQm91bmRzKGJvdW5kcy5taW4uc3VidHJhY3QocCksIGJvdW5kcy5tYXguYWRkKHApKTtcblxuXHRcdHRoaXMuX3BhcnRzID0gW107XG5cdFx0aWYgKCF0aGlzLl9weEJvdW5kcyB8fCAhdGhpcy5fcHhCb3VuZHMuaW50ZXJzZWN0cyhib3VuZHMpKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5ub0NsaXApIHtcblx0XHRcdHRoaXMuX3BhcnRzID0gdGhpcy5fcmluZ3M7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHRoaXMuX3JpbmdzLmxlbmd0aCwgY2xpcHBlZDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRjbGlwcGVkID0gY2xpcFBvbHlnb24odGhpcy5fcmluZ3NbaV0sIGJvdW5kcywgdHJ1ZSk7XG5cdFx0XHRpZiAoY2xpcHBlZC5sZW5ndGgpIHtcblx0XHRcdFx0dGhpcy5fcGFydHMucHVzaChjbGlwcGVkKTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0X3VwZGF0ZVBhdGg6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9yZW5kZXJlci5fdXBkYXRlUG9seSh0aGlzLCB0cnVlKTtcblx0fSxcblxuXHQvLyBOZWVkZWQgYnkgdGhlIGBDYW52YXNgIHJlbmRlcmVyIGZvciBpbnRlcmFjdGl2aXR5XG5cdF9jb250YWluc1BvaW50OiBmdW5jdGlvbiAocCkge1xuXHRcdHZhciBpbnNpZGUgPSBmYWxzZSxcblx0XHQgICAgcGFydCwgcDEsIHAyLCBpLCBqLCBrLCBsZW4sIGxlbjI7XG5cblx0XHRpZiAoIXRoaXMuX3B4Qm91bmRzIHx8ICF0aGlzLl9weEJvdW5kcy5jb250YWlucyhwKSkgeyByZXR1cm4gZmFsc2U7IH1cblxuXHRcdC8vIHJheSBjYXN0aW5nIGFsZ29yaXRobSBmb3IgZGV0ZWN0aW5nIGlmIHBvaW50IGlzIGluIHBvbHlnb25cblx0XHRmb3IgKGkgPSAwLCBsZW4gPSB0aGlzLl9wYXJ0cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0cGFydCA9IHRoaXMuX3BhcnRzW2ldO1xuXG5cdFx0XHRmb3IgKGogPSAwLCBsZW4yID0gcGFydC5sZW5ndGgsIGsgPSBsZW4yIC0gMTsgaiA8IGxlbjI7IGsgPSBqKyspIHtcblx0XHRcdFx0cDEgPSBwYXJ0W2pdO1xuXHRcdFx0XHRwMiA9IHBhcnRba107XG5cblx0XHRcdFx0aWYgKCgocDEueSA+IHAueSkgIT09IChwMi55ID4gcC55KSkgJiYgKHAueCA8IChwMi54IC0gcDEueCkgKiAocC55IC0gcDEueSkgLyAocDIueSAtIHAxLnkpICsgcDEueCkpIHtcblx0XHRcdFx0XHRpbnNpZGUgPSAhaW5zaWRlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gYWxzbyBjaGVjayBpZiBpdCdzIG9uIHBvbHlnb24gc3Ryb2tlXG5cdFx0cmV0dXJuIGluc2lkZSB8fCBQb2x5bGluZS5wcm90b3R5cGUuX2NvbnRhaW5zUG9pbnQuY2FsbCh0aGlzLCBwLCB0cnVlKTtcblx0fVxuXG59KTtcblxuXG4vLyBAZmFjdG9yeSBMLnBvbHlnb24obGF0bG5nczogTGF0TG5nW10sIG9wdGlvbnM/OiBQb2x5bGluZSBvcHRpb25zKVxuZnVuY3Rpb24gcG9seWdvbihsYXRsbmdzLCBvcHRpb25zKSB7XG5cdHJldHVybiBuZXcgUG9seWdvbihsYXRsbmdzLCBvcHRpb25zKTtcbn1cblxuLypcclxuICogQGNsYXNzIEdlb0pTT05cclxuICogQGFrYSBMLkdlb0pTT05cclxuICogQGluaGVyaXRzIEZlYXR1cmVHcm91cFxyXG4gKlxyXG4gKiBSZXByZXNlbnRzIGEgR2VvSlNPTiBvYmplY3Qgb3IgYW4gYXJyYXkgb2YgR2VvSlNPTiBvYmplY3RzLiBBbGxvd3MgeW91IHRvIHBhcnNlXHJcbiAqIEdlb0pTT04gZGF0YSBhbmQgZGlzcGxheSBpdCBvbiB0aGUgbWFwLiBFeHRlbmRzIGBGZWF0dXJlR3JvdXBgLlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiBMLmdlb0pTT04oZGF0YSwge1xyXG4gKiBcdHN0eWxlOiBmdW5jdGlvbiAoZmVhdHVyZSkge1xyXG4gKiBcdFx0cmV0dXJuIHtjb2xvcjogZmVhdHVyZS5wcm9wZXJ0aWVzLmNvbG9yfTtcclxuICogXHR9XHJcbiAqIH0pLmJpbmRQb3B1cChmdW5jdGlvbiAobGF5ZXIpIHtcclxuICogXHRyZXR1cm4gbGF5ZXIuZmVhdHVyZS5wcm9wZXJ0aWVzLmRlc2NyaXB0aW9uO1xyXG4gKiB9KS5hZGRUbyhtYXApO1xyXG4gKiBgYGBcclxuICovXHJcblxyXG52YXIgR2VvSlNPTiA9IEZlYXR1cmVHcm91cC5leHRlbmQoe1xyXG5cclxuXHQvKiBAc2VjdGlvblxyXG5cdCAqIEBha2EgR2VvSlNPTiBvcHRpb25zXHJcblx0ICpcclxuXHQgKiBAb3B0aW9uIHBvaW50VG9MYXllcjogRnVuY3Rpb24gPSAqXHJcblx0ICogQSBgRnVuY3Rpb25gIGRlZmluaW5nIGhvdyBHZW9KU09OIHBvaW50cyBzcGF3biBMZWFmbGV0IGxheWVycy4gSXQgaXMgaW50ZXJuYWxseVxyXG5cdCAqIGNhbGxlZCB3aGVuIGRhdGEgaXMgYWRkZWQsIHBhc3NpbmcgdGhlIEdlb0pTT04gcG9pbnQgZmVhdHVyZSBhbmQgaXRzIGBMYXRMbmdgLlxyXG5cdCAqIFRoZSBkZWZhdWx0IGlzIHRvIHNwYXduIGEgZGVmYXVsdCBgTWFya2VyYDpcclxuXHQgKiBgYGBqc1xyXG5cdCAqIGZ1bmN0aW9uKGdlb0pzb25Qb2ludCwgbGF0bG5nKSB7XHJcblx0ICogXHRyZXR1cm4gTC5tYXJrZXIobGF0bG5nKTtcclxuXHQgKiB9XHJcblx0ICogYGBgXHJcblx0ICpcclxuXHQgKiBAb3B0aW9uIHN0eWxlOiBGdW5jdGlvbiA9ICpcclxuXHQgKiBBIGBGdW5jdGlvbmAgZGVmaW5pbmcgdGhlIGBQYXRoIG9wdGlvbnNgIGZvciBzdHlsaW5nIEdlb0pTT04gbGluZXMgYW5kIHBvbHlnb25zLFxyXG5cdCAqIGNhbGxlZCBpbnRlcm5hbGx5IHdoZW4gZGF0YSBpcyBhZGRlZC5cclxuXHQgKiBUaGUgZGVmYXVsdCB2YWx1ZSBpcyB0byBub3Qgb3ZlcnJpZGUgYW55IGRlZmF1bHRzOlxyXG5cdCAqIGBgYGpzXHJcblx0ICogZnVuY3Rpb24gKGdlb0pzb25GZWF0dXJlKSB7XHJcblx0ICogXHRyZXR1cm4ge31cclxuXHQgKiB9XHJcblx0ICogYGBgXHJcblx0ICpcclxuXHQgKiBAb3B0aW9uIG9uRWFjaEZlYXR1cmU6IEZ1bmN0aW9uID0gKlxyXG5cdCAqIEEgYEZ1bmN0aW9uYCB0aGF0IHdpbGwgYmUgY2FsbGVkIG9uY2UgZm9yIGVhY2ggY3JlYXRlZCBgRmVhdHVyZWAsIGFmdGVyIGl0IGhhc1xyXG5cdCAqIGJlZW4gY3JlYXRlZCBhbmQgc3R5bGVkLiBVc2VmdWwgZm9yIGF0dGFjaGluZyBldmVudHMgYW5kIHBvcHVwcyB0byBmZWF0dXJlcy5cclxuXHQgKiBUaGUgZGVmYXVsdCBpcyB0byBkbyBub3RoaW5nIHdpdGggdGhlIG5ld2x5IGNyZWF0ZWQgbGF5ZXJzOlxyXG5cdCAqIGBgYGpzXHJcblx0ICogZnVuY3Rpb24gKGZlYXR1cmUsIGxheWVyKSB7fVxyXG5cdCAqIGBgYFxyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBmaWx0ZXI6IEZ1bmN0aW9uID0gKlxyXG5cdCAqIEEgYEZ1bmN0aW9uYCB0aGF0IHdpbGwgYmUgdXNlZCB0byBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIGEgZmVhdHVyZSBvciBub3QuXHJcblx0ICogVGhlIGRlZmF1bHQgaXMgdG8gaW5jbHVkZSBhbGwgZmVhdHVyZXM6XHJcblx0ICogYGBganNcclxuXHQgKiBmdW5jdGlvbiAoZ2VvSnNvbkZlYXR1cmUpIHtcclxuXHQgKiBcdHJldHVybiB0cnVlO1xyXG5cdCAqIH1cclxuXHQgKiBgYGBcclxuXHQgKiBOb3RlOiBkeW5hbWljYWxseSBjaGFuZ2luZyB0aGUgYGZpbHRlcmAgb3B0aW9uIHdpbGwgaGF2ZSBlZmZlY3Qgb25seSBvbiBuZXdseVxyXG5cdCAqIGFkZGVkIGRhdGEuIEl0IHdpbGwgX25vdF8gcmUtZXZhbHVhdGUgYWxyZWFkeSBpbmNsdWRlZCBmZWF0dXJlcy5cclxuXHQgKlxyXG5cdCAqIEBvcHRpb24gY29vcmRzVG9MYXRMbmc6IEZ1bmN0aW9uID0gKlxyXG5cdCAqIEEgYEZ1bmN0aW9uYCB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgY29udmVydGluZyBHZW9KU09OIGNvb3JkaW5hdGVzIHRvIGBMYXRMbmdgcy5cclxuXHQgKiBUaGUgZGVmYXVsdCBpcyB0aGUgYGNvb3Jkc1RvTGF0TG5nYCBzdGF0aWMgbWV0aG9kLlxyXG5cdCAqL1xyXG5cclxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAoZ2VvanNvbiwgb3B0aW9ucykge1xyXG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcblx0XHR0aGlzLl9sYXllcnMgPSB7fTtcclxuXHJcblx0XHRpZiAoZ2VvanNvbikge1xyXG5cdFx0XHR0aGlzLmFkZERhdGEoZ2VvanNvbik7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBhZGREYXRhKCA8R2VvSlNPTj4gZGF0YSApOiB0aGlzXHJcblx0Ly8gQWRkcyBhIEdlb0pTT04gb2JqZWN0IHRvIHRoZSBsYXllci5cclxuXHRhZGREYXRhOiBmdW5jdGlvbiAoZ2VvanNvbikge1xyXG5cdFx0dmFyIGZlYXR1cmVzID0gaXNBcnJheShnZW9qc29uKSA/IGdlb2pzb24gOiBnZW9qc29uLmZlYXR1cmVzLFxyXG5cdFx0ICAgIGksIGxlbiwgZmVhdHVyZTtcclxuXHJcblx0XHRpZiAoZmVhdHVyZXMpIHtcclxuXHRcdFx0Zm9yIChpID0gMCwgbGVuID0gZmVhdHVyZXMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0XHQvLyBvbmx5IGFkZCB0aGlzIGlmIGdlb21ldHJ5IG9yIGdlb21ldHJpZXMgYXJlIHNldCBhbmQgbm90IG51bGxcclxuXHRcdFx0XHRmZWF0dXJlID0gZmVhdHVyZXNbaV07XHJcblx0XHRcdFx0aWYgKGZlYXR1cmUuZ2VvbWV0cmllcyB8fCBmZWF0dXJlLmdlb21ldHJ5IHx8IGZlYXR1cmUuZmVhdHVyZXMgfHwgZmVhdHVyZS5jb29yZGluYXRlcykge1xyXG5cdFx0XHRcdFx0dGhpcy5hZGREYXRhKGZlYXR1cmUpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gdGhpcztcclxuXHRcdH1cclxuXHJcblx0XHR2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcclxuXHJcblx0XHRpZiAob3B0aW9ucy5maWx0ZXIgJiYgIW9wdGlvbnMuZmlsdGVyKGdlb2pzb24pKSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG5cdFx0dmFyIGxheWVyID0gZ2VvbWV0cnlUb0xheWVyKGdlb2pzb24sIG9wdGlvbnMpO1xyXG5cdFx0aWYgKCFsYXllcikge1xyXG5cdFx0XHRyZXR1cm4gdGhpcztcclxuXHRcdH1cclxuXHRcdGxheWVyLmZlYXR1cmUgPSBhc0ZlYXR1cmUoZ2VvanNvbik7XHJcblxyXG5cdFx0bGF5ZXIuZGVmYXVsdE9wdGlvbnMgPSBsYXllci5vcHRpb25zO1xyXG5cdFx0dGhpcy5yZXNldFN0eWxlKGxheWVyKTtcclxuXHJcblx0XHRpZiAob3B0aW9ucy5vbkVhY2hGZWF0dXJlKSB7XHJcblx0XHRcdG9wdGlvbnMub25FYWNoRmVhdHVyZShnZW9qc29uLCBsYXllcik7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXMuYWRkTGF5ZXIobGF5ZXIpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgcmVzZXRTdHlsZSggPFBhdGg+IGxheWVyICk6IHRoaXNcclxuXHQvLyBSZXNldHMgdGhlIGdpdmVuIHZlY3RvciBsYXllcidzIHN0eWxlIHRvIHRoZSBvcmlnaW5hbCBHZW9KU09OIHN0eWxlLCB1c2VmdWwgZm9yIHJlc2V0dGluZyBzdHlsZSBhZnRlciBob3ZlciBldmVudHMuXHJcblx0cmVzZXRTdHlsZTogZnVuY3Rpb24gKGxheWVyKSB7XHJcblx0XHQvLyByZXNldCBhbnkgY3VzdG9tIHN0eWxlc1xyXG5cdFx0bGF5ZXIub3B0aW9ucyA9IGV4dGVuZCh7fSwgbGF5ZXIuZGVmYXVsdE9wdGlvbnMpO1xyXG5cdFx0dGhpcy5fc2V0TGF5ZXJTdHlsZShsYXllciwgdGhpcy5vcHRpb25zLnN0eWxlKTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0U3R5bGUoIDxGdW5jdGlvbj4gc3R5bGUgKTogdGhpc1xyXG5cdC8vIENoYW5nZXMgc3R5bGVzIG9mIEdlb0pTT04gdmVjdG9yIGxheWVycyB3aXRoIHRoZSBnaXZlbiBzdHlsZSBmdW5jdGlvbi5cclxuXHRzZXRTdHlsZTogZnVuY3Rpb24gKHN0eWxlKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5lYWNoTGF5ZXIoZnVuY3Rpb24gKGxheWVyKSB7XHJcblx0XHRcdHRoaXMuX3NldExheWVyU3R5bGUobGF5ZXIsIHN0eWxlKTtcclxuXHRcdH0sIHRoaXMpO1xyXG5cdH0sXHJcblxyXG5cdF9zZXRMYXllclN0eWxlOiBmdW5jdGlvbiAobGF5ZXIsIHN0eWxlKSB7XHJcblx0XHRpZiAobGF5ZXIuc2V0U3R5bGUpIHtcclxuXHRcdFx0aWYgKHR5cGVvZiBzdHlsZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG5cdFx0XHRcdHN0eWxlID0gc3R5bGUobGF5ZXIuZmVhdHVyZSk7XHJcblx0XHRcdH1cclxuXHRcdFx0bGF5ZXIuc2V0U3R5bGUoc3R5bGUpO1xyXG5cdFx0fVxyXG5cdH1cclxufSk7XHJcblxyXG4vLyBAc2VjdGlvblxyXG4vLyBUaGVyZSBhcmUgc2V2ZXJhbCBzdGF0aWMgZnVuY3Rpb25zIHdoaWNoIGNhbiBiZSBjYWxsZWQgd2l0aG91dCBpbnN0YW50aWF0aW5nIEwuR2VvSlNPTjpcclxuXHJcbi8vIEBmdW5jdGlvbiBnZW9tZXRyeVRvTGF5ZXIoZmVhdHVyZURhdGE6IE9iamVjdCwgb3B0aW9ucz86IEdlb0pTT04gb3B0aW9ucyk6IExheWVyXHJcbi8vIENyZWF0ZXMgYSBgTGF5ZXJgIGZyb20gYSBnaXZlbiBHZW9KU09OIGZlYXR1cmUuIENhbiB1c2UgYSBjdXN0b21cclxuLy8gW2Bwb2ludFRvTGF5ZXJgXSgjZ2VvanNvbi1wb2ludHRvbGF5ZXIpIGFuZC9vciBbYGNvb3Jkc1RvTGF0TG5nYF0oI2dlb2pzb24tY29vcmRzdG9sYXRsbmcpXHJcbi8vIGZ1bmN0aW9ucyBpZiBwcm92aWRlZCBhcyBvcHRpb25zLlxyXG5mdW5jdGlvbiBnZW9tZXRyeVRvTGF5ZXIoZ2VvanNvbiwgb3B0aW9ucykge1xyXG5cclxuXHR2YXIgZ2VvbWV0cnkgPSBnZW9qc29uLnR5cGUgPT09ICdGZWF0dXJlJyA/IGdlb2pzb24uZ2VvbWV0cnkgOiBnZW9qc29uLFxyXG5cdCAgICBjb29yZHMgPSBnZW9tZXRyeSA/IGdlb21ldHJ5LmNvb3JkaW5hdGVzIDogbnVsbCxcclxuXHQgICAgbGF5ZXJzID0gW10sXHJcblx0ICAgIHBvaW50VG9MYXllciA9IG9wdGlvbnMgJiYgb3B0aW9ucy5wb2ludFRvTGF5ZXIsXHJcblx0ICAgIF9jb29yZHNUb0xhdExuZyA9IG9wdGlvbnMgJiYgb3B0aW9ucy5jb29yZHNUb0xhdExuZyB8fCBjb29yZHNUb0xhdExuZyxcclxuXHQgICAgbGF0bG5nLCBsYXRsbmdzLCBpLCBsZW47XHJcblxyXG5cdGlmICghY29vcmRzICYmICFnZW9tZXRyeSkge1xyXG5cdFx0cmV0dXJuIG51bGw7XHJcblx0fVxyXG5cclxuXHRzd2l0Y2ggKGdlb21ldHJ5LnR5cGUpIHtcclxuXHRjYXNlICdQb2ludCc6XHJcblx0XHRsYXRsbmcgPSBfY29vcmRzVG9MYXRMbmcoY29vcmRzKTtcclxuXHRcdHJldHVybiBwb2ludFRvTGF5ZXIgPyBwb2ludFRvTGF5ZXIoZ2VvanNvbiwgbGF0bG5nKSA6IG5ldyBNYXJrZXIobGF0bG5nKTtcclxuXHJcblx0Y2FzZSAnTXVsdGlQb2ludCc6XHJcblx0XHRmb3IgKGkgPSAwLCBsZW4gPSBjb29yZHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0bGF0bG5nID0gX2Nvb3Jkc1RvTGF0TG5nKGNvb3Jkc1tpXSk7XHJcblx0XHRcdGxheWVycy5wdXNoKHBvaW50VG9MYXllciA/IHBvaW50VG9MYXllcihnZW9qc29uLCBsYXRsbmcpIDogbmV3IE1hcmtlcihsYXRsbmcpKTtcclxuXHRcdH1cclxuXHRcdHJldHVybiBuZXcgRmVhdHVyZUdyb3VwKGxheWVycyk7XHJcblxyXG5cdGNhc2UgJ0xpbmVTdHJpbmcnOlxyXG5cdGNhc2UgJ011bHRpTGluZVN0cmluZyc6XHJcblx0XHRsYXRsbmdzID0gY29vcmRzVG9MYXRMbmdzKGNvb3JkcywgZ2VvbWV0cnkudHlwZSA9PT0gJ0xpbmVTdHJpbmcnID8gMCA6IDEsIF9jb29yZHNUb0xhdExuZyk7XHJcblx0XHRyZXR1cm4gbmV3IFBvbHlsaW5lKGxhdGxuZ3MsIG9wdGlvbnMpO1xyXG5cclxuXHRjYXNlICdQb2x5Z29uJzpcclxuXHRjYXNlICdNdWx0aVBvbHlnb24nOlxyXG5cdFx0bGF0bG5ncyA9IGNvb3Jkc1RvTGF0TG5ncyhjb29yZHMsIGdlb21ldHJ5LnR5cGUgPT09ICdQb2x5Z29uJyA/IDEgOiAyLCBfY29vcmRzVG9MYXRMbmcpO1xyXG5cdFx0cmV0dXJuIG5ldyBQb2x5Z29uKGxhdGxuZ3MsIG9wdGlvbnMpO1xyXG5cclxuXHRjYXNlICdHZW9tZXRyeUNvbGxlY3Rpb24nOlxyXG5cdFx0Zm9yIChpID0gMCwgbGVuID0gZ2VvbWV0cnkuZ2VvbWV0cmllcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0XHR2YXIgbGF5ZXIgPSBnZW9tZXRyeVRvTGF5ZXIoe1xyXG5cdFx0XHRcdGdlb21ldHJ5OiBnZW9tZXRyeS5nZW9tZXRyaWVzW2ldLFxyXG5cdFx0XHRcdHR5cGU6ICdGZWF0dXJlJyxcclxuXHRcdFx0XHRwcm9wZXJ0aWVzOiBnZW9qc29uLnByb3BlcnRpZXNcclxuXHRcdFx0fSwgb3B0aW9ucyk7XHJcblxyXG5cdFx0XHRpZiAobGF5ZXIpIHtcclxuXHRcdFx0XHRsYXllcnMucHVzaChsYXllcik7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHRcdHJldHVybiBuZXcgRmVhdHVyZUdyb3VwKGxheWVycyk7XHJcblxyXG5cdGRlZmF1bHQ6XHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgR2VvSlNPTiBvYmplY3QuJyk7XHJcblx0fVxyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gY29vcmRzVG9MYXRMbmcoY29vcmRzOiBBcnJheSk6IExhdExuZ1xyXG4vLyBDcmVhdGVzIGEgYExhdExuZ2Agb2JqZWN0IGZyb20gYW4gYXJyYXkgb2YgMiBudW1iZXJzIChsb25naXR1ZGUsIGxhdGl0dWRlKVxyXG4vLyBvciAzIG51bWJlcnMgKGxvbmdpdHVkZSwgbGF0aXR1ZGUsIGFsdGl0dWRlKSB1c2VkIGluIEdlb0pTT04gZm9yIHBvaW50cy5cclxuZnVuY3Rpb24gY29vcmRzVG9MYXRMbmcoY29vcmRzKSB7XHJcblx0cmV0dXJuIG5ldyBMYXRMbmcoY29vcmRzWzFdLCBjb29yZHNbMF0sIGNvb3Jkc1syXSk7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBjb29yZHNUb0xhdExuZ3MoY29vcmRzOiBBcnJheSwgbGV2ZWxzRGVlcD86IE51bWJlciwgY29vcmRzVG9MYXRMbmc/OiBGdW5jdGlvbik6IEFycmF5XHJcbi8vIENyZWF0ZXMgYSBtdWx0aWRpbWVuc2lvbmFsIGFycmF5IG9mIGBMYXRMbmdgcyBmcm9tIGEgR2VvSlNPTiBjb29yZGluYXRlcyBhcnJheS5cclxuLy8gYGxldmVsc0RlZXBgIHNwZWNpZmllcyB0aGUgbmVzdGluZyBsZXZlbCAoMCBpcyBmb3IgYW4gYXJyYXkgb2YgcG9pbnRzLCAxIGZvciBhbiBhcnJheSBvZiBhcnJheXMgb2YgcG9pbnRzLCBldGMuLCAwIGJ5IGRlZmF1bHQpLlxyXG4vLyBDYW4gdXNlIGEgY3VzdG9tIFtgY29vcmRzVG9MYXRMbmdgXSgjZ2VvanNvbi1jb29yZHN0b2xhdGxuZykgZnVuY3Rpb24uXHJcbmZ1bmN0aW9uIGNvb3Jkc1RvTGF0TG5ncyhjb29yZHMsIGxldmVsc0RlZXAsIF9jb29yZHNUb0xhdExuZykge1xyXG5cdHZhciBsYXRsbmdzID0gW107XHJcblxyXG5cdGZvciAodmFyIGkgPSAwLCBsZW4gPSBjb29yZHMubGVuZ3RoLCBsYXRsbmc7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0bGF0bG5nID0gbGV2ZWxzRGVlcCA/XHJcblx0XHRcdGNvb3Jkc1RvTGF0TG5ncyhjb29yZHNbaV0sIGxldmVsc0RlZXAgLSAxLCBfY29vcmRzVG9MYXRMbmcpIDpcclxuXHRcdFx0KF9jb29yZHNUb0xhdExuZyB8fCBjb29yZHNUb0xhdExuZykoY29vcmRzW2ldKTtcclxuXHJcblx0XHRsYXRsbmdzLnB1c2gobGF0bG5nKTtcclxuXHR9XHJcblxyXG5cdHJldHVybiBsYXRsbmdzO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gbGF0TG5nVG9Db29yZHMobGF0bG5nOiBMYXRMbmcsIHByZWNpc2lvbj86IE51bWJlcik6IEFycmF5XHJcbi8vIFJldmVyc2Ugb2YgW2Bjb29yZHNUb0xhdExuZ2BdKCNnZW9qc29uLWNvb3Jkc3RvbGF0bG5nKVxyXG5mdW5jdGlvbiBsYXRMbmdUb0Nvb3JkcyhsYXRsbmcsIHByZWNpc2lvbikge1xyXG5cdHByZWNpc2lvbiA9IHR5cGVvZiBwcmVjaXNpb24gPT09ICdudW1iZXInID8gcHJlY2lzaW9uIDogNjtcclxuXHRyZXR1cm4gbGF0bG5nLmFsdCAhPT0gdW5kZWZpbmVkID9cclxuXHRcdFtmb3JtYXROdW0obGF0bG5nLmxuZywgcHJlY2lzaW9uKSwgZm9ybWF0TnVtKGxhdGxuZy5sYXQsIHByZWNpc2lvbiksIGZvcm1hdE51bShsYXRsbmcuYWx0LCBwcmVjaXNpb24pXSA6XHJcblx0XHRbZm9ybWF0TnVtKGxhdGxuZy5sbmcsIHByZWNpc2lvbiksIGZvcm1hdE51bShsYXRsbmcubGF0LCBwcmVjaXNpb24pXTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGxhdExuZ3NUb0Nvb3JkcyhsYXRsbmdzOiBBcnJheSwgbGV2ZWxzRGVlcD86IE51bWJlciwgY2xvc2VkPzogQm9vbGVhbik6IEFycmF5XHJcbi8vIFJldmVyc2Ugb2YgW2Bjb29yZHNUb0xhdExuZ3NgXSgjZ2VvanNvbi1jb29yZHN0b2xhdGxuZ3MpXHJcbi8vIGBjbG9zZWRgIGRldGVybWluZXMgd2hldGhlciB0aGUgZmlyc3QgcG9pbnQgc2hvdWxkIGJlIGFwcGVuZGVkIHRvIHRoZSBlbmQgb2YgdGhlIGFycmF5IHRvIGNsb3NlIHRoZSBmZWF0dXJlLCBvbmx5IHVzZWQgd2hlbiBgbGV2ZWxzRGVlcGAgaXMgMC4gRmFsc2UgYnkgZGVmYXVsdC5cclxuZnVuY3Rpb24gbGF0TG5nc1RvQ29vcmRzKGxhdGxuZ3MsIGxldmVsc0RlZXAsIGNsb3NlZCwgcHJlY2lzaW9uKSB7XHJcblx0dmFyIGNvb3JkcyA9IFtdO1xyXG5cclxuXHRmb3IgKHZhciBpID0gMCwgbGVuID0gbGF0bG5ncy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0Y29vcmRzLnB1c2gobGV2ZWxzRGVlcCA/XHJcblx0XHRcdGxhdExuZ3NUb0Nvb3JkcyhsYXRsbmdzW2ldLCBsZXZlbHNEZWVwIC0gMSwgY2xvc2VkLCBwcmVjaXNpb24pIDpcclxuXHRcdFx0bGF0TG5nVG9Db29yZHMobGF0bG5nc1tpXSwgcHJlY2lzaW9uKSk7XHJcblx0fVxyXG5cclxuXHRpZiAoIWxldmVsc0RlZXAgJiYgY2xvc2VkKSB7XHJcblx0XHRjb29yZHMucHVzaChjb29yZHNbMF0pO1xyXG5cdH1cclxuXHJcblx0cmV0dXJuIGNvb3JkcztcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0RmVhdHVyZShsYXllciwgbmV3R2VvbWV0cnkpIHtcclxuXHRyZXR1cm4gbGF5ZXIuZmVhdHVyZSA/XHJcblx0XHRleHRlbmQoe30sIGxheWVyLmZlYXR1cmUsIHtnZW9tZXRyeTogbmV3R2VvbWV0cnl9KSA6XHJcblx0XHRhc0ZlYXR1cmUobmV3R2VvbWV0cnkpO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gYXNGZWF0dXJlKGdlb2pzb246IE9iamVjdCk6IE9iamVjdFxyXG4vLyBOb3JtYWxpemUgR2VvSlNPTiBnZW9tZXRyaWVzL2ZlYXR1cmVzIGludG8gR2VvSlNPTiBmZWF0dXJlcy5cclxuZnVuY3Rpb24gYXNGZWF0dXJlKGdlb2pzb24pIHtcclxuXHRpZiAoZ2VvanNvbi50eXBlID09PSAnRmVhdHVyZScgfHwgZ2VvanNvbi50eXBlID09PSAnRmVhdHVyZUNvbGxlY3Rpb24nKSB7XHJcblx0XHRyZXR1cm4gZ2VvanNvbjtcclxuXHR9XHJcblxyXG5cdHJldHVybiB7XHJcblx0XHR0eXBlOiAnRmVhdHVyZScsXHJcblx0XHRwcm9wZXJ0aWVzOiB7fSxcclxuXHRcdGdlb21ldHJ5OiBnZW9qc29uXHJcblx0fTtcclxufVxyXG5cclxudmFyIFBvaW50VG9HZW9KU09OID0ge1xyXG5cdHRvR2VvSlNPTjogZnVuY3Rpb24gKHByZWNpc2lvbikge1xyXG5cdFx0cmV0dXJuIGdldEZlYXR1cmUodGhpcywge1xyXG5cdFx0XHR0eXBlOiAnUG9pbnQnLFxyXG5cdFx0XHRjb29yZGluYXRlczogbGF0TG5nVG9Db29yZHModGhpcy5nZXRMYXRMbmcoKSwgcHJlY2lzaW9uKVxyXG5cdFx0fSk7XHJcblx0fVxyXG59O1xyXG5cclxuLy8gQG5hbWVzcGFjZSBNYXJrZXJcclxuLy8gQG1ldGhvZCB0b0dlb0pTT04ocHJlY2lzaW9uPzogTnVtYmVyKTogT2JqZWN0XHJcbi8vIGBwcmVjaXNpb25gIGlzIHRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgZm9yIGNvb3JkaW5hdGVzLlxyXG4vLyBUaGUgZGVmYXVsdCB2YWx1ZSBpcyA2IHBsYWNlcy5cclxuLy8gUmV0dXJucyBhIFtgR2VvSlNPTmBdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvR2VvSlNPTikgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1hcmtlciAoYXMgYSBHZW9KU09OIGBQb2ludGAgRmVhdHVyZSkuXHJcbk1hcmtlci5pbmNsdWRlKFBvaW50VG9HZW9KU09OKTtcclxuXHJcbi8vIEBuYW1lc3BhY2UgQ2lyY2xlTWFya2VyXHJcbi8vIEBtZXRob2QgdG9HZW9KU09OKHByZWNpc2lvbj86IE51bWJlcik6IE9iamVjdFxyXG4vLyBgcHJlY2lzaW9uYCBpcyB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGZvciBjb29yZGluYXRlcy5cclxuLy8gVGhlIGRlZmF1bHQgdmFsdWUgaXMgNiBwbGFjZXMuXHJcbi8vIFJldHVybnMgYSBbYEdlb0pTT05gXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dlb0pTT04pIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBjaXJjbGUgbWFya2VyIChhcyBhIEdlb0pTT04gYFBvaW50YCBGZWF0dXJlKS5cclxuQ2lyY2xlLmluY2x1ZGUoUG9pbnRUb0dlb0pTT04pO1xyXG5DaXJjbGVNYXJrZXIuaW5jbHVkZShQb2ludFRvR2VvSlNPTik7XHJcblxyXG5cclxuLy8gQG5hbWVzcGFjZSBQb2x5bGluZVxyXG4vLyBAbWV0aG9kIHRvR2VvSlNPTihwcmVjaXNpb24/OiBOdW1iZXIpOiBPYmplY3RcclxuLy8gYHByZWNpc2lvbmAgaXMgdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgY29vcmRpbmF0ZXMuXHJcbi8vIFRoZSBkZWZhdWx0IHZhbHVlIGlzIDYgcGxhY2VzLlxyXG4vLyBSZXR1cm5zIGEgW2BHZW9KU09OYF0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HZW9KU09OKSByZXByZXNlbnRhdGlvbiBvZiB0aGUgcG9seWxpbmUgKGFzIGEgR2VvSlNPTiBgTGluZVN0cmluZ2Agb3IgYE11bHRpTGluZVN0cmluZ2AgRmVhdHVyZSkuXHJcblBvbHlsaW5lLmluY2x1ZGUoe1xyXG5cdHRvR2VvSlNPTjogZnVuY3Rpb24gKHByZWNpc2lvbikge1xyXG5cdFx0dmFyIG11bHRpID0gIWlzRmxhdCh0aGlzLl9sYXRsbmdzKTtcclxuXHJcblx0XHR2YXIgY29vcmRzID0gbGF0TG5nc1RvQ29vcmRzKHRoaXMuX2xhdGxuZ3MsIG11bHRpID8gMSA6IDAsIGZhbHNlLCBwcmVjaXNpb24pO1xyXG5cclxuXHRcdHJldHVybiBnZXRGZWF0dXJlKHRoaXMsIHtcclxuXHRcdFx0dHlwZTogKG11bHRpID8gJ011bHRpJyA6ICcnKSArICdMaW5lU3RyaW5nJyxcclxuXHRcdFx0Y29vcmRpbmF0ZXM6IGNvb3Jkc1xyXG5cdFx0fSk7XHJcblx0fVxyXG59KTtcclxuXHJcbi8vIEBuYW1lc3BhY2UgUG9seWdvblxyXG4vLyBAbWV0aG9kIHRvR2VvSlNPTihwcmVjaXNpb24/OiBOdW1iZXIpOiBPYmplY3RcclxuLy8gYHByZWNpc2lvbmAgaXMgdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgY29vcmRpbmF0ZXMuXHJcbi8vIFRoZSBkZWZhdWx0IHZhbHVlIGlzIDYgcGxhY2VzLlxyXG4vLyBSZXR1cm5zIGEgW2BHZW9KU09OYF0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HZW9KU09OKSByZXByZXNlbnRhdGlvbiBvZiB0aGUgcG9seWdvbiAoYXMgYSBHZW9KU09OIGBQb2x5Z29uYCBvciBgTXVsdGlQb2x5Z29uYCBGZWF0dXJlKS5cclxuUG9seWdvbi5pbmNsdWRlKHtcclxuXHR0b0dlb0pTT046IGZ1bmN0aW9uIChwcmVjaXNpb24pIHtcclxuXHRcdHZhciBob2xlcyA9ICFpc0ZsYXQodGhpcy5fbGF0bG5ncyksXHJcblx0XHQgICAgbXVsdGkgPSBob2xlcyAmJiAhaXNGbGF0KHRoaXMuX2xhdGxuZ3NbMF0pO1xyXG5cclxuXHRcdHZhciBjb29yZHMgPSBsYXRMbmdzVG9Db29yZHModGhpcy5fbGF0bG5ncywgbXVsdGkgPyAyIDogaG9sZXMgPyAxIDogMCwgdHJ1ZSwgcHJlY2lzaW9uKTtcclxuXHJcblx0XHRpZiAoIWhvbGVzKSB7XHJcblx0XHRcdGNvb3JkcyA9IFtjb29yZHNdO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBnZXRGZWF0dXJlKHRoaXMsIHtcclxuXHRcdFx0dHlwZTogKG11bHRpID8gJ011bHRpJyA6ICcnKSArICdQb2x5Z29uJyxcclxuXHRcdFx0Y29vcmRpbmF0ZXM6IGNvb3Jkc1xyXG5cdFx0fSk7XHJcblx0fVxyXG59KTtcclxuXHJcblxyXG4vLyBAbmFtZXNwYWNlIExheWVyR3JvdXBcclxuTGF5ZXJHcm91cC5pbmNsdWRlKHtcclxuXHR0b011bHRpUG9pbnQ6IGZ1bmN0aW9uIChwcmVjaXNpb24pIHtcclxuXHRcdHZhciBjb29yZHMgPSBbXTtcclxuXHJcblx0XHR0aGlzLmVhY2hMYXllcihmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHRcdFx0Y29vcmRzLnB1c2gobGF5ZXIudG9HZW9KU09OKHByZWNpc2lvbikuZ2VvbWV0cnkuY29vcmRpbmF0ZXMpO1xyXG5cdFx0fSk7XHJcblxyXG5cdFx0cmV0dXJuIGdldEZlYXR1cmUodGhpcywge1xyXG5cdFx0XHR0eXBlOiAnTXVsdGlQb2ludCcsXHJcblx0XHRcdGNvb3JkaW5hdGVzOiBjb29yZHNcclxuXHRcdH0pO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgdG9HZW9KU09OKHByZWNpc2lvbj86IE51bWJlcik6IE9iamVjdFxyXG5cdC8vIGBwcmVjaXNpb25gIGlzIHRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgZm9yIGNvb3JkaW5hdGVzLlxyXG5cdC8vIFRoZSBkZWZhdWx0IHZhbHVlIGlzIDYgcGxhY2VzLlxyXG5cdC8vIFJldHVybnMgYSBbYEdlb0pTT05gXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dlb0pTT04pIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBsYXllciBncm91cCAoYXMgYSBHZW9KU09OIGBGZWF0dXJlQ29sbGVjdGlvbmAsIGBHZW9tZXRyeUNvbGxlY3Rpb25gLCBvciBgTXVsdGlQb2ludGApLlxyXG5cdHRvR2VvSlNPTjogZnVuY3Rpb24gKHByZWNpc2lvbikge1xyXG5cclxuXHRcdHZhciB0eXBlID0gdGhpcy5mZWF0dXJlICYmIHRoaXMuZmVhdHVyZS5nZW9tZXRyeSAmJiB0aGlzLmZlYXR1cmUuZ2VvbWV0cnkudHlwZTtcclxuXHJcblx0XHRpZiAodHlwZSA9PT0gJ011bHRpUG9pbnQnKSB7XHJcblx0XHRcdHJldHVybiB0aGlzLnRvTXVsdGlQb2ludChwcmVjaXNpb24pO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBpc0dlb21ldHJ5Q29sbGVjdGlvbiA9IHR5cGUgPT09ICdHZW9tZXRyeUNvbGxlY3Rpb24nLFxyXG5cdFx0ICAgIGpzb25zID0gW107XHJcblxyXG5cdFx0dGhpcy5lYWNoTGF5ZXIoZnVuY3Rpb24gKGxheWVyKSB7XHJcblx0XHRcdGlmIChsYXllci50b0dlb0pTT04pIHtcclxuXHRcdFx0XHR2YXIganNvbiA9IGxheWVyLnRvR2VvSlNPTihwcmVjaXNpb24pO1xyXG5cdFx0XHRcdGlmIChpc0dlb21ldHJ5Q29sbGVjdGlvbikge1xyXG5cdFx0XHRcdFx0anNvbnMucHVzaChqc29uLmdlb21ldHJ5KTtcclxuXHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0dmFyIGZlYXR1cmUgPSBhc0ZlYXR1cmUoanNvbik7XHJcblx0XHRcdFx0XHQvLyBTcXVhc2ggbmVzdGVkIGZlYXR1cmUgY29sbGVjdGlvbnNcclxuXHRcdFx0XHRcdGlmIChmZWF0dXJlLnR5cGUgPT09ICdGZWF0dXJlQ29sbGVjdGlvbicpIHtcclxuXHRcdFx0XHRcdFx0anNvbnMucHVzaC5hcHBseShqc29ucywgZmVhdHVyZS5mZWF0dXJlcyk7XHJcblx0XHRcdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdFx0XHRqc29ucy5wdXNoKGZlYXR1cmUpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fSk7XHJcblxyXG5cdFx0aWYgKGlzR2VvbWV0cnlDb2xsZWN0aW9uKSB7XHJcblx0XHRcdHJldHVybiBnZXRGZWF0dXJlKHRoaXMsIHtcclxuXHRcdFx0XHRnZW9tZXRyaWVzOiBqc29ucyxcclxuXHRcdFx0XHR0eXBlOiAnR2VvbWV0cnlDb2xsZWN0aW9uJ1xyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4ge1xyXG5cdFx0XHR0eXBlOiAnRmVhdHVyZUNvbGxlY3Rpb24nLFxyXG5cdFx0XHRmZWF0dXJlczoganNvbnNcclxuXHRcdH07XHJcblx0fVxyXG59KTtcclxuXHJcbi8vIEBuYW1lc3BhY2UgR2VvSlNPTlxyXG4vLyBAZmFjdG9yeSBMLmdlb0pTT04oZ2VvanNvbj86IE9iamVjdCwgb3B0aW9ucz86IEdlb0pTT04gb3B0aW9ucylcclxuLy8gQ3JlYXRlcyBhIEdlb0pTT04gbGF5ZXIuIE9wdGlvbmFsbHkgYWNjZXB0cyBhbiBvYmplY3QgaW5cclxuLy8gW0dlb0pTT04gZm9ybWF0XShodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNzk0NikgdG8gZGlzcGxheSBvbiB0aGUgbWFwXHJcbi8vICh5b3UgY2FuIGFsdGVybmF0aXZlbHkgYWRkIGl0IGxhdGVyIHdpdGggYGFkZERhdGFgIG1ldGhvZCkgYW5kIGFuIGBvcHRpb25zYCBvYmplY3QuXHJcbmZ1bmN0aW9uIGdlb0pTT04oZ2VvanNvbiwgb3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgR2VvSlNPTihnZW9qc29uLCBvcHRpb25zKTtcclxufVxyXG5cclxuLy8gQmFja3dhcmQgY29tcGF0aWJpbGl0eS5cclxudmFyIGdlb0pzb24gPSBnZW9KU09OO1xuXG4vKlxyXG4gKiBAY2xhc3MgSW1hZ2VPdmVybGF5XHJcbiAqIEBha2EgTC5JbWFnZU92ZXJsYXlcclxuICogQGluaGVyaXRzIEludGVyYWN0aXZlIGxheWVyXHJcbiAqXHJcbiAqIFVzZWQgdG8gbG9hZCBhbmQgZGlzcGxheSBhIHNpbmdsZSBpbWFnZSBvdmVyIHNwZWNpZmljIGJvdW5kcyBvZiB0aGUgbWFwLiBFeHRlbmRzIGBMYXllcmAuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBpbWFnZVVybCA9ICdodHRwOi8vd3d3LmxpYi51dGV4YXMuZWR1L21hcHMvaGlzdG9yaWNhbC9uZXdhcmtfbmpfMTkyMi5qcGcnLFxyXG4gKiBcdGltYWdlQm91bmRzID0gW1s0MC43MTIyMTYsIC03NC4yMjY1NV0sIFs0MC43NzM5NDEsIC03NC4xMjU0NF1dO1xyXG4gKiBMLmltYWdlT3ZlcmxheShpbWFnZVVybCwgaW1hZ2VCb3VuZHMpLmFkZFRvKG1hcCk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBJbWFnZU92ZXJsYXkgPSBMYXllci5leHRlbmQoe1xyXG5cclxuXHQvLyBAc2VjdGlvblxyXG5cdC8vIEBha2EgSW1hZ2VPdmVybGF5IG9wdGlvbnNcclxuXHRvcHRpb25zOiB7XHJcblx0XHQvLyBAb3B0aW9uIG9wYWNpdHk6IE51bWJlciA9IDEuMFxyXG5cdFx0Ly8gVGhlIG9wYWNpdHkgb2YgdGhlIGltYWdlIG92ZXJsYXkuXHJcblx0XHRvcGFjaXR5OiAxLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gYWx0OiBTdHJpbmcgPSAnJ1xyXG5cdFx0Ly8gVGV4dCBmb3IgdGhlIGBhbHRgIGF0dHJpYnV0ZSBvZiB0aGUgaW1hZ2UgKHVzZWZ1bCBmb3IgYWNjZXNzaWJpbGl0eSkuXHJcblx0XHRhbHQ6ICcnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gaW50ZXJhY3RpdmU6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gSWYgYHRydWVgLCB0aGUgaW1hZ2Ugb3ZlcmxheSB3aWxsIGVtaXQgW21vdXNlIGV2ZW50c10oI2ludGVyYWN0aXZlLWxheWVyKSB3aGVuIGNsaWNrZWQgb3IgaG92ZXJlZC5cclxuXHRcdGludGVyYWN0aXZlOiBmYWxzZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGNyb3NzT3JpZ2luOiBCb29sZWFufFN0cmluZyA9IGZhbHNlXHJcblx0XHQvLyBXaGV0aGVyIHRoZSBjcm9zc09yaWdpbiBhdHRyaWJ1dGUgd2lsbCBiZSBhZGRlZCB0byB0aGUgaW1hZ2UuXHJcblx0XHQvLyBJZiBhIFN0cmluZyBpcyBwcm92aWRlZCwgdGhlIGltYWdlIHdpbGwgaGF2ZSBpdHMgY3Jvc3NPcmlnaW4gYXR0cmlidXRlIHNldCB0byB0aGUgU3RyaW5nIHByb3ZpZGVkLiBUaGlzIGlzIG5lZWRlZCBpZiB5b3Ugd2FudCB0byBhY2Nlc3MgaW1hZ2UgcGl4ZWwgZGF0YS5cclxuXHRcdC8vIFJlZmVyIHRvIFtDT1JTIFNldHRpbmdzXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVE1ML0NPUlNfc2V0dGluZ3NfYXR0cmlidXRlcykgZm9yIHZhbGlkIFN0cmluZyB2YWx1ZXMuXHJcblx0XHRjcm9zc09yaWdpbjogZmFsc2UsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBlcnJvck92ZXJsYXlVcmw6IFN0cmluZyA9ICcnXHJcblx0XHQvLyBVUkwgdG8gdGhlIG92ZXJsYXkgaW1hZ2UgdG8gc2hvdyBpbiBwbGFjZSBvZiB0aGUgb3ZlcmxheSB0aGF0IGZhaWxlZCB0byBsb2FkLlxyXG5cdFx0ZXJyb3JPdmVybGF5VXJsOiAnJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHpJbmRleDogTnVtYmVyID0gMVxyXG5cdFx0Ly8gVGhlIGV4cGxpY2l0IFt6SW5kZXhdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0NTUy9DU1NfUG9zaXRpb25pbmcvVW5kZXJzdGFuZGluZ196X2luZGV4KSBvZiB0aGUgb3ZlcmxheSBsYXllci5cclxuXHRcdHpJbmRleDogMSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGNsYXNzTmFtZTogU3RyaW5nID0gJydcclxuXHRcdC8vIEEgY3VzdG9tIGNsYXNzIG5hbWUgdG8gYXNzaWduIHRvIHRoZSBpbWFnZS4gRW1wdHkgYnkgZGVmYXVsdC5cclxuXHRcdGNsYXNzTmFtZTogJydcclxuXHR9LFxyXG5cclxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAodXJsLCBib3VuZHMsIG9wdGlvbnMpIHsgLy8gKFN0cmluZywgTGF0TG5nQm91bmRzLCBPYmplY3QpXHJcblx0XHR0aGlzLl91cmwgPSB1cmw7XHJcblx0XHR0aGlzLl9ib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblx0fSxcclxuXHJcblx0b25BZGQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICghdGhpcy5faW1hZ2UpIHtcclxuXHRcdFx0dGhpcy5faW5pdEltYWdlKCk7XHJcblxyXG5cdFx0XHRpZiAodGhpcy5vcHRpb25zLm9wYWNpdHkgPCAxKSB7XHJcblx0XHRcdFx0dGhpcy5fdXBkYXRlT3BhY2l0eSgpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xyXG5cdFx0XHRhZGRDbGFzcyh0aGlzLl9pbWFnZSwgJ2xlYWZsZXQtaW50ZXJhY3RpdmUnKTtcclxuXHRcdFx0dGhpcy5hZGRJbnRlcmFjdGl2ZVRhcmdldCh0aGlzLl9pbWFnZSk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5nZXRQYW5lKCkuYXBwZW5kQ2hpbGQodGhpcy5faW1hZ2UpO1xyXG5cdFx0dGhpcy5fcmVzZXQoKTtcclxuXHR9LFxyXG5cclxuXHRvblJlbW92ZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmVtb3ZlKHRoaXMuX2ltYWdlKTtcclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHtcclxuXHRcdFx0dGhpcy5yZW1vdmVJbnRlcmFjdGl2ZVRhcmdldCh0aGlzLl9pbWFnZSk7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRPcGFjaXR5KG9wYWNpdHk6IE51bWJlcik6IHRoaXNcclxuXHQvLyBTZXRzIHRoZSBvcGFjaXR5IG9mIHRoZSBvdmVybGF5LlxyXG5cdHNldE9wYWNpdHk6IGZ1bmN0aW9uIChvcGFjaXR5KSB7XHJcblx0XHR0aGlzLm9wdGlvbnMub3BhY2l0eSA9IG9wYWNpdHk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX2ltYWdlKSB7XHJcblx0XHRcdHRoaXMuX3VwZGF0ZU9wYWNpdHkoKTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdHNldFN0eWxlOiBmdW5jdGlvbiAoc3R5bGVPcHRzKSB7XHJcblx0XHRpZiAoc3R5bGVPcHRzLm9wYWNpdHkpIHtcclxuXHRcdFx0dGhpcy5zZXRPcGFjaXR5KHN0eWxlT3B0cy5vcGFjaXR5KTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgYnJpbmdUb0Zyb250KCk6IHRoaXNcclxuXHQvLyBCcmluZ3MgdGhlIGxheWVyIHRvIHRoZSB0b3Agb2YgYWxsIG92ZXJsYXlzLlxyXG5cdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKHRoaXMuX21hcCkge1xyXG5cdFx0XHR0b0Zyb250KHRoaXMuX2ltYWdlKTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgYnJpbmdUb0JhY2soKTogdGhpc1xyXG5cdC8vIEJyaW5ncyB0aGUgbGF5ZXIgdG8gdGhlIGJvdHRvbSBvZiBhbGwgb3ZlcmxheXMuXHJcblx0YnJpbmdUb0JhY2s6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh0aGlzLl9tYXApIHtcclxuXHRcdFx0dG9CYWNrKHRoaXMuX2ltYWdlKTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0VXJsKHVybDogU3RyaW5nKTogdGhpc1xyXG5cdC8vIENoYW5nZXMgdGhlIFVSTCBvZiB0aGUgaW1hZ2UuXHJcblx0c2V0VXJsOiBmdW5jdGlvbiAodXJsKSB7XHJcblx0XHR0aGlzLl91cmwgPSB1cmw7XHJcblxyXG5cdFx0aWYgKHRoaXMuX2ltYWdlKSB7XHJcblx0XHRcdHRoaXMuX2ltYWdlLnNyYyA9IHVybDtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0Qm91bmRzKGJvdW5kczogTGF0TG5nQm91bmRzKTogdGhpc1xyXG5cdC8vIFVwZGF0ZSB0aGUgYm91bmRzIHRoYXQgdGhpcyBJbWFnZU92ZXJsYXkgY292ZXJzXHJcblx0c2V0Qm91bmRzOiBmdW5jdGlvbiAoYm91bmRzKSB7XHJcblx0XHR0aGlzLl9ib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyhib3VuZHMpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9tYXApIHtcclxuXHRcdFx0dGhpcy5fcmVzZXQoKTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdGdldEV2ZW50czogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGV2ZW50cyA9IHtcclxuXHRcdFx0em9vbTogdGhpcy5fcmVzZXQsXHJcblx0XHRcdHZpZXdyZXNldDogdGhpcy5fcmVzZXRcclxuXHRcdH07XHJcblxyXG5cdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xyXG5cdFx0XHRldmVudHMuem9vbWFuaW0gPSB0aGlzLl9hbmltYXRlWm9vbTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gZXZlbnRzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0WkluZGV4KHZhbHVlOiBOdW1iZXIpOiB0aGlzXHJcblx0Ly8gQ2hhbmdlcyB0aGUgW3pJbmRleF0oI2ltYWdlb3ZlcmxheS16aW5kZXgpIG9mIHRoZSBpbWFnZSBvdmVybGF5LlxyXG5cdHNldFpJbmRleDogZnVuY3Rpb24gKHZhbHVlKSB7XHJcblx0XHR0aGlzLm9wdGlvbnMuekluZGV4ID0gdmFsdWU7XHJcblx0XHR0aGlzLl91cGRhdGVaSW5kZXgoKTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0Qm91bmRzKCk6IExhdExuZ0JvdW5kc1xyXG5cdC8vIEdldCB0aGUgYm91bmRzIHRoYXQgdGhpcyBJbWFnZU92ZXJsYXkgY292ZXJzXHJcblx0Z2V0Qm91bmRzOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fYm91bmRzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0RWxlbWVudCgpOiBIVE1MRWxlbWVudFxyXG5cdC8vIFJldHVybnMgdGhlIGluc3RhbmNlIG9mIFtgSFRNTEltYWdlRWxlbWVudGBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9IVE1MSW1hZ2VFbGVtZW50KVxyXG5cdC8vIHVzZWQgYnkgdGhpcyBvdmVybGF5LlxyXG5cdGdldEVsZW1lbnQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9pbWFnZTtcclxuXHR9LFxyXG5cclxuXHRfaW5pdEltYWdlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgd2FzRWxlbWVudFN1cHBsaWVkID0gdGhpcy5fdXJsLnRhZ05hbWUgPT09ICdJTUcnO1xyXG5cdFx0dmFyIGltZyA9IHRoaXMuX2ltYWdlID0gd2FzRWxlbWVudFN1cHBsaWVkID8gdGhpcy5fdXJsIDogY3JlYXRlJDEoJ2ltZycpO1xyXG5cclxuXHRcdGFkZENsYXNzKGltZywgJ2xlYWZsZXQtaW1hZ2UtbGF5ZXInKTtcclxuXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHsgYWRkQ2xhc3MoaW1nLCAnbGVhZmxldC16b29tLWFuaW1hdGVkJyk7IH1cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuY2xhc3NOYW1lKSB7IGFkZENsYXNzKGltZywgdGhpcy5vcHRpb25zLmNsYXNzTmFtZSk7IH1cclxuXHJcblx0XHRpbWcub25zZWxlY3RzdGFydCA9IGZhbHNlRm47XHJcblx0XHRpbWcub25tb3VzZW1vdmUgPSBmYWxzZUZuO1xyXG5cclxuXHRcdC8vIEBldmVudCBsb2FkOiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgSW1hZ2VPdmVybGF5IGxheWVyIGhhcyBsb2FkZWQgaXRzIGltYWdlXHJcblx0XHRpbWcub25sb2FkID0gYmluZCh0aGlzLmZpcmUsIHRoaXMsICdsb2FkJyk7XHJcblx0XHRpbWcub25lcnJvciA9IGJpbmQodGhpcy5fb3ZlcmxheU9uRXJyb3IsIHRoaXMsICdlcnJvcicpO1xyXG5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW4gfHwgdGhpcy5vcHRpb25zLmNyb3NzT3JpZ2luID09PSAnJykge1xyXG5cdFx0XHRpbWcuY3Jvc3NPcmlnaW4gPSB0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW4gPT09IHRydWUgPyAnJyA6IHRoaXMub3B0aW9ucy5jcm9zc09yaWdpbjtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAodGhpcy5vcHRpb25zLnpJbmRleCkge1xyXG5cdFx0XHR0aGlzLl91cGRhdGVaSW5kZXgoKTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAod2FzRWxlbWVudFN1cHBsaWVkKSB7XHJcblx0XHRcdHRoaXMuX3VybCA9IGltZy5zcmM7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRpbWcuc3JjID0gdGhpcy5fdXJsO1xyXG5cdFx0aW1nLmFsdCA9IHRoaXMub3B0aW9ucy5hbHQ7XHJcblx0fSxcclxuXHJcblx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0dmFyIHNjYWxlID0gdGhpcy5fbWFwLmdldFpvb21TY2FsZShlLnpvb20pLFxyXG5cdFx0ICAgIG9mZnNldCA9IHRoaXMuX21hcC5fbGF0TG5nQm91bmRzVG9OZXdMYXllckJvdW5kcyh0aGlzLl9ib3VuZHMsIGUuem9vbSwgZS5jZW50ZXIpLm1pbjtcclxuXHJcblx0XHRzZXRUcmFuc2Zvcm0odGhpcy5faW1hZ2UsIG9mZnNldCwgc2NhbGUpO1xyXG5cdH0sXHJcblxyXG5cdF9yZXNldDogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGltYWdlID0gdGhpcy5faW1hZ2UsXHJcblx0XHQgICAgYm91bmRzID0gbmV3IEJvdW5kcyhcclxuXHRcdCAgICAgICAgdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9ib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpLFxyXG5cdFx0ICAgICAgICB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KHRoaXMuX2JvdW5kcy5nZXRTb3V0aEVhc3QoKSkpLFxyXG5cdFx0ICAgIHNpemUgPSBib3VuZHMuZ2V0U2l6ZSgpO1xyXG5cclxuXHRcdHNldFBvc2l0aW9uKGltYWdlLCBib3VuZHMubWluKTtcclxuXHJcblx0XHRpbWFnZS5zdHlsZS53aWR0aCAgPSBzaXplLnggKyAncHgnO1xyXG5cdFx0aW1hZ2Uuc3R5bGUuaGVpZ2h0ID0gc2l6ZS55ICsgJ3B4JztcclxuXHR9LFxyXG5cclxuXHRfdXBkYXRlT3BhY2l0eTogZnVuY3Rpb24gKCkge1xyXG5cdFx0c2V0T3BhY2l0eSh0aGlzLl9pbWFnZSwgdGhpcy5vcHRpb25zLm9wYWNpdHkpO1xyXG5cdH0sXHJcblxyXG5cdF91cGRhdGVaSW5kZXg6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh0aGlzLl9pbWFnZSAmJiB0aGlzLm9wdGlvbnMuekluZGV4ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5vcHRpb25zLnpJbmRleCAhPT0gbnVsbCkge1xyXG5cdFx0XHR0aGlzLl9pbWFnZS5zdHlsZS56SW5kZXggPSB0aGlzLm9wdGlvbnMuekluZGV4O1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9vdmVybGF5T25FcnJvcjogZnVuY3Rpb24gKCkge1xyXG5cdFx0Ly8gQGV2ZW50IGVycm9yOiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgSW1hZ2VPdmVybGF5IGxheWVyIGZhaWxzIHRvIGxvYWQgaXRzIGltYWdlXHJcblx0XHR0aGlzLmZpcmUoJ2Vycm9yJyk7XHJcblxyXG5cdFx0dmFyIGVycm9yVXJsID0gdGhpcy5vcHRpb25zLmVycm9yT3ZlcmxheVVybDtcclxuXHRcdGlmIChlcnJvclVybCAmJiB0aGlzLl91cmwgIT09IGVycm9yVXJsKSB7XHJcblx0XHRcdHRoaXMuX3VybCA9IGVycm9yVXJsO1xyXG5cdFx0XHR0aGlzLl9pbWFnZS5zcmMgPSBlcnJvclVybDtcclxuXHRcdH1cclxuXHR9XHJcbn0pO1xyXG5cclxuLy8gQGZhY3RvcnkgTC5pbWFnZU92ZXJsYXkoaW1hZ2VVcmw6IFN0cmluZywgYm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBJbWFnZU92ZXJsYXkgb3B0aW9ucylcclxuLy8gSW5zdGFudGlhdGVzIGFuIGltYWdlIG92ZXJsYXkgb2JqZWN0IGdpdmVuIHRoZSBVUkwgb2YgdGhlIGltYWdlIGFuZCB0aGVcclxuLy8gZ2VvZ3JhcGhpY2FsIGJvdW5kcyBpdCBpcyB0aWVkIHRvLlxyXG52YXIgaW1hZ2VPdmVybGF5ID0gZnVuY3Rpb24gKHVybCwgYm91bmRzLCBvcHRpb25zKSB7XHJcblx0cmV0dXJuIG5ldyBJbWFnZU92ZXJsYXkodXJsLCBib3VuZHMsIG9wdGlvbnMpO1xyXG59O1xuXG4vKlxyXG4gKiBAY2xhc3MgVmlkZW9PdmVybGF5XHJcbiAqIEBha2EgTC5WaWRlb092ZXJsYXlcclxuICogQGluaGVyaXRzIEltYWdlT3ZlcmxheVxyXG4gKlxyXG4gKiBVc2VkIHRvIGxvYWQgYW5kIGRpc3BsYXkgYSB2aWRlbyBwbGF5ZXIgb3ZlciBzcGVjaWZpYyBib3VuZHMgb2YgdGhlIG1hcC4gRXh0ZW5kcyBgSW1hZ2VPdmVybGF5YC5cclxuICpcclxuICogQSB2aWRlbyBvdmVybGF5IHVzZXMgdGhlIFtgPHZpZGVvPmBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0hUTUwvRWxlbWVudC92aWRlbylcclxuICogSFRNTDUgZWxlbWVudC5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogdmFyIHZpZGVvVXJsID0gJ2h0dHBzOi8vd3d3Lm1hcGJveC5jb20vYml0ZXMvMDAxODgvcGF0cmljaWFfbmFzYS53ZWJtJyxcclxuICogXHR2aWRlb0JvdW5kcyA9IFtbIDMyLCAtMTMwXSwgWyAxMywgLTEwMF1dO1xyXG4gKiBMLnZpZGVvT3ZlcmxheSh2aWRlb1VybCwgdmlkZW9Cb3VuZHMgKS5hZGRUbyhtYXApO1xyXG4gKiBgYGBcclxuICovXHJcblxyXG52YXIgVmlkZW9PdmVybGF5ID0gSW1hZ2VPdmVybGF5LmV4dGVuZCh7XHJcblxyXG5cdC8vIEBzZWN0aW9uXHJcblx0Ly8gQGFrYSBWaWRlb092ZXJsYXkgb3B0aW9uc1xyXG5cdG9wdGlvbnM6IHtcclxuXHRcdC8vIEBvcHRpb24gYXV0b3BsYXk6IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBXaGV0aGVyIHRoZSB2aWRlbyBzdGFydHMgcGxheWluZyBhdXRvbWF0aWNhbGx5IHdoZW4gbG9hZGVkLlxyXG5cdFx0YXV0b3BsYXk6IHRydWUsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBsb29wOiBCb29sZWFuID0gdHJ1ZVxyXG5cdFx0Ly8gV2hldGhlciB0aGUgdmlkZW8gd2lsbCBsb29wIGJhY2sgdG8gdGhlIGJlZ2lubmluZyB3aGVuIHBsYXllZC5cclxuXHRcdGxvb3A6IHRydWUsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBrZWVwQXNwZWN0UmF0aW86IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBXaGV0aGVyIHRoZSB2aWRlbyB3aWxsIHNhdmUgYXNwZWN0IHJhdGlvIGFmdGVyIHRoZSBwcm9qZWN0aW9uLlxyXG5cdFx0Ly8gUmVsZXZhbnQgZm9yIHN1cHBvcnRlZCBicm93c2Vycy4gQnJvd3NlciBjb21wYXRpYmlsaXR5LSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9DU1Mvb2JqZWN0LWZpdFxyXG5cdFx0a2VlcEFzcGVjdFJhdGlvOiB0cnVlXHJcblx0fSxcclxuXHJcblx0X2luaXRJbWFnZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIHdhc0VsZW1lbnRTdXBwbGllZCA9IHRoaXMuX3VybC50YWdOYW1lID09PSAnVklERU8nO1xyXG5cdFx0dmFyIHZpZCA9IHRoaXMuX2ltYWdlID0gd2FzRWxlbWVudFN1cHBsaWVkID8gdGhpcy5fdXJsIDogY3JlYXRlJDEoJ3ZpZGVvJyk7XHJcblxyXG5cdFx0YWRkQ2xhc3ModmlkLCAnbGVhZmxldC1pbWFnZS1sYXllcicpO1xyXG5cdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkgeyBhZGRDbGFzcyh2aWQsICdsZWFmbGV0LXpvb20tYW5pbWF0ZWQnKTsgfVxyXG5cclxuXHRcdHZpZC5vbnNlbGVjdHN0YXJ0ID0gZmFsc2VGbjtcclxuXHRcdHZpZC5vbm1vdXNlbW92ZSA9IGZhbHNlRm47XHJcblxyXG5cdFx0Ly8gQGV2ZW50IGxvYWQ6IEV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSB2aWRlbyBoYXMgZmluaXNoZWQgbG9hZGluZyB0aGUgZmlyc3QgZnJhbWVcclxuXHRcdHZpZC5vbmxvYWRlZGRhdGEgPSBiaW5kKHRoaXMuZmlyZSwgdGhpcywgJ2xvYWQnKTtcclxuXHJcblx0XHRpZiAod2FzRWxlbWVudFN1cHBsaWVkKSB7XHJcblx0XHRcdHZhciBzb3VyY2VFbGVtZW50cyA9IHZpZC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnc291cmNlJyk7XHJcblx0XHRcdHZhciBzb3VyY2VzID0gW107XHJcblx0XHRcdGZvciAodmFyIGogPSAwOyBqIDwgc291cmNlRWxlbWVudHMubGVuZ3RoOyBqKyspIHtcclxuXHRcdFx0XHRzb3VyY2VzLnB1c2goc291cmNlRWxlbWVudHNbal0uc3JjKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0dGhpcy5fdXJsID0gKHNvdXJjZUVsZW1lbnRzLmxlbmd0aCA+IDApID8gc291cmNlcyA6IFt2aWQuc3JjXTtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICghaXNBcnJheSh0aGlzLl91cmwpKSB7IHRoaXMuX3VybCA9IFt0aGlzLl91cmxdOyB9XHJcblxyXG5cdFx0aWYgKCF0aGlzLm9wdGlvbnMua2VlcEFzcGVjdFJhdGlvICYmIHZpZC5zdHlsZS5oYXNPd25Qcm9wZXJ0eSgnb2JqZWN0Rml0JykpIHsgdmlkLnN0eWxlWydvYmplY3RGaXQnXSA9ICdmaWxsJzsgfVxyXG5cdFx0dmlkLmF1dG9wbGF5ID0gISF0aGlzLm9wdGlvbnMuYXV0b3BsYXk7XHJcblx0XHR2aWQubG9vcCA9ICEhdGhpcy5vcHRpb25zLmxvb3A7XHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3VybC5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHR2YXIgc291cmNlID0gY3JlYXRlJDEoJ3NvdXJjZScpO1xyXG5cdFx0XHRzb3VyY2Uuc3JjID0gdGhpcy5fdXJsW2ldO1xyXG5cdFx0XHR2aWQuYXBwZW5kQ2hpbGQoc291cmNlKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0RWxlbWVudCgpOiBIVE1MVmlkZW9FbGVtZW50XHJcblx0Ly8gUmV0dXJucyB0aGUgaW5zdGFuY2Ugb2YgW2BIVE1MVmlkZW9FbGVtZW50YF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0hUTUxWaWRlb0VsZW1lbnQpXHJcblx0Ly8gdXNlZCBieSB0aGlzIG92ZXJsYXkuXHJcbn0pO1xyXG5cclxuXHJcbi8vIEBmYWN0b3J5IEwudmlkZW9PdmVybGF5KHZpZGVvOiBTdHJpbmd8QXJyYXl8SFRNTFZpZGVvRWxlbWVudCwgYm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBWaWRlb092ZXJsYXkgb3B0aW9ucylcclxuLy8gSW5zdGFudGlhdGVzIGFuIGltYWdlIG92ZXJsYXkgb2JqZWN0IGdpdmVuIHRoZSBVUkwgb2YgdGhlIHZpZGVvIChvciBhcnJheSBvZiBVUkxzLCBvciBldmVuIGEgdmlkZW8gZWxlbWVudCkgYW5kIHRoZVxyXG4vLyBnZW9ncmFwaGljYWwgYm91bmRzIGl0IGlzIHRpZWQgdG8uXHJcblxyXG5mdW5jdGlvbiB2aWRlb092ZXJsYXkodmlkZW8sIGJvdW5kcywgb3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgVmlkZW9PdmVybGF5KHZpZGVvLCBib3VuZHMsIG9wdGlvbnMpO1xyXG59XG5cbi8qXG4gKiBAY2xhc3MgU1ZHT3ZlcmxheVxuICogQGFrYSBMLlNWR092ZXJsYXlcbiAqIEBpbmhlcml0cyBJbWFnZU92ZXJsYXlcbiAqXG4gKiBVc2VkIHRvIGxvYWQsIGRpc3BsYXkgYW5kIHByb3ZpZGUgRE9NIGFjY2VzcyB0byBhbiBTVkcgZmlsZSBvdmVyIHNwZWNpZmljIGJvdW5kcyBvZiB0aGUgbWFwLiBFeHRlbmRzIGBJbWFnZU92ZXJsYXlgLlxuICpcbiAqIEFuIFNWRyBvdmVybGF5IHVzZXMgdGhlIFtgPHN2Zz5gXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvRWxlbWVudC9zdmcpIGVsZW1lbnQuXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGBqc1xuICogdmFyIGVsZW1lbnQgPSAnPHN2ZyB3aWR0aD1cIjIwMFwiIGhlaWdodD1cIjIwMFwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB4bWxuczp4bGluaz1cImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmtcIj48aW1hZ2UgeGxpbms6aHJlZj1cImh0dHBzOi8vbWRuLm1vemlsbGFkZW1vcy5vcmcvZmlsZXMvNjQ1Ny9tZG5fbG9nb19vbmx5X2NvbG9yLnBuZ1wiIGhlaWdodD1cIjIwMFwiIHdpZHRoPVwiMjAwXCIvPjwvc3ZnPicsXG4gKiBcdFx0IGVsZW1lbnRCb3VuZHMgPSBbIFsgMzIsIC0xMzAgXSwgWyAxMywgLTEwMCBdIF07XG4gKiBMLnN2Z092ZXJsYXkoZWxlbWVudCwgZWxlbWVudEJvdW5kcykuYWRkVG8obWFwKTtcbiAqIGBgYFxuICovXG5cbnZhciBTVkdPdmVybGF5ID0gSW1hZ2VPdmVybGF5LmV4dGVuZCh7XG5cdF9pbml0SW1hZ2U6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgZWwgPSB0aGlzLl9pbWFnZSA9IHRoaXMuX3VybDtcblxuXHRcdGFkZENsYXNzKGVsLCAnbGVhZmxldC1pbWFnZS1sYXllcicpO1xuXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHsgYWRkQ2xhc3MoZWwsICdsZWFmbGV0LXpvb20tYW5pbWF0ZWQnKTsgfVxuXG5cdFx0ZWwub25zZWxlY3RzdGFydCA9IGZhbHNlRm47XG5cdFx0ZWwub25tb3VzZW1vdmUgPSBmYWxzZUZuO1xuXHR9XG5cblx0Ly8gQG1ldGhvZCBnZXRFbGVtZW50KCk6IFNWR0VsZW1lbnRcblx0Ly8gUmV0dXJucyB0aGUgaW5zdGFuY2Ugb2YgW2BTVkdFbGVtZW50YF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL1NWR0VsZW1lbnQpXG5cdC8vIHVzZWQgYnkgdGhpcyBvdmVybGF5LlxufSk7XG5cblxuLy8gQGZhY3RvcnkgTC5zdmdPdmVybGF5KHN2ZzogU3RyaW5nfFNWR0VsZW1lbnQsIGJvdW5kczogTGF0TG5nQm91bmRzLCBvcHRpb25zPzogU1ZHT3ZlcmxheSBvcHRpb25zKVxuLy8gSW5zdGFudGlhdGVzIGFuIGltYWdlIG92ZXJsYXkgb2JqZWN0IGdpdmVuIGFuIFNWRyBlbGVtZW50IGFuZCB0aGUgZ2VvZ3JhcGhpY2FsIGJvdW5kcyBpdCBpcyB0aWVkIHRvLlxuLy8gQSB2aWV3Qm94IGF0dHJpYnV0ZSBpcyByZXF1aXJlZCBvbiB0aGUgU1ZHIGVsZW1lbnQgdG8gem9vbSBpbiBhbmQgb3V0IHByb3Blcmx5LlxuXG5mdW5jdGlvbiBzdmdPdmVybGF5KGVsLCBib3VuZHMsIG9wdGlvbnMpIHtcblx0cmV0dXJuIG5ldyBTVkdPdmVybGF5KGVsLCBib3VuZHMsIG9wdGlvbnMpO1xufVxuXG4vKlxyXG4gKiBAY2xhc3MgRGl2T3ZlcmxheVxyXG4gKiBAaW5oZXJpdHMgTGF5ZXJcclxuICogQGFrYSBMLkRpdk92ZXJsYXlcclxuICogQmFzZSBtb2RlbCBmb3IgTC5Qb3B1cCBhbmQgTC5Ub29sdGlwLiBJbmhlcml0IGZyb20gaXQgZm9yIGN1c3RvbSBwb3B1cCBsaWtlIHBsdWdpbnMuXHJcbiAqL1xyXG5cclxuLy8gQG5hbWVzcGFjZSBEaXZPdmVybGF5XHJcbnZhciBEaXZPdmVybGF5ID0gTGF5ZXIuZXh0ZW5kKHtcclxuXHJcblx0Ly8gQHNlY3Rpb25cclxuXHQvLyBAYWthIERpdk92ZXJsYXkgb3B0aW9uc1xyXG5cdG9wdGlvbnM6IHtcclxuXHRcdC8vIEBvcHRpb24gb2Zmc2V0OiBQb2ludCA9IFBvaW50KDAsIDcpXHJcblx0XHQvLyBUaGUgb2Zmc2V0IG9mIHRoZSBwb3B1cCBwb3NpdGlvbi4gVXNlZnVsIHRvIGNvbnRyb2wgdGhlIGFuY2hvclxyXG5cdFx0Ly8gb2YgdGhlIHBvcHVwIHdoZW4gb3BlbmluZyBpdCBvbiBzb21lIG92ZXJsYXlzLlxyXG5cdFx0b2Zmc2V0OiBbMCwgN10sXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9ICcnXHJcblx0XHQvLyBBIGN1c3RvbSBDU1MgY2xhc3MgbmFtZSB0byBhc3NpZ24gdG8gdGhlIHBvcHVwLlxyXG5cdFx0Y2xhc3NOYW1lOiAnJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHBhbmU6IFN0cmluZyA9ICdwb3B1cFBhbmUnXHJcblx0XHQvLyBgTWFwIHBhbmVgIHdoZXJlIHRoZSBwb3B1cCB3aWxsIGJlIGFkZGVkLlxyXG5cdFx0cGFuZTogJ3BvcHVwUGFuZSdcclxuXHR9LFxyXG5cclxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAob3B0aW9ucywgc291cmNlKSB7XHJcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuXHRcdHRoaXMuX3NvdXJjZSA9IHNvdXJjZTtcclxuXHR9LFxyXG5cclxuXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0dGhpcy5fem9vbUFuaW1hdGVkID0gbWFwLl96b29tQW5pbWF0ZWQ7XHJcblxyXG5cdFx0aWYgKCF0aGlzLl9jb250YWluZXIpIHtcclxuXHRcdFx0dGhpcy5faW5pdExheW91dCgpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChtYXAuX2ZhZGVBbmltYXRlZCkge1xyXG5cdFx0XHRzZXRPcGFjaXR5KHRoaXMuX2NvbnRhaW5lciwgMCk7XHJcblx0XHR9XHJcblxyXG5cdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3JlbW92ZVRpbWVvdXQpO1xyXG5cdFx0dGhpcy5nZXRQYW5lKCkuYXBwZW5kQ2hpbGQodGhpcy5fY29udGFpbmVyKTtcclxuXHRcdHRoaXMudXBkYXRlKCk7XHJcblxyXG5cdFx0aWYgKG1hcC5fZmFkZUFuaW1hdGVkKSB7XHJcblx0XHRcdHNldE9wYWNpdHkodGhpcy5fY29udGFpbmVyLCAxKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLmJyaW5nVG9Gcm9udCgpO1xyXG5cdH0sXHJcblxyXG5cdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XHJcblx0XHRpZiAobWFwLl9mYWRlQW5pbWF0ZWQpIHtcclxuXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9jb250YWluZXIsIDApO1xyXG5cdFx0XHR0aGlzLl9yZW1vdmVUaW1lb3V0ID0gc2V0VGltZW91dChiaW5kKHJlbW92ZSwgdW5kZWZpbmVkLCB0aGlzLl9jb250YWluZXIpLCAyMDApO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0Ly8gQG5hbWVzcGFjZSBQb3B1cFxyXG5cdC8vIEBtZXRob2QgZ2V0TGF0TG5nOiBMYXRMbmdcclxuXHQvLyBSZXR1cm5zIHRoZSBnZW9ncmFwaGljYWwgcG9pbnQgb2YgcG9wdXAuXHJcblx0Z2V0TGF0TG5nOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fbGF0bG5nO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0TGF0TG5nKGxhdGxuZzogTGF0TG5nKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIGdlb2dyYXBoaWNhbCBwb2ludCB3aGVyZSB0aGUgcG9wdXAgd2lsbCBvcGVuLlxyXG5cdHNldExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xyXG5cdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcclxuXHRcdGlmICh0aGlzLl9tYXApIHtcclxuXHRcdFx0dGhpcy5fdXBkYXRlUG9zaXRpb24oKTtcclxuXHRcdFx0dGhpcy5fYWRqdXN0UGFuKCk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldENvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudFxyXG5cdC8vIFJldHVybnMgdGhlIGNvbnRlbnQgb2YgdGhlIHBvcHVwLlxyXG5cdGdldENvbnRlbnQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9jb250ZW50O1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0Q29udGVudChodG1sQ29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fEZ1bmN0aW9uKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIEhUTUwgY29udGVudCBvZiB0aGUgcG9wdXAuIElmIGEgZnVuY3Rpb24gaXMgcGFzc2VkIHRoZSBzb3VyY2UgbGF5ZXIgd2lsbCBiZSBwYXNzZWQgdG8gdGhlIGZ1bmN0aW9uLiBUaGUgZnVuY3Rpb24gc2hvdWxkIHJldHVybiBhIGBTdHJpbmdgIG9yIGBIVE1MRWxlbWVudGAgdG8gYmUgdXNlZCBpbiB0aGUgcG9wdXAuXHJcblx0c2V0Q29udGVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcclxuXHRcdHRoaXMuX2NvbnRlbnQgPSBjb250ZW50O1xyXG5cdFx0dGhpcy51cGRhdGUoKTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0RWxlbWVudDogU3RyaW5nfEhUTUxFbGVtZW50XHJcblx0Ly8gQWxpYXMgZm9yIFtnZXRDb250ZW50KCldKCNwb3B1cC1nZXRjb250ZW50KVxyXG5cdGdldEVsZW1lbnQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9jb250YWluZXI7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB1cGRhdGU6IG51bGxcclxuXHQvLyBVcGRhdGVzIHRoZSBwb3B1cCBjb250ZW50LCBsYXlvdXQgYW5kIHBvc2l0aW9uLiBVc2VmdWwgZm9yIHVwZGF0aW5nIHRoZSBwb3B1cCBhZnRlciBzb21ldGhpbmcgaW5zaWRlIGNoYW5nZWQsIGUuZy4gaW1hZ2UgbG9hZGVkLlxyXG5cdHVwZGF0ZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0dGhpcy5fY29udGFpbmVyLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcclxuXHJcblx0XHR0aGlzLl91cGRhdGVDb250ZW50KCk7XHJcblx0XHR0aGlzLl91cGRhdGVMYXlvdXQoKTtcclxuXHRcdHRoaXMuX3VwZGF0ZVBvc2l0aW9uKCk7XHJcblxyXG5cdFx0dGhpcy5fY29udGFpbmVyLnN0eWxlLnZpc2liaWxpdHkgPSAnJztcclxuXHJcblx0XHR0aGlzLl9hZGp1c3RQYW4oKTtcclxuXHR9LFxyXG5cclxuXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBldmVudHMgPSB7XHJcblx0XHRcdHpvb206IHRoaXMuX3VwZGF0ZVBvc2l0aW9uLFxyXG5cdFx0XHR2aWV3cmVzZXQ6IHRoaXMuX3VwZGF0ZVBvc2l0aW9uXHJcblx0XHR9O1xyXG5cclxuXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuXHRcdFx0ZXZlbnRzLnpvb21hbmltID0gdGhpcy5fYW5pbWF0ZVpvb207XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gZXZlbnRzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgaXNPcGVuOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgd2hlbiB0aGUgcG9wdXAgaXMgdmlzaWJsZSBvbiB0aGUgbWFwLlxyXG5cdGlzT3BlbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuICEhdGhpcy5fbWFwICYmIHRoaXMuX21hcC5oYXNMYXllcih0aGlzKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udDogdGhpc1xyXG5cdC8vIEJyaW5ncyB0aGlzIHBvcHVwIGluIGZyb250IG9mIG90aGVyIHBvcHVwcyAoaW4gdGhlIHNhbWUgbWFwIHBhbmUpLlxyXG5cdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKHRoaXMuX21hcCkge1xyXG5cdFx0XHR0b0Zyb250KHRoaXMuX2NvbnRhaW5lcik7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGJyaW5nVG9CYWNrOiB0aGlzXHJcblx0Ly8gQnJpbmdzIHRoaXMgcG9wdXAgdG8gdGhlIGJhY2sgb2Ygb3RoZXIgcG9wdXBzIChpbiB0aGUgc2FtZSBtYXAgcGFuZSkuXHJcblx0YnJpbmdUb0JhY2s6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh0aGlzLl9tYXApIHtcclxuXHRcdFx0dG9CYWNrKHRoaXMuX2NvbnRhaW5lcik7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRfcHJlcGFyZU9wZW46IGZ1bmN0aW9uIChwYXJlbnQsIGxheWVyLCBsYXRsbmcpIHtcclxuXHRcdGlmICghKGxheWVyIGluc3RhbmNlb2YgTGF5ZXIpKSB7XHJcblx0XHRcdGxhdGxuZyA9IGxheWVyO1xyXG5cdFx0XHRsYXllciA9IHBhcmVudDtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAobGF5ZXIgaW5zdGFuY2VvZiBGZWF0dXJlR3JvdXApIHtcclxuXHRcdFx0Zm9yICh2YXIgaWQgaW4gcGFyZW50Ll9sYXllcnMpIHtcclxuXHRcdFx0XHRsYXllciA9IHBhcmVudC5fbGF5ZXJzW2lkXTtcclxuXHRcdFx0XHRicmVhaztcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdGlmICghbGF0bG5nKSB7XHJcblx0XHRcdGlmIChsYXllci5nZXRDZW50ZXIpIHtcclxuXHRcdFx0XHRsYXRsbmcgPSBsYXllci5nZXRDZW50ZXIoKTtcclxuXHRcdFx0fSBlbHNlIGlmIChsYXllci5nZXRMYXRMbmcpIHtcclxuXHRcdFx0XHRsYXRsbmcgPSBsYXllci5nZXRMYXRMbmcoKTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1VuYWJsZSB0byBnZXQgc291cmNlIGxheWVyIExhdExuZy4nKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIHNldCBvdmVybGF5IHNvdXJjZSB0byB0aGlzIGxheWVyXHJcblx0XHR0aGlzLl9zb3VyY2UgPSBsYXllcjtcclxuXHJcblx0XHQvLyB1cGRhdGUgdGhlIG92ZXJsYXkgKGNvbnRlbnQsIGxheW91dCwgZWN0Li4uKVxyXG5cdFx0dGhpcy51cGRhdGUoKTtcclxuXHJcblx0XHRyZXR1cm4gbGF0bG5nO1xyXG5cdH0sXHJcblxyXG5cdF91cGRhdGVDb250ZW50OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAoIXRoaXMuX2NvbnRlbnQpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0dmFyIG5vZGUgPSB0aGlzLl9jb250ZW50Tm9kZTtcclxuXHRcdHZhciBjb250ZW50ID0gKHR5cGVvZiB0aGlzLl9jb250ZW50ID09PSAnZnVuY3Rpb24nKSA/IHRoaXMuX2NvbnRlbnQodGhpcy5fc291cmNlIHx8IHRoaXMpIDogdGhpcy5fY29udGVudDtcclxuXHJcblx0XHRpZiAodHlwZW9mIGNvbnRlbnQgPT09ICdzdHJpbmcnKSB7XHJcblx0XHRcdG5vZGUuaW5uZXJIVE1MID0gY29udGVudDtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHdoaWxlIChub2RlLmhhc0NoaWxkTm9kZXMoKSkge1xyXG5cdFx0XHRcdG5vZGUucmVtb3ZlQ2hpbGQobm9kZS5maXJzdENoaWxkKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRub2RlLmFwcGVuZENoaWxkKGNvbnRlbnQpO1xyXG5cdFx0fVxyXG5cdFx0dGhpcy5maXJlKCdjb250ZW50dXBkYXRlJyk7XHJcblx0fSxcclxuXHJcblx0X3VwZGF0ZVBvc2l0aW9uOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAoIXRoaXMuX21hcCkgeyByZXR1cm47IH1cclxuXHJcblx0XHR2YXIgcG9zID0gdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcpLFxyXG5cdFx0ICAgIG9mZnNldCA9IHRvUG9pbnQodGhpcy5vcHRpb25zLm9mZnNldCksXHJcblx0XHQgICAgYW5jaG9yID0gdGhpcy5fZ2V0QW5jaG9yKCk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xyXG5cdFx0XHRzZXRQb3NpdGlvbih0aGlzLl9jb250YWluZXIsIHBvcy5hZGQoYW5jaG9yKSk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRvZmZzZXQgPSBvZmZzZXQuYWRkKHBvcykuYWRkKGFuY2hvcik7XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIGJvdHRvbSA9IHRoaXMuX2NvbnRhaW5lckJvdHRvbSA9IC1vZmZzZXQueSxcclxuXHRcdCAgICBsZWZ0ID0gdGhpcy5fY29udGFpbmVyTGVmdCA9IC1NYXRoLnJvdW5kKHRoaXMuX2NvbnRhaW5lcldpZHRoIC8gMikgKyBvZmZzZXQueDtcclxuXHJcblx0XHQvLyBib3R0b20gcG9zaXRpb24gdGhlIHBvcHVwIGluIGNhc2UgdGhlIGhlaWdodCBvZiB0aGUgcG9wdXAgY2hhbmdlcyAoaW1hZ2VzIGxvYWRpbmcgZXRjKVxyXG5cdFx0dGhpcy5fY29udGFpbmVyLnN0eWxlLmJvdHRvbSA9IGJvdHRvbSArICdweCc7XHJcblx0XHR0aGlzLl9jb250YWluZXIuc3R5bGUubGVmdCA9IGxlZnQgKyAncHgnO1xyXG5cdH0sXHJcblxyXG5cdF9nZXRBbmNob3I6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiBbMCwgMF07XHJcblx0fVxyXG5cclxufSk7XG5cbi8qXHJcbiAqIEBjbGFzcyBQb3B1cFxyXG4gKiBAaW5oZXJpdHMgRGl2T3ZlcmxheVxyXG4gKiBAYWthIEwuUG9wdXBcclxuICogVXNlZCB0byBvcGVuIHBvcHVwcyBpbiBjZXJ0YWluIHBsYWNlcyBvZiB0aGUgbWFwLiBVc2UgW01hcC5vcGVuUG9wdXBdKCNtYXAtb3BlbnBvcHVwKSB0b1xyXG4gKiBvcGVuIHBvcHVwcyB3aGlsZSBtYWtpbmcgc3VyZSB0aGF0IG9ubHkgb25lIHBvcHVwIGlzIG9wZW4gYXQgb25lIHRpbWVcclxuICogKHJlY29tbWVuZGVkIGZvciB1c2FiaWxpdHkpLCBvciB1c2UgW01hcC5hZGRMYXllcl0oI21hcC1hZGRsYXllcikgdG8gb3BlbiBhcyBtYW55IGFzIHlvdSB3YW50LlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBJZiB5b3Ugd2FudCB0byBqdXN0IGJpbmQgYSBwb3B1cCB0byBtYXJrZXIgY2xpY2sgYW5kIHRoZW4gb3BlbiBpdCwgaXQncyByZWFsbHkgZWFzeTpcclxuICpcclxuICogYGBganNcclxuICogbWFya2VyLmJpbmRQb3B1cChwb3B1cENvbnRlbnQpLm9wZW5Qb3B1cCgpO1xyXG4gKiBgYGBcclxuICogUGF0aCBvdmVybGF5cyBsaWtlIHBvbHlsaW5lcyBhbHNvIGhhdmUgYSBgYmluZFBvcHVwYCBtZXRob2QuXHJcbiAqIEhlcmUncyBhIG1vcmUgY29tcGxpY2F0ZWQgd2F5IHRvIG9wZW4gYSBwb3B1cCBvbiBhIG1hcDpcclxuICpcclxuICogYGBganNcclxuICogdmFyIHBvcHVwID0gTC5wb3B1cCgpXHJcbiAqIFx0LnNldExhdExuZyhsYXRsbmcpXHJcbiAqIFx0LnNldENvbnRlbnQoJzxwPkhlbGxvIHdvcmxkITxiciAvPlRoaXMgaXMgYSBuaWNlIHBvcHVwLjwvcD4nKVxyXG4gKiBcdC5vcGVuT24obWFwKTtcclxuICogYGBgXHJcbiAqL1xyXG5cclxuXHJcbi8vIEBuYW1lc3BhY2UgUG9wdXBcclxudmFyIFBvcHVwID0gRGl2T3ZlcmxheS5leHRlbmQoe1xyXG5cclxuXHQvLyBAc2VjdGlvblxyXG5cdC8vIEBha2EgUG9wdXAgb3B0aW9uc1xyXG5cdG9wdGlvbnM6IHtcclxuXHRcdC8vIEBvcHRpb24gbWF4V2lkdGg6IE51bWJlciA9IDMwMFxyXG5cdFx0Ly8gTWF4IHdpZHRoIG9mIHRoZSBwb3B1cCwgaW4gcGl4ZWxzLlxyXG5cdFx0bWF4V2lkdGg6IDMwMCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIG1pbldpZHRoOiBOdW1iZXIgPSA1MFxyXG5cdFx0Ly8gTWluIHdpZHRoIG9mIHRoZSBwb3B1cCwgaW4gcGl4ZWxzLlxyXG5cdFx0bWluV2lkdGg6IDUwLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gbWF4SGVpZ2h0OiBOdW1iZXIgPSBudWxsXHJcblx0XHQvLyBJZiBzZXQsIGNyZWF0ZXMgYSBzY3JvbGxhYmxlIGNvbnRhaW5lciBvZiB0aGUgZ2l2ZW4gaGVpZ2h0XHJcblx0XHQvLyBpbnNpZGUgYSBwb3B1cCBpZiBpdHMgY29udGVudCBleGNlZWRzIGl0LlxyXG5cdFx0bWF4SGVpZ2h0OiBudWxsLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gYXV0b1BhbjogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIFNldCBpdCB0byBgZmFsc2VgIGlmIHlvdSBkb24ndCB3YW50IHRoZSBtYXAgdG8gZG8gcGFubmluZyBhbmltYXRpb25cclxuXHRcdC8vIHRvIGZpdCB0aGUgb3BlbmVkIHBvcHVwLlxyXG5cdFx0YXV0b1BhbjogdHJ1ZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGF1dG9QYW5QYWRkaW5nVG9wTGVmdDogUG9pbnQgPSBudWxsXHJcblx0XHQvLyBUaGUgbWFyZ2luIGJldHdlZW4gdGhlIHBvcHVwIGFuZCB0aGUgdG9wIGxlZnQgY29ybmVyIG9mIHRoZSBtYXBcclxuXHRcdC8vIHZpZXcgYWZ0ZXIgYXV0b3Bhbm5pbmcgd2FzIHBlcmZvcm1lZC5cclxuXHRcdGF1dG9QYW5QYWRkaW5nVG9wTGVmdDogbnVsbCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGF1dG9QYW5QYWRkaW5nQm90dG9tUmlnaHQ6IFBvaW50ID0gbnVsbFxyXG5cdFx0Ly8gVGhlIG1hcmdpbiBiZXR3ZWVuIHRoZSBwb3B1cCBhbmQgdGhlIGJvdHRvbSByaWdodCBjb3JuZXIgb2YgdGhlIG1hcFxyXG5cdFx0Ly8gdmlldyBhZnRlciBhdXRvcGFubmluZyB3YXMgcGVyZm9ybWVkLlxyXG5cdFx0YXV0b1BhblBhZGRpbmdCb3R0b21SaWdodDogbnVsbCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGF1dG9QYW5QYWRkaW5nOiBQb2ludCA9IFBvaW50KDUsIDUpXHJcblx0XHQvLyBFcXVpdmFsZW50IG9mIHNldHRpbmcgYm90aCB0b3AgbGVmdCBhbmQgYm90dG9tIHJpZ2h0IGF1dG9wYW4gcGFkZGluZyB0byB0aGUgc2FtZSB2YWx1ZS5cclxuXHRcdGF1dG9QYW5QYWRkaW5nOiBbNSwgNV0sXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBrZWVwSW5WaWV3OiBCb29sZWFuID0gZmFsc2VcclxuXHRcdC8vIFNldCBpdCB0byBgdHJ1ZWAgaWYgeW91IHdhbnQgdG8gcHJldmVudCB1c2VycyBmcm9tIHBhbm5pbmcgdGhlIHBvcHVwXHJcblx0XHQvLyBvZmYgb2YgdGhlIHNjcmVlbiB3aGlsZSBpdCBpcyBvcGVuLlxyXG5cdFx0a2VlcEluVmlldzogZmFsc2UsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBjbG9zZUJ1dHRvbjogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIENvbnRyb2xzIHRoZSBwcmVzZW5jZSBvZiBhIGNsb3NlIGJ1dHRvbiBpbiB0aGUgcG9wdXAuXHJcblx0XHRjbG9zZUJ1dHRvbjogdHJ1ZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGF1dG9DbG9zZTogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIFNldCBpdCB0byBgZmFsc2VgIGlmIHlvdSB3YW50IHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mXHJcblx0XHQvLyB0aGUgcG9wdXAgY2xvc2luZyB3aGVuIGFub3RoZXIgcG9wdXAgaXMgb3BlbmVkLlxyXG5cdFx0YXV0b0Nsb3NlOiB0cnVlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gY2xvc2VPbkVzY2FwZUtleTogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIFNldCBpdCB0byBgZmFsc2VgIGlmIHlvdSB3YW50IHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mXHJcblx0XHQvLyB0aGUgRVNDIGtleSBmb3IgY2xvc2luZyBvZiB0aGUgcG9wdXAuXHJcblx0XHRjbG9zZU9uRXNjYXBlS2V5OiB0cnVlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gY2xvc2VPbkNsaWNrOiBCb29sZWFuID0gKlxyXG5cdFx0Ly8gU2V0IGl0IGlmIHlvdSB3YW50IHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIHRoZSBwb3B1cCBjbG9zaW5nIHdoZW4gdXNlciBjbGlja3NcclxuXHRcdC8vIG9uIHRoZSBtYXAuIERlZmF1bHRzIHRvIHRoZSBtYXAncyBbYGNsb3NlUG9wdXBPbkNsaWNrYF0oI21hcC1jbG9zZXBvcHVwb25jbGljaykgb3B0aW9uLlxyXG5cclxuXHRcdC8vIEBvcHRpb24gY2xhc3NOYW1lOiBTdHJpbmcgPSAnJ1xyXG5cdFx0Ly8gQSBjdXN0b20gQ1NTIGNsYXNzIG5hbWUgdG8gYXNzaWduIHRvIHRoZSBwb3B1cC5cclxuXHRcdGNsYXNzTmFtZTogJydcclxuXHR9LFxyXG5cclxuXHQvLyBAbmFtZXNwYWNlIFBvcHVwXHJcblx0Ly8gQG1ldGhvZCBvcGVuT24obWFwOiBNYXApOiB0aGlzXHJcblx0Ly8gQWRkcyB0aGUgcG9wdXAgdG8gdGhlIG1hcCBhbmQgY2xvc2VzIHRoZSBwcmV2aW91cyBvbmUuIFRoZSBzYW1lIGFzIGBtYXAub3BlblBvcHVwKHBvcHVwKWAuXHJcblx0b3Blbk9uOiBmdW5jdGlvbiAobWFwKSB7XHJcblx0XHRtYXAub3BlblBvcHVwKHRoaXMpO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuXHRcdERpdk92ZXJsYXkucHJvdG90eXBlLm9uQWRkLmNhbGwodGhpcywgbWFwKTtcclxuXHJcblx0XHQvLyBAbmFtZXNwYWNlIE1hcFxyXG5cdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcblx0XHQvLyBAZXZlbnQgcG9wdXBvcGVuOiBQb3B1cEV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIGEgcG9wdXAgaXMgb3BlbmVkIGluIHRoZSBtYXBcclxuXHRcdG1hcC5maXJlKCdwb3B1cG9wZW4nLCB7cG9wdXA6IHRoaXN9KTtcclxuXHJcblx0XHRpZiAodGhpcy5fc291cmNlKSB7XHJcblx0XHRcdC8vIEBuYW1lc3BhY2UgTGF5ZXJcclxuXHRcdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcblx0XHRcdC8vIEBldmVudCBwb3B1cG9wZW46IFBvcHVwRXZlbnRcclxuXHRcdFx0Ly8gRmlyZWQgd2hlbiBhIHBvcHVwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgaXMgb3BlbmVkXHJcblx0XHRcdHRoaXMuX3NvdXJjZS5maXJlKCdwb3B1cG9wZW4nLCB7cG9wdXA6IHRoaXN9LCB0cnVlKTtcclxuXHRcdFx0Ly8gRm9yIG5vbi1wYXRoIGxheWVycywgd2UgdG9nZ2xlIHRoZSBwb3B1cCB3aGVuIGNsaWNraW5nXHJcblx0XHRcdC8vIGFnYWluIHRoZSBsYXllciwgc28gcHJldmVudCB0aGUgbWFwIHRvIHJlb3BlbiBpdC5cclxuXHRcdFx0aWYgKCEodGhpcy5fc291cmNlIGluc3RhbmNlb2YgUGF0aCkpIHtcclxuXHRcdFx0XHR0aGlzLl9zb3VyY2Uub24oJ3ByZWNsaWNrJywgc3RvcFByb3BhZ2F0aW9uKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XHJcblx0XHREaXZPdmVybGF5LnByb3RvdHlwZS5vblJlbW92ZS5jYWxsKHRoaXMsIG1hcCk7XHJcblxyXG5cdFx0Ly8gQG5hbWVzcGFjZSBNYXBcclxuXHRcdC8vIEBzZWN0aW9uIFBvcHVwIGV2ZW50c1xyXG5cdFx0Ly8gQGV2ZW50IHBvcHVwY2xvc2U6IFBvcHVwRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gYSBwb3B1cCBpbiB0aGUgbWFwIGlzIGNsb3NlZFxyXG5cdFx0bWFwLmZpcmUoJ3BvcHVwY2xvc2UnLCB7cG9wdXA6IHRoaXN9KTtcclxuXHJcblx0XHRpZiAodGhpcy5fc291cmNlKSB7XHJcblx0XHRcdC8vIEBuYW1lc3BhY2UgTGF5ZXJcclxuXHRcdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcblx0XHRcdC8vIEBldmVudCBwb3B1cGNsb3NlOiBQb3B1cEV2ZW50XHJcblx0XHRcdC8vIEZpcmVkIHdoZW4gYSBwb3B1cCBib3VuZCB0byB0aGlzIGxheWVyIGlzIGNsb3NlZFxyXG5cdFx0XHR0aGlzLl9zb3VyY2UuZmlyZSgncG9wdXBjbG9zZScsIHtwb3B1cDogdGhpc30sIHRydWUpO1xyXG5cdFx0XHRpZiAoISh0aGlzLl9zb3VyY2UgaW5zdGFuY2VvZiBQYXRoKSkge1xyXG5cdFx0XHRcdHRoaXMuX3NvdXJjZS5vZmYoJ3ByZWNsaWNrJywgc3RvcFByb3BhZ2F0aW9uKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdGdldEV2ZW50czogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGV2ZW50cyA9IERpdk92ZXJsYXkucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xyXG5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuY2xvc2VPbkNsaWNrICE9PSB1bmRlZmluZWQgPyB0aGlzLm9wdGlvbnMuY2xvc2VPbkNsaWNrIDogdGhpcy5fbWFwLm9wdGlvbnMuY2xvc2VQb3B1cE9uQ2xpY2spIHtcclxuXHRcdFx0ZXZlbnRzLnByZWNsaWNrID0gdGhpcy5fY2xvc2U7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5rZWVwSW5WaWV3KSB7XHJcblx0XHRcdGV2ZW50cy5tb3ZlZW5kID0gdGhpcy5fYWRqdXN0UGFuO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBldmVudHM7XHJcblx0fSxcclxuXHJcblx0X2Nsb3NlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAodGhpcy5fbWFwKSB7XHJcblx0XHRcdHRoaXMuX21hcC5jbG9zZVBvcHVwKHRoaXMpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9pbml0TGF5b3V0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgcHJlZml4ID0gJ2xlYWZsZXQtcG9wdXAnLFxyXG5cdFx0ICAgIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLFxyXG5cdFx0XHRwcmVmaXggKyAnICcgKyAodGhpcy5vcHRpb25zLmNsYXNzTmFtZSB8fCAnJykgK1xyXG5cdFx0XHQnIGxlYWZsZXQtem9vbS1hbmltYXRlZCcpO1xyXG5cclxuXHRcdHZhciB3cmFwcGVyID0gdGhpcy5fd3JhcHBlciA9IGNyZWF0ZSQxKCdkaXYnLCBwcmVmaXggKyAnLWNvbnRlbnQtd3JhcHBlcicsIGNvbnRhaW5lcik7XHJcblx0XHR0aGlzLl9jb250ZW50Tm9kZSA9IGNyZWF0ZSQxKCdkaXYnLCBwcmVmaXggKyAnLWNvbnRlbnQnLCB3cmFwcGVyKTtcclxuXHJcblx0XHRkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbih3cmFwcGVyKTtcclxuXHRcdGRpc2FibGVTY3JvbGxQcm9wYWdhdGlvbih0aGlzLl9jb250ZW50Tm9kZSk7XHJcblx0XHRvbih3cmFwcGVyLCAnY29udGV4dG1lbnUnLCBzdG9wUHJvcGFnYXRpb24pO1xyXG5cclxuXHRcdHRoaXMuX3RpcENvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLCBwcmVmaXggKyAnLXRpcC1jb250YWluZXInLCBjb250YWluZXIpO1xyXG5cdFx0dGhpcy5fdGlwID0gY3JlYXRlJDEoJ2RpdicsIHByZWZpeCArICctdGlwJywgdGhpcy5fdGlwQ29udGFpbmVyKTtcclxuXHJcblx0XHRpZiAodGhpcy5vcHRpb25zLmNsb3NlQnV0dG9uKSB7XHJcblx0XHRcdHZhciBjbG9zZUJ1dHRvbiA9IHRoaXMuX2Nsb3NlQnV0dG9uID0gY3JlYXRlJDEoJ2EnLCBwcmVmaXggKyAnLWNsb3NlLWJ1dHRvbicsIGNvbnRhaW5lcik7XHJcblx0XHRcdGNsb3NlQnV0dG9uLmhyZWYgPSAnI2Nsb3NlJztcclxuXHRcdFx0Y2xvc2VCdXR0b24uaW5uZXJIVE1MID0gJyYjMjE1Oyc7XHJcblxyXG5cdFx0XHRvbihjbG9zZUJ1dHRvbiwgJ2NsaWNrJywgdGhpcy5fb25DbG9zZUJ1dHRvbkNsaWNrLCB0aGlzKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfdXBkYXRlTGF5b3V0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGVudE5vZGUsXHJcblx0XHQgICAgc3R5bGUgPSBjb250YWluZXIuc3R5bGU7XHJcblxyXG5cdFx0c3R5bGUud2lkdGggPSAnJztcclxuXHRcdHN0eWxlLndoaXRlU3BhY2UgPSAnbm93cmFwJztcclxuXHJcblx0XHR2YXIgd2lkdGggPSBjb250YWluZXIub2Zmc2V0V2lkdGg7XHJcblx0XHR3aWR0aCA9IE1hdGgubWluKHdpZHRoLCB0aGlzLm9wdGlvbnMubWF4V2lkdGgpO1xyXG5cdFx0d2lkdGggPSBNYXRoLm1heCh3aWR0aCwgdGhpcy5vcHRpb25zLm1pbldpZHRoKTtcclxuXHJcblx0XHRzdHlsZS53aWR0aCA9ICh3aWR0aCArIDEpICsgJ3B4JztcclxuXHRcdHN0eWxlLndoaXRlU3BhY2UgPSAnJztcclxuXHJcblx0XHRzdHlsZS5oZWlnaHQgPSAnJztcclxuXHJcblx0XHR2YXIgaGVpZ2h0ID0gY29udGFpbmVyLm9mZnNldEhlaWdodCxcclxuXHRcdCAgICBtYXhIZWlnaHQgPSB0aGlzLm9wdGlvbnMubWF4SGVpZ2h0LFxyXG5cdFx0ICAgIHNjcm9sbGVkQ2xhc3MgPSAnbGVhZmxldC1wb3B1cC1zY3JvbGxlZCc7XHJcblxyXG5cdFx0aWYgKG1heEhlaWdodCAmJiBoZWlnaHQgPiBtYXhIZWlnaHQpIHtcclxuXHRcdFx0c3R5bGUuaGVpZ2h0ID0gbWF4SGVpZ2h0ICsgJ3B4JztcclxuXHRcdFx0YWRkQ2xhc3MoY29udGFpbmVyLCBzY3JvbGxlZENsYXNzKTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHJlbW92ZUNsYXNzKGNvbnRhaW5lciwgc2Nyb2xsZWRDbGFzcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fY29udGFpbmVyV2lkdGggPSB0aGlzLl9jb250YWluZXIub2Zmc2V0V2lkdGg7XHJcblx0fSxcclxuXHJcblx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0dmFyIHBvcyA9IHRoaXMuX21hcC5fbGF0TG5nVG9OZXdMYXllclBvaW50KHRoaXMuX2xhdGxuZywgZS56b29tLCBlLmNlbnRlciksXHJcblx0XHQgICAgYW5jaG9yID0gdGhpcy5fZ2V0QW5jaG9yKCk7XHJcblx0XHRzZXRQb3NpdGlvbih0aGlzLl9jb250YWluZXIsIHBvcy5hZGQoYW5jaG9yKSk7XHJcblx0fSxcclxuXHJcblx0X2FkanVzdFBhbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKCF0aGlzLm9wdGlvbnMuYXV0b1BhbikgeyByZXR1cm47IH1cclxuXHRcdGlmICh0aGlzLl9tYXAuX3BhbkFuaW0pIHsgdGhpcy5fbWFwLl9wYW5BbmltLnN0b3AoKTsgfVxyXG5cclxuXHRcdHZhciBtYXAgPSB0aGlzLl9tYXAsXHJcblx0XHQgICAgbWFyZ2luQm90dG9tID0gcGFyc2VJbnQoZ2V0U3R5bGUodGhpcy5fY29udGFpbmVyLCAnbWFyZ2luQm90dG9tJyksIDEwKSB8fCAwLFxyXG5cdFx0ICAgIGNvbnRhaW5lckhlaWdodCA9IHRoaXMuX2NvbnRhaW5lci5vZmZzZXRIZWlnaHQgKyBtYXJnaW5Cb3R0b20sXHJcblx0XHQgICAgY29udGFpbmVyV2lkdGggPSB0aGlzLl9jb250YWluZXJXaWR0aCxcclxuXHRcdCAgICBsYXllclBvcyA9IG5ldyBQb2ludCh0aGlzLl9jb250YWluZXJMZWZ0LCAtY29udGFpbmVySGVpZ2h0IC0gdGhpcy5fY29udGFpbmVyQm90dG9tKTtcclxuXHJcblx0XHRsYXllclBvcy5fYWRkKGdldFBvc2l0aW9uKHRoaXMuX2NvbnRhaW5lcikpO1xyXG5cclxuXHRcdHZhciBjb250YWluZXJQb3MgPSBtYXAubGF5ZXJQb2ludFRvQ29udGFpbmVyUG9pbnQobGF5ZXJQb3MpLFxyXG5cdFx0ICAgIHBhZGRpbmcgPSB0b1BvaW50KHRoaXMub3B0aW9ucy5hdXRvUGFuUGFkZGluZyksXHJcblx0XHQgICAgcGFkZGluZ1RMID0gdG9Qb2ludCh0aGlzLm9wdGlvbnMuYXV0b1BhblBhZGRpbmdUb3BMZWZ0IHx8IHBhZGRpbmcpLFxyXG5cdFx0ICAgIHBhZGRpbmdCUiA9IHRvUG9pbnQodGhpcy5vcHRpb25zLmF1dG9QYW5QYWRkaW5nQm90dG9tUmlnaHQgfHwgcGFkZGluZyksXHJcblx0XHQgICAgc2l6ZSA9IG1hcC5nZXRTaXplKCksXHJcblx0XHQgICAgZHggPSAwLFxyXG5cdFx0ICAgIGR5ID0gMDtcclxuXHJcblx0XHRpZiAoY29udGFpbmVyUG9zLnggKyBjb250YWluZXJXaWR0aCArIHBhZGRpbmdCUi54ID4gc2l6ZS54KSB7IC8vIHJpZ2h0XHJcblx0XHRcdGR4ID0gY29udGFpbmVyUG9zLnggKyBjb250YWluZXJXaWR0aCAtIHNpemUueCArIHBhZGRpbmdCUi54O1xyXG5cdFx0fVxyXG5cdFx0aWYgKGNvbnRhaW5lclBvcy54IC0gZHggLSBwYWRkaW5nVEwueCA8IDApIHsgLy8gbGVmdFxyXG5cdFx0XHRkeCA9IGNvbnRhaW5lclBvcy54IC0gcGFkZGluZ1RMLng7XHJcblx0XHR9XHJcblx0XHRpZiAoY29udGFpbmVyUG9zLnkgKyBjb250YWluZXJIZWlnaHQgKyBwYWRkaW5nQlIueSA+IHNpemUueSkgeyAvLyBib3R0b21cclxuXHRcdFx0ZHkgPSBjb250YWluZXJQb3MueSArIGNvbnRhaW5lckhlaWdodCAtIHNpemUueSArIHBhZGRpbmdCUi55O1xyXG5cdFx0fVxyXG5cdFx0aWYgKGNvbnRhaW5lclBvcy55IC0gZHkgLSBwYWRkaW5nVEwueSA8IDApIHsgLy8gdG9wXHJcblx0XHRcdGR5ID0gY29udGFpbmVyUG9zLnkgLSBwYWRkaW5nVEwueTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBAbmFtZXNwYWNlIE1hcFxyXG5cdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcblx0XHQvLyBAZXZlbnQgYXV0b3BhbnN0YXJ0OiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIHN0YXJ0cyBhdXRvcGFubmluZyB3aGVuIG9wZW5pbmcgYSBwb3B1cC5cclxuXHRcdGlmIChkeCB8fCBkeSkge1xyXG5cdFx0XHRtYXBcclxuXHRcdFx0ICAgIC5maXJlKCdhdXRvcGFuc3RhcnQnKVxyXG5cdFx0XHQgICAgLnBhbkJ5KFtkeCwgZHldKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfb25DbG9zZUJ1dHRvbkNsaWNrOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0dGhpcy5fY2xvc2UoKTtcclxuXHRcdHN0b3AoZSk7XHJcblx0fSxcclxuXHJcblx0X2dldEFuY2hvcjogZnVuY3Rpb24gKCkge1xyXG5cdFx0Ly8gV2hlcmUgc2hvdWxkIHdlIGFuY2hvciB0aGUgcG9wdXAgb24gdGhlIHNvdXJjZSBsYXllcj9cclxuXHRcdHJldHVybiB0b1BvaW50KHRoaXMuX3NvdXJjZSAmJiB0aGlzLl9zb3VyY2UuX2dldFBvcHVwQW5jaG9yID8gdGhpcy5fc291cmNlLl9nZXRQb3B1cEFuY2hvcigpIDogWzAsIDBdKTtcclxuXHR9XHJcblxyXG59KTtcclxuXHJcbi8vIEBuYW1lc3BhY2UgUG9wdXBcclxuLy8gQGZhY3RvcnkgTC5wb3B1cChvcHRpb25zPzogUG9wdXAgb3B0aW9ucywgc291cmNlPzogTGF5ZXIpXHJcbi8vIEluc3RhbnRpYXRlcyBhIGBQb3B1cGAgb2JqZWN0IGdpdmVuIGFuIG9wdGlvbmFsIGBvcHRpb25zYCBvYmplY3QgdGhhdCBkZXNjcmliZXMgaXRzIGFwcGVhcmFuY2UgYW5kIGxvY2F0aW9uIGFuZCBhbiBvcHRpb25hbCBgc291cmNlYCBvYmplY3QgdGhhdCBpcyB1c2VkIHRvIHRhZyB0aGUgcG9wdXAgd2l0aCBhIHJlZmVyZW5jZSB0byB0aGUgTGF5ZXIgdG8gd2hpY2ggaXQgcmVmZXJzLlxyXG52YXIgcG9wdXAgPSBmdW5jdGlvbiAob3B0aW9ucywgc291cmNlKSB7XHJcblx0cmV0dXJuIG5ldyBQb3B1cChvcHRpb25zLCBzb3VyY2UpO1xyXG59O1xyXG5cclxuXHJcbi8qIEBuYW1lc3BhY2UgTWFwXHJcbiAqIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcclxuICogQG9wdGlvbiBjbG9zZVBvcHVwT25DbGljazogQm9vbGVhbiA9IHRydWVcclxuICogU2V0IGl0IHRvIGBmYWxzZWAgaWYgeW91IGRvbid0IHdhbnQgcG9wdXBzIHRvIGNsb3NlIHdoZW4gdXNlciBjbGlja3MgdGhlIG1hcC5cclxuICovXHJcbk1hcC5tZXJnZU9wdGlvbnMoe1xyXG5cdGNsb3NlUG9wdXBPbkNsaWNrOiB0cnVlXHJcbn0pO1xyXG5cclxuXHJcbi8vIEBuYW1lc3BhY2UgTWFwXHJcbi8vIEBzZWN0aW9uIE1ldGhvZHMgZm9yIExheWVycyBhbmQgQ29udHJvbHNcclxuTWFwLmluY2x1ZGUoe1xyXG5cdC8vIEBtZXRob2Qgb3BlblBvcHVwKHBvcHVwOiBQb3B1cCk6IHRoaXNcclxuXHQvLyBPcGVucyB0aGUgc3BlY2lmaWVkIHBvcHVwIHdoaWxlIGNsb3NpbmcgdGhlIHByZXZpb3VzbHkgb3BlbmVkICh0byBtYWtlIHN1cmUgb25seSBvbmUgaXMgb3BlbmVkIGF0IG9uZSB0aW1lIGZvciB1c2FiaWxpdHkpLlxyXG5cdC8vIEBhbHRlcm5hdGl2ZVxyXG5cdC8vIEBtZXRob2Qgb3BlblBvcHVwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudCwgbGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBQb3B1cCBvcHRpb25zKTogdGhpc1xyXG5cdC8vIENyZWF0ZXMgYSBwb3B1cCB3aXRoIHRoZSBzcGVjaWZpZWQgY29udGVudCBhbmQgb3B0aW9ucyBhbmQgb3BlbnMgaXQgaW4gdGhlIGdpdmVuIHBvaW50IG9uIGEgbWFwLlxyXG5cdG9wZW5Qb3B1cDogZnVuY3Rpb24gKHBvcHVwLCBsYXRsbmcsIG9wdGlvbnMpIHtcclxuXHRcdGlmICghKHBvcHVwIGluc3RhbmNlb2YgUG9wdXApKSB7XHJcblx0XHRcdHBvcHVwID0gbmV3IFBvcHVwKG9wdGlvbnMpLnNldENvbnRlbnQocG9wdXApO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChsYXRsbmcpIHtcclxuXHRcdFx0cG9wdXAuc2V0TGF0TG5nKGxhdGxuZyk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKHRoaXMuaGFzTGF5ZXIocG9wdXApKSB7XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLl9wb3B1cCAmJiB0aGlzLl9wb3B1cC5vcHRpb25zLmF1dG9DbG9zZSkge1xyXG5cdFx0XHR0aGlzLmNsb3NlUG9wdXAoKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9wb3B1cCA9IHBvcHVwO1xyXG5cdFx0cmV0dXJuIHRoaXMuYWRkTGF5ZXIocG9wdXApO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY2xvc2VQb3B1cChwb3B1cD86IFBvcHVwKTogdGhpc1xyXG5cdC8vIENsb3NlcyB0aGUgcG9wdXAgcHJldmlvdXNseSBvcGVuZWQgd2l0aCBbb3BlblBvcHVwXSgjbWFwLW9wZW5wb3B1cCkgKG9yIHRoZSBnaXZlbiBvbmUpLlxyXG5cdGNsb3NlUG9wdXA6IGZ1bmN0aW9uIChwb3B1cCkge1xyXG5cdFx0aWYgKCFwb3B1cCB8fCBwb3B1cCA9PT0gdGhpcy5fcG9wdXApIHtcclxuXHRcdFx0cG9wdXAgPSB0aGlzLl9wb3B1cDtcclxuXHRcdFx0dGhpcy5fcG9wdXAgPSBudWxsO1xyXG5cdFx0fVxyXG5cdFx0aWYgKHBvcHVwKSB7XHJcblx0XHRcdHRoaXMucmVtb3ZlTGF5ZXIocG9wdXApO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fVxyXG59KTtcclxuXHJcbi8qXHJcbiAqIEBuYW1lc3BhY2UgTGF5ZXJcclxuICogQHNlY3Rpb24gUG9wdXAgbWV0aG9kcyBleGFtcGxlXHJcbiAqXHJcbiAqIEFsbCBsYXllcnMgc2hhcmUgYSBzZXQgb2YgbWV0aG9kcyBjb252ZW5pZW50IGZvciBiaW5kaW5nIHBvcHVwcyB0byBpdC5cclxuICpcclxuICogYGBganNcclxuICogdmFyIGxheWVyID0gTC5Qb2x5Z29uKGxhdGxuZ3MpLmJpbmRQb3B1cCgnSGkgVGhlcmUhJykuYWRkVG8obWFwKTtcclxuICogbGF5ZXIub3BlblBvcHVwKCk7XHJcbiAqIGxheWVyLmNsb3NlUG9wdXAoKTtcclxuICogYGBgXHJcbiAqXHJcbiAqIFBvcHVwcyB3aWxsIGFsc28gYmUgYXV0b21hdGljYWxseSBvcGVuZWQgd2hlbiB0aGUgbGF5ZXIgaXMgY2xpY2tlZCBvbiBhbmQgY2xvc2VkIHdoZW4gdGhlIGxheWVyIGlzIHJlbW92ZWQgZnJvbSB0aGUgbWFwIG9yIGFub3RoZXIgcG9wdXAgaXMgb3BlbmVkLlxyXG4gKi9cclxuXHJcbi8vIEBzZWN0aW9uIFBvcHVwIG1ldGhvZHNcclxuTGF5ZXIuaW5jbHVkZSh7XHJcblxyXG5cdC8vIEBtZXRob2QgYmluZFBvcHVwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudHxGdW5jdGlvbnxQb3B1cCwgb3B0aW9ucz86IFBvcHVwIG9wdGlvbnMpOiB0aGlzXHJcblx0Ly8gQmluZHMgYSBwb3B1cCB0byB0aGUgbGF5ZXIgd2l0aCB0aGUgcGFzc2VkIGBjb250ZW50YCBhbmQgc2V0cyB1cCB0aGVcclxuXHQvLyBuZWNlc3NhcnkgZXZlbnQgbGlzdGVuZXJzLiBJZiBhIGBGdW5jdGlvbmAgaXMgcGFzc2VkIGl0IHdpbGwgcmVjZWl2ZVxyXG5cdC8vIHRoZSBsYXllciBhcyB0aGUgZmlyc3QgYXJndW1lbnQgYW5kIHNob3VsZCByZXR1cm4gYSBgU3RyaW5nYCBvciBgSFRNTEVsZW1lbnRgLlxyXG5cdGJpbmRQb3B1cDogZnVuY3Rpb24gKGNvbnRlbnQsIG9wdGlvbnMpIHtcclxuXHJcblx0XHRpZiAoY29udGVudCBpbnN0YW5jZW9mIFBvcHVwKSB7XHJcblx0XHRcdHNldE9wdGlvbnMoY29udGVudCwgb3B0aW9ucyk7XHJcblx0XHRcdHRoaXMuX3BvcHVwID0gY29udGVudDtcclxuXHRcdFx0Y29udGVudC5fc291cmNlID0gdGhpcztcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGlmICghdGhpcy5fcG9wdXAgfHwgb3B0aW9ucykge1xyXG5cdFx0XHRcdHRoaXMuX3BvcHVwID0gbmV3IFBvcHVwKG9wdGlvbnMsIHRoaXMpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXMuX3BvcHVwLnNldENvbnRlbnQoY29udGVudCk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCF0aGlzLl9wb3B1cEhhbmRsZXJzQWRkZWQpIHtcclxuXHRcdFx0dGhpcy5vbih7XHJcblx0XHRcdFx0Y2xpY2s6IHRoaXMuX29wZW5Qb3B1cCxcclxuXHRcdFx0XHRrZXlwcmVzczogdGhpcy5fb25LZXlQcmVzcyxcclxuXHRcdFx0XHRyZW1vdmU6IHRoaXMuY2xvc2VQb3B1cCxcclxuXHRcdFx0XHRtb3ZlOiB0aGlzLl9tb3ZlUG9wdXBcclxuXHRcdFx0fSk7XHJcblx0XHRcdHRoaXMuX3BvcHVwSGFuZGxlcnNBZGRlZCA9IHRydWU7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB1bmJpbmRQb3B1cCgpOiB0aGlzXHJcblx0Ly8gUmVtb3ZlcyB0aGUgcG9wdXAgcHJldmlvdXNseSBib3VuZCB3aXRoIGBiaW5kUG9wdXBgLlxyXG5cdHVuYmluZFBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAodGhpcy5fcG9wdXApIHtcclxuXHRcdFx0dGhpcy5vZmYoe1xyXG5cdFx0XHRcdGNsaWNrOiB0aGlzLl9vcGVuUG9wdXAsXHJcblx0XHRcdFx0a2V5cHJlc3M6IHRoaXMuX29uS2V5UHJlc3MsXHJcblx0XHRcdFx0cmVtb3ZlOiB0aGlzLmNsb3NlUG9wdXAsXHJcblx0XHRcdFx0bW92ZTogdGhpcy5fbW92ZVBvcHVwXHJcblx0XHRcdH0pO1xyXG5cdFx0XHR0aGlzLl9wb3B1cEhhbmRsZXJzQWRkZWQgPSBmYWxzZTtcclxuXHRcdFx0dGhpcy5fcG9wdXAgPSBudWxsO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBvcGVuUG9wdXAobGF0bG5nPzogTGF0TG5nKTogdGhpc1xyXG5cdC8vIE9wZW5zIHRoZSBib3VuZCBwb3B1cCBhdCB0aGUgc3BlY2lmaWVkIGBsYXRsbmdgIG9yIGF0IHRoZSBkZWZhdWx0IHBvcHVwIGFuY2hvciBpZiBubyBgbGF0bG5nYCBpcyBwYXNzZWQuXHJcblx0b3BlblBvcHVwOiBmdW5jdGlvbiAobGF5ZXIsIGxhdGxuZykge1xyXG5cdFx0aWYgKHRoaXMuX3BvcHVwICYmIHRoaXMuX21hcCkge1xyXG5cdFx0XHRsYXRsbmcgPSB0aGlzLl9wb3B1cC5fcHJlcGFyZU9wZW4odGhpcywgbGF5ZXIsIGxhdGxuZyk7XHJcblxyXG5cdFx0XHQvLyBvcGVuIHRoZSBwb3B1cCBvbiB0aGUgbWFwXHJcblx0XHRcdHRoaXMuX21hcC5vcGVuUG9wdXAodGhpcy5fcG9wdXAsIGxhdGxuZyk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBjbG9zZVBvcHVwKCk6IHRoaXNcclxuXHQvLyBDbG9zZXMgdGhlIHBvcHVwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgaWYgaXQgaXMgb3Blbi5cclxuXHRjbG9zZVBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAodGhpcy5fcG9wdXApIHtcclxuXHRcdFx0dGhpcy5fcG9wdXAuX2Nsb3NlKCk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHRvZ2dsZVBvcHVwKCk6IHRoaXNcclxuXHQvLyBPcGVucyBvciBjbG9zZXMgdGhlIHBvcHVwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgZGVwZW5kaW5nIG9uIGl0cyBjdXJyZW50IHN0YXRlLlxyXG5cdHRvZ2dsZVBvcHVwOiBmdW5jdGlvbiAodGFyZ2V0KSB7XHJcblx0XHRpZiAodGhpcy5fcG9wdXApIHtcclxuXHRcdFx0aWYgKHRoaXMuX3BvcHVwLl9tYXApIHtcclxuXHRcdFx0XHR0aGlzLmNsb3NlUG9wdXAoKTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHR0aGlzLm9wZW5Qb3B1cCh0YXJnZXQpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGlzUG9wdXBPcGVuKCk6IGJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcG9wdXAgYm91bmQgdG8gdGhpcyBsYXllciBpcyBjdXJyZW50bHkgb3Blbi5cclxuXHRpc1BvcHVwT3BlbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuICh0aGlzLl9wb3B1cCA/IHRoaXMuX3BvcHVwLmlzT3BlbigpIDogZmFsc2UpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0UG9wdXBDb250ZW50KGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudHxQb3B1cCk6IHRoaXNcclxuXHQvLyBTZXRzIHRoZSBjb250ZW50IG9mIHRoZSBwb3B1cCBib3VuZCB0byB0aGlzIGxheWVyLlxyXG5cdHNldFBvcHVwQ29udGVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcclxuXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG5cdFx0XHR0aGlzLl9wb3B1cC5zZXRDb250ZW50KGNvbnRlbnQpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRQb3B1cCgpOiBQb3B1cFxyXG5cdC8vIFJldHVybnMgdGhlIHBvcHVwIGJvdW5kIHRvIHRoaXMgbGF5ZXIuXHJcblx0Z2V0UG9wdXA6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9wb3B1cDtcclxuXHR9LFxyXG5cclxuXHRfb3BlblBvcHVwOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0dmFyIGxheWVyID0gZS5sYXllciB8fCBlLnRhcmdldDtcclxuXHJcblx0XHRpZiAoIXRoaXMuX3BvcHVwKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIXRoaXMuX21hcCkge1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gcHJldmVudCBtYXAgY2xpY2tcclxuXHRcdHN0b3AoZSk7XHJcblxyXG5cdFx0Ly8gaWYgdGhpcyBpbmhlcml0cyBmcm9tIFBhdGggaXRzIGEgdmVjdG9yIGFuZCB3ZSBjYW4ganVzdFxyXG5cdFx0Ly8gb3BlbiB0aGUgcG9wdXAgYXQgdGhlIG5ldyBsb2NhdGlvblxyXG5cdFx0aWYgKGxheWVyIGluc3RhbmNlb2YgUGF0aCkge1xyXG5cdFx0XHR0aGlzLm9wZW5Qb3B1cChlLmxheWVyIHx8IGUudGFyZ2V0LCBlLmxhdGxuZyk7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBvdGhlcndpc2UgdHJlYXQgaXQgbGlrZSBhIG1hcmtlciBhbmQgZmlndXJlIG91dFxyXG5cdFx0Ly8gaWYgd2Ugc2hvdWxkIHRvZ2dsZSBpdCBvcGVuL2Nsb3NlZFxyXG5cdFx0aWYgKHRoaXMuX21hcC5oYXNMYXllcih0aGlzLl9wb3B1cCkgJiYgdGhpcy5fcG9wdXAuX3NvdXJjZSA9PT0gbGF5ZXIpIHtcclxuXHRcdFx0dGhpcy5jbG9zZVBvcHVwKCk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHR0aGlzLm9wZW5Qb3B1cChsYXllciwgZS5sYXRsbmcpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9tb3ZlUG9wdXA6IGZ1bmN0aW9uIChlKSB7XHJcblx0XHR0aGlzLl9wb3B1cC5zZXRMYXRMbmcoZS5sYXRsbmcpO1xyXG5cdH0sXHJcblxyXG5cdF9vbktleVByZXNzOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0aWYgKGUub3JpZ2luYWxFdmVudC5rZXlDb2RlID09PSAxMykge1xyXG5cdFx0XHR0aGlzLl9vcGVuUG9wdXAoZSk7XHJcblx0XHR9XHJcblx0fVxyXG59KTtcblxuLypcbiAqIEBjbGFzcyBUb29sdGlwXG4gKiBAaW5oZXJpdHMgRGl2T3ZlcmxheVxuICogQGFrYSBMLlRvb2x0aXBcbiAqIFVzZWQgdG8gZGlzcGxheSBzbWFsbCB0ZXh0cyBvbiB0b3Agb2YgbWFwIGxheWVycy5cbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIGBgYGpzXG4gKiBtYXJrZXIuYmluZFRvb2x0aXAoXCJteSB0b29sdGlwIHRleHRcIikub3BlblRvb2x0aXAoKTtcbiAqIGBgYFxuICogTm90ZSBhYm91dCB0b29sdGlwIG9mZnNldC4gTGVhZmxldCB0YWtlcyB0d28gb3B0aW9ucyBpbiBjb25zaWRlcmF0aW9uXG4gKiBmb3IgY29tcHV0aW5nIHRvb2x0aXAgb2Zmc2V0dGluZzpcbiAqIC0gdGhlIGBvZmZzZXRgIFRvb2x0aXAgb3B0aW9uOiBpdCBkZWZhdWx0cyB0byBbMCwgMF0sIGFuZCBpdCdzIHNwZWNpZmljIHRvIG9uZSB0b29sdGlwLlxuICogICBBZGQgYSBwb3NpdGl2ZSB4IG9mZnNldCB0byBtb3ZlIHRoZSB0b29sdGlwIHRvIHRoZSByaWdodCwgYW5kIGEgcG9zaXRpdmUgeSBvZmZzZXQgdG9cbiAqICAgbW92ZSBpdCB0byB0aGUgYm90dG9tLiBOZWdhdGl2ZXMgd2lsbCBtb3ZlIHRvIHRoZSBsZWZ0IGFuZCB0b3AuXG4gKiAtIHRoZSBgdG9vbHRpcEFuY2hvcmAgSWNvbiBvcHRpb246IHRoaXMgd2lsbCBvbmx5IGJlIGNvbnNpZGVyZWQgZm9yIE1hcmtlci4gWW91XG4gKiAgIHNob3VsZCBhZGFwdCB0aGlzIHZhbHVlIGlmIHlvdSB1c2UgYSBjdXN0b20gaWNvbi5cbiAqL1xuXG5cbi8vIEBuYW1lc3BhY2UgVG9vbHRpcFxudmFyIFRvb2x0aXAgPSBEaXZPdmVybGF5LmV4dGVuZCh7XG5cblx0Ly8gQHNlY3Rpb25cblx0Ly8gQGFrYSBUb29sdGlwIG9wdGlvbnNcblx0b3B0aW9uczoge1xuXHRcdC8vIEBvcHRpb24gcGFuZTogU3RyaW5nID0gJ3Rvb2x0aXBQYW5lJ1xuXHRcdC8vIGBNYXAgcGFuZWAgd2hlcmUgdGhlIHRvb2x0aXAgd2lsbCBiZSBhZGRlZC5cblx0XHRwYW5lOiAndG9vbHRpcFBhbmUnLFxuXG5cdFx0Ly8gQG9wdGlvbiBvZmZzZXQ6IFBvaW50ID0gUG9pbnQoMCwgMClcblx0XHQvLyBPcHRpb25hbCBvZmZzZXQgb2YgdGhlIHRvb2x0aXAgcG9zaXRpb24uXG5cdFx0b2Zmc2V0OiBbMCwgMF0sXG5cblx0XHQvLyBAb3B0aW9uIGRpcmVjdGlvbjogU3RyaW5nID0gJ2F1dG8nXG5cdFx0Ly8gRGlyZWN0aW9uIHdoZXJlIHRvIG9wZW4gdGhlIHRvb2x0aXAuIFBvc3NpYmxlIHZhbHVlcyBhcmU6IGByaWdodGAsIGBsZWZ0YCxcblx0XHQvLyBgdG9wYCwgYGJvdHRvbWAsIGBjZW50ZXJgLCBgYXV0b2AuXG5cdFx0Ly8gYGF1dG9gIHdpbGwgZHluYW1pY2FsbHkgc3dpdGNoIGJldHdlZW4gYHJpZ2h0YCBhbmQgYGxlZnRgIGFjY29yZGluZyB0byB0aGUgdG9vbHRpcFxuXHRcdC8vIHBvc2l0aW9uIG9uIHRoZSBtYXAuXG5cdFx0ZGlyZWN0aW9uOiAnYXV0bycsXG5cblx0XHQvLyBAb3B0aW9uIHBlcm1hbmVudDogQm9vbGVhbiA9IGZhbHNlXG5cdFx0Ly8gV2hldGhlciB0byBvcGVuIHRoZSB0b29sdGlwIHBlcm1hbmVudGx5IG9yIG9ubHkgb24gbW91c2VvdmVyLlxuXHRcdHBlcm1hbmVudDogZmFsc2UsXG5cblx0XHQvLyBAb3B0aW9uIHN0aWNreTogQm9vbGVhbiA9IGZhbHNlXG5cdFx0Ly8gSWYgdHJ1ZSwgdGhlIHRvb2x0aXAgd2lsbCBmb2xsb3cgdGhlIG1vdXNlIGluc3RlYWQgb2YgYmVpbmcgZml4ZWQgYXQgdGhlIGZlYXR1cmUgY2VudGVyLlxuXHRcdHN0aWNreTogZmFsc2UsXG5cblx0XHQvLyBAb3B0aW9uIGludGVyYWN0aXZlOiBCb29sZWFuID0gZmFsc2Vcblx0XHQvLyBJZiB0cnVlLCB0aGUgdG9vbHRpcCB3aWxsIGxpc3RlbiB0byB0aGUgZmVhdHVyZSBldmVudHMuXG5cdFx0aW50ZXJhY3RpdmU6IGZhbHNlLFxuXG5cdFx0Ly8gQG9wdGlvbiBvcGFjaXR5OiBOdW1iZXIgPSAwLjlcblx0XHQvLyBUb29sdGlwIGNvbnRhaW5lciBvcGFjaXR5LlxuXHRcdG9wYWNpdHk6IDAuOVxuXHR9LFxuXG5cdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XG5cdFx0RGl2T3ZlcmxheS5wcm90b3R5cGUub25BZGQuY2FsbCh0aGlzLCBtYXApO1xuXHRcdHRoaXMuc2V0T3BhY2l0eSh0aGlzLm9wdGlvbnMub3BhY2l0eSk7XG5cblx0XHQvLyBAbmFtZXNwYWNlIE1hcFxuXHRcdC8vIEBzZWN0aW9uIFRvb2x0aXAgZXZlbnRzXG5cdFx0Ly8gQGV2ZW50IHRvb2x0aXBvcGVuOiBUb29sdGlwRXZlbnRcblx0XHQvLyBGaXJlZCB3aGVuIGEgdG9vbHRpcCBpcyBvcGVuZWQgaW4gdGhlIG1hcC5cblx0XHRtYXAuZmlyZSgndG9vbHRpcG9wZW4nLCB7dG9vbHRpcDogdGhpc30pO1xuXG5cdFx0aWYgKHRoaXMuX3NvdXJjZSkge1xuXHRcdFx0Ly8gQG5hbWVzcGFjZSBMYXllclxuXHRcdFx0Ly8gQHNlY3Rpb24gVG9vbHRpcCBldmVudHNcblx0XHRcdC8vIEBldmVudCB0b29sdGlwb3BlbjogVG9vbHRpcEV2ZW50XG5cdFx0XHQvLyBGaXJlZCB3aGVuIGEgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGlzIG9wZW5lZC5cblx0XHRcdHRoaXMuX3NvdXJjZS5maXJlKCd0b29sdGlwb3BlbicsIHt0b29sdGlwOiB0aGlzfSwgdHJ1ZSk7XG5cdFx0fVxuXHR9LFxuXG5cdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XG5cdFx0RGl2T3ZlcmxheS5wcm90b3R5cGUub25SZW1vdmUuY2FsbCh0aGlzLCBtYXApO1xuXG5cdFx0Ly8gQG5hbWVzcGFjZSBNYXBcblx0XHQvLyBAc2VjdGlvbiBUb29sdGlwIGV2ZW50c1xuXHRcdC8vIEBldmVudCB0b29sdGlwY2xvc2U6IFRvb2x0aXBFdmVudFxuXHRcdC8vIEZpcmVkIHdoZW4gYSB0b29sdGlwIGluIHRoZSBtYXAgaXMgY2xvc2VkLlxuXHRcdG1hcC5maXJlKCd0b29sdGlwY2xvc2UnLCB7dG9vbHRpcDogdGhpc30pO1xuXG5cdFx0aWYgKHRoaXMuX3NvdXJjZSkge1xuXHRcdFx0Ly8gQG5hbWVzcGFjZSBMYXllclxuXHRcdFx0Ly8gQHNlY3Rpb24gVG9vbHRpcCBldmVudHNcblx0XHRcdC8vIEBldmVudCB0b29sdGlwY2xvc2U6IFRvb2x0aXBFdmVudFxuXHRcdFx0Ly8gRmlyZWQgd2hlbiBhIHRvb2x0aXAgYm91bmQgdG8gdGhpcyBsYXllciBpcyBjbG9zZWQuXG5cdFx0XHR0aGlzLl9zb3VyY2UuZmlyZSgndG9vbHRpcGNsb3NlJywge3Rvb2x0aXA6IHRoaXN9LCB0cnVlKTtcblx0XHR9XG5cdH0sXG5cblx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGV2ZW50cyA9IERpdk92ZXJsYXkucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xuXG5cdFx0aWYgKHRvdWNoICYmICF0aGlzLm9wdGlvbnMucGVybWFuZW50KSB7XG5cdFx0XHRldmVudHMucHJlY2xpY2sgPSB0aGlzLl9jbG9zZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZXZlbnRzO1xuXHR9LFxuXG5cdF9jbG9zZTogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9tYXApIHtcblx0XHRcdHRoaXMuX21hcC5jbG9zZVRvb2x0aXAodGhpcyk7XG5cdFx0fVxuXHR9LFxuXG5cdF9pbml0TGF5b3V0OiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHByZWZpeCA9ICdsZWFmbGV0LXRvb2x0aXAnLFxuXHRcdCAgICBjbGFzc05hbWUgPSBwcmVmaXggKyAnICcgKyAodGhpcy5vcHRpb25zLmNsYXNzTmFtZSB8fCAnJykgKyAnIGxlYWZsZXQtem9vbS0nICsgKHRoaXMuX3pvb21BbmltYXRlZCA/ICdhbmltYXRlZCcgOiAnaGlkZScpO1xuXG5cdFx0dGhpcy5fY29udGVudE5vZGUgPSB0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lKTtcblx0fSxcblxuXHRfdXBkYXRlTGF5b3V0OiBmdW5jdGlvbiAoKSB7fSxcblxuXHRfYWRqdXN0UGFuOiBmdW5jdGlvbiAoKSB7fSxcblxuXHRfc2V0UG9zaXRpb246IGZ1bmN0aW9uIChwb3MpIHtcblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuXHRcdCAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIsXG5cdFx0ICAgIGNlbnRlclBvaW50ID0gbWFwLmxhdExuZ1RvQ29udGFpbmVyUG9pbnQobWFwLmdldENlbnRlcigpKSxcblx0XHQgICAgdG9vbHRpcFBvaW50ID0gbWFwLmxheWVyUG9pbnRUb0NvbnRhaW5lclBvaW50KHBvcyksXG5cdFx0ICAgIGRpcmVjdGlvbiA9IHRoaXMub3B0aW9ucy5kaXJlY3Rpb24sXG5cdFx0ICAgIHRvb2x0aXBXaWR0aCA9IGNvbnRhaW5lci5vZmZzZXRXaWR0aCxcblx0XHQgICAgdG9vbHRpcEhlaWdodCA9IGNvbnRhaW5lci5vZmZzZXRIZWlnaHQsXG5cdFx0ICAgIG9mZnNldCA9IHRvUG9pbnQodGhpcy5vcHRpb25zLm9mZnNldCksXG5cdFx0ICAgIGFuY2hvciA9IHRoaXMuX2dldEFuY2hvcigpO1xuXG5cdFx0aWYgKGRpcmVjdGlvbiA9PT0gJ3RvcCcpIHtcblx0XHRcdHBvcyA9IHBvcy5hZGQodG9Qb2ludCgtdG9vbHRpcFdpZHRoIC8gMiArIG9mZnNldC54LCAtdG9vbHRpcEhlaWdodCArIG9mZnNldC55ICsgYW5jaG9yLnksIHRydWUpKTtcblx0XHR9IGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gJ2JvdHRvbScpIHtcblx0XHRcdHBvcyA9IHBvcy5zdWJ0cmFjdCh0b1BvaW50KHRvb2x0aXBXaWR0aCAvIDIgLSBvZmZzZXQueCwgLW9mZnNldC55LCB0cnVlKSk7XG5cdFx0fSBlbHNlIGlmIChkaXJlY3Rpb24gPT09ICdjZW50ZXInKSB7XG5cdFx0XHRwb3MgPSBwb3Muc3VidHJhY3QodG9Qb2ludCh0b29sdGlwV2lkdGggLyAyICsgb2Zmc2V0LngsIHRvb2x0aXBIZWlnaHQgLyAyIC0gYW5jaG9yLnkgKyBvZmZzZXQueSwgdHJ1ZSkpO1xuXHRcdH0gZWxzZSBpZiAoZGlyZWN0aW9uID09PSAncmlnaHQnIHx8IGRpcmVjdGlvbiA9PT0gJ2F1dG8nICYmIHRvb2x0aXBQb2ludC54IDwgY2VudGVyUG9pbnQueCkge1xuXHRcdFx0ZGlyZWN0aW9uID0gJ3JpZ2h0Jztcblx0XHRcdHBvcyA9IHBvcy5hZGQodG9Qb2ludChvZmZzZXQueCArIGFuY2hvci54LCBhbmNob3IueSAtIHRvb2x0aXBIZWlnaHQgLyAyICsgb2Zmc2V0LnksIHRydWUpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZGlyZWN0aW9uID0gJ2xlZnQnO1xuXHRcdFx0cG9zID0gcG9zLnN1YnRyYWN0KHRvUG9pbnQodG9vbHRpcFdpZHRoICsgYW5jaG9yLnggLSBvZmZzZXQueCwgdG9vbHRpcEhlaWdodCAvIDIgLSBhbmNob3IueSAtIG9mZnNldC55LCB0cnVlKSk7XG5cdFx0fVxuXG5cdFx0cmVtb3ZlQ2xhc3MoY29udGFpbmVyLCAnbGVhZmxldC10b29sdGlwLXJpZ2h0Jyk7XG5cdFx0cmVtb3ZlQ2xhc3MoY29udGFpbmVyLCAnbGVhZmxldC10b29sdGlwLWxlZnQnKTtcblx0XHRyZW1vdmVDbGFzcyhjb250YWluZXIsICdsZWFmbGV0LXRvb2x0aXAtdG9wJyk7XG5cdFx0cmVtb3ZlQ2xhc3MoY29udGFpbmVyLCAnbGVhZmxldC10b29sdGlwLWJvdHRvbScpO1xuXHRcdGFkZENsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdG9vbHRpcC0nICsgZGlyZWN0aW9uKTtcblx0XHRzZXRQb3NpdGlvbihjb250YWluZXIsIHBvcyk7XG5cdH0sXG5cblx0X3VwZGF0ZVBvc2l0aW9uOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHBvcyA9IHRoaXMuX21hcC5sYXRMbmdUb0xheWVyUG9pbnQodGhpcy5fbGF0bG5nKTtcblx0XHR0aGlzLl9zZXRQb3NpdGlvbihwb3MpO1xuXHR9LFxuXG5cdHNldE9wYWNpdHk6IGZ1bmN0aW9uIChvcGFjaXR5KSB7XG5cdFx0dGhpcy5vcHRpb25zLm9wYWNpdHkgPSBvcGFjaXR5O1xuXG5cdFx0aWYgKHRoaXMuX2NvbnRhaW5lcikge1xuXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9jb250YWluZXIsIG9wYWNpdHkpO1xuXHRcdH1cblx0fSxcblxuXHRfYW5pbWF0ZVpvb206IGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIHBvcyA9IHRoaXMuX21hcC5fbGF0TG5nVG9OZXdMYXllclBvaW50KHRoaXMuX2xhdGxuZywgZS56b29tLCBlLmNlbnRlcik7XG5cdFx0dGhpcy5fc2V0UG9zaXRpb24ocG9zKTtcblx0fSxcblxuXHRfZ2V0QW5jaG9yOiBmdW5jdGlvbiAoKSB7XG5cdFx0Ly8gV2hlcmUgc2hvdWxkIHdlIGFuY2hvciB0aGUgdG9vbHRpcCBvbiB0aGUgc291cmNlIGxheWVyP1xuXHRcdHJldHVybiB0b1BvaW50KHRoaXMuX3NvdXJjZSAmJiB0aGlzLl9zb3VyY2UuX2dldFRvb2x0aXBBbmNob3IgJiYgIXRoaXMub3B0aW9ucy5zdGlja3kgPyB0aGlzLl9zb3VyY2UuX2dldFRvb2x0aXBBbmNob3IoKSA6IFswLCAwXSk7XG5cdH1cblxufSk7XG5cbi8vIEBuYW1lc3BhY2UgVG9vbHRpcFxuLy8gQGZhY3RvcnkgTC50b29sdGlwKG9wdGlvbnM/OiBUb29sdGlwIG9wdGlvbnMsIHNvdXJjZT86IExheWVyKVxuLy8gSW5zdGFudGlhdGVzIGEgVG9vbHRpcCBvYmplY3QgZ2l2ZW4gYW4gb3B0aW9uYWwgYG9wdGlvbnNgIG9iamVjdCB0aGF0IGRlc2NyaWJlcyBpdHMgYXBwZWFyYW5jZSBhbmQgbG9jYXRpb24gYW5kIGFuIG9wdGlvbmFsIGBzb3VyY2VgIG9iamVjdCB0aGF0IGlzIHVzZWQgdG8gdGFnIHRoZSB0b29sdGlwIHdpdGggYSByZWZlcmVuY2UgdG8gdGhlIExheWVyIHRvIHdoaWNoIGl0IHJlZmVycy5cbnZhciB0b29sdGlwID0gZnVuY3Rpb24gKG9wdGlvbnMsIHNvdXJjZSkge1xuXHRyZXR1cm4gbmV3IFRvb2x0aXAob3B0aW9ucywgc291cmNlKTtcbn07XG5cbi8vIEBuYW1lc3BhY2UgTWFwXG4vLyBAc2VjdGlvbiBNZXRob2RzIGZvciBMYXllcnMgYW5kIENvbnRyb2xzXG5NYXAuaW5jbHVkZSh7XG5cblx0Ly8gQG1ldGhvZCBvcGVuVG9vbHRpcCh0b29sdGlwOiBUb29sdGlwKTogdGhpc1xuXHQvLyBPcGVucyB0aGUgc3BlY2lmaWVkIHRvb2x0aXAuXG5cdC8vIEBhbHRlcm5hdGl2ZVxuXHQvLyBAbWV0aG9kIG9wZW5Ub29sdGlwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudCwgbGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBUb29sdGlwIG9wdGlvbnMpOiB0aGlzXG5cdC8vIENyZWF0ZXMgYSB0b29sdGlwIHdpdGggdGhlIHNwZWNpZmllZCBjb250ZW50IGFuZCBvcHRpb25zIGFuZCBvcGVuIGl0LlxuXHRvcGVuVG9vbHRpcDogZnVuY3Rpb24gKHRvb2x0aXAsIGxhdGxuZywgb3B0aW9ucykge1xuXHRcdGlmICghKHRvb2x0aXAgaW5zdGFuY2VvZiBUb29sdGlwKSkge1xuXHRcdFx0dG9vbHRpcCA9IG5ldyBUb29sdGlwKG9wdGlvbnMpLnNldENvbnRlbnQodG9vbHRpcCk7XG5cdFx0fVxuXG5cdFx0aWYgKGxhdGxuZykge1xuXHRcdFx0dG9vbHRpcC5zZXRMYXRMbmcobGF0bG5nKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5oYXNMYXllcih0b29sdGlwKSkge1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuYWRkTGF5ZXIodG9vbHRpcCk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBjbG9zZVRvb2x0aXAodG9vbHRpcD86IFRvb2x0aXApOiB0aGlzXG5cdC8vIENsb3NlcyB0aGUgdG9vbHRpcCBnaXZlbiBhcyBwYXJhbWV0ZXIuXG5cdGNsb3NlVG9vbHRpcDogZnVuY3Rpb24gKHRvb2x0aXApIHtcblx0XHRpZiAodG9vbHRpcCkge1xuXHRcdFx0dGhpcy5yZW1vdmVMYXllcih0b29sdGlwKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxufSk7XG5cbi8qXG4gKiBAbmFtZXNwYWNlIExheWVyXG4gKiBAc2VjdGlvbiBUb29sdGlwIG1ldGhvZHMgZXhhbXBsZVxuICpcbiAqIEFsbCBsYXllcnMgc2hhcmUgYSBzZXQgb2YgbWV0aG9kcyBjb252ZW5pZW50IGZvciBiaW5kaW5nIHRvb2x0aXBzIHRvIGl0LlxuICpcbiAqIGBgYGpzXG4gKiB2YXIgbGF5ZXIgPSBMLlBvbHlnb24obGF0bG5ncykuYmluZFRvb2x0aXAoJ0hpIFRoZXJlIScpLmFkZFRvKG1hcCk7XG4gKiBsYXllci5vcGVuVG9vbHRpcCgpO1xuICogbGF5ZXIuY2xvc2VUb29sdGlwKCk7XG4gKiBgYGBcbiAqL1xuXG4vLyBAc2VjdGlvbiBUb29sdGlwIG1ldGhvZHNcbkxheWVyLmluY2x1ZGUoe1xuXG5cdC8vIEBtZXRob2QgYmluZFRvb2x0aXAoY29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fEZ1bmN0aW9ufFRvb2x0aXAsIG9wdGlvbnM/OiBUb29sdGlwIG9wdGlvbnMpOiB0aGlzXG5cdC8vIEJpbmRzIGEgdG9vbHRpcCB0byB0aGUgbGF5ZXIgd2l0aCB0aGUgcGFzc2VkIGBjb250ZW50YCBhbmQgc2V0cyB1cCB0aGVcblx0Ly8gbmVjZXNzYXJ5IGV2ZW50IGxpc3RlbmVycy4gSWYgYSBgRnVuY3Rpb25gIGlzIHBhc3NlZCBpdCB3aWxsIHJlY2VpdmVcblx0Ly8gdGhlIGxheWVyIGFzIHRoZSBmaXJzdCBhcmd1bWVudCBhbmQgc2hvdWxkIHJldHVybiBhIGBTdHJpbmdgIG9yIGBIVE1MRWxlbWVudGAuXG5cdGJpbmRUb29sdGlwOiBmdW5jdGlvbiAoY29udGVudCwgb3B0aW9ucykge1xuXG5cdFx0aWYgKGNvbnRlbnQgaW5zdGFuY2VvZiBUb29sdGlwKSB7XG5cdFx0XHRzZXRPcHRpb25zKGNvbnRlbnQsIG9wdGlvbnMpO1xuXHRcdFx0dGhpcy5fdG9vbHRpcCA9IGNvbnRlbnQ7XG5cdFx0XHRjb250ZW50Ll9zb3VyY2UgPSB0aGlzO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIXRoaXMuX3Rvb2x0aXAgfHwgb3B0aW9ucykge1xuXHRcdFx0XHR0aGlzLl90b29sdGlwID0gbmV3IFRvb2x0aXAob3B0aW9ucywgdGhpcyk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLl90b29sdGlwLnNldENvbnRlbnQoY29udGVudCk7XG5cblx0XHR9XG5cblx0XHR0aGlzLl9pbml0VG9vbHRpcEludGVyYWN0aW9ucygpO1xuXG5cdFx0aWYgKHRoaXMuX3Rvb2x0aXAub3B0aW9ucy5wZXJtYW5lbnQgJiYgdGhpcy5fbWFwICYmIHRoaXMuX21hcC5oYXNMYXllcih0aGlzKSkge1xuXHRcdFx0dGhpcy5vcGVuVG9vbHRpcCgpO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgdW5iaW5kVG9vbHRpcCgpOiB0aGlzXG5cdC8vIFJlbW92ZXMgdGhlIHRvb2x0aXAgcHJldmlvdXNseSBib3VuZCB3aXRoIGBiaW5kVG9vbHRpcGAuXG5cdHVuYmluZFRvb2x0aXA6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAodGhpcy5fdG9vbHRpcCkge1xuXHRcdFx0dGhpcy5faW5pdFRvb2x0aXBJbnRlcmFjdGlvbnModHJ1ZSk7XG5cdFx0XHR0aGlzLmNsb3NlVG9vbHRpcCgpO1xuXHRcdFx0dGhpcy5fdG9vbHRpcCA9IG51bGw7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdF9pbml0VG9vbHRpcEludGVyYWN0aW9uczogZnVuY3Rpb24gKHJlbW92ZSQkMSkge1xuXHRcdGlmICghcmVtb3ZlJCQxICYmIHRoaXMuX3Rvb2x0aXBIYW5kbGVyc0FkZGVkKSB7IHJldHVybjsgfVxuXHRcdHZhciBvbk9mZiA9IHJlbW92ZSQkMSA/ICdvZmYnIDogJ29uJyxcblx0XHQgICAgZXZlbnRzID0ge1xuXHRcdFx0cmVtb3ZlOiB0aGlzLmNsb3NlVG9vbHRpcCxcblx0XHRcdG1vdmU6IHRoaXMuX21vdmVUb29sdGlwXG5cdFx0ICAgIH07XG5cdFx0aWYgKCF0aGlzLl90b29sdGlwLm9wdGlvbnMucGVybWFuZW50KSB7XG5cdFx0XHRldmVudHMubW91c2VvdmVyID0gdGhpcy5fb3BlblRvb2x0aXA7XG5cdFx0XHRldmVudHMubW91c2VvdXQgPSB0aGlzLmNsb3NlVG9vbHRpcDtcblx0XHRcdGlmICh0aGlzLl90b29sdGlwLm9wdGlvbnMuc3RpY2t5KSB7XG5cdFx0XHRcdGV2ZW50cy5tb3VzZW1vdmUgPSB0aGlzLl9tb3ZlVG9vbHRpcDtcblx0XHRcdH1cblx0XHRcdGlmICh0b3VjaCkge1xuXHRcdFx0XHRldmVudHMuY2xpY2sgPSB0aGlzLl9vcGVuVG9vbHRpcDtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0ZXZlbnRzLmFkZCA9IHRoaXMuX29wZW5Ub29sdGlwO1xuXHRcdH1cblx0XHR0aGlzW29uT2ZmXShldmVudHMpO1xuXHRcdHRoaXMuX3Rvb2x0aXBIYW5kbGVyc0FkZGVkID0gIXJlbW92ZSQkMTtcblx0fSxcblxuXHQvLyBAbWV0aG9kIG9wZW5Ub29sdGlwKGxhdGxuZz86IExhdExuZyk6IHRoaXNcblx0Ly8gT3BlbnMgdGhlIGJvdW5kIHRvb2x0aXAgYXQgdGhlIHNwZWNpZmllZCBgbGF0bG5nYCBvciBhdCB0aGUgZGVmYXVsdCB0b29sdGlwIGFuY2hvciBpZiBubyBgbGF0bG5nYCBpcyBwYXNzZWQuXG5cdG9wZW5Ub29sdGlwOiBmdW5jdGlvbiAobGF5ZXIsIGxhdGxuZykge1xuXHRcdGlmICh0aGlzLl90b29sdGlwICYmIHRoaXMuX21hcCkge1xuXHRcdFx0bGF0bG5nID0gdGhpcy5fdG9vbHRpcC5fcHJlcGFyZU9wZW4odGhpcywgbGF5ZXIsIGxhdGxuZyk7XG5cblx0XHRcdC8vIG9wZW4gdGhlIHRvb2x0aXAgb24gdGhlIG1hcFxuXHRcdFx0dGhpcy5fbWFwLm9wZW5Ub29sdGlwKHRoaXMuX3Rvb2x0aXAsIGxhdGxuZyk7XG5cblx0XHRcdC8vIFRvb2x0aXAgY29udGFpbmVyIG1heSBub3QgYmUgZGVmaW5lZCBpZiBub3QgcGVybWFuZW50IGFuZCBuZXZlclxuXHRcdFx0Ly8gb3BlbmVkLlxuXHRcdFx0aWYgKHRoaXMuX3Rvb2x0aXAub3B0aW9ucy5pbnRlcmFjdGl2ZSAmJiB0aGlzLl90b29sdGlwLl9jb250YWluZXIpIHtcblx0XHRcdFx0YWRkQ2xhc3ModGhpcy5fdG9vbHRpcC5fY29udGFpbmVyLCAnbGVhZmxldC1jbGlja2FibGUnKTtcblx0XHRcdFx0dGhpcy5hZGRJbnRlcmFjdGl2ZVRhcmdldCh0aGlzLl90b29sdGlwLl9jb250YWluZXIpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgY2xvc2VUb29sdGlwKCk6IHRoaXNcblx0Ly8gQ2xvc2VzIHRoZSB0b29sdGlwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgaWYgaXQgaXMgb3Blbi5cblx0Y2xvc2VUb29sdGlwOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX3Rvb2x0aXApIHtcblx0XHRcdHRoaXMuX3Rvb2x0aXAuX2Nsb3NlKCk7XG5cdFx0XHRpZiAodGhpcy5fdG9vbHRpcC5vcHRpb25zLmludGVyYWN0aXZlICYmIHRoaXMuX3Rvb2x0aXAuX2NvbnRhaW5lcikge1xuXHRcdFx0XHRyZW1vdmVDbGFzcyh0aGlzLl90b29sdGlwLl9jb250YWluZXIsICdsZWFmbGV0LWNsaWNrYWJsZScpO1xuXHRcdFx0XHR0aGlzLnJlbW92ZUludGVyYWN0aXZlVGFyZ2V0KHRoaXMuX3Rvb2x0aXAuX2NvbnRhaW5lcik7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgdG9nZ2xlVG9vbHRpcCgpOiB0aGlzXG5cdC8vIE9wZW5zIG9yIGNsb3NlcyB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGRlcGVuZGluZyBvbiBpdHMgY3VycmVudCBzdGF0ZS5cblx0dG9nZ2xlVG9vbHRpcDogZnVuY3Rpb24gKHRhcmdldCkge1xuXHRcdGlmICh0aGlzLl90b29sdGlwKSB7XG5cdFx0XHRpZiAodGhpcy5fdG9vbHRpcC5fbWFwKSB7XG5cdFx0XHRcdHRoaXMuY2xvc2VUb29sdGlwKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLm9wZW5Ub29sdGlwKHRhcmdldCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgaXNUb29sdGlwT3BlbigpOiBib29sZWFuXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSB0b29sdGlwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgaXMgY3VycmVudGx5IG9wZW4uXG5cdGlzVG9vbHRpcE9wZW46IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdG9vbHRpcC5pc09wZW4oKTtcblx0fSxcblxuXHQvLyBAbWV0aG9kIHNldFRvb2x0aXBDb250ZW50KGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudHxUb29sdGlwKTogdGhpc1xuXHQvLyBTZXRzIHRoZSBjb250ZW50IG9mIHRoZSB0b29sdGlwIGJvdW5kIHRvIHRoaXMgbGF5ZXIuXG5cdHNldFRvb2x0aXBDb250ZW50OiBmdW5jdGlvbiAoY29udGVudCkge1xuXHRcdGlmICh0aGlzLl90b29sdGlwKSB7XG5cdFx0XHR0aGlzLl90b29sdGlwLnNldENvbnRlbnQoY29udGVudCk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgZ2V0VG9vbHRpcCgpOiBUb29sdGlwXG5cdC8vIFJldHVybnMgdGhlIHRvb2x0aXAgYm91bmQgdG8gdGhpcyBsYXllci5cblx0Z2V0VG9vbHRpcDogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLl90b29sdGlwO1xuXHR9LFxuXG5cdF9vcGVuVG9vbHRpcDogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgbGF5ZXIgPSBlLmxheWVyIHx8IGUudGFyZ2V0O1xuXG5cdFx0aWYgKCF0aGlzLl90b29sdGlwIHx8ICF0aGlzLl9tYXApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0dGhpcy5vcGVuVG9vbHRpcChsYXllciwgdGhpcy5fdG9vbHRpcC5vcHRpb25zLnN0aWNreSA/IGUubGF0bG5nIDogdW5kZWZpbmVkKTtcblx0fSxcblxuXHRfbW92ZVRvb2x0aXA6IGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIGxhdGxuZyA9IGUubGF0bG5nLCBjb250YWluZXJQb2ludCwgbGF5ZXJQb2ludDtcblx0XHRpZiAodGhpcy5fdG9vbHRpcC5vcHRpb25zLnN0aWNreSAmJiBlLm9yaWdpbmFsRXZlbnQpIHtcblx0XHRcdGNvbnRhaW5lclBvaW50ID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUub3JpZ2luYWxFdmVudCk7XG5cdFx0XHRsYXllclBvaW50ID0gdGhpcy5fbWFwLmNvbnRhaW5lclBvaW50VG9MYXllclBvaW50KGNvbnRhaW5lclBvaW50KTtcblx0XHRcdGxhdGxuZyA9IHRoaXMuX21hcC5sYXllclBvaW50VG9MYXRMbmcobGF5ZXJQb2ludCk7XG5cdFx0fVxuXHRcdHRoaXMuX3Rvb2x0aXAuc2V0TGF0TG5nKGxhdGxuZyk7XG5cdH1cbn0pO1xuXG4vKlxuICogQGNsYXNzIERpdkljb25cbiAqIEBha2EgTC5EaXZJY29uXG4gKiBAaW5oZXJpdHMgSWNvblxuICpcbiAqIFJlcHJlc2VudHMgYSBsaWdodHdlaWdodCBpY29uIGZvciBtYXJrZXJzIHRoYXQgdXNlcyBhIHNpbXBsZSBgPGRpdj5gXG4gKiBlbGVtZW50IGluc3RlYWQgb2YgYW4gaW1hZ2UuIEluaGVyaXRzIGZyb20gYEljb25gIGJ1dCBpZ25vcmVzIHRoZSBgaWNvblVybGAgYW5kIHNoYWRvdyBvcHRpb25zLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBqc1xuICogdmFyIG15SWNvbiA9IEwuZGl2SWNvbih7Y2xhc3NOYW1lOiAnbXktZGl2LWljb24nfSk7XG4gKiAvLyB5b3UgY2FuIHNldCAubXktZGl2LWljb24gc3R5bGVzIGluIENTU1xuICpcbiAqIEwubWFya2VyKFs1MC41MDUsIDMwLjU3XSwge2ljb246IG15SWNvbn0pLmFkZFRvKG1hcCk7XG4gKiBgYGBcbiAqXG4gKiBCeSBkZWZhdWx0LCBpdCBoYXMgYSAnbGVhZmxldC1kaXYtaWNvbicgQ1NTIGNsYXNzIGFuZCBpcyBzdHlsZWQgYXMgYSBsaXR0bGUgd2hpdGUgc3F1YXJlIHdpdGggYSBzaGFkb3cuXG4gKi9cblxudmFyIERpdkljb24gPSBJY29uLmV4dGVuZCh7XG5cdG9wdGlvbnM6IHtcblx0XHQvLyBAc2VjdGlvblxuXHRcdC8vIEBha2EgRGl2SWNvbiBvcHRpb25zXG5cdFx0aWNvblNpemU6IFsxMiwgMTJdLCAvLyBhbHNvIGNhbiBiZSBzZXQgdGhyb3VnaCBDU1NcblxuXHRcdC8vIGljb25BbmNob3I6IChQb2ludCksXG5cdFx0Ly8gcG9wdXBBbmNob3I6IChQb2ludCksXG5cblx0XHQvLyBAb3B0aW9uIGh0bWw6IFN0cmluZ3xIVE1MRWxlbWVudCA9ICcnXG5cdFx0Ly8gQ3VzdG9tIEhUTUwgY29kZSB0byBwdXQgaW5zaWRlIHRoZSBkaXYgZWxlbWVudCwgZW1wdHkgYnkgZGVmYXVsdC4gQWx0ZXJuYXRpdmVseSxcblx0XHQvLyBhbiBpbnN0YW5jZSBvZiBgSFRNTEVsZW1lbnRgLlxuXHRcdGh0bWw6IGZhbHNlLFxuXG5cdFx0Ly8gQG9wdGlvbiBiZ1BvczogUG9pbnQgPSBbMCwgMF1cblx0XHQvLyBPcHRpb25hbCByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgYmFja2dyb3VuZCwgaW4gcGl4ZWxzXG5cdFx0YmdQb3M6IG51bGwsXG5cblx0XHRjbGFzc05hbWU6ICdsZWFmbGV0LWRpdi1pY29uJ1xuXHR9LFxuXG5cdGNyZWF0ZUljb246IGZ1bmN0aW9uIChvbGRJY29uKSB7XG5cdFx0dmFyIGRpdiA9IChvbGRJY29uICYmIG9sZEljb24udGFnTmFtZSA9PT0gJ0RJVicpID8gb2xkSWNvbiA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLFxuXHRcdCAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuXG5cdFx0aWYgKG9wdGlvbnMuaHRtbCBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcblx0XHRcdGVtcHR5KGRpdik7XG5cdFx0XHRkaXYuYXBwZW5kQ2hpbGQob3B0aW9ucy5odG1sKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZGl2LmlubmVySFRNTCA9IG9wdGlvbnMuaHRtbCAhPT0gZmFsc2UgPyBvcHRpb25zLmh0bWwgOiAnJztcblx0XHR9XG5cblx0XHRpZiAob3B0aW9ucy5iZ1Bvcykge1xuXHRcdFx0dmFyIGJnUG9zID0gdG9Qb2ludChvcHRpb25zLmJnUG9zKTtcblx0XHRcdGRpdi5zdHlsZS5iYWNrZ3JvdW5kUG9zaXRpb24gPSAoLWJnUG9zLngpICsgJ3B4ICcgKyAoLWJnUG9zLnkpICsgJ3B4Jztcblx0XHR9XG5cdFx0dGhpcy5fc2V0SWNvblN0eWxlcyhkaXYsICdpY29uJyk7XG5cblx0XHRyZXR1cm4gZGl2O1xuXHR9LFxuXG5cdGNyZWF0ZVNoYWRvdzogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG59KTtcblxuLy8gQGZhY3RvcnkgTC5kaXZJY29uKG9wdGlvbnM6IERpdkljb24gb3B0aW9ucylcbi8vIENyZWF0ZXMgYSBgRGl2SWNvbmAgaW5zdGFuY2Ugd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy5cbmZ1bmN0aW9uIGRpdkljb24ob3B0aW9ucykge1xuXHRyZXR1cm4gbmV3IERpdkljb24ob3B0aW9ucyk7XG59XG5cbkljb24uRGVmYXVsdCA9IEljb25EZWZhdWx0O1xuXG4vKlxuICogQGNsYXNzIEdyaWRMYXllclxuICogQGluaGVyaXRzIExheWVyXG4gKiBAYWthIEwuR3JpZExheWVyXG4gKlxuICogR2VuZXJpYyBjbGFzcyBmb3IgaGFuZGxpbmcgYSB0aWxlZCBncmlkIG9mIEhUTUwgZWxlbWVudHMuIFRoaXMgaXMgdGhlIGJhc2UgY2xhc3MgZm9yIGFsbCB0aWxlIGxheWVycyBhbmQgcmVwbGFjZXMgYFRpbGVMYXllci5DYW52YXNgLlxuICogR3JpZExheWVyIGNhbiBiZSBleHRlbmRlZCB0byBjcmVhdGUgYSB0aWxlZCBncmlkIG9mIEhUTUwgZWxlbWVudHMgbGlrZSBgPGNhbnZhcz5gLCBgPGltZz5gIG9yIGA8ZGl2PmAuIEdyaWRMYXllciB3aWxsIGhhbmRsZSBjcmVhdGluZyBhbmQgYW5pbWF0aW5nIHRoZXNlIERPTSBlbGVtZW50cyBmb3IgeW91LlxuICpcbiAqXG4gKiBAc2VjdGlvbiBTeW5jaHJvbm91cyB1c2FnZVxuICogQGV4YW1wbGVcbiAqXG4gKiBUbyBjcmVhdGUgYSBjdXN0b20gbGF5ZXIsIGV4dGVuZCBHcmlkTGF5ZXIgYW5kIGltcGxlbWVudCB0aGUgYGNyZWF0ZVRpbGUoKWAgbWV0aG9kLCB3aGljaCB3aWxsIGJlIHBhc3NlZCBhIGBQb2ludGAgb2JqZWN0IHdpdGggdGhlIGB4YCwgYHlgLCBhbmQgYHpgICh6b29tIGxldmVsKSBjb29yZGluYXRlcyB0byBkcmF3IHlvdXIgdGlsZS5cbiAqXG4gKiBgYGBqc1xuICogdmFyIENhbnZhc0xheWVyID0gTC5HcmlkTGF5ZXIuZXh0ZW5kKHtcbiAqICAgICBjcmVhdGVUaWxlOiBmdW5jdGlvbihjb29yZHMpe1xuICogICAgICAgICAvLyBjcmVhdGUgYSA8Y2FudmFzPiBlbGVtZW50IGZvciBkcmF3aW5nXG4gKiAgICAgICAgIHZhciB0aWxlID0gTC5Eb21VdGlsLmNyZWF0ZSgnY2FudmFzJywgJ2xlYWZsZXQtdGlsZScpO1xuICpcbiAqICAgICAgICAgLy8gc2V0dXAgdGlsZSB3aWR0aCBhbmQgaGVpZ2h0IGFjY29yZGluZyB0byB0aGUgb3B0aW9uc1xuICogICAgICAgICB2YXIgc2l6ZSA9IHRoaXMuZ2V0VGlsZVNpemUoKTtcbiAqICAgICAgICAgdGlsZS53aWR0aCA9IHNpemUueDtcbiAqICAgICAgICAgdGlsZS5oZWlnaHQgPSBzaXplLnk7XG4gKlxuICogICAgICAgICAvLyBnZXQgYSBjYW52YXMgY29udGV4dCBhbmQgZHJhdyBzb21ldGhpbmcgb24gaXQgdXNpbmcgY29vcmRzLngsIGNvb3Jkcy55IGFuZCBjb29yZHMuelxuICogICAgICAgICB2YXIgY3R4ID0gdGlsZS5nZXRDb250ZXh0KCcyZCcpO1xuICpcbiAqICAgICAgICAgLy8gcmV0dXJuIHRoZSB0aWxlIHNvIGl0IGNhbiBiZSByZW5kZXJlZCBvbiBzY3JlZW5cbiAqICAgICAgICAgcmV0dXJuIHRpbGU7XG4gKiAgICAgfVxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAc2VjdGlvbiBBc3luY2hyb25vdXMgdXNhZ2VcbiAqIEBleGFtcGxlXG4gKlxuICogVGlsZSBjcmVhdGlvbiBjYW4gYWxzbyBiZSBhc3luY2hyb25vdXMsIHRoaXMgaXMgdXNlZnVsIHdoZW4gdXNpbmcgYSB0aGlyZC1wYXJ0eSBkcmF3aW5nIGxpYnJhcnkuIE9uY2UgdGhlIHRpbGUgaXMgZmluaXNoZWQgZHJhd2luZyBpdCBjYW4gYmUgcGFzc2VkIHRvIHRoZSBgZG9uZSgpYCBjYWxsYmFjay5cbiAqXG4gKiBgYGBqc1xuICogdmFyIENhbnZhc0xheWVyID0gTC5HcmlkTGF5ZXIuZXh0ZW5kKHtcbiAqICAgICBjcmVhdGVUaWxlOiBmdW5jdGlvbihjb29yZHMsIGRvbmUpe1xuICogICAgICAgICB2YXIgZXJyb3I7XG4gKlxuICogICAgICAgICAvLyBjcmVhdGUgYSA8Y2FudmFzPiBlbGVtZW50IGZvciBkcmF3aW5nXG4gKiAgICAgICAgIHZhciB0aWxlID0gTC5Eb21VdGlsLmNyZWF0ZSgnY2FudmFzJywgJ2xlYWZsZXQtdGlsZScpO1xuICpcbiAqICAgICAgICAgLy8gc2V0dXAgdGlsZSB3aWR0aCBhbmQgaGVpZ2h0IGFjY29yZGluZyB0byB0aGUgb3B0aW9uc1xuICogICAgICAgICB2YXIgc2l6ZSA9IHRoaXMuZ2V0VGlsZVNpemUoKTtcbiAqICAgICAgICAgdGlsZS53aWR0aCA9IHNpemUueDtcbiAqICAgICAgICAgdGlsZS5oZWlnaHQgPSBzaXplLnk7XG4gKlxuICogICAgICAgICAvLyBkcmF3IHNvbWV0aGluZyBhc3luY2hyb25vdXNseSBhbmQgcGFzcyB0aGUgdGlsZSB0byB0aGUgZG9uZSgpIGNhbGxiYWNrXG4gKiAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gKiAgICAgICAgICAgICBkb25lKGVycm9yLCB0aWxlKTtcbiAqICAgICAgICAgfSwgMTAwMCk7XG4gKlxuICogICAgICAgICByZXR1cm4gdGlsZTtcbiAqICAgICB9XG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqIEBzZWN0aW9uXG4gKi9cblxuXG52YXIgR3JpZExheWVyID0gTGF5ZXIuZXh0ZW5kKHtcblxuXHQvLyBAc2VjdGlvblxuXHQvLyBAYWthIEdyaWRMYXllciBvcHRpb25zXG5cdG9wdGlvbnM6IHtcblx0XHQvLyBAb3B0aW9uIHRpbGVTaXplOiBOdW1iZXJ8UG9pbnQgPSAyNTZcblx0XHQvLyBXaWR0aCBhbmQgaGVpZ2h0IG9mIHRpbGVzIGluIHRoZSBncmlkLiBVc2UgYSBudW1iZXIgaWYgd2lkdGggYW5kIGhlaWdodCBhcmUgZXF1YWwsIG9yIGBMLnBvaW50KHdpZHRoLCBoZWlnaHQpYCBvdGhlcndpc2UuXG5cdFx0dGlsZVNpemU6IDI1NixcblxuXHRcdC8vIEBvcHRpb24gb3BhY2l0eTogTnVtYmVyID0gMS4wXG5cdFx0Ly8gT3BhY2l0eSBvZiB0aGUgdGlsZXMuIENhbiBiZSB1c2VkIGluIHRoZSBgY3JlYXRlVGlsZSgpYCBmdW5jdGlvbi5cblx0XHRvcGFjaXR5OiAxLFxuXG5cdFx0Ly8gQG9wdGlvbiB1cGRhdGVXaGVuSWRsZTogQm9vbGVhbiA9IChkZXBlbmRzKVxuXHRcdC8vIExvYWQgbmV3IHRpbGVzIG9ubHkgd2hlbiBwYW5uaW5nIGVuZHMuXG5cdFx0Ly8gYHRydWVgIGJ5IGRlZmF1bHQgb24gbW9iaWxlIGJyb3dzZXJzLCBpbiBvcmRlciB0byBhdm9pZCB0b28gbWFueSByZXF1ZXN0cyBhbmQga2VlcCBzbW9vdGggbmF2aWdhdGlvbi5cblx0XHQvLyBgZmFsc2VgIG90aGVyd2lzZSBpbiBvcmRlciB0byBkaXNwbGF5IG5ldyB0aWxlcyBfZHVyaW5nXyBwYW5uaW5nLCBzaW5jZSBpdCBpcyBlYXN5IHRvIHBhbiBvdXRzaWRlIHRoZVxuXHRcdC8vIFtga2VlcEJ1ZmZlcmBdKCNncmlkbGF5ZXIta2VlcGJ1ZmZlcikgb3B0aW9uIGluIGRlc2t0b3AgYnJvd3NlcnMuXG5cdFx0dXBkYXRlV2hlbklkbGU6IG1vYmlsZSxcblxuXHRcdC8vIEBvcHRpb24gdXBkYXRlV2hlblpvb21pbmc6IEJvb2xlYW4gPSB0cnVlXG5cdFx0Ly8gQnkgZGVmYXVsdCwgYSBzbW9vdGggem9vbSBhbmltYXRpb24gKGR1cmluZyBhIFt0b3VjaCB6b29tXSgjbWFwLXRvdWNoem9vbSkgb3IgYSBbYGZseVRvKClgXSgjbWFwLWZseXRvKSkgd2lsbCB1cGRhdGUgZ3JpZCBsYXllcnMgZXZlcnkgaW50ZWdlciB6b29tIGxldmVsLiBTZXR0aW5nIHRoaXMgb3B0aW9uIHRvIGBmYWxzZWAgd2lsbCB1cGRhdGUgdGhlIGdyaWQgbGF5ZXIgb25seSB3aGVuIHRoZSBzbW9vdGggYW5pbWF0aW9uIGVuZHMuXG5cdFx0dXBkYXRlV2hlblpvb21pbmc6IHRydWUsXG5cblx0XHQvLyBAb3B0aW9uIHVwZGF0ZUludGVydmFsOiBOdW1iZXIgPSAyMDBcblx0XHQvLyBUaWxlcyB3aWxsIG5vdCB1cGRhdGUgbW9yZSB0aGFuIG9uY2UgZXZlcnkgYHVwZGF0ZUludGVydmFsYCBtaWxsaXNlY29uZHMgd2hlbiBwYW5uaW5nLlxuXHRcdHVwZGF0ZUludGVydmFsOiAyMDAsXG5cblx0XHQvLyBAb3B0aW9uIHpJbmRleDogTnVtYmVyID0gMVxuXHRcdC8vIFRoZSBleHBsaWNpdCB6SW5kZXggb2YgdGhlIHRpbGUgbGF5ZXIuXG5cdFx0ekluZGV4OiAxLFxuXG5cdFx0Ly8gQG9wdGlvbiBib3VuZHM6IExhdExuZ0JvdW5kcyA9IHVuZGVmaW5lZFxuXHRcdC8vIElmIHNldCwgdGlsZXMgd2lsbCBvbmx5IGJlIGxvYWRlZCBpbnNpZGUgdGhlIHNldCBgTGF0TG5nQm91bmRzYC5cblx0XHRib3VuZHM6IG51bGwsXG5cblx0XHQvLyBAb3B0aW9uIG1pblpvb206IE51bWJlciA9IDBcblx0XHQvLyBUaGUgbWluaW11bSB6b29tIGxldmVsIGRvd24gdG8gd2hpY2ggdGhpcyBsYXllciB3aWxsIGJlIGRpc3BsYXllZCAoaW5jbHVzaXZlKS5cblx0XHRtaW5ab29tOiAwLFxuXG5cdFx0Ly8gQG9wdGlvbiBtYXhab29tOiBOdW1iZXIgPSB1bmRlZmluZWRcblx0XHQvLyBUaGUgbWF4aW11bSB6b29tIGxldmVsIHVwIHRvIHdoaWNoIHRoaXMgbGF5ZXIgd2lsbCBiZSBkaXNwbGF5ZWQgKGluY2x1c2l2ZSkuXG5cdFx0bWF4Wm9vbTogdW5kZWZpbmVkLFxuXG5cdFx0Ly8gQG9wdGlvbiBtYXhOYXRpdmVab29tOiBOdW1iZXIgPSB1bmRlZmluZWRcblx0XHQvLyBNYXhpbXVtIHpvb20gbnVtYmVyIHRoZSB0aWxlIHNvdXJjZSBoYXMgYXZhaWxhYmxlLiBJZiBpdCBpcyBzcGVjaWZpZWQsXG5cdFx0Ly8gdGhlIHRpbGVzIG9uIGFsbCB6b29tIGxldmVscyBoaWdoZXIgdGhhbiBgbWF4TmF0aXZlWm9vbWAgd2lsbCBiZSBsb2FkZWRcblx0XHQvLyBmcm9tIGBtYXhOYXRpdmVab29tYCBsZXZlbCBhbmQgYXV0by1zY2FsZWQuXG5cdFx0bWF4TmF0aXZlWm9vbTogdW5kZWZpbmVkLFxuXG5cdFx0Ly8gQG9wdGlvbiBtaW5OYXRpdmVab29tOiBOdW1iZXIgPSB1bmRlZmluZWRcblx0XHQvLyBNaW5pbXVtIHpvb20gbnVtYmVyIHRoZSB0aWxlIHNvdXJjZSBoYXMgYXZhaWxhYmxlLiBJZiBpdCBpcyBzcGVjaWZpZWQsXG5cdFx0Ly8gdGhlIHRpbGVzIG9uIGFsbCB6b29tIGxldmVscyBsb3dlciB0aGFuIGBtaW5OYXRpdmVab29tYCB3aWxsIGJlIGxvYWRlZFxuXHRcdC8vIGZyb20gYG1pbk5hdGl2ZVpvb21gIGxldmVsIGFuZCBhdXRvLXNjYWxlZC5cblx0XHRtaW5OYXRpdmVab29tOiB1bmRlZmluZWQsXG5cblx0XHQvLyBAb3B0aW9uIG5vV3JhcDogQm9vbGVhbiA9IGZhbHNlXG5cdFx0Ly8gV2hldGhlciB0aGUgbGF5ZXIgaXMgd3JhcHBlZCBhcm91bmQgdGhlIGFudGltZXJpZGlhbi4gSWYgYHRydWVgLCB0aGVcblx0XHQvLyBHcmlkTGF5ZXIgd2lsbCBvbmx5IGJlIGRpc3BsYXllZCBvbmNlIGF0IGxvdyB6b29tIGxldmVscy4gSGFzIG5vXG5cdFx0Ly8gZWZmZWN0IHdoZW4gdGhlIFttYXAgQ1JTXSgjbWFwLWNycykgZG9lc24ndCB3cmFwIGFyb3VuZC4gQ2FuIGJlIHVzZWRcblx0XHQvLyBpbiBjb21iaW5hdGlvbiB3aXRoIFtgYm91bmRzYF0oI2dyaWRsYXllci1ib3VuZHMpIHRvIHByZXZlbnQgcmVxdWVzdGluZ1xuXHRcdC8vIHRpbGVzIG91dHNpZGUgdGhlIENSUyBsaW1pdHMuXG5cdFx0bm9XcmFwOiBmYWxzZSxcblxuXHRcdC8vIEBvcHRpb24gcGFuZTogU3RyaW5nID0gJ3RpbGVQYW5lJ1xuXHRcdC8vIGBNYXAgcGFuZWAgd2hlcmUgdGhlIGdyaWQgbGF5ZXIgd2lsbCBiZSBhZGRlZC5cblx0XHRwYW5lOiAndGlsZVBhbmUnLFxuXG5cdFx0Ly8gQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9ICcnXG5cdFx0Ly8gQSBjdXN0b20gY2xhc3MgbmFtZSB0byBhc3NpZ24gdG8gdGhlIHRpbGUgbGF5ZXIuIEVtcHR5IGJ5IGRlZmF1bHQuXG5cdFx0Y2xhc3NOYW1lOiAnJyxcblxuXHRcdC8vIEBvcHRpb24ga2VlcEJ1ZmZlcjogTnVtYmVyID0gMlxuXHRcdC8vIFdoZW4gcGFubmluZyB0aGUgbWFwLCBrZWVwIHRoaXMgbWFueSByb3dzIGFuZCBjb2x1bW5zIG9mIHRpbGVzIGJlZm9yZSB1bmxvYWRpbmcgdGhlbS5cblx0XHRrZWVwQnVmZmVyOiAyXG5cdH0sXG5cblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xuXHR9LFxuXG5cdG9uQWRkOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5faW5pdENvbnRhaW5lcigpO1xuXG5cdFx0dGhpcy5fbGV2ZWxzID0ge307XG5cdFx0dGhpcy5fdGlsZXMgPSB7fTtcblxuXHRcdHRoaXMuX3Jlc2V0VmlldygpO1xuXHRcdHRoaXMuX3VwZGF0ZSgpO1xuXHR9LFxuXG5cdGJlZm9yZUFkZDogZnVuY3Rpb24gKG1hcCkge1xuXHRcdG1hcC5fYWRkWm9vbUxpbWl0KHRoaXMpO1xuXHR9LFxuXG5cdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XG5cdFx0dGhpcy5fcmVtb3ZlQWxsVGlsZXMoKTtcblx0XHRyZW1vdmUodGhpcy5fY29udGFpbmVyKTtcblx0XHRtYXAuX3JlbW92ZVpvb21MaW1pdCh0aGlzKTtcblx0XHR0aGlzLl9jb250YWluZXIgPSBudWxsO1xuXHRcdHRoaXMuX3RpbGVab29tID0gdW5kZWZpbmVkO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgYnJpbmdUb0Zyb250OiB0aGlzXG5cdC8vIEJyaW5ncyB0aGUgdGlsZSBsYXllciB0byB0aGUgdG9wIG9mIGFsbCB0aWxlIGxheWVycy5cblx0YnJpbmdUb0Zyb250OiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcCkge1xuXHRcdFx0dG9Gcm9udCh0aGlzLl9jb250YWluZXIpO1xuXHRcdFx0dGhpcy5fc2V0QXV0b1pJbmRleChNYXRoLm1heCk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgYnJpbmdUb0JhY2s6IHRoaXNcblx0Ly8gQnJpbmdzIHRoZSB0aWxlIGxheWVyIHRvIHRoZSBib3R0b20gb2YgYWxsIHRpbGUgbGF5ZXJzLlxuXHRicmluZ1RvQmFjazogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9tYXApIHtcblx0XHRcdHRvQmFjayh0aGlzLl9jb250YWluZXIpO1xuXHRcdFx0dGhpcy5fc2V0QXV0b1pJbmRleChNYXRoLm1pbik7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgZ2V0Q29udGFpbmVyOiBIVE1MRWxlbWVudFxuXHQvLyBSZXR1cm5zIHRoZSBIVE1MIGVsZW1lbnQgdGhhdCBjb250YWlucyB0aGUgdGlsZXMgZm9yIHRoaXMgbGF5ZXIuXG5cdGdldENvbnRhaW5lcjogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLl9jb250YWluZXI7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBzZXRPcGFjaXR5KG9wYWNpdHk6IE51bWJlcik6IHRoaXNcblx0Ly8gQ2hhbmdlcyB0aGUgW29wYWNpdHldKCNncmlkbGF5ZXItb3BhY2l0eSkgb2YgdGhlIGdyaWQgbGF5ZXIuXG5cdHNldE9wYWNpdHk6IGZ1bmN0aW9uIChvcGFjaXR5KSB7XG5cdFx0dGhpcy5vcHRpb25zLm9wYWNpdHkgPSBvcGFjaXR5O1xuXHRcdHRoaXMuX3VwZGF0ZU9wYWNpdHkoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIHNldFpJbmRleCh6SW5kZXg6IE51bWJlcik6IHRoaXNcblx0Ly8gQ2hhbmdlcyB0aGUgW3pJbmRleF0oI2dyaWRsYXllci16aW5kZXgpIG9mIHRoZSBncmlkIGxheWVyLlxuXHRzZXRaSW5kZXg6IGZ1bmN0aW9uICh6SW5kZXgpIHtcblx0XHR0aGlzLm9wdGlvbnMuekluZGV4ID0gekluZGV4O1xuXHRcdHRoaXMuX3VwZGF0ZVpJbmRleCgpO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBpc0xvYWRpbmc6IEJvb2xlYW5cblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgYW55IHRpbGUgaW4gdGhlIGdyaWQgbGF5ZXIgaGFzIG5vdCBmaW5pc2hlZCBsb2FkaW5nLlxuXHRpc0xvYWRpbmc6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fbG9hZGluZztcblx0fSxcblxuXHQvLyBAbWV0aG9kIHJlZHJhdzogdGhpc1xuXHQvLyBDYXVzZXMgdGhlIGxheWVyIHRvIGNsZWFyIGFsbCB0aGUgdGlsZXMgYW5kIHJlcXVlc3QgdGhlbSBhZ2Fpbi5cblx0cmVkcmF3OiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcCkge1xuXHRcdFx0dGhpcy5fcmVtb3ZlQWxsVGlsZXMoKTtcblx0XHRcdHRoaXMuX3VwZGF0ZSgpO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgZXZlbnRzID0ge1xuXHRcdFx0dmlld3ByZXJlc2V0OiB0aGlzLl9pbnZhbGlkYXRlQWxsLFxuXHRcdFx0dmlld3Jlc2V0OiB0aGlzLl9yZXNldFZpZXcsXG5cdFx0XHR6b29tOiB0aGlzLl9yZXNldFZpZXcsXG5cdFx0XHRtb3ZlZW5kOiB0aGlzLl9vbk1vdmVFbmRcblx0XHR9O1xuXG5cdFx0aWYgKCF0aGlzLm9wdGlvbnMudXBkYXRlV2hlbklkbGUpIHtcblx0XHRcdC8vIHVwZGF0ZSB0aWxlcyBvbiBtb3ZlLCBidXQgbm90IG1vcmUgb2Z0ZW4gdGhhbiBvbmNlIHBlciBnaXZlbiBpbnRlcnZhbFxuXHRcdFx0aWYgKCF0aGlzLl9vbk1vdmUpIHtcblx0XHRcdFx0dGhpcy5fb25Nb3ZlID0gdGhyb3R0bGUodGhpcy5fb25Nb3ZlRW5kLCB0aGlzLm9wdGlvbnMudXBkYXRlSW50ZXJ2YWwsIHRoaXMpO1xuXHRcdFx0fVxuXG5cdFx0XHRldmVudHMubW92ZSA9IHRoaXMuX29uTW92ZTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5fem9vbUFuaW1hdGVkKSB7XG5cdFx0XHRldmVudHMuem9vbWFuaW0gPSB0aGlzLl9hbmltYXRlWm9vbTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZXZlbnRzO1xuXHR9LFxuXG5cdC8vIEBzZWN0aW9uIEV4dGVuc2lvbiBtZXRob2RzXG5cdC8vIExheWVycyBleHRlbmRpbmcgYEdyaWRMYXllcmAgc2hhbGwgcmVpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBtZXRob2QuXG5cdC8vIEBtZXRob2QgY3JlYXRlVGlsZShjb29yZHM6IE9iamVjdCwgZG9uZT86IEZ1bmN0aW9uKTogSFRNTEVsZW1lbnRcblx0Ly8gQ2FsbGVkIG9ubHkgaW50ZXJuYWxseSwgbXVzdCBiZSBvdmVycmlkZGVuIGJ5IGNsYXNzZXMgZXh0ZW5kaW5nIGBHcmlkTGF5ZXJgLlxuXHQvLyBSZXR1cm5zIHRoZSBgSFRNTEVsZW1lbnRgIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGdpdmVuIGBjb29yZHNgLiBJZiB0aGUgYGRvbmVgIGNhbGxiYWNrXG5cdC8vIGlzIHNwZWNpZmllZCwgaXQgbXVzdCBiZSBjYWxsZWQgd2hlbiB0aGUgdGlsZSBoYXMgZmluaXNoZWQgbG9hZGluZyBhbmQgZHJhd2luZy5cblx0Y3JlYXRlVGlsZTogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblx0fSxcblxuXHQvLyBAc2VjdGlvblxuXHQvLyBAbWV0aG9kIGdldFRpbGVTaXplOiBQb2ludFxuXHQvLyBOb3JtYWxpemVzIHRoZSBbdGlsZVNpemUgb3B0aW9uXSgjZ3JpZGxheWVyLXRpbGVzaXplKSBpbnRvIGEgcG9pbnQuIFVzZWQgYnkgdGhlIGBjcmVhdGVUaWxlKClgIG1ldGhvZC5cblx0Z2V0VGlsZVNpemU6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgcyA9IHRoaXMub3B0aW9ucy50aWxlU2l6ZTtcblx0XHRyZXR1cm4gcyBpbnN0YW5jZW9mIFBvaW50ID8gcyA6IG5ldyBQb2ludChzLCBzKTtcblx0fSxcblxuXHRfdXBkYXRlWkluZGV4OiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX2NvbnRhaW5lciAmJiB0aGlzLm9wdGlvbnMuekluZGV4ICE9PSB1bmRlZmluZWQgJiYgdGhpcy5vcHRpb25zLnpJbmRleCAhPT0gbnVsbCkge1xuXHRcdFx0dGhpcy5fY29udGFpbmVyLnN0eWxlLnpJbmRleCA9IHRoaXMub3B0aW9ucy56SW5kZXg7XG5cdFx0fVxuXHR9LFxuXG5cdF9zZXRBdXRvWkluZGV4OiBmdW5jdGlvbiAoY29tcGFyZSkge1xuXHRcdC8vIGdvIHRocm91Z2ggYWxsIG90aGVyIGxheWVycyBvZiB0aGUgc2FtZSBwYW5lLCBzZXQgekluZGV4IHRvIG1heCArIDEgKGZyb250KSBvciBtaW4gLSAxIChiYWNrKVxuXG5cdFx0dmFyIGxheWVycyA9IHRoaXMuZ2V0UGFuZSgpLmNoaWxkcmVuLFxuXHRcdCAgICBlZGdlWkluZGV4ID0gLWNvbXBhcmUoLUluZmluaXR5LCBJbmZpbml0eSk7IC8vIC1JbmZpbml0eSBmb3IgbWF4LCBJbmZpbml0eSBmb3IgbWluXG5cblx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gbGF5ZXJzLmxlbmd0aCwgekluZGV4OyBpIDwgbGVuOyBpKyspIHtcblxuXHRcdFx0ekluZGV4ID0gbGF5ZXJzW2ldLnN0eWxlLnpJbmRleDtcblxuXHRcdFx0aWYgKGxheWVyc1tpXSAhPT0gdGhpcy5fY29udGFpbmVyICYmIHpJbmRleCkge1xuXHRcdFx0XHRlZGdlWkluZGV4ID0gY29tcGFyZShlZGdlWkluZGV4LCArekluZGV4KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoaXNGaW5pdGUoZWRnZVpJbmRleCkpIHtcblx0XHRcdHRoaXMub3B0aW9ucy56SW5kZXggPSBlZGdlWkluZGV4ICsgY29tcGFyZSgtMSwgMSk7XG5cdFx0XHR0aGlzLl91cGRhdGVaSW5kZXgoKTtcblx0XHR9XG5cdH0sXG5cblx0X3VwZGF0ZU9wYWNpdHk6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoIXRoaXMuX21hcCkgeyByZXR1cm47IH1cblxuXHRcdC8vIElFIGRvZXNuJ3QgaW5oZXJpdCBmaWx0ZXIgb3BhY2l0eSBwcm9wZXJseSwgc28gd2UncmUgZm9yY2VkIHRvIHNldCBpdCBvbiB0aWxlc1xuXHRcdGlmIChpZWx0OSkgeyByZXR1cm47IH1cblxuXHRcdHNldE9wYWNpdHkodGhpcy5fY29udGFpbmVyLCB0aGlzLm9wdGlvbnMub3BhY2l0eSk7XG5cblx0XHR2YXIgbm93ID0gK25ldyBEYXRlKCksXG5cdFx0ICAgIG5leHRGcmFtZSA9IGZhbHNlLFxuXHRcdCAgICB3aWxsUHJ1bmUgPSBmYWxzZTtcblxuXHRcdGZvciAodmFyIGtleSBpbiB0aGlzLl90aWxlcykge1xuXHRcdFx0dmFyIHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xuXHRcdFx0aWYgKCF0aWxlLmN1cnJlbnQgfHwgIXRpbGUubG9hZGVkKSB7IGNvbnRpbnVlOyB9XG5cblx0XHRcdHZhciBmYWRlID0gTWF0aC5taW4oMSwgKG5vdyAtIHRpbGUubG9hZGVkKSAvIDIwMCk7XG5cblx0XHRcdHNldE9wYWNpdHkodGlsZS5lbCwgZmFkZSk7XG5cdFx0XHRpZiAoZmFkZSA8IDEpIHtcblx0XHRcdFx0bmV4dEZyYW1lID0gdHJ1ZTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmICh0aWxlLmFjdGl2ZSkge1xuXHRcdFx0XHRcdHdpbGxQcnVuZSA9IHRydWU7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhpcy5fb25PcGFxdWVUaWxlKHRpbGUpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRpbGUuYWN0aXZlID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAod2lsbFBydW5lICYmICF0aGlzLl9ub1BydW5lKSB7IHRoaXMuX3BydW5lVGlsZXMoKTsgfVxuXG5cdFx0aWYgKG5leHRGcmFtZSkge1xuXHRcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2ZhZGVGcmFtZSk7XG5cdFx0XHR0aGlzLl9mYWRlRnJhbWUgPSByZXF1ZXN0QW5pbUZyYW1lKHRoaXMuX3VwZGF0ZU9wYWNpdHksIHRoaXMpO1xuXHRcdH1cblx0fSxcblxuXHRfb25PcGFxdWVUaWxlOiBmYWxzZUZuLFxuXG5cdF9pbml0Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX2NvbnRhaW5lcikgeyByZXR1cm47IH1cblxuXHRcdHRoaXMuX2NvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLCAnbGVhZmxldC1sYXllciAnICsgKHRoaXMub3B0aW9ucy5jbGFzc05hbWUgfHwgJycpKTtcblx0XHR0aGlzLl91cGRhdGVaSW5kZXgoKTtcblxuXHRcdGlmICh0aGlzLm9wdGlvbnMub3BhY2l0eSA8IDEpIHtcblx0XHRcdHRoaXMuX3VwZGF0ZU9wYWNpdHkoKTtcblx0XHR9XG5cblx0XHR0aGlzLmdldFBhbmUoKS5hcHBlbmRDaGlsZCh0aGlzLl9jb250YWluZXIpO1xuXHR9LFxuXG5cdF91cGRhdGVMZXZlbHM6IGZ1bmN0aW9uICgpIHtcblxuXHRcdHZhciB6b29tID0gdGhpcy5fdGlsZVpvb20sXG5cdFx0ICAgIG1heFpvb20gPSB0aGlzLm9wdGlvbnMubWF4Wm9vbTtcblxuXHRcdGlmICh6b29tID09PSB1bmRlZmluZWQpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfVxuXG5cdFx0Zm9yICh2YXIgeiBpbiB0aGlzLl9sZXZlbHMpIHtcblx0XHRcdGlmICh0aGlzLl9sZXZlbHNbel0uZWwuY2hpbGRyZW4ubGVuZ3RoIHx8IHogPT09IHpvb20pIHtcblx0XHRcdFx0dGhpcy5fbGV2ZWxzW3pdLmVsLnN0eWxlLnpJbmRleCA9IG1heFpvb20gLSBNYXRoLmFicyh6b29tIC0geik7XG5cdFx0XHRcdHRoaXMuX29uVXBkYXRlTGV2ZWwoeik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZW1vdmUodGhpcy5fbGV2ZWxzW3pdLmVsKTtcblx0XHRcdFx0dGhpcy5fcmVtb3ZlVGlsZXNBdFpvb20oeik7XG5cdFx0XHRcdHRoaXMuX29uUmVtb3ZlTGV2ZWwoeik7XG5cdFx0XHRcdGRlbGV0ZSB0aGlzLl9sZXZlbHNbel07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dmFyIGxldmVsID0gdGhpcy5fbGV2ZWxzW3pvb21dLFxuXHRcdCAgICBtYXAgPSB0aGlzLl9tYXA7XG5cblx0XHRpZiAoIWxldmVsKSB7XG5cdFx0XHRsZXZlbCA9IHRoaXMuX2xldmVsc1t6b29tXSA9IHt9O1xuXG5cdFx0XHRsZXZlbC5lbCA9IGNyZWF0ZSQxKCdkaXYnLCAnbGVhZmxldC10aWxlLWNvbnRhaW5lciBsZWFmbGV0LXpvb20tYW5pbWF0ZWQnLCB0aGlzLl9jb250YWluZXIpO1xuXHRcdFx0bGV2ZWwuZWwuc3R5bGUuekluZGV4ID0gbWF4Wm9vbTtcblxuXHRcdFx0bGV2ZWwub3JpZ2luID0gbWFwLnByb2plY3QobWFwLnVucHJvamVjdChtYXAuZ2V0UGl4ZWxPcmlnaW4oKSksIHpvb20pLnJvdW5kKCk7XG5cdFx0XHRsZXZlbC56b29tID0gem9vbTtcblxuXHRcdFx0dGhpcy5fc2V0Wm9vbVRyYW5zZm9ybShsZXZlbCwgbWFwLmdldENlbnRlcigpLCBtYXAuZ2V0Wm9vbSgpKTtcblxuXHRcdFx0Ly8gZm9yY2UgdGhlIGJyb3dzZXIgdG8gY29uc2lkZXIgdGhlIG5ld2x5IGFkZGVkIGVsZW1lbnQgZm9yIHRyYW5zaXRpb25cblx0XHRcdGZhbHNlRm4obGV2ZWwuZWwub2Zmc2V0V2lkdGgpO1xuXG5cdFx0XHR0aGlzLl9vbkNyZWF0ZUxldmVsKGxldmVsKTtcblx0XHR9XG5cblx0XHR0aGlzLl9sZXZlbCA9IGxldmVsO1xuXG5cdFx0cmV0dXJuIGxldmVsO1xuXHR9LFxuXG5cdF9vblVwZGF0ZUxldmVsOiBmYWxzZUZuLFxuXG5cdF9vblJlbW92ZUxldmVsOiBmYWxzZUZuLFxuXG5cdF9vbkNyZWF0ZUxldmVsOiBmYWxzZUZuLFxuXG5cdF9wcnVuZVRpbGVzOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKCF0aGlzLl9tYXApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIga2V5LCB0aWxlO1xuXG5cdFx0dmFyIHpvb20gPSB0aGlzLl9tYXAuZ2V0Wm9vbSgpO1xuXHRcdGlmICh6b29tID4gdGhpcy5vcHRpb25zLm1heFpvb20gfHxcblx0XHRcdHpvb20gPCB0aGlzLm9wdGlvbnMubWluWm9vbSkge1xuXHRcdFx0dGhpcy5fcmVtb3ZlQWxsVGlsZXMoKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRmb3IgKGtleSBpbiB0aGlzLl90aWxlcykge1xuXHRcdFx0dGlsZSA9IHRoaXMuX3RpbGVzW2tleV07XG5cdFx0XHR0aWxlLnJldGFpbiA9IHRpbGUuY3VycmVudDtcblx0XHR9XG5cblx0XHRmb3IgKGtleSBpbiB0aGlzLl90aWxlcykge1xuXHRcdFx0dGlsZSA9IHRoaXMuX3RpbGVzW2tleV07XG5cdFx0XHRpZiAodGlsZS5jdXJyZW50ICYmICF0aWxlLmFjdGl2ZSkge1xuXHRcdFx0XHR2YXIgY29vcmRzID0gdGlsZS5jb29yZHM7XG5cdFx0XHRcdGlmICghdGhpcy5fcmV0YWluUGFyZW50KGNvb3Jkcy54LCBjb29yZHMueSwgY29vcmRzLnosIGNvb3Jkcy56IC0gNSkpIHtcblx0XHRcdFx0XHR0aGlzLl9yZXRhaW5DaGlsZHJlbihjb29yZHMueCwgY29vcmRzLnksIGNvb3Jkcy56LCBjb29yZHMueiArIDIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Zm9yIChrZXkgaW4gdGhpcy5fdGlsZXMpIHtcblx0XHRcdGlmICghdGhpcy5fdGlsZXNba2V5XS5yZXRhaW4pIHtcblx0XHRcdFx0dGhpcy5fcmVtb3ZlVGlsZShrZXkpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHRfcmVtb3ZlVGlsZXNBdFpvb206IGZ1bmN0aW9uICh6b29tKSB7XG5cdFx0Zm9yICh2YXIga2V5IGluIHRoaXMuX3RpbGVzKSB7XG5cdFx0XHRpZiAodGhpcy5fdGlsZXNba2V5XS5jb29yZHMueiAhPT0gem9vbSkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblx0XHRcdHRoaXMuX3JlbW92ZVRpbGUoa2V5KTtcblx0XHR9XG5cdH0sXG5cblx0X3JlbW92ZUFsbFRpbGVzOiBmdW5jdGlvbiAoKSB7XG5cdFx0Zm9yICh2YXIga2V5IGluIHRoaXMuX3RpbGVzKSB7XG5cdFx0XHR0aGlzLl9yZW1vdmVUaWxlKGtleSk7XG5cdFx0fVxuXHR9LFxuXG5cdF9pbnZhbGlkYXRlQWxsOiBmdW5jdGlvbiAoKSB7XG5cdFx0Zm9yICh2YXIgeiBpbiB0aGlzLl9sZXZlbHMpIHtcblx0XHRcdHJlbW92ZSh0aGlzLl9sZXZlbHNbel0uZWwpO1xuXHRcdFx0dGhpcy5fb25SZW1vdmVMZXZlbCh6KTtcblx0XHRcdGRlbGV0ZSB0aGlzLl9sZXZlbHNbel07XG5cdFx0fVxuXHRcdHRoaXMuX3JlbW92ZUFsbFRpbGVzKCk7XG5cblx0XHR0aGlzLl90aWxlWm9vbSA9IHVuZGVmaW5lZDtcblx0fSxcblxuXHRfcmV0YWluUGFyZW50OiBmdW5jdGlvbiAoeCwgeSwgeiwgbWluWm9vbSkge1xuXHRcdHZhciB4MiA9IE1hdGguZmxvb3IoeCAvIDIpLFxuXHRcdCAgICB5MiA9IE1hdGguZmxvb3IoeSAvIDIpLFxuXHRcdCAgICB6MiA9IHogLSAxLFxuXHRcdCAgICBjb29yZHMyID0gbmV3IFBvaW50KCt4MiwgK3kyKTtcblx0XHRjb29yZHMyLnogPSArejI7XG5cblx0XHR2YXIga2V5ID0gdGhpcy5fdGlsZUNvb3Jkc1RvS2V5KGNvb3JkczIpLFxuXHRcdCAgICB0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcblxuXHRcdGlmICh0aWxlICYmIHRpbGUuYWN0aXZlKSB7XG5cdFx0XHR0aWxlLnJldGFpbiA9IHRydWU7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblxuXHRcdH0gZWxzZSBpZiAodGlsZSAmJiB0aWxlLmxvYWRlZCkge1xuXHRcdFx0dGlsZS5yZXRhaW4gPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICh6MiA+IG1pblpvb20pIHtcblx0XHRcdHJldHVybiB0aGlzLl9yZXRhaW5QYXJlbnQoeDIsIHkyLCB6MiwgbWluWm9vbSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9LFxuXG5cdF9yZXRhaW5DaGlsZHJlbjogZnVuY3Rpb24gKHgsIHksIHosIG1heFpvb20pIHtcblxuXHRcdGZvciAodmFyIGkgPSAyICogeDsgaSA8IDIgKiB4ICsgMjsgaSsrKSB7XG5cdFx0XHRmb3IgKHZhciBqID0gMiAqIHk7IGogPCAyICogeSArIDI7IGorKykge1xuXG5cdFx0XHRcdHZhciBjb29yZHMgPSBuZXcgUG9pbnQoaSwgaik7XG5cdFx0XHRcdGNvb3Jkcy56ID0geiArIDE7XG5cblx0XHRcdFx0dmFyIGtleSA9IHRoaXMuX3RpbGVDb29yZHNUb0tleShjb29yZHMpLFxuXHRcdFx0XHQgICAgdGlsZSA9IHRoaXMuX3RpbGVzW2tleV07XG5cblx0XHRcdFx0aWYgKHRpbGUgJiYgdGlsZS5hY3RpdmUpIHtcblx0XHRcdFx0XHR0aWxlLnJldGFpbiA9IHRydWU7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cblx0XHRcdFx0fSBlbHNlIGlmICh0aWxlICYmIHRpbGUubG9hZGVkKSB7XG5cdFx0XHRcdFx0dGlsZS5yZXRhaW4gPSB0cnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKHogKyAxIDwgbWF4Wm9vbSkge1xuXHRcdFx0XHRcdHRoaXMuX3JldGFpbkNoaWxkcmVuKGksIGosIHogKyAxLCBtYXhab29tKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHRfcmVzZXRWaWV3OiBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBhbmltYXRpbmcgPSBlICYmIChlLnBpbmNoIHx8IGUuZmx5VG8pO1xuXHRcdHRoaXMuX3NldFZpZXcodGhpcy5fbWFwLmdldENlbnRlcigpLCB0aGlzLl9tYXAuZ2V0Wm9vbSgpLCBhbmltYXRpbmcsIGFuaW1hdGluZyk7XG5cdH0sXG5cblx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAoZSkge1xuXHRcdHRoaXMuX3NldFZpZXcoZS5jZW50ZXIsIGUuem9vbSwgdHJ1ZSwgZS5ub1VwZGF0ZSk7XG5cdH0sXG5cblx0X2NsYW1wWm9vbTogZnVuY3Rpb24gKHpvb20pIHtcblx0XHR2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcblxuXHRcdGlmICh1bmRlZmluZWQgIT09IG9wdGlvbnMubWluTmF0aXZlWm9vbSAmJiB6b29tIDwgb3B0aW9ucy5taW5OYXRpdmVab29tKSB7XG5cdFx0XHRyZXR1cm4gb3B0aW9ucy5taW5OYXRpdmVab29tO1xuXHRcdH1cblxuXHRcdGlmICh1bmRlZmluZWQgIT09IG9wdGlvbnMubWF4TmF0aXZlWm9vbSAmJiBvcHRpb25zLm1heE5hdGl2ZVpvb20gPCB6b29tKSB7XG5cdFx0XHRyZXR1cm4gb3B0aW9ucy5tYXhOYXRpdmVab29tO1xuXHRcdH1cblxuXHRcdHJldHVybiB6b29tO1xuXHR9LFxuXG5cdF9zZXRWaWV3OiBmdW5jdGlvbiAoY2VudGVyLCB6b29tLCBub1BydW5lLCBub1VwZGF0ZSkge1xuXHRcdHZhciB0aWxlWm9vbSA9IHRoaXMuX2NsYW1wWm9vbShNYXRoLnJvdW5kKHpvb20pKTtcblx0XHRpZiAoKHRoaXMub3B0aW9ucy5tYXhab29tICE9PSB1bmRlZmluZWQgJiYgdGlsZVpvb20gPiB0aGlzLm9wdGlvbnMubWF4Wm9vbSkgfHxcblx0XHQgICAgKHRoaXMub3B0aW9ucy5taW5ab29tICE9PSB1bmRlZmluZWQgJiYgdGlsZVpvb20gPCB0aGlzLm9wdGlvbnMubWluWm9vbSkpIHtcblx0XHRcdHRpbGVab29tID0gdW5kZWZpbmVkO1xuXHRcdH1cblxuXHRcdHZhciB0aWxlWm9vbUNoYW5nZWQgPSB0aGlzLm9wdGlvbnMudXBkYXRlV2hlblpvb21pbmcgJiYgKHRpbGVab29tICE9PSB0aGlzLl90aWxlWm9vbSk7XG5cblx0XHRpZiAoIW5vVXBkYXRlIHx8IHRpbGVab29tQ2hhbmdlZCkge1xuXG5cdFx0XHR0aGlzLl90aWxlWm9vbSA9IHRpbGVab29tO1xuXG5cdFx0XHRpZiAodGhpcy5fYWJvcnRMb2FkaW5nKSB7XG5cdFx0XHRcdHRoaXMuX2Fib3J0TG9hZGluZygpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl91cGRhdGVMZXZlbHMoKTtcblx0XHRcdHRoaXMuX3Jlc2V0R3JpZCgpO1xuXG5cdFx0XHRpZiAodGlsZVpvb20gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHR0aGlzLl91cGRhdGUoY2VudGVyKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCFub1BydW5lKSB7XG5cdFx0XHRcdHRoaXMuX3BydW5lVGlsZXMoKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRmxhZyB0byBwcmV2ZW50IF91cGRhdGVPcGFjaXR5IGZyb20gcHJ1bmluZyB0aWxlcyBkdXJpbmdcblx0XHRcdC8vIGEgem9vbSBhbmltIG9yIGEgcGluY2ggZ2VzdHVyZVxuXHRcdFx0dGhpcy5fbm9QcnVuZSA9ICEhbm9QcnVuZTtcblx0XHR9XG5cblx0XHR0aGlzLl9zZXRab29tVHJhbnNmb3JtcyhjZW50ZXIsIHpvb20pO1xuXHR9LFxuXG5cdF9zZXRab29tVHJhbnNmb3JtczogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xuXHRcdGZvciAodmFyIGkgaW4gdGhpcy5fbGV2ZWxzKSB7XG5cdFx0XHR0aGlzLl9zZXRab29tVHJhbnNmb3JtKHRoaXMuX2xldmVsc1tpXSwgY2VudGVyLCB6b29tKTtcblx0XHR9XG5cdH0sXG5cblx0X3NldFpvb21UcmFuc2Zvcm06IGZ1bmN0aW9uIChsZXZlbCwgY2VudGVyLCB6b29tKSB7XG5cdFx0dmFyIHNjYWxlID0gdGhpcy5fbWFwLmdldFpvb21TY2FsZSh6b29tLCBsZXZlbC56b29tKSxcblx0XHQgICAgdHJhbnNsYXRlID0gbGV2ZWwub3JpZ2luLm11bHRpcGx5Qnkoc2NhbGUpXG5cdFx0ICAgICAgICAuc3VidHJhY3QodGhpcy5fbWFwLl9nZXROZXdQaXhlbE9yaWdpbihjZW50ZXIsIHpvb20pKS5yb3VuZCgpO1xuXG5cdFx0aWYgKGFueTNkKSB7XG5cdFx0XHRzZXRUcmFuc2Zvcm0obGV2ZWwuZWwsIHRyYW5zbGF0ZSwgc2NhbGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzZXRQb3NpdGlvbihsZXZlbC5lbCwgdHJhbnNsYXRlKTtcblx0XHR9XG5cdH0sXG5cblx0X3Jlc2V0R3JpZDogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBtYXAgPSB0aGlzLl9tYXAsXG5cdFx0ICAgIGNycyA9IG1hcC5vcHRpb25zLmNycyxcblx0XHQgICAgdGlsZVNpemUgPSB0aGlzLl90aWxlU2l6ZSA9IHRoaXMuZ2V0VGlsZVNpemUoKSxcblx0XHQgICAgdGlsZVpvb20gPSB0aGlzLl90aWxlWm9vbTtcblxuXHRcdHZhciBib3VuZHMgPSB0aGlzLl9tYXAuZ2V0UGl4ZWxXb3JsZEJvdW5kcyh0aGlzLl90aWxlWm9vbSk7XG5cdFx0aWYgKGJvdW5kcykge1xuXHRcdFx0dGhpcy5fZ2xvYmFsVGlsZVJhbmdlID0gdGhpcy5fcHhCb3VuZHNUb1RpbGVSYW5nZShib3VuZHMpO1xuXHRcdH1cblxuXHRcdHRoaXMuX3dyYXBYID0gY3JzLndyYXBMbmcgJiYgIXRoaXMub3B0aW9ucy5ub1dyYXAgJiYgW1xuXHRcdFx0TWF0aC5mbG9vcihtYXAucHJvamVjdChbMCwgY3JzLndyYXBMbmdbMF1dLCB0aWxlWm9vbSkueCAvIHRpbGVTaXplLngpLFxuXHRcdFx0TWF0aC5jZWlsKG1hcC5wcm9qZWN0KFswLCBjcnMud3JhcExuZ1sxXV0sIHRpbGVab29tKS54IC8gdGlsZVNpemUueSlcblx0XHRdO1xuXHRcdHRoaXMuX3dyYXBZID0gY3JzLndyYXBMYXQgJiYgIXRoaXMub3B0aW9ucy5ub1dyYXAgJiYgW1xuXHRcdFx0TWF0aC5mbG9vcihtYXAucHJvamVjdChbY3JzLndyYXBMYXRbMF0sIDBdLCB0aWxlWm9vbSkueSAvIHRpbGVTaXplLngpLFxuXHRcdFx0TWF0aC5jZWlsKG1hcC5wcm9qZWN0KFtjcnMud3JhcExhdFsxXSwgMF0sIHRpbGVab29tKS55IC8gdGlsZVNpemUueSlcblx0XHRdO1xuXHR9LFxuXG5cdF9vbk1vdmVFbmQ6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoIXRoaXMuX21hcCB8fCB0aGlzLl9tYXAuX2FuaW1hdGluZ1pvb20pIHsgcmV0dXJuOyB9XG5cblx0XHR0aGlzLl91cGRhdGUoKTtcblx0fSxcblxuXHRfZ2V0VGlsZWRQaXhlbEJvdW5kczogZnVuY3Rpb24gKGNlbnRlcikge1xuXHRcdHZhciBtYXAgPSB0aGlzLl9tYXAsXG5cdFx0ICAgIG1hcFpvb20gPSBtYXAuX2FuaW1hdGluZ1pvb20gPyBNYXRoLm1heChtYXAuX2FuaW1hdGVUb1pvb20sIG1hcC5nZXRab29tKCkpIDogbWFwLmdldFpvb20oKSxcblx0XHQgICAgc2NhbGUgPSBtYXAuZ2V0Wm9vbVNjYWxlKG1hcFpvb20sIHRoaXMuX3RpbGVab29tKSxcblx0XHQgICAgcGl4ZWxDZW50ZXIgPSBtYXAucHJvamVjdChjZW50ZXIsIHRoaXMuX3RpbGVab29tKS5mbG9vcigpLFxuXHRcdCAgICBoYWxmU2l6ZSA9IG1hcC5nZXRTaXplKCkuZGl2aWRlQnkoc2NhbGUgKiAyKTtcblxuXHRcdHJldHVybiBuZXcgQm91bmRzKHBpeGVsQ2VudGVyLnN1YnRyYWN0KGhhbGZTaXplKSwgcGl4ZWxDZW50ZXIuYWRkKGhhbGZTaXplKSk7XG5cdH0sXG5cblx0Ly8gUHJpdmF0ZSBtZXRob2QgdG8gbG9hZCB0aWxlcyBpbiB0aGUgZ3JpZCdzIGFjdGl2ZSB6b29tIGxldmVsIGFjY29yZGluZyB0byBtYXAgYm91bmRzXG5cdF91cGRhdGU6IGZ1bmN0aW9uIChjZW50ZXIpIHtcblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwO1xuXHRcdGlmICghbWFwKSB7IHJldHVybjsgfVxuXHRcdHZhciB6b29tID0gdGhpcy5fY2xhbXBab29tKG1hcC5nZXRab29tKCkpO1xuXG5cdFx0aWYgKGNlbnRlciA9PT0gdW5kZWZpbmVkKSB7IGNlbnRlciA9IG1hcC5nZXRDZW50ZXIoKTsgfVxuXHRcdGlmICh0aGlzLl90aWxlWm9vbSA9PT0gdW5kZWZpbmVkKSB7IHJldHVybjsgfVx0Ly8gaWYgb3V0IG9mIG1pbnpvb20vbWF4em9vbVxuXG5cdFx0dmFyIHBpeGVsQm91bmRzID0gdGhpcy5fZ2V0VGlsZWRQaXhlbEJvdW5kcyhjZW50ZXIpLFxuXHRcdCAgICB0aWxlUmFuZ2UgPSB0aGlzLl9weEJvdW5kc1RvVGlsZVJhbmdlKHBpeGVsQm91bmRzKSxcblx0XHQgICAgdGlsZUNlbnRlciA9IHRpbGVSYW5nZS5nZXRDZW50ZXIoKSxcblx0XHQgICAgcXVldWUgPSBbXSxcblx0XHQgICAgbWFyZ2luID0gdGhpcy5vcHRpb25zLmtlZXBCdWZmZXIsXG5cdFx0ICAgIG5vUHJ1bmVSYW5nZSA9IG5ldyBCb3VuZHModGlsZVJhbmdlLmdldEJvdHRvbUxlZnQoKS5zdWJ0cmFjdChbbWFyZ2luLCAtbWFyZ2luXSksXG5cdFx0ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlsZVJhbmdlLmdldFRvcFJpZ2h0KCkuYWRkKFttYXJnaW4sIC1tYXJnaW5dKSk7XG5cblx0XHQvLyBTYW5pdHkgY2hlY2s6IHBhbmljIGlmIHRoZSB0aWxlIHJhbmdlIGNvbnRhaW5zIEluZmluaXR5IHNvbWV3aGVyZS5cblx0XHRpZiAoIShpc0Zpbml0ZSh0aWxlUmFuZ2UubWluLngpICYmXG5cdFx0ICAgICAgaXNGaW5pdGUodGlsZVJhbmdlLm1pbi55KSAmJlxuXHRcdCAgICAgIGlzRmluaXRlKHRpbGVSYW5nZS5tYXgueCkgJiZcblx0XHQgICAgICBpc0Zpbml0ZSh0aWxlUmFuZ2UubWF4LnkpKSkgeyB0aHJvdyBuZXcgRXJyb3IoJ0F0dGVtcHRlZCB0byBsb2FkIGFuIGluZmluaXRlIG51bWJlciBvZiB0aWxlcycpOyB9XG5cblx0XHRmb3IgKHZhciBrZXkgaW4gdGhpcy5fdGlsZXMpIHtcblx0XHRcdHZhciBjID0gdGhpcy5fdGlsZXNba2V5XS5jb29yZHM7XG5cdFx0XHRpZiAoYy56ICE9PSB0aGlzLl90aWxlWm9vbSB8fCAhbm9QcnVuZVJhbmdlLmNvbnRhaW5zKG5ldyBQb2ludChjLngsIGMueSkpKSB7XG5cdFx0XHRcdHRoaXMuX3RpbGVzW2tleV0uY3VycmVudCA9IGZhbHNlO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIF91cGRhdGUganVzdCBsb2FkcyBtb3JlIHRpbGVzLiBJZiB0aGUgdGlsZSB6b29tIGxldmVsIGRpZmZlcnMgdG9vIG11Y2hcblx0XHQvLyBmcm9tIHRoZSBtYXAncywgbGV0IF9zZXRWaWV3IHJlc2V0IGxldmVscyBhbmQgcHJ1bmUgb2xkIHRpbGVzLlxuXHRcdGlmIChNYXRoLmFicyh6b29tIC0gdGhpcy5fdGlsZVpvb20pID4gMSkgeyB0aGlzLl9zZXRWaWV3KGNlbnRlciwgem9vbSk7IHJldHVybjsgfVxuXG5cdFx0Ly8gY3JlYXRlIGEgcXVldWUgb2YgY29vcmRpbmF0ZXMgdG8gbG9hZCB0aWxlcyBmcm9tXG5cdFx0Zm9yICh2YXIgaiA9IHRpbGVSYW5nZS5taW4ueTsgaiA8PSB0aWxlUmFuZ2UubWF4Lnk7IGorKykge1xuXHRcdFx0Zm9yICh2YXIgaSA9IHRpbGVSYW5nZS5taW4ueDsgaSA8PSB0aWxlUmFuZ2UubWF4Lng7IGkrKykge1xuXHRcdFx0XHR2YXIgY29vcmRzID0gbmV3IFBvaW50KGksIGopO1xuXHRcdFx0XHRjb29yZHMueiA9IHRoaXMuX3RpbGVab29tO1xuXG5cdFx0XHRcdGlmICghdGhpcy5faXNWYWxpZFRpbGUoY29vcmRzKSkgeyBjb250aW51ZTsgfVxuXG5cdFx0XHRcdHZhciB0aWxlID0gdGhpcy5fdGlsZXNbdGhpcy5fdGlsZUNvb3Jkc1RvS2V5KGNvb3JkcyldO1xuXHRcdFx0XHRpZiAodGlsZSkge1xuXHRcdFx0XHRcdHRpbGUuY3VycmVudCA9IHRydWU7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cXVldWUucHVzaChjb29yZHMpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gc29ydCB0aWxlIHF1ZXVlIHRvIGxvYWQgdGlsZXMgaW4gb3JkZXIgb2YgdGhlaXIgZGlzdGFuY2UgdG8gY2VudGVyXG5cdFx0cXVldWUuc29ydChmdW5jdGlvbiAoYSwgYikge1xuXHRcdFx0cmV0dXJuIGEuZGlzdGFuY2VUbyh0aWxlQ2VudGVyKSAtIGIuZGlzdGFuY2VUbyh0aWxlQ2VudGVyKTtcblx0XHR9KTtcblxuXHRcdGlmIChxdWV1ZS5sZW5ndGggIT09IDApIHtcblx0XHRcdC8vIGlmIGl0J3MgdGhlIGZpcnN0IGJhdGNoIG9mIHRpbGVzIHRvIGxvYWRcblx0XHRcdGlmICghdGhpcy5fbG9hZGluZykge1xuXHRcdFx0XHR0aGlzLl9sb2FkaW5nID0gdHJ1ZTtcblx0XHRcdFx0Ly8gQGV2ZW50IGxvYWRpbmc6IEV2ZW50XG5cdFx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlIGdyaWQgbGF5ZXIgc3RhcnRzIGxvYWRpbmcgdGlsZXMuXG5cdFx0XHRcdHRoaXMuZmlyZSgnbG9hZGluZycpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBjcmVhdGUgRE9NIGZyYWdtZW50IHRvIGFwcGVuZCB0aWxlcyBpbiBvbmUgYmF0Y2hcblx0XHRcdHZhciBmcmFnbWVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcblxuXHRcdFx0Zm9yIChpID0gMDsgaSA8IHF1ZXVlLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdHRoaXMuX2FkZFRpbGUocXVldWVbaV0sIGZyYWdtZW50KTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5fbGV2ZWwuZWwuYXBwZW5kQ2hpbGQoZnJhZ21lbnQpO1xuXHRcdH1cblx0fSxcblxuXHRfaXNWYWxpZFRpbGU6IGZ1bmN0aW9uIChjb29yZHMpIHtcblx0XHR2YXIgY3JzID0gdGhpcy5fbWFwLm9wdGlvbnMuY3JzO1xuXG5cdFx0aWYgKCFjcnMuaW5maW5pdGUpIHtcblx0XHRcdC8vIGRvbid0IGxvYWQgdGlsZSBpZiBpdCdzIG91dCBvZiBib3VuZHMgYW5kIG5vdCB3cmFwcGVkXG5cdFx0XHR2YXIgYm91bmRzID0gdGhpcy5fZ2xvYmFsVGlsZVJhbmdlO1xuXHRcdFx0aWYgKCghY3JzLndyYXBMbmcgJiYgKGNvb3Jkcy54IDwgYm91bmRzLm1pbi54IHx8IGNvb3Jkcy54ID4gYm91bmRzLm1heC54KSkgfHxcblx0XHRcdCAgICAoIWNycy53cmFwTGF0ICYmIChjb29yZHMueSA8IGJvdW5kcy5taW4ueSB8fCBjb29yZHMueSA+IGJvdW5kcy5tYXgueSkpKSB7IHJldHVybiBmYWxzZTsgfVxuXHRcdH1cblxuXHRcdGlmICghdGhpcy5vcHRpb25zLmJvdW5kcykgeyByZXR1cm4gdHJ1ZTsgfVxuXG5cdFx0Ly8gZG9uJ3QgbG9hZCB0aWxlIGlmIGl0IGRvZXNuJ3QgaW50ZXJzZWN0IHRoZSBib3VuZHMgaW4gb3B0aW9uc1xuXHRcdHZhciB0aWxlQm91bmRzID0gdGhpcy5fdGlsZUNvb3Jkc1RvQm91bmRzKGNvb3Jkcyk7XG5cdFx0cmV0dXJuIHRvTGF0TG5nQm91bmRzKHRoaXMub3B0aW9ucy5ib3VuZHMpLm92ZXJsYXBzKHRpbGVCb3VuZHMpO1xuXHR9LFxuXG5cdF9rZXlUb0JvdW5kczogZnVuY3Rpb24gKGtleSkge1xuXHRcdHJldHVybiB0aGlzLl90aWxlQ29vcmRzVG9Cb3VuZHModGhpcy5fa2V5VG9UaWxlQ29vcmRzKGtleSkpO1xuXHR9LFxuXG5cdF90aWxlQ29vcmRzVG9Od1NlOiBmdW5jdGlvbiAoY29vcmRzKSB7XG5cdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcblx0XHQgICAgdGlsZVNpemUgPSB0aGlzLmdldFRpbGVTaXplKCksXG5cdFx0ICAgIG53UG9pbnQgPSBjb29yZHMuc2NhbGVCeSh0aWxlU2l6ZSksXG5cdFx0ICAgIHNlUG9pbnQgPSBud1BvaW50LmFkZCh0aWxlU2l6ZSksXG5cdFx0ICAgIG53ID0gbWFwLnVucHJvamVjdChud1BvaW50LCBjb29yZHMueiksXG5cdFx0ICAgIHNlID0gbWFwLnVucHJvamVjdChzZVBvaW50LCBjb29yZHMueik7XG5cdFx0cmV0dXJuIFtudywgc2VdO1xuXHR9LFxuXG5cdC8vIGNvbnZlcnRzIHRpbGUgY29vcmRpbmF0ZXMgdG8gaXRzIGdlb2dyYXBoaWNhbCBib3VuZHNcblx0X3RpbGVDb29yZHNUb0JvdW5kczogZnVuY3Rpb24gKGNvb3Jkcykge1xuXHRcdHZhciBicCA9IHRoaXMuX3RpbGVDb29yZHNUb053U2UoY29vcmRzKSxcblx0XHQgICAgYm91bmRzID0gbmV3IExhdExuZ0JvdW5kcyhicFswXSwgYnBbMV0pO1xuXG5cdFx0aWYgKCF0aGlzLm9wdGlvbnMubm9XcmFwKSB7XG5cdFx0XHRib3VuZHMgPSB0aGlzLl9tYXAud3JhcExhdExuZ0JvdW5kcyhib3VuZHMpO1xuXHRcdH1cblx0XHRyZXR1cm4gYm91bmRzO1xuXHR9LFxuXHQvLyBjb252ZXJ0cyB0aWxlIGNvb3JkaW5hdGVzIHRvIGtleSBmb3IgdGhlIHRpbGUgY2FjaGVcblx0X3RpbGVDb29yZHNUb0tleTogZnVuY3Rpb24gKGNvb3Jkcykge1xuXHRcdHJldHVybiBjb29yZHMueCArICc6JyArIGNvb3Jkcy55ICsgJzonICsgY29vcmRzLno7XG5cdH0sXG5cblx0Ly8gY29udmVydHMgdGlsZSBjYWNoZSBrZXkgdG8gY29vcmRpbmF0ZXNcblx0X2tleVRvVGlsZUNvb3JkczogZnVuY3Rpb24gKGtleSkge1xuXHRcdHZhciBrID0ga2V5LnNwbGl0KCc6JyksXG5cdFx0ICAgIGNvb3JkcyA9IG5ldyBQb2ludCgra1swXSwgK2tbMV0pO1xuXHRcdGNvb3Jkcy56ID0gK2tbMl07XG5cdFx0cmV0dXJuIGNvb3Jkcztcblx0fSxcblxuXHRfcmVtb3ZlVGlsZTogZnVuY3Rpb24gKGtleSkge1xuXHRcdHZhciB0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcblx0XHRpZiAoIXRpbGUpIHsgcmV0dXJuOyB9XG5cblx0XHRyZW1vdmUodGlsZS5lbCk7XG5cblx0XHRkZWxldGUgdGhpcy5fdGlsZXNba2V5XTtcblxuXHRcdC8vIEBldmVudCB0aWxldW5sb2FkOiBUaWxlRXZlbnRcblx0XHQvLyBGaXJlZCB3aGVuIGEgdGlsZSBpcyByZW1vdmVkIChlLmcuIHdoZW4gYSB0aWxlIGdvZXMgb2ZmIHRoZSBzY3JlZW4pLlxuXHRcdHRoaXMuZmlyZSgndGlsZXVubG9hZCcsIHtcblx0XHRcdHRpbGU6IHRpbGUuZWwsXG5cdFx0XHRjb29yZHM6IHRoaXMuX2tleVRvVGlsZUNvb3JkcyhrZXkpXG5cdFx0fSk7XG5cdH0sXG5cblx0X2luaXRUaWxlOiBmdW5jdGlvbiAodGlsZSkge1xuXHRcdGFkZENsYXNzKHRpbGUsICdsZWFmbGV0LXRpbGUnKTtcblxuXHRcdHZhciB0aWxlU2l6ZSA9IHRoaXMuZ2V0VGlsZVNpemUoKTtcblx0XHR0aWxlLnN0eWxlLndpZHRoID0gdGlsZVNpemUueCArICdweCc7XG5cdFx0dGlsZS5zdHlsZS5oZWlnaHQgPSB0aWxlU2l6ZS55ICsgJ3B4JztcblxuXHRcdHRpbGUub25zZWxlY3RzdGFydCA9IGZhbHNlRm47XG5cdFx0dGlsZS5vbm1vdXNlbW92ZSA9IGZhbHNlRm47XG5cblx0XHQvLyB1cGRhdGUgb3BhY2l0eSBvbiB0aWxlcyBpbiBJRTctOCBiZWNhdXNlIG9mIGZpbHRlciBpbmhlcml0YW5jZSBwcm9ibGVtc1xuXHRcdGlmIChpZWx0OSAmJiB0aGlzLm9wdGlvbnMub3BhY2l0eSA8IDEpIHtcblx0XHRcdHNldE9wYWNpdHkodGlsZSwgdGhpcy5vcHRpb25zLm9wYWNpdHkpO1xuXHRcdH1cblxuXHRcdC8vIHdpdGhvdXQgdGhpcyBoYWNrLCB0aWxlcyBkaXNhcHBlYXIgYWZ0ZXIgem9vbSBvbiBDaHJvbWUgZm9yIEFuZHJvaWRcblx0XHQvLyBodHRwczovL2dpdGh1Yi5jb20vTGVhZmxldC9MZWFmbGV0L2lzc3Vlcy8yMDc4XG5cdFx0aWYgKGFuZHJvaWQgJiYgIWFuZHJvaWQyMykge1xuXHRcdFx0dGlsZS5zdHlsZS5XZWJraXRCYWNrZmFjZVZpc2liaWxpdHkgPSAnaGlkZGVuJztcblx0XHR9XG5cdH0sXG5cblx0X2FkZFRpbGU6IGZ1bmN0aW9uIChjb29yZHMsIGNvbnRhaW5lcikge1xuXHRcdHZhciB0aWxlUG9zID0gdGhpcy5fZ2V0VGlsZVBvcyhjb29yZHMpLFxuXHRcdCAgICBrZXkgPSB0aGlzLl90aWxlQ29vcmRzVG9LZXkoY29vcmRzKTtcblxuXHRcdHZhciB0aWxlID0gdGhpcy5jcmVhdGVUaWxlKHRoaXMuX3dyYXBDb29yZHMoY29vcmRzKSwgYmluZCh0aGlzLl90aWxlUmVhZHksIHRoaXMsIGNvb3JkcykpO1xuXG5cdFx0dGhpcy5faW5pdFRpbGUodGlsZSk7XG5cblx0XHQvLyBpZiBjcmVhdGVUaWxlIGlzIGRlZmluZWQgd2l0aCBhIHNlY29uZCBhcmd1bWVudCAoXCJkb25lXCIgY2FsbGJhY2spLFxuXHRcdC8vIHdlIGtub3cgdGhhdCB0aWxlIGlzIGFzeW5jIGFuZCB3aWxsIGJlIHJlYWR5IGxhdGVyOyBvdGhlcndpc2Vcblx0XHRpZiAodGhpcy5jcmVhdGVUaWxlLmxlbmd0aCA8IDIpIHtcblx0XHRcdC8vIG1hcmsgdGlsZSBhcyByZWFkeSwgYnV0IGRlbGF5IG9uZSBmcmFtZSBmb3Igb3BhY2l0eSBhbmltYXRpb24gdG8gaGFwcGVuXG5cdFx0XHRyZXF1ZXN0QW5pbUZyYW1lKGJpbmQodGhpcy5fdGlsZVJlYWR5LCB0aGlzLCBjb29yZHMsIG51bGwsIHRpbGUpKTtcblx0XHR9XG5cblx0XHRzZXRQb3NpdGlvbih0aWxlLCB0aWxlUG9zKTtcblxuXHRcdC8vIHNhdmUgdGlsZSBpbiBjYWNoZVxuXHRcdHRoaXMuX3RpbGVzW2tleV0gPSB7XG5cdFx0XHRlbDogdGlsZSxcblx0XHRcdGNvb3JkczogY29vcmRzLFxuXHRcdFx0Y3VycmVudDogdHJ1ZVxuXHRcdH07XG5cblx0XHRjb250YWluZXIuYXBwZW5kQ2hpbGQodGlsZSk7XG5cdFx0Ly8gQGV2ZW50IHRpbGVsb2Fkc3RhcnQ6IFRpbGVFdmVudFxuXHRcdC8vIEZpcmVkIHdoZW4gYSB0aWxlIGlzIHJlcXVlc3RlZCBhbmQgc3RhcnRzIGxvYWRpbmcuXG5cdFx0dGhpcy5maXJlKCd0aWxlbG9hZHN0YXJ0Jywge1xuXHRcdFx0dGlsZTogdGlsZSxcblx0XHRcdGNvb3JkczogY29vcmRzXG5cdFx0fSk7XG5cdH0sXG5cblx0X3RpbGVSZWFkeTogZnVuY3Rpb24gKGNvb3JkcywgZXJyLCB0aWxlKSB7XG5cdFx0aWYgKGVycikge1xuXHRcdFx0Ly8gQGV2ZW50IHRpbGVlcnJvcjogVGlsZUVycm9yRXZlbnRcblx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3IgbG9hZGluZyBhIHRpbGUuXG5cdFx0XHR0aGlzLmZpcmUoJ3RpbGVlcnJvcicsIHtcblx0XHRcdFx0ZXJyb3I6IGVycixcblx0XHRcdFx0dGlsZTogdGlsZSxcblx0XHRcdFx0Y29vcmRzOiBjb29yZHNcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdHZhciBrZXkgPSB0aGlzLl90aWxlQ29vcmRzVG9LZXkoY29vcmRzKTtcblxuXHRcdHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xuXHRcdGlmICghdGlsZSkgeyByZXR1cm47IH1cblxuXHRcdHRpbGUubG9hZGVkID0gK25ldyBEYXRlKCk7XG5cdFx0aWYgKHRoaXMuX21hcC5fZmFkZUFuaW1hdGVkKSB7XG5cdFx0XHRzZXRPcGFjaXR5KHRpbGUuZWwsIDApO1xuXHRcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2ZhZGVGcmFtZSk7XG5cdFx0XHR0aGlzLl9mYWRlRnJhbWUgPSByZXF1ZXN0QW5pbUZyYW1lKHRoaXMuX3VwZGF0ZU9wYWNpdHksIHRoaXMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aWxlLmFjdGl2ZSA9IHRydWU7XG5cdFx0XHR0aGlzLl9wcnVuZVRpbGVzKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCFlcnIpIHtcblx0XHRcdGFkZENsYXNzKHRpbGUuZWwsICdsZWFmbGV0LXRpbGUtbG9hZGVkJyk7XG5cblx0XHRcdC8vIEBldmVudCB0aWxlbG9hZDogVGlsZUV2ZW50XG5cdFx0XHQvLyBGaXJlZCB3aGVuIGEgdGlsZSBsb2Fkcy5cblx0XHRcdHRoaXMuZmlyZSgndGlsZWxvYWQnLCB7XG5cdFx0XHRcdHRpbGU6IHRpbGUuZWwsXG5cdFx0XHRcdGNvb3JkczogY29vcmRzXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5fbm9UaWxlc1RvTG9hZCgpKSB7XG5cdFx0XHR0aGlzLl9sb2FkaW5nID0gZmFsc2U7XG5cdFx0XHQvLyBAZXZlbnQgbG9hZDogRXZlbnRcblx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlIGdyaWQgbGF5ZXIgbG9hZGVkIGFsbCB2aXNpYmxlIHRpbGVzLlxuXHRcdFx0dGhpcy5maXJlKCdsb2FkJyk7XG5cblx0XHRcdGlmIChpZWx0OSB8fCAhdGhpcy5fbWFwLl9mYWRlQW5pbWF0ZWQpIHtcblx0XHRcdFx0cmVxdWVzdEFuaW1GcmFtZSh0aGlzLl9wcnVuZVRpbGVzLCB0aGlzKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIFdhaXQgYSBiaXQgbW9yZSB0aGFuIDAuMiBzZWNzICh0aGUgZHVyYXRpb24gb2YgdGhlIHRpbGUgZmFkZS1pbilcblx0XHRcdFx0Ly8gdG8gdHJpZ2dlciBhIHBydW5pbmcuXG5cdFx0XHRcdHNldFRpbWVvdXQoYmluZCh0aGlzLl9wcnVuZVRpbGVzLCB0aGlzKSwgMjUwKTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0X2dldFRpbGVQb3M6IGZ1bmN0aW9uIChjb29yZHMpIHtcblx0XHRyZXR1cm4gY29vcmRzLnNjYWxlQnkodGhpcy5nZXRUaWxlU2l6ZSgpKS5zdWJ0cmFjdCh0aGlzLl9sZXZlbC5vcmlnaW4pO1xuXHR9LFxuXG5cdF93cmFwQ29vcmRzOiBmdW5jdGlvbiAoY29vcmRzKSB7XG5cdFx0dmFyIG5ld0Nvb3JkcyA9IG5ldyBQb2ludChcblx0XHRcdHRoaXMuX3dyYXBYID8gd3JhcE51bShjb29yZHMueCwgdGhpcy5fd3JhcFgpIDogY29vcmRzLngsXG5cdFx0XHR0aGlzLl93cmFwWSA/IHdyYXBOdW0oY29vcmRzLnksIHRoaXMuX3dyYXBZKSA6IGNvb3Jkcy55KTtcblx0XHRuZXdDb29yZHMueiA9IGNvb3Jkcy56O1xuXHRcdHJldHVybiBuZXdDb29yZHM7XG5cdH0sXG5cblx0X3B4Qm91bmRzVG9UaWxlUmFuZ2U6IGZ1bmN0aW9uIChib3VuZHMpIHtcblx0XHR2YXIgdGlsZVNpemUgPSB0aGlzLmdldFRpbGVTaXplKCk7XG5cdFx0cmV0dXJuIG5ldyBCb3VuZHMoXG5cdFx0XHRib3VuZHMubWluLnVuc2NhbGVCeSh0aWxlU2l6ZSkuZmxvb3IoKSxcblx0XHRcdGJvdW5kcy5tYXgudW5zY2FsZUJ5KHRpbGVTaXplKS5jZWlsKCkuc3VidHJhY3QoWzEsIDFdKSk7XG5cdH0sXG5cblx0X25vVGlsZXNUb0xvYWQ6IGZ1bmN0aW9uICgpIHtcblx0XHRmb3IgKHZhciBrZXkgaW4gdGhpcy5fdGlsZXMpIHtcblx0XHRcdGlmICghdGhpcy5fdGlsZXNba2V5XS5sb2FkZWQpIHsgcmV0dXJuIGZhbHNlOyB9XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG59KTtcblxuLy8gQGZhY3RvcnkgTC5ncmlkTGF5ZXIob3B0aW9ucz86IEdyaWRMYXllciBvcHRpb25zKVxuLy8gQ3JlYXRlcyBhIG5ldyBpbnN0YW5jZSBvZiBHcmlkTGF5ZXIgd2l0aCB0aGUgc3VwcGxpZWQgb3B0aW9ucy5cbmZ1bmN0aW9uIGdyaWRMYXllcihvcHRpb25zKSB7XG5cdHJldHVybiBuZXcgR3JpZExheWVyKG9wdGlvbnMpO1xufVxuXG4vKlxyXG4gKiBAY2xhc3MgVGlsZUxheWVyXHJcbiAqIEBpbmhlcml0cyBHcmlkTGF5ZXJcclxuICogQGFrYSBMLlRpbGVMYXllclxyXG4gKiBVc2VkIHRvIGxvYWQgYW5kIGRpc3BsYXkgdGlsZSBsYXllcnMgb24gdGhlIG1hcC4gTm90ZSB0aGF0IG1vc3QgdGlsZSBzZXJ2ZXJzIHJlcXVpcmUgYXR0cmlidXRpb24sIHdoaWNoIHlvdSBjYW4gc2V0IHVuZGVyIGBMYXllcmAuIEV4dGVuZHMgYEdyaWRMYXllcmAuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIEwudGlsZUxheWVyKCdodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZz97Zm9vfScsIHtmb286ICdiYXInLCBhdHRyaWJ1dGlvbjogJ01hcCBkYXRhICZjb3B5OyA8YSBocmVmPVwiaHR0cHM6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvXCI+T3BlblN0cmVldE1hcDwvYT4gY29udHJpYnV0b3JzLCA8YSBocmVmPVwiaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzIuMC9cIj5DQy1CWS1TQTwvYT4nfSkuYWRkVG8obWFwKTtcclxuICogYGBgXHJcbiAqXHJcbiAqIEBzZWN0aW9uIFVSTCB0ZW1wbGF0ZVxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBBIHN0cmluZyBvZiB0aGUgZm9sbG93aW5nIGZvcm06XHJcbiAqXHJcbiAqIGBgYFxyXG4gKiAnaHR0cDovL3tzfS5zb21lZG9tYWluLmNvbS9ibGFibGEve3p9L3t4fS97eX17cn0ucG5nJ1xyXG4gKiBgYGBcclxuICpcclxuICogYHtzfWAgbWVhbnMgb25lIG9mIHRoZSBhdmFpbGFibGUgc3ViZG9tYWlucyAodXNlZCBzZXF1ZW50aWFsbHkgdG8gaGVscCB3aXRoIGJyb3dzZXIgcGFyYWxsZWwgcmVxdWVzdHMgcGVyIGRvbWFpbiBsaW1pdGF0aW9uOyBzdWJkb21haW4gdmFsdWVzIGFyZSBzcGVjaWZpZWQgaW4gb3B0aW9uczsgYGFgLCBgYmAgb3IgYGNgIGJ5IGRlZmF1bHQsIGNhbiBiZSBvbWl0dGVkKSwgYHt6fWAg4oCUIHpvb20gbGV2ZWwsIGB7eH1gIGFuZCBge3l9YCDigJQgdGlsZSBjb29yZGluYXRlcy4gYHtyfWAgY2FuIGJlIHVzZWQgdG8gYWRkIFwiJmNvbW1hdDsyeFwiIHRvIHRoZSBVUkwgdG8gbG9hZCByZXRpbmEgdGlsZXMuXHJcbiAqXHJcbiAqIFlvdSBjYW4gdXNlIGN1c3RvbSBrZXlzIGluIHRoZSB0ZW1wbGF0ZSwgd2hpY2ggd2lsbCBiZSBbZXZhbHVhdGVkXSgjdXRpbC10ZW1wbGF0ZSkgZnJvbSBUaWxlTGF5ZXIgb3B0aW9ucywgbGlrZSB0aGlzOlxyXG4gKlxyXG4gKiBgYGBcclxuICogTC50aWxlTGF5ZXIoJ2h0dHA6Ly97c30uc29tZWRvbWFpbi5jb20ve2Zvb30ve3p9L3t4fS97eX0ucG5nJywge2ZvbzogJ2Jhcid9KTtcclxuICogYGBgXHJcbiAqL1xyXG5cclxuXHJcbnZhciBUaWxlTGF5ZXIgPSBHcmlkTGF5ZXIuZXh0ZW5kKHtcclxuXHJcblx0Ly8gQHNlY3Rpb25cclxuXHQvLyBAYWthIFRpbGVMYXllciBvcHRpb25zXHJcblx0b3B0aW9uczoge1xyXG5cdFx0Ly8gQG9wdGlvbiBtaW5ab29tOiBOdW1iZXIgPSAwXHJcblx0XHQvLyBUaGUgbWluaW11bSB6b29tIGxldmVsIGRvd24gdG8gd2hpY2ggdGhpcyBsYXllciB3aWxsIGJlIGRpc3BsYXllZCAoaW5jbHVzaXZlKS5cclxuXHRcdG1pblpvb206IDAsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBtYXhab29tOiBOdW1iZXIgPSAxOFxyXG5cdFx0Ly8gVGhlIG1heGltdW0gem9vbSBsZXZlbCB1cCB0byB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmUgZGlzcGxheWVkIChpbmNsdXNpdmUpLlxyXG5cdFx0bWF4Wm9vbTogMTgsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBzdWJkb21haW5zOiBTdHJpbmd8U3RyaW5nW10gPSAnYWJjJ1xyXG5cdFx0Ly8gU3ViZG9tYWlucyBvZiB0aGUgdGlsZSBzZXJ2aWNlLiBDYW4gYmUgcGFzc2VkIGluIHRoZSBmb3JtIG9mIG9uZSBzdHJpbmcgKHdoZXJlIGVhY2ggbGV0dGVyIGlzIGEgc3ViZG9tYWluIG5hbWUpIG9yIGFuIGFycmF5IG9mIHN0cmluZ3MuXHJcblx0XHRzdWJkb21haW5zOiAnYWJjJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGVycm9yVGlsZVVybDogU3RyaW5nID0gJydcclxuXHRcdC8vIFVSTCB0byB0aGUgdGlsZSBpbWFnZSB0byBzaG93IGluIHBsYWNlIG9mIHRoZSB0aWxlIHRoYXQgZmFpbGVkIHRvIGxvYWQuXHJcblx0XHRlcnJvclRpbGVVcmw6ICcnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gem9vbU9mZnNldDogTnVtYmVyID0gMFxyXG5cdFx0Ly8gVGhlIHpvb20gbnVtYmVyIHVzZWQgaW4gdGlsZSBVUkxzIHdpbGwgYmUgb2Zmc2V0IHdpdGggdGhpcyB2YWx1ZS5cclxuXHRcdHpvb21PZmZzZXQ6IDAsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB0bXM6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gSWYgYHRydWVgLCBpbnZlcnNlcyBZIGF4aXMgbnVtYmVyaW5nIGZvciB0aWxlcyAodHVybiB0aGlzIG9uIGZvciBbVE1TXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9UaWxlX01hcF9TZXJ2aWNlKSBzZXJ2aWNlcykuXHJcblx0XHR0bXM6IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gem9vbVJldmVyc2U6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gSWYgc2V0IHRvIHRydWUsIHRoZSB6b29tIG51bWJlciB1c2VkIGluIHRpbGUgVVJMcyB3aWxsIGJlIHJldmVyc2VkIChgbWF4Wm9vbSAtIHpvb21gIGluc3RlYWQgb2YgYHpvb21gKVxyXG5cdFx0em9vbVJldmVyc2U6IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gZGV0ZWN0UmV0aW5hOiBCb29sZWFuID0gZmFsc2VcclxuXHRcdC8vIElmIGB0cnVlYCBhbmQgdXNlciBpcyBvbiBhIHJldGluYSBkaXNwbGF5LCBpdCB3aWxsIHJlcXVlc3QgZm91ciB0aWxlcyBvZiBoYWxmIHRoZSBzcGVjaWZpZWQgc2l6ZSBhbmQgYSBiaWdnZXIgem9vbSBsZXZlbCBpbiBwbGFjZSBvZiBvbmUgdG8gdXRpbGl6ZSB0aGUgaGlnaCByZXNvbHV0aW9uLlxyXG5cdFx0ZGV0ZWN0UmV0aW5hOiBmYWxzZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGNyb3NzT3JpZ2luOiBCb29sZWFufFN0cmluZyA9IGZhbHNlXHJcblx0XHQvLyBXaGV0aGVyIHRoZSBjcm9zc09yaWdpbiBhdHRyaWJ1dGUgd2lsbCBiZSBhZGRlZCB0byB0aGUgdGlsZXMuXHJcblx0XHQvLyBJZiBhIFN0cmluZyBpcyBwcm92aWRlZCwgYWxsIHRpbGVzIHdpbGwgaGF2ZSB0aGVpciBjcm9zc09yaWdpbiBhdHRyaWJ1dGUgc2V0IHRvIHRoZSBTdHJpbmcgcHJvdmlkZWQuIFRoaXMgaXMgbmVlZGVkIGlmIHlvdSB3YW50IHRvIGFjY2VzcyB0aWxlIHBpeGVsIGRhdGEuXHJcblx0XHQvLyBSZWZlciB0byBbQ09SUyBTZXR0aW5nc10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9DT1JTX3NldHRpbmdzX2F0dHJpYnV0ZXMpIGZvciB2YWxpZCBTdHJpbmcgdmFsdWVzLlxyXG5cdFx0Y3Jvc3NPcmlnaW46IGZhbHNlXHJcblx0fSxcclxuXHJcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKHVybCwgb3B0aW9ucykge1xyXG5cclxuXHRcdHRoaXMuX3VybCA9IHVybDtcclxuXHJcblx0XHRvcHRpb25zID0gc2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcblx0XHQvLyBkZXRlY3RpbmcgcmV0aW5hIGRpc3BsYXlzLCBhZGp1c3RpbmcgdGlsZVNpemUgYW5kIHpvb20gbGV2ZWxzXHJcblx0XHRpZiAob3B0aW9ucy5kZXRlY3RSZXRpbmEgJiYgcmV0aW5hICYmIG9wdGlvbnMubWF4Wm9vbSA+IDApIHtcclxuXHJcblx0XHRcdG9wdGlvbnMudGlsZVNpemUgPSBNYXRoLmZsb29yKG9wdGlvbnMudGlsZVNpemUgLyAyKTtcclxuXHJcblx0XHRcdGlmICghb3B0aW9ucy56b29tUmV2ZXJzZSkge1xyXG5cdFx0XHRcdG9wdGlvbnMuem9vbU9mZnNldCsrO1xyXG5cdFx0XHRcdG9wdGlvbnMubWF4Wm9vbS0tO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdG9wdGlvbnMuem9vbU9mZnNldC0tO1xyXG5cdFx0XHRcdG9wdGlvbnMubWluWm9vbSsrO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRvcHRpb25zLm1pblpvb20gPSBNYXRoLm1heCgwLCBvcHRpb25zLm1pblpvb20pO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0eXBlb2Ygb3B0aW9ucy5zdWJkb21haW5zID09PSAnc3RyaW5nJykge1xyXG5cdFx0XHRvcHRpb25zLnN1YmRvbWFpbnMgPSBvcHRpb25zLnN1YmRvbWFpbnMuc3BsaXQoJycpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIGZvciBodHRwczovL2dpdGh1Yi5jb20vTGVhZmxldC9MZWFmbGV0L2lzc3Vlcy8xMzdcclxuXHRcdGlmICghYW5kcm9pZCkge1xyXG5cdFx0XHR0aGlzLm9uKCd0aWxldW5sb2FkJywgdGhpcy5fb25UaWxlUmVtb3ZlKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNldFVybCh1cmw6IFN0cmluZywgbm9SZWRyYXc/OiBCb29sZWFuKTogdGhpc1xyXG5cdC8vIFVwZGF0ZXMgdGhlIGxheWVyJ3MgVVJMIHRlbXBsYXRlIGFuZCByZWRyYXdzIGl0ICh1bmxlc3MgYG5vUmVkcmF3YCBpcyBzZXQgdG8gYHRydWVgKS5cclxuXHQvLyBJZiB0aGUgVVJMIGRvZXMgbm90IGNoYW5nZSwgdGhlIGxheWVyIHdpbGwgbm90IGJlIHJlZHJhd24gdW5sZXNzXHJcblx0Ly8gdGhlIG5vUmVkcmF3IHBhcmFtZXRlciBpcyBzZXQgdG8gZmFsc2UuXHJcblx0c2V0VXJsOiBmdW5jdGlvbiAodXJsLCBub1JlZHJhdykge1xyXG5cdFx0aWYgKHRoaXMuX3VybCA9PT0gdXJsICYmIG5vUmVkcmF3ID09PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0bm9SZWRyYXcgPSB0cnVlO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX3VybCA9IHVybDtcclxuXHJcblx0XHRpZiAoIW5vUmVkcmF3KSB7XHJcblx0XHRcdHRoaXMucmVkcmF3KCk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGNyZWF0ZVRpbGUoY29vcmRzOiBPYmplY3QsIGRvbmU/OiBGdW5jdGlvbik6IEhUTUxFbGVtZW50XHJcblx0Ly8gQ2FsbGVkIG9ubHkgaW50ZXJuYWxseSwgb3ZlcnJpZGVzIEdyaWRMYXllcidzIFtgY3JlYXRlVGlsZSgpYF0oI2dyaWRsYXllci1jcmVhdGV0aWxlKVxyXG5cdC8vIHRvIHJldHVybiBhbiBgPGltZz5gIEhUTUwgZWxlbWVudCB3aXRoIHRoZSBhcHByb3ByaWF0ZSBpbWFnZSBVUkwgZ2l2ZW4gYGNvb3Jkc2AuIFRoZSBgZG9uZWBcclxuXHQvLyBjYWxsYmFjayBpcyBjYWxsZWQgd2hlbiB0aGUgdGlsZSBoYXMgYmVlbiBsb2FkZWQuXHJcblx0Y3JlYXRlVGlsZTogZnVuY3Rpb24gKGNvb3JkcywgZG9uZSkge1xyXG5cdFx0dmFyIHRpbGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcclxuXHJcblx0XHRvbih0aWxlLCAnbG9hZCcsIGJpbmQodGhpcy5fdGlsZU9uTG9hZCwgdGhpcywgZG9uZSwgdGlsZSkpO1xyXG5cdFx0b24odGlsZSwgJ2Vycm9yJywgYmluZCh0aGlzLl90aWxlT25FcnJvciwgdGhpcywgZG9uZSwgdGlsZSkpO1xyXG5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW4gfHwgdGhpcy5vcHRpb25zLmNyb3NzT3JpZ2luID09PSAnJykge1xyXG5cdFx0XHR0aWxlLmNyb3NzT3JpZ2luID0gdGhpcy5vcHRpb25zLmNyb3NzT3JpZ2luID09PSB0cnVlID8gJycgOiB0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW47XHJcblx0XHR9XHJcblxyXG5cdFx0LypcclxuXHRcdCBBbHQgdGFnIGlzIHNldCB0byBlbXB0eSBzdHJpbmcgdG8ga2VlcCBzY3JlZW4gcmVhZGVycyBmcm9tIHJlYWRpbmcgVVJMIGFuZCBmb3IgY29tcGxpYW5jZSByZWFzb25zXHJcblx0XHQgaHR0cDovL3d3dy53My5vcmcvVFIvV0NBRzIwLVRFQ0hTL0g2N1xyXG5cdFx0Ki9cclxuXHRcdHRpbGUuYWx0ID0gJyc7XHJcblxyXG5cdFx0LypcclxuXHRcdCBTZXQgcm9sZT1cInByZXNlbnRhdGlvblwiIHRvIGZvcmNlIHNjcmVlbiByZWFkZXJzIHRvIGlnbm9yZSB0aGlzXHJcblx0XHQgaHR0cHM6Ly93d3cudzMub3JnL1RSL3dhaS1hcmlhL3JvbGVzI3RleHRhbHRlcm5hdGl2ZWNvbXB1dGF0aW9uXHJcblx0XHQqL1xyXG5cdFx0dGlsZS5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAncHJlc2VudGF0aW9uJyk7XHJcblxyXG5cdFx0dGlsZS5zcmMgPSB0aGlzLmdldFRpbGVVcmwoY29vcmRzKTtcclxuXHJcblx0XHRyZXR1cm4gdGlsZTtcclxuXHR9LFxyXG5cclxuXHQvLyBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xyXG5cdC8vIEB1bmluaGVyaXRhYmxlXHJcblx0Ly8gTGF5ZXJzIGV4dGVuZGluZyBgVGlsZUxheWVyYCBtaWdodCByZWltcGxlbWVudCB0aGUgZm9sbG93aW5nIG1ldGhvZC5cclxuXHQvLyBAbWV0aG9kIGdldFRpbGVVcmwoY29vcmRzOiBPYmplY3QpOiBTdHJpbmdcclxuXHQvLyBDYWxsZWQgb25seSBpbnRlcm5hbGx5LCByZXR1cm5zIHRoZSBVUkwgZm9yIGEgdGlsZSBnaXZlbiBpdHMgY29vcmRpbmF0ZXMuXHJcblx0Ly8gQ2xhc3NlcyBleHRlbmRpbmcgYFRpbGVMYXllcmAgY2FuIG92ZXJyaWRlIHRoaXMgZnVuY3Rpb24gdG8gcHJvdmlkZSBjdXN0b20gdGlsZSBVUkwgbmFtaW5nIHNjaGVtZXMuXHJcblx0Z2V0VGlsZVVybDogZnVuY3Rpb24gKGNvb3Jkcykge1xyXG5cdFx0dmFyIGRhdGEgPSB7XHJcblx0XHRcdHI6IHJldGluYSA/ICdAMngnIDogJycsXHJcblx0XHRcdHM6IHRoaXMuX2dldFN1YmRvbWFpbihjb29yZHMpLFxyXG5cdFx0XHR4OiBjb29yZHMueCxcclxuXHRcdFx0eTogY29vcmRzLnksXHJcblx0XHRcdHo6IHRoaXMuX2dldFpvb21Gb3JVcmwoKVxyXG5cdFx0fTtcclxuXHRcdGlmICh0aGlzLl9tYXAgJiYgIXRoaXMuX21hcC5vcHRpb25zLmNycy5pbmZpbml0ZSkge1xyXG5cdFx0XHR2YXIgaW52ZXJ0ZWRZID0gdGhpcy5fZ2xvYmFsVGlsZVJhbmdlLm1heC55IC0gY29vcmRzLnk7XHJcblx0XHRcdGlmICh0aGlzLm9wdGlvbnMudG1zKSB7XHJcblx0XHRcdFx0ZGF0YVsneSddID0gaW52ZXJ0ZWRZO1xyXG5cdFx0XHR9XHJcblx0XHRcdGRhdGFbJy15J10gPSBpbnZlcnRlZFk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRlbXBsYXRlKHRoaXMuX3VybCwgZXh0ZW5kKGRhdGEsIHRoaXMub3B0aW9ucykpO1xyXG5cdH0sXHJcblxyXG5cdF90aWxlT25Mb2FkOiBmdW5jdGlvbiAoZG9uZSwgdGlsZSkge1xyXG5cdFx0Ly8gRm9yIGh0dHBzOi8vZ2l0aHViLmNvbS9MZWFmbGV0L0xlYWZsZXQvaXNzdWVzLzMzMzJcclxuXHRcdGlmIChpZWx0OSkge1xyXG5cdFx0XHRzZXRUaW1lb3V0KGJpbmQoZG9uZSwgdGhpcywgbnVsbCwgdGlsZSksIDApO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0ZG9uZShudWxsLCB0aWxlKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfdGlsZU9uRXJyb3I6IGZ1bmN0aW9uIChkb25lLCB0aWxlLCBlKSB7XHJcblx0XHR2YXIgZXJyb3JVcmwgPSB0aGlzLm9wdGlvbnMuZXJyb3JUaWxlVXJsO1xyXG5cdFx0aWYgKGVycm9yVXJsICYmIHRpbGUuZ2V0QXR0cmlidXRlKCdzcmMnKSAhPT0gZXJyb3JVcmwpIHtcclxuXHRcdFx0dGlsZS5zcmMgPSBlcnJvclVybDtcclxuXHRcdH1cclxuXHRcdGRvbmUoZSwgdGlsZSk7XHJcblx0fSxcclxuXHJcblx0X29uVGlsZVJlbW92ZTogZnVuY3Rpb24gKGUpIHtcclxuXHRcdGUudGlsZS5vbmxvYWQgPSBudWxsO1xyXG5cdH0sXHJcblxyXG5cdF9nZXRab29tRm9yVXJsOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgem9vbSA9IHRoaXMuX3RpbGVab29tLFxyXG5cdFx0bWF4Wm9vbSA9IHRoaXMub3B0aW9ucy5tYXhab29tLFxyXG5cdFx0em9vbVJldmVyc2UgPSB0aGlzLm9wdGlvbnMuem9vbVJldmVyc2UsXHJcblx0XHR6b29tT2Zmc2V0ID0gdGhpcy5vcHRpb25zLnpvb21PZmZzZXQ7XHJcblxyXG5cdFx0aWYgKHpvb21SZXZlcnNlKSB7XHJcblx0XHRcdHpvb20gPSBtYXhab29tIC0gem9vbTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gem9vbSArIHpvb21PZmZzZXQ7XHJcblx0fSxcclxuXHJcblx0X2dldFN1YmRvbWFpbjogZnVuY3Rpb24gKHRpbGVQb2ludCkge1xyXG5cdFx0dmFyIGluZGV4ID0gTWF0aC5hYnModGlsZVBvaW50LnggKyB0aWxlUG9pbnQueSkgJSB0aGlzLm9wdGlvbnMuc3ViZG9tYWlucy5sZW5ndGg7XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLnN1YmRvbWFpbnNbaW5kZXhdO1xyXG5cdH0sXHJcblxyXG5cdC8vIHN0b3BzIGxvYWRpbmcgYWxsIHRpbGVzIGluIHRoZSBiYWNrZ3JvdW5kIGxheWVyXHJcblx0X2Fib3J0TG9hZGluZzogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGksIHRpbGU7XHJcblx0XHRmb3IgKGkgaW4gdGhpcy5fdGlsZXMpIHtcclxuXHRcdFx0aWYgKHRoaXMuX3RpbGVzW2ldLmNvb3Jkcy56ICE9PSB0aGlzLl90aWxlWm9vbSkge1xyXG5cdFx0XHRcdHRpbGUgPSB0aGlzLl90aWxlc1tpXS5lbDtcclxuXHJcblx0XHRcdFx0dGlsZS5vbmxvYWQgPSBmYWxzZUZuO1xyXG5cdFx0XHRcdHRpbGUub25lcnJvciA9IGZhbHNlRm47XHJcblxyXG5cdFx0XHRcdGlmICghdGlsZS5jb21wbGV0ZSkge1xyXG5cdFx0XHRcdFx0dGlsZS5zcmMgPSBlbXB0eUltYWdlVXJsO1xyXG5cdFx0XHRcdFx0cmVtb3ZlKHRpbGUpO1xyXG5cdFx0XHRcdFx0ZGVsZXRlIHRoaXMuX3RpbGVzW2ldO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9yZW1vdmVUaWxlOiBmdW5jdGlvbiAoa2V5KSB7XHJcblx0XHR2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW2tleV07XHJcblx0XHRpZiAoIXRpbGUpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0Ly8gQ2FuY2VscyBhbnkgcGVuZGluZyBodHRwIHJlcXVlc3RzIGFzc29jaWF0ZWQgd2l0aCB0aGUgdGlsZVxyXG5cdFx0Ly8gdW5sZXNzIHdlJ3JlIG9uIEFuZHJvaWQncyBzdG9jayBicm93c2VyLFxyXG5cdFx0Ly8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9MZWFmbGV0L0xlYWZsZXQvaXNzdWVzLzEzN1xyXG5cdFx0aWYgKCFhbmRyb2lkU3RvY2spIHtcclxuXHRcdFx0dGlsZS5lbC5zZXRBdHRyaWJ1dGUoJ3NyYycsIGVtcHR5SW1hZ2VVcmwpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBHcmlkTGF5ZXIucHJvdG90eXBlLl9yZW1vdmVUaWxlLmNhbGwodGhpcywga2V5KTtcclxuXHR9LFxyXG5cclxuXHRfdGlsZVJlYWR5OiBmdW5jdGlvbiAoY29vcmRzLCBlcnIsIHRpbGUpIHtcclxuXHRcdGlmICghdGhpcy5fbWFwIHx8ICh0aWxlICYmIHRpbGUuZ2V0QXR0cmlidXRlKCdzcmMnKSA9PT0gZW1wdHlJbWFnZVVybCkpIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBHcmlkTGF5ZXIucHJvdG90eXBlLl90aWxlUmVhZHkuY2FsbCh0aGlzLCBjb29yZHMsIGVyciwgdGlsZSk7XHJcblx0fVxyXG59KTtcclxuXHJcblxyXG4vLyBAZmFjdG9yeSBMLnRpbGVsYXllcih1cmxUZW1wbGF0ZTogU3RyaW5nLCBvcHRpb25zPzogVGlsZUxheWVyIG9wdGlvbnMpXHJcbi8vIEluc3RhbnRpYXRlcyBhIHRpbGUgbGF5ZXIgb2JqZWN0IGdpdmVuIGEgYFVSTCB0ZW1wbGF0ZWAgYW5kIG9wdGlvbmFsbHkgYW4gb3B0aW9ucyBvYmplY3QuXHJcblxyXG5mdW5jdGlvbiB0aWxlTGF5ZXIodXJsLCBvcHRpb25zKSB7XHJcblx0cmV0dXJuIG5ldyBUaWxlTGF5ZXIodXJsLCBvcHRpb25zKTtcclxufVxuXG4vKlxyXG4gKiBAY2xhc3MgVGlsZUxheWVyLldNU1xyXG4gKiBAaW5oZXJpdHMgVGlsZUxheWVyXHJcbiAqIEBha2EgTC5UaWxlTGF5ZXIuV01TXHJcbiAqIFVzZWQgdG8gZGlzcGxheSBbV01TXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9XZWJfTWFwX1NlcnZpY2UpIHNlcnZpY2VzIGFzIHRpbGUgbGF5ZXJzIG9uIHRoZSBtYXAuIEV4dGVuZHMgYFRpbGVMYXllcmAuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBuZXhyYWQgPSBMLnRpbGVMYXllci53bXMoXCJodHRwOi8vbWVzb25ldC5hZ3Jvbi5pYXN0YXRlLmVkdS9jZ2ktYmluL3dtcy9uZXhyYWQvbjByLmNnaVwiLCB7XHJcbiAqIFx0bGF5ZXJzOiAnbmV4cmFkLW4wci05MDA5MTMnLFxyXG4gKiBcdGZvcm1hdDogJ2ltYWdlL3BuZycsXHJcbiAqIFx0dHJhbnNwYXJlbnQ6IHRydWUsXHJcbiAqIFx0YXR0cmlidXRpb246IFwiV2VhdGhlciBkYXRhIMKpIDIwMTIgSUVNIE5leHJhZFwiXHJcbiAqIH0pO1xyXG4gKiBgYGBcclxuICovXHJcblxyXG52YXIgVGlsZUxheWVyV01TID0gVGlsZUxheWVyLmV4dGVuZCh7XHJcblxyXG5cdC8vIEBzZWN0aW9uXHJcblx0Ly8gQGFrYSBUaWxlTGF5ZXIuV01TIG9wdGlvbnNcclxuXHQvLyBJZiBhbnkgY3VzdG9tIG9wdGlvbnMgbm90IGRvY3VtZW50ZWQgaGVyZSBhcmUgdXNlZCwgdGhleSB3aWxsIGJlIHNlbnQgdG8gdGhlXHJcblx0Ly8gV01TIHNlcnZlciBhcyBleHRyYSBwYXJhbWV0ZXJzIGluIGVhY2ggcmVxdWVzdCBVUkwuIFRoaXMgY2FuIGJlIHVzZWZ1bCBmb3JcclxuXHQvLyBbbm9uLXN0YW5kYXJkIHZlbmRvciBXTVMgcGFyYW1ldGVyc10oaHR0cDovL2RvY3MuZ2Vvc2VydmVyLm9yZy9zdGFibGUvZW4vdXNlci9zZXJ2aWNlcy93bXMvdmVuZG9yLmh0bWwpLlxyXG5cdGRlZmF1bHRXbXNQYXJhbXM6IHtcclxuXHRcdHNlcnZpY2U6ICdXTVMnLFxyXG5cdFx0cmVxdWVzdDogJ0dldE1hcCcsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBsYXllcnM6IFN0cmluZyA9ICcnXHJcblx0XHQvLyAqKihyZXF1aXJlZCkqKiBDb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBXTVMgbGF5ZXJzIHRvIHNob3cuXHJcblx0XHRsYXllcnM6ICcnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gc3R5bGVzOiBTdHJpbmcgPSAnJ1xyXG5cdFx0Ly8gQ29tbWEtc2VwYXJhdGVkIGxpc3Qgb2YgV01TIHN0eWxlcy5cclxuXHRcdHN0eWxlczogJycsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBmb3JtYXQ6IFN0cmluZyA9ICdpbWFnZS9qcGVnJ1xyXG5cdFx0Ly8gV01TIGltYWdlIGZvcm1hdCAodXNlIGAnaW1hZ2UvcG5nJ2AgZm9yIGxheWVycyB3aXRoIHRyYW5zcGFyZW5jeSkuXHJcblx0XHRmb3JtYXQ6ICdpbWFnZS9qcGVnJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHRyYW5zcGFyZW50OiBCb29sZWFuID0gZmFsc2VcclxuXHRcdC8vIElmIGB0cnVlYCwgdGhlIFdNUyBzZXJ2aWNlIHdpbGwgcmV0dXJuIGltYWdlcyB3aXRoIHRyYW5zcGFyZW5jeS5cclxuXHRcdHRyYW5zcGFyZW50OiBmYWxzZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHZlcnNpb246IFN0cmluZyA9ICcxLjEuMSdcclxuXHRcdC8vIFZlcnNpb24gb2YgdGhlIFdNUyBzZXJ2aWNlIHRvIHVzZVxyXG5cdFx0dmVyc2lvbjogJzEuMS4xJ1xyXG5cdH0sXHJcblxyXG5cdG9wdGlvbnM6IHtcclxuXHRcdC8vIEBvcHRpb24gY3JzOiBDUlMgPSBudWxsXHJcblx0XHQvLyBDb29yZGluYXRlIFJlZmVyZW5jZSBTeXN0ZW0gdG8gdXNlIGZvciB0aGUgV01TIHJlcXVlc3RzLCBkZWZhdWx0cyB0b1xyXG5cdFx0Ly8gbWFwIENSUy4gRG9uJ3QgY2hhbmdlIHRoaXMgaWYgeW91J3JlIG5vdCBzdXJlIHdoYXQgaXQgbWVhbnMuXHJcblx0XHRjcnM6IG51bGwsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB1cHBlcmNhc2U6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gSWYgYHRydWVgLCBXTVMgcmVxdWVzdCBwYXJhbWV0ZXIga2V5cyB3aWxsIGJlIHVwcGVyY2FzZS5cclxuXHRcdHVwcGVyY2FzZTogZmFsc2VcclxuXHR9LFxyXG5cclxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAodXJsLCBvcHRpb25zKSB7XHJcblxyXG5cdFx0dGhpcy5fdXJsID0gdXJsO1xyXG5cclxuXHRcdHZhciB3bXNQYXJhbXMgPSBleHRlbmQoe30sIHRoaXMuZGVmYXVsdFdtc1BhcmFtcyk7XHJcblxyXG5cdFx0Ly8gYWxsIGtleXMgdGhhdCBhcmUgbm90IFRpbGVMYXllciBvcHRpb25zIGdvIHRvIFdNUyBwYXJhbXNcclxuXHRcdGZvciAodmFyIGkgaW4gb3B0aW9ucykge1xyXG5cdFx0XHRpZiAoIShpIGluIHRoaXMub3B0aW9ucykpIHtcclxuXHRcdFx0XHR3bXNQYXJhbXNbaV0gPSBvcHRpb25zW2ldO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0b3B0aW9ucyA9IHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblxyXG5cdFx0dmFyIHJlYWxSZXRpbmEgPSBvcHRpb25zLmRldGVjdFJldGluYSAmJiByZXRpbmEgPyAyIDogMTtcclxuXHRcdHZhciB0aWxlU2l6ZSA9IHRoaXMuZ2V0VGlsZVNpemUoKTtcclxuXHRcdHdtc1BhcmFtcy53aWR0aCA9IHRpbGVTaXplLnggKiByZWFsUmV0aW5hO1xyXG5cdFx0d21zUGFyYW1zLmhlaWdodCA9IHRpbGVTaXplLnkgKiByZWFsUmV0aW5hO1xyXG5cclxuXHRcdHRoaXMud21zUGFyYW1zID0gd21zUGFyYW1zO1xyXG5cdH0sXHJcblxyXG5cdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XHJcblxyXG5cdFx0dGhpcy5fY3JzID0gdGhpcy5vcHRpb25zLmNycyB8fCBtYXAub3B0aW9ucy5jcnM7XHJcblx0XHR0aGlzLl93bXNWZXJzaW9uID0gcGFyc2VGbG9hdCh0aGlzLndtc1BhcmFtcy52ZXJzaW9uKTtcclxuXHJcblx0XHR2YXIgcHJvamVjdGlvbktleSA9IHRoaXMuX3dtc1ZlcnNpb24gPj0gMS4zID8gJ2NycycgOiAnc3JzJztcclxuXHRcdHRoaXMud21zUGFyYW1zW3Byb2plY3Rpb25LZXldID0gdGhpcy5fY3JzLmNvZGU7XHJcblxyXG5cdFx0VGlsZUxheWVyLnByb3RvdHlwZS5vbkFkZC5jYWxsKHRoaXMsIG1hcCk7XHJcblx0fSxcclxuXHJcblx0Z2V0VGlsZVVybDogZnVuY3Rpb24gKGNvb3Jkcykge1xyXG5cclxuXHRcdHZhciB0aWxlQm91bmRzID0gdGhpcy5fdGlsZUNvb3Jkc1RvTndTZShjb29yZHMpLFxyXG5cdFx0ICAgIGNycyA9IHRoaXMuX2NycyxcclxuXHRcdCAgICBib3VuZHMgPSB0b0JvdW5kcyhjcnMucHJvamVjdCh0aWxlQm91bmRzWzBdKSwgY3JzLnByb2plY3QodGlsZUJvdW5kc1sxXSkpLFxyXG5cdFx0ICAgIG1pbiA9IGJvdW5kcy5taW4sXHJcblx0XHQgICAgbWF4ID0gYm91bmRzLm1heCxcclxuXHRcdCAgICBiYm94ID0gKHRoaXMuX3dtc1ZlcnNpb24gPj0gMS4zICYmIHRoaXMuX2NycyA9PT0gRVBTRzQzMjYgP1xyXG5cdFx0ICAgIFttaW4ueSwgbWluLngsIG1heC55LCBtYXgueF0gOlxyXG5cdFx0ICAgIFttaW4ueCwgbWluLnksIG1heC54LCBtYXgueV0pLmpvaW4oJywnKSxcclxuXHRcdCAgICB1cmwgPSBUaWxlTGF5ZXIucHJvdG90eXBlLmdldFRpbGVVcmwuY2FsbCh0aGlzLCBjb29yZHMpO1xyXG5cdFx0cmV0dXJuIHVybCArXHJcblx0XHRcdGdldFBhcmFtU3RyaW5nKHRoaXMud21zUGFyYW1zLCB1cmwsIHRoaXMub3B0aW9ucy51cHBlcmNhc2UpICtcclxuXHRcdFx0KHRoaXMub3B0aW9ucy51cHBlcmNhc2UgPyAnJkJCT1g9JyA6ICcmYmJveD0nKSArIGJib3g7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRQYXJhbXMocGFyYW1zOiBPYmplY3QsIG5vUmVkcmF3PzogQm9vbGVhbik6IHRoaXNcclxuXHQvLyBNZXJnZXMgYW4gb2JqZWN0IHdpdGggdGhlIG5ldyBwYXJhbWV0ZXJzIGFuZCByZS1yZXF1ZXN0cyB0aWxlcyBvbiB0aGUgY3VycmVudCBzY3JlZW4gKHVubGVzcyBgbm9SZWRyYXdgIHdhcyBzZXQgdG8gdHJ1ZSkuXHJcblx0c2V0UGFyYW1zOiBmdW5jdGlvbiAocGFyYW1zLCBub1JlZHJhdykge1xyXG5cclxuXHRcdGV4dGVuZCh0aGlzLndtc1BhcmFtcywgcGFyYW1zKTtcclxuXHJcblx0XHRpZiAoIW5vUmVkcmF3KSB7XHJcblx0XHRcdHRoaXMucmVkcmF3KCk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fVxyXG59KTtcclxuXHJcblxyXG4vLyBAZmFjdG9yeSBMLnRpbGVMYXllci53bXMoYmFzZVVybDogU3RyaW5nLCBvcHRpb25zOiBUaWxlTGF5ZXIuV01TIG9wdGlvbnMpXHJcbi8vIEluc3RhbnRpYXRlcyBhIFdNUyB0aWxlIGxheWVyIG9iamVjdCBnaXZlbiBhIGJhc2UgVVJMIG9mIHRoZSBXTVMgc2VydmljZSBhbmQgYSBXTVMgcGFyYW1ldGVycy9vcHRpb25zIG9iamVjdC5cclxuZnVuY3Rpb24gdGlsZUxheWVyV01TKHVybCwgb3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgVGlsZUxheWVyV01TKHVybCwgb3B0aW9ucyk7XHJcbn1cblxuVGlsZUxheWVyLldNUyA9IFRpbGVMYXllcldNUztcbnRpbGVMYXllci53bXMgPSB0aWxlTGF5ZXJXTVM7XG5cbi8qXG4gKiBAY2xhc3MgUmVuZGVyZXJcbiAqIEBpbmhlcml0cyBMYXllclxuICogQGFrYSBMLlJlbmRlcmVyXG4gKlxuICogQmFzZSBjbGFzcyBmb3IgdmVjdG9yIHJlbmRlcmVyIGltcGxlbWVudGF0aW9ucyAoYFNWR2AsIGBDYW52YXNgKS4gSGFuZGxlcyB0aGVcbiAqIERPTSBjb250YWluZXIgb2YgdGhlIHJlbmRlcmVyLCBpdHMgYm91bmRzLCBhbmQgaXRzIHpvb20gYW5pbWF0aW9uLlxuICpcbiAqIEEgYFJlbmRlcmVyYCB3b3JrcyBhcyBhbiBpbXBsaWNpdCBsYXllciBncm91cCBmb3IgYWxsIGBQYXRoYHMgLSB0aGUgcmVuZGVyZXJcbiAqIGl0c2VsZiBjYW4gYmUgYWRkZWQgb3IgcmVtb3ZlZCB0byB0aGUgbWFwLiBBbGwgcGF0aHMgdXNlIGEgcmVuZGVyZXIsIHdoaWNoIGNhblxuICogYmUgaW1wbGljaXQgKHRoZSBtYXAgd2lsbCBkZWNpZGUgdGhlIHR5cGUgb2YgcmVuZGVyZXIgYW5kIHVzZSBpdCBhdXRvbWF0aWNhbGx5KVxuICogb3IgZXhwbGljaXQgKHVzaW5nIHRoZSBbYHJlbmRlcmVyYF0oI3BhdGgtcmVuZGVyZXIpIG9wdGlvbiBvZiB0aGUgcGF0aCkuXG4gKlxuICogRG8gbm90IHVzZSB0aGlzIGNsYXNzIGRpcmVjdGx5LCB1c2UgYFNWR2AgYW5kIGBDYW52YXNgIGluc3RlYWQuXG4gKlxuICogQGV2ZW50IHVwZGF0ZTogRXZlbnRcbiAqIEZpcmVkIHdoZW4gdGhlIHJlbmRlcmVyIHVwZGF0ZXMgaXRzIGJvdW5kcywgY2VudGVyIGFuZCB6b29tLCBmb3IgZXhhbXBsZSB3aGVuXG4gKiBpdHMgbWFwIGhhcyBtb3ZlZFxuICovXG5cbnZhciBSZW5kZXJlciA9IExheWVyLmV4dGVuZCh7XG5cblx0Ly8gQHNlY3Rpb25cblx0Ly8gQGFrYSBSZW5kZXJlciBvcHRpb25zXG5cdG9wdGlvbnM6IHtcblx0XHQvLyBAb3B0aW9uIHBhZGRpbmc6IE51bWJlciA9IDAuMVxuXHRcdC8vIEhvdyBtdWNoIHRvIGV4dGVuZCB0aGUgY2xpcCBhcmVhIGFyb3VuZCB0aGUgbWFwIHZpZXcgKHJlbGF0aXZlIHRvIGl0cyBzaXplKVxuXHRcdC8vIGUuZy4gMC4xIHdvdWxkIGJlIDEwJSBvZiBtYXAgdmlldyBpbiBlYWNoIGRpcmVjdGlvblxuXHRcdHBhZGRpbmc6IDAuMSxcblxuXHRcdC8vIEBvcHRpb24gdG9sZXJhbmNlOiBOdW1iZXIgPSAwXG5cdFx0Ly8gSG93IG11Y2ggdG8gZXh0ZW5kIGNsaWNrIHRvbGVyYW5jZSByb3VuZCBhIHBhdGgvb2JqZWN0IG9uIHRoZSBtYXBcblx0XHR0b2xlcmFuY2UgOiAwXG5cdH0sXG5cblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xuXHRcdHN0YW1wKHRoaXMpO1xuXHRcdHRoaXMuX2xheWVycyA9IHRoaXMuX2xheWVycyB8fCB7fTtcblx0fSxcblxuXHRvbkFkZDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICghdGhpcy5fY29udGFpbmVyKSB7XG5cdFx0XHR0aGlzLl9pbml0Q29udGFpbmVyKCk7IC8vIGRlZmluZWQgYnkgcmVuZGVyZXIgaW1wbGVtZW50YXRpb25zXG5cblx0XHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcblx0XHRcdFx0YWRkQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC16b29tLWFuaW1hdGVkJyk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5nZXRQYW5lKCkuYXBwZW5kQ2hpbGQodGhpcy5fY29udGFpbmVyKTtcblx0XHR0aGlzLl91cGRhdGUoKTtcblx0XHR0aGlzLm9uKCd1cGRhdGUnLCB0aGlzLl91cGRhdGVQYXRocywgdGhpcyk7XG5cdH0sXG5cblx0b25SZW1vdmU6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLm9mZigndXBkYXRlJywgdGhpcy5fdXBkYXRlUGF0aHMsIHRoaXMpO1xuXHRcdHRoaXMuX2Rlc3Ryb3lDb250YWluZXIoKTtcblx0fSxcblxuXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgZXZlbnRzID0ge1xuXHRcdFx0dmlld3Jlc2V0OiB0aGlzLl9yZXNldCxcblx0XHRcdHpvb206IHRoaXMuX29uWm9vbSxcblx0XHRcdG1vdmVlbmQ6IHRoaXMuX3VwZGF0ZSxcblx0XHRcdHpvb21lbmQ6IHRoaXMuX29uWm9vbUVuZFxuXHRcdH07XG5cdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xuXHRcdFx0ZXZlbnRzLnpvb21hbmltID0gdGhpcy5fb25BbmltWm9vbTtcblx0XHR9XG5cdFx0cmV0dXJuIGV2ZW50cztcblx0fSxcblxuXHRfb25BbmltWm9vbTogZnVuY3Rpb24gKGV2KSB7XG5cdFx0dGhpcy5fdXBkYXRlVHJhbnNmb3JtKGV2LmNlbnRlciwgZXYuem9vbSk7XG5cdH0sXG5cblx0X29uWm9vbTogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3VwZGF0ZVRyYW5zZm9ybSh0aGlzLl9tYXAuZ2V0Q2VudGVyKCksIHRoaXMuX21hcC5nZXRab29tKCkpO1xuXHR9LFxuXG5cdF91cGRhdGVUcmFuc2Zvcm06IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20pIHtcblx0XHR2YXIgc2NhbGUgPSB0aGlzLl9tYXAuZ2V0Wm9vbVNjYWxlKHpvb20sIHRoaXMuX3pvb20pLFxuXHRcdCAgICBwb3NpdGlvbiA9IGdldFBvc2l0aW9uKHRoaXMuX2NvbnRhaW5lciksXG5cdFx0ICAgIHZpZXdIYWxmID0gdGhpcy5fbWFwLmdldFNpemUoKS5tdWx0aXBseUJ5KDAuNSArIHRoaXMub3B0aW9ucy5wYWRkaW5nKSxcblx0XHQgICAgY3VycmVudENlbnRlclBvaW50ID0gdGhpcy5fbWFwLnByb2plY3QodGhpcy5fY2VudGVyLCB6b29tKSxcblx0XHQgICAgZGVzdENlbnRlclBvaW50ID0gdGhpcy5fbWFwLnByb2plY3QoY2VudGVyLCB6b29tKSxcblx0XHQgICAgY2VudGVyT2Zmc2V0ID0gZGVzdENlbnRlclBvaW50LnN1YnRyYWN0KGN1cnJlbnRDZW50ZXJQb2ludCksXG5cblx0XHQgICAgdG9wTGVmdE9mZnNldCA9IHZpZXdIYWxmLm11bHRpcGx5QnkoLXNjYWxlKS5hZGQocG9zaXRpb24pLmFkZCh2aWV3SGFsZikuc3VidHJhY3QoY2VudGVyT2Zmc2V0KTtcblxuXHRcdGlmIChhbnkzZCkge1xuXHRcdFx0c2V0VHJhbnNmb3JtKHRoaXMuX2NvbnRhaW5lciwgdG9wTGVmdE9mZnNldCwgc2NhbGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzZXRQb3NpdGlvbih0aGlzLl9jb250YWluZXIsIHRvcExlZnRPZmZzZXQpO1xuXHRcdH1cblx0fSxcblxuXHRfcmVzZXQ6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl91cGRhdGUoKTtcblx0XHR0aGlzLl91cGRhdGVUcmFuc2Zvcm0odGhpcy5fY2VudGVyLCB0aGlzLl96b29tKTtcblxuXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuXHRcdFx0dGhpcy5fbGF5ZXJzW2lkXS5fcmVzZXQoKTtcblx0XHR9XG5cdH0sXG5cblx0X29uWm9vbUVuZDogZnVuY3Rpb24gKCkge1xuXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuXHRcdFx0dGhpcy5fbGF5ZXJzW2lkXS5fcHJvamVjdCgpO1xuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlUGF0aHM6IGZ1bmN0aW9uICgpIHtcblx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9sYXllcnMpIHtcblx0XHRcdHRoaXMuX2xheWVyc1tpZF0uX3VwZGF0ZSgpO1xuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0Ly8gVXBkYXRlIHBpeGVsIGJvdW5kcyBvZiByZW5kZXJlciBjb250YWluZXIgKGZvciBwb3NpdGlvbmluZy9zaXppbmcvY2xpcHBpbmcgbGF0ZXIpXG5cdFx0Ly8gU3ViY2xhc3NlcyBhcmUgcmVzcG9uc2libGUgb2YgZmlyaW5nIHRoZSAndXBkYXRlJyBldmVudC5cblx0XHR2YXIgcCA9IHRoaXMub3B0aW9ucy5wYWRkaW5nLFxuXHRcdCAgICBzaXplID0gdGhpcy5fbWFwLmdldFNpemUoKSxcblx0XHQgICAgbWluID0gdGhpcy5fbWFwLmNvbnRhaW5lclBvaW50VG9MYXllclBvaW50KHNpemUubXVsdGlwbHlCeSgtcCkpLnJvdW5kKCk7XG5cblx0XHR0aGlzLl9ib3VuZHMgPSBuZXcgQm91bmRzKG1pbiwgbWluLmFkZChzaXplLm11bHRpcGx5QnkoMSArIHAgKiAyKSkucm91bmQoKSk7XG5cblx0XHR0aGlzLl9jZW50ZXIgPSB0aGlzLl9tYXAuZ2V0Q2VudGVyKCk7XG5cdFx0dGhpcy5fem9vbSA9IHRoaXMuX21hcC5nZXRab29tKCk7XG5cdH1cbn0pO1xuXG4vKlxuICogQGNsYXNzIENhbnZhc1xuICogQGluaGVyaXRzIFJlbmRlcmVyXG4gKiBAYWthIEwuQ2FudmFzXG4gKlxuICogQWxsb3dzIHZlY3RvciBsYXllcnMgdG8gYmUgZGlzcGxheWVkIHdpdGggW2A8Y2FudmFzPmBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9DYW52YXNfQVBJKS5cbiAqIEluaGVyaXRzIGBSZW5kZXJlcmAuXG4gKlxuICogRHVlIHRvIFt0ZWNobmljYWwgbGltaXRhdGlvbnNdKGh0dHA6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPWNhbnZhcyksIENhbnZhcyBpcyBub3RcbiAqIGF2YWlsYWJsZSBpbiBhbGwgd2ViIGJyb3dzZXJzLCBub3RhYmx5IElFOCwgYW5kIG92ZXJsYXBwaW5nIGdlb21ldHJpZXMgbWlnaHRcbiAqIG5vdCBkaXNwbGF5IHByb3Blcmx5IGluIHNvbWUgZWRnZSBjYXNlcy5cbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIFVzZSBDYW52YXMgYnkgZGVmYXVsdCBmb3IgYWxsIHBhdGhzIGluIHRoZSBtYXA6XG4gKlxuICogYGBganNcbiAqIHZhciBtYXAgPSBMLm1hcCgnbWFwJywge1xuICogXHRyZW5kZXJlcjogTC5jYW52YXMoKVxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBVc2UgYSBDYW52YXMgcmVuZGVyZXIgd2l0aCBleHRyYSBwYWRkaW5nIGZvciBzcGVjaWZpYyB2ZWN0b3IgZ2VvbWV0cmllczpcbiAqXG4gKiBgYGBqc1xuICogdmFyIG1hcCA9IEwubWFwKCdtYXAnKTtcbiAqIHZhciBteVJlbmRlcmVyID0gTC5jYW52YXMoeyBwYWRkaW5nOiAwLjUgfSk7XG4gKiB2YXIgbGluZSA9IEwucG9seWxpbmUoIGNvb3JkaW5hdGVzLCB7IHJlbmRlcmVyOiBteVJlbmRlcmVyIH0gKTtcbiAqIHZhciBjaXJjbGUgPSBMLmNpcmNsZSggY2VudGVyLCB7IHJlbmRlcmVyOiBteVJlbmRlcmVyIH0gKTtcbiAqIGBgYFxuICovXG5cbnZhciBDYW52YXMgPSBSZW5kZXJlci5leHRlbmQoe1xuXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgZXZlbnRzID0gUmVuZGVyZXIucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xuXHRcdGV2ZW50cy52aWV3cHJlcmVzZXQgPSB0aGlzLl9vblZpZXdQcmVSZXNldDtcblx0XHRyZXR1cm4gZXZlbnRzO1xuXHR9LFxuXG5cdF9vblZpZXdQcmVSZXNldDogZnVuY3Rpb24gKCkge1xuXHRcdC8vIFNldCBhIGZsYWcgc28gdGhhdCBhIHZpZXdwcmVyZXNldCttb3ZlZW5kK3ZpZXdyZXNldCBvbmx5IHVwZGF0ZXMmcmVkcmF3cyBvbmNlXG5cdFx0dGhpcy5fcG9zdHBvbmVVcGRhdGVQYXRocyA9IHRydWU7XG5cdH0sXG5cblx0b25BZGQ6IGZ1bmN0aW9uICgpIHtcblx0XHRSZW5kZXJlci5wcm90b3R5cGUub25BZGQuY2FsbCh0aGlzKTtcblxuXHRcdC8vIFJlZHJhdyB2ZWN0b3JzIHNpbmNlIGNhbnZhcyBpcyBjbGVhcmVkIHVwb24gcmVtb3ZhbCxcblx0XHQvLyBpbiBjYXNlIG9mIHJlbW92aW5nIHRoZSByZW5kZXJlciBpdHNlbGYgZnJvbSB0aGUgbWFwLlxuXHRcdHRoaXMuX2RyYXcoKTtcblx0fSxcblxuXHRfaW5pdENvbnRhaW5lcjogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcblxuXHRcdG9uKGNvbnRhaW5lciwgJ21vdXNlbW92ZScsIHRocm90dGxlKHRoaXMuX29uTW91c2VNb3ZlLCAzMiwgdGhpcyksIHRoaXMpO1xuXHRcdG9uKGNvbnRhaW5lciwgJ2NsaWNrIGRibGNsaWNrIG1vdXNlZG93biBtb3VzZXVwIGNvbnRleHRtZW51JywgdGhpcy5fb25DbGljaywgdGhpcyk7XG5cdFx0b24oY29udGFpbmVyLCAnbW91c2VvdXQnLCB0aGlzLl9oYW5kbGVNb3VzZU91dCwgdGhpcyk7XG5cblx0XHR0aGlzLl9jdHggPSBjb250YWluZXIuZ2V0Q29udGV4dCgnMmQnKTtcblx0fSxcblxuXHRfZGVzdHJveUNvbnRhaW5lcjogZnVuY3Rpb24gKCkge1xuXHRcdGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9yZWRyYXdSZXF1ZXN0KTtcblx0XHRkZWxldGUgdGhpcy5fY3R4O1xuXHRcdHJlbW92ZSh0aGlzLl9jb250YWluZXIpO1xuXHRcdG9mZih0aGlzLl9jb250YWluZXIpO1xuXHRcdGRlbGV0ZSB0aGlzLl9jb250YWluZXI7XG5cdH0sXG5cblx0X3VwZGF0ZVBhdGhzOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX3Bvc3Rwb25lVXBkYXRlUGF0aHMpIHsgcmV0dXJuOyB9XG5cblx0XHR2YXIgbGF5ZXI7XG5cdFx0dGhpcy5fcmVkcmF3Qm91bmRzID0gbnVsbDtcblx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9sYXllcnMpIHtcblx0XHRcdGxheWVyID0gdGhpcy5fbGF5ZXJzW2lkXTtcblx0XHRcdGxheWVyLl91cGRhdGUoKTtcblx0XHR9XG5cdFx0dGhpcy5fcmVkcmF3KCk7XG5cdH0sXG5cblx0X3VwZGF0ZTogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9tYXAuX2FuaW1hdGluZ1pvb20gJiYgdGhpcy5fYm91bmRzKSB7IHJldHVybjsgfVxuXG5cdFx0UmVuZGVyZXIucHJvdG90eXBlLl91cGRhdGUuY2FsbCh0aGlzKTtcblxuXHRcdHZhciBiID0gdGhpcy5fYm91bmRzLFxuXHRcdCAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIsXG5cdFx0ICAgIHNpemUgPSBiLmdldFNpemUoKSxcblx0XHQgICAgbSA9IHJldGluYSA/IDIgOiAxO1xuXG5cdFx0c2V0UG9zaXRpb24oY29udGFpbmVyLCBiLm1pbik7XG5cblx0XHQvLyBzZXQgY2FudmFzIHNpemUgKGFsc28gY2xlYXJpbmcgaXQpOyB1c2UgZG91YmxlIHNpemUgb24gcmV0aW5hXG5cdFx0Y29udGFpbmVyLndpZHRoID0gbSAqIHNpemUueDtcblx0XHRjb250YWluZXIuaGVpZ2h0ID0gbSAqIHNpemUueTtcblx0XHRjb250YWluZXIuc3R5bGUud2lkdGggPSBzaXplLnggKyAncHgnO1xuXHRcdGNvbnRhaW5lci5zdHlsZS5oZWlnaHQgPSBzaXplLnkgKyAncHgnO1xuXG5cdFx0aWYgKHJldGluYSkge1xuXHRcdFx0dGhpcy5fY3R4LnNjYWxlKDIsIDIpO1xuXHRcdH1cblxuXHRcdC8vIHRyYW5zbGF0ZSBzbyB3ZSB1c2UgdGhlIHNhbWUgcGF0aCBjb29yZGluYXRlcyBhZnRlciBjYW52YXMgZWxlbWVudCBtb3Zlc1xuXHRcdHRoaXMuX2N0eC50cmFuc2xhdGUoLWIubWluLngsIC1iLm1pbi55KTtcblxuXHRcdC8vIFRlbGwgcGF0aHMgdG8gcmVkcmF3IHRoZW1zZWx2ZXNcblx0XHR0aGlzLmZpcmUoJ3VwZGF0ZScpO1xuXHR9LFxuXG5cdF9yZXNldDogZnVuY3Rpb24gKCkge1xuXHRcdFJlbmRlcmVyLnByb3RvdHlwZS5fcmVzZXQuY2FsbCh0aGlzKTtcblxuXHRcdGlmICh0aGlzLl9wb3N0cG9uZVVwZGF0ZVBhdGhzKSB7XG5cdFx0XHR0aGlzLl9wb3N0cG9uZVVwZGF0ZVBhdGhzID0gZmFsc2U7XG5cdFx0XHR0aGlzLl91cGRhdGVQYXRocygpO1xuXHRcdH1cblx0fSxcblxuXHRfaW5pdFBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHRoaXMuX3VwZGF0ZURhc2hBcnJheShsYXllcik7XG5cdFx0dGhpcy5fbGF5ZXJzW3N0YW1wKGxheWVyKV0gPSBsYXllcjtcblxuXHRcdHZhciBvcmRlciA9IGxheWVyLl9vcmRlciA9IHtcblx0XHRcdGxheWVyOiBsYXllcixcblx0XHRcdHByZXY6IHRoaXMuX2RyYXdMYXN0LFxuXHRcdFx0bmV4dDogbnVsbFxuXHRcdH07XG5cdFx0aWYgKHRoaXMuX2RyYXdMYXN0KSB7IHRoaXMuX2RyYXdMYXN0Lm5leHQgPSBvcmRlcjsgfVxuXHRcdHRoaXMuX2RyYXdMYXN0ID0gb3JkZXI7XG5cdFx0dGhpcy5fZHJhd0ZpcnN0ID0gdGhpcy5fZHJhd0ZpcnN0IHx8IHRoaXMuX2RyYXdMYXN0O1xuXHR9LFxuXG5cdF9hZGRQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcblx0fSxcblxuXHRfcmVtb3ZlUGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dmFyIG9yZGVyID0gbGF5ZXIuX29yZGVyO1xuXHRcdHZhciBuZXh0ID0gb3JkZXIubmV4dDtcblx0XHR2YXIgcHJldiA9IG9yZGVyLnByZXY7XG5cblx0XHRpZiAobmV4dCkge1xuXHRcdFx0bmV4dC5wcmV2ID0gcHJldjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5fZHJhd0xhc3QgPSBwcmV2O1xuXHRcdH1cblx0XHRpZiAocHJldikge1xuXHRcdFx0cHJldi5uZXh0ID0gbmV4dDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5fZHJhd0ZpcnN0ID0gbmV4dDtcblx0XHR9XG5cblx0XHRkZWxldGUgbGF5ZXIuX29yZGVyO1xuXG5cdFx0ZGVsZXRlIHRoaXMuX2xheWVyc1tzdGFtcChsYXllcildO1xuXG5cdFx0dGhpcy5fcmVxdWVzdFJlZHJhdyhsYXllcik7XG5cdH0sXG5cblx0X3VwZGF0ZVBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdC8vIFJlZHJhdyB0aGUgdW5pb24gb2YgdGhlIGxheWVyJ3Mgb2xkIHBpeGVsXG5cdFx0Ly8gYm91bmRzIGFuZCB0aGUgbmV3IHBpeGVsIGJvdW5kcy5cblx0XHR0aGlzLl9leHRlbmRSZWRyYXdCb3VuZHMobGF5ZXIpO1xuXHRcdGxheWVyLl9wcm9qZWN0KCk7XG5cdFx0bGF5ZXIuX3VwZGF0ZSgpO1xuXHRcdC8vIFRoZSByZWRyYXcgd2lsbCBleHRlbmQgdGhlIHJlZHJhdyBib3VuZHNcblx0XHQvLyB3aXRoIHRoZSBuZXcgcGl4ZWwgYm91bmRzLlxuXHRcdHRoaXMuX3JlcXVlc3RSZWRyYXcobGF5ZXIpO1xuXHR9LFxuXG5cdF91cGRhdGVTdHlsZTogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dGhpcy5fdXBkYXRlRGFzaEFycmF5KGxheWVyKTtcblx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcblx0fSxcblxuXHRfdXBkYXRlRGFzaEFycmF5OiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHRpZiAodHlwZW9mIGxheWVyLm9wdGlvbnMuZGFzaEFycmF5ID09PSAnc3RyaW5nJykge1xuXHRcdFx0dmFyIHBhcnRzID0gbGF5ZXIub3B0aW9ucy5kYXNoQXJyYXkuc3BsaXQoL1ssIF0rLyksXG5cdFx0XHQgICAgZGFzaEFycmF5ID0gW10sXG5cdFx0XHQgICAgZGFzaFZhbHVlLFxuXHRcdFx0ICAgIGk7XG5cdFx0XHRmb3IgKGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0ZGFzaFZhbHVlID0gTnVtYmVyKHBhcnRzW2ldKTtcblx0XHRcdFx0Ly8gSWdub3JlIGRhc2ggYXJyYXkgY29udGFpbmluZyBpbnZhbGlkIGxlbmd0aHNcblx0XHRcdFx0aWYgKGlzTmFOKGRhc2hWYWx1ZSkpIHsgcmV0dXJuOyB9XG5cdFx0XHRcdGRhc2hBcnJheS5wdXNoKGRhc2hWYWx1ZSk7XG5cdFx0XHR9XG5cdFx0XHRsYXllci5vcHRpb25zLl9kYXNoQXJyYXkgPSBkYXNoQXJyYXk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGxheWVyLm9wdGlvbnMuX2Rhc2hBcnJheSA9IGxheWVyLm9wdGlvbnMuZGFzaEFycmF5O1xuXHRcdH1cblx0fSxcblxuXHRfcmVxdWVzdFJlZHJhdzogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cblx0XHR0aGlzLl9leHRlbmRSZWRyYXdCb3VuZHMobGF5ZXIpO1xuXHRcdHRoaXMuX3JlZHJhd1JlcXVlc3QgPSB0aGlzLl9yZWRyYXdSZXF1ZXN0IHx8IHJlcXVlc3RBbmltRnJhbWUodGhpcy5fcmVkcmF3LCB0aGlzKTtcblx0fSxcblxuXHRfZXh0ZW5kUmVkcmF3Qm91bmRzOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHRpZiAobGF5ZXIuX3B4Qm91bmRzKSB7XG5cdFx0XHR2YXIgcGFkZGluZyA9IChsYXllci5vcHRpb25zLndlaWdodCB8fCAwKSArIDE7XG5cdFx0XHR0aGlzLl9yZWRyYXdCb3VuZHMgPSB0aGlzLl9yZWRyYXdCb3VuZHMgfHwgbmV3IEJvdW5kcygpO1xuXHRcdFx0dGhpcy5fcmVkcmF3Qm91bmRzLmV4dGVuZChsYXllci5fcHhCb3VuZHMubWluLnN1YnRyYWN0KFtwYWRkaW5nLCBwYWRkaW5nXSkpO1xuXHRcdFx0dGhpcy5fcmVkcmF3Qm91bmRzLmV4dGVuZChsYXllci5fcHhCb3VuZHMubWF4LmFkZChbcGFkZGluZywgcGFkZGluZ10pKTtcblx0XHR9XG5cdH0sXG5cblx0X3JlZHJhdzogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3JlZHJhd1JlcXVlc3QgPSBudWxsO1xuXG5cdFx0aWYgKHRoaXMuX3JlZHJhd0JvdW5kcykge1xuXHRcdFx0dGhpcy5fcmVkcmF3Qm91bmRzLm1pbi5fZmxvb3IoKTtcblx0XHRcdHRoaXMuX3JlZHJhd0JvdW5kcy5tYXguX2NlaWwoKTtcblx0XHR9XG5cblx0XHR0aGlzLl9jbGVhcigpOyAvLyBjbGVhciBsYXllcnMgaW4gcmVkcmF3IGJvdW5kc1xuXHRcdHRoaXMuX2RyYXcoKTsgLy8gZHJhdyBsYXllcnNcblxuXHRcdHRoaXMuX3JlZHJhd0JvdW5kcyA9IG51bGw7XG5cdH0sXG5cblx0X2NsZWFyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGJvdW5kcyA9IHRoaXMuX3JlZHJhd0JvdW5kcztcblx0XHRpZiAoYm91bmRzKSB7XG5cdFx0XHR2YXIgc2l6ZSA9IGJvdW5kcy5nZXRTaXplKCk7XG5cdFx0XHR0aGlzLl9jdHguY2xlYXJSZWN0KGJvdW5kcy5taW4ueCwgYm91bmRzLm1pbi55LCBzaXplLngsIHNpemUueSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX2N0eC5jbGVhclJlY3QoMCwgMCwgdGhpcy5fY29udGFpbmVyLndpZHRoLCB0aGlzLl9jb250YWluZXIuaGVpZ2h0KTtcblx0XHR9XG5cdH0sXG5cblx0X2RyYXc6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbGF5ZXIsIGJvdW5kcyA9IHRoaXMuX3JlZHJhd0JvdW5kcztcblx0XHR0aGlzLl9jdHguc2F2ZSgpO1xuXHRcdGlmIChib3VuZHMpIHtcblx0XHRcdHZhciBzaXplID0gYm91bmRzLmdldFNpemUoKTtcblx0XHRcdHRoaXMuX2N0eC5iZWdpblBhdGgoKTtcblx0XHRcdHRoaXMuX2N0eC5yZWN0KGJvdW5kcy5taW4ueCwgYm91bmRzLm1pbi55LCBzaXplLngsIHNpemUueSk7XG5cdFx0XHR0aGlzLl9jdHguY2xpcCgpO1xuXHRcdH1cblxuXHRcdHRoaXMuX2RyYXdpbmcgPSB0cnVlO1xuXG5cdFx0Zm9yICh2YXIgb3JkZXIgPSB0aGlzLl9kcmF3Rmlyc3Q7IG9yZGVyOyBvcmRlciA9IG9yZGVyLm5leHQpIHtcblx0XHRcdGxheWVyID0gb3JkZXIubGF5ZXI7XG5cdFx0XHRpZiAoIWJvdW5kcyB8fCAobGF5ZXIuX3B4Qm91bmRzICYmIGxheWVyLl9weEJvdW5kcy5pbnRlcnNlY3RzKGJvdW5kcykpKSB7XG5cdFx0XHRcdGxheWVyLl91cGRhdGVQYXRoKCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5fZHJhd2luZyA9IGZhbHNlO1xuXG5cdFx0dGhpcy5fY3R4LnJlc3RvcmUoKTsgIC8vIFJlc3RvcmUgc3RhdGUgYmVmb3JlIGNsaXBwaW5nLlxuXHR9LFxuXG5cdF91cGRhdGVQb2x5OiBmdW5jdGlvbiAobGF5ZXIsIGNsb3NlZCkge1xuXHRcdGlmICghdGhpcy5fZHJhd2luZykgeyByZXR1cm47IH1cblxuXHRcdHZhciBpLCBqLCBsZW4yLCBwLFxuXHRcdCAgICBwYXJ0cyA9IGxheWVyLl9wYXJ0cyxcblx0XHQgICAgbGVuID0gcGFydHMubGVuZ3RoLFxuXHRcdCAgICBjdHggPSB0aGlzLl9jdHg7XG5cblx0XHRpZiAoIWxlbikgeyByZXR1cm47IH1cblxuXHRcdGN0eC5iZWdpblBhdGgoKTtcblxuXHRcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0Zm9yIChqID0gMCwgbGVuMiA9IHBhcnRzW2ldLmxlbmd0aDsgaiA8IGxlbjI7IGorKykge1xuXHRcdFx0XHRwID0gcGFydHNbaV1bal07XG5cdFx0XHRcdGN0eFtqID8gJ2xpbmVUbycgOiAnbW92ZVRvJ10ocC54LCBwLnkpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGNsb3NlZCkge1xuXHRcdFx0XHRjdHguY2xvc2VQYXRoKCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5fZmlsbFN0cm9rZShjdHgsIGxheWVyKTtcblxuXHRcdC8vIFRPRE8gb3B0aW1pemF0aW9uOiAxIGZpbGwvc3Ryb2tlIGZvciBhbGwgZmVhdHVyZXMgd2l0aCBlcXVhbCBzdHlsZSBpbnN0ZWFkIG9mIDEgZm9yIGVhY2ggZmVhdHVyZVxuXHR9LFxuXG5cdF91cGRhdGVDaXJjbGU6IGZ1bmN0aW9uIChsYXllcikge1xuXG5cdFx0aWYgKCF0aGlzLl9kcmF3aW5nIHx8IGxheWVyLl9lbXB0eSgpKSB7IHJldHVybjsgfVxuXG5cdFx0dmFyIHAgPSBsYXllci5fcG9pbnQsXG5cdFx0ICAgIGN0eCA9IHRoaXMuX2N0eCxcblx0XHQgICAgciA9IE1hdGgubWF4KE1hdGgucm91bmQobGF5ZXIuX3JhZGl1cyksIDEpLFxuXHRcdCAgICBzID0gKE1hdGgubWF4KE1hdGgucm91bmQobGF5ZXIuX3JhZGl1c1kpLCAxKSB8fCByKSAvIHI7XG5cblx0XHRpZiAocyAhPT0gMSkge1xuXHRcdFx0Y3R4LnNhdmUoKTtcblx0XHRcdGN0eC5zY2FsZSgxLCBzKTtcblx0XHR9XG5cblx0XHRjdHguYmVnaW5QYXRoKCk7XG5cdFx0Y3R4LmFyYyhwLngsIHAueSAvIHMsIHIsIDAsIE1hdGguUEkgKiAyLCBmYWxzZSk7XG5cblx0XHRpZiAocyAhPT0gMSkge1xuXHRcdFx0Y3R4LnJlc3RvcmUoKTtcblx0XHR9XG5cblx0XHR0aGlzLl9maWxsU3Ryb2tlKGN0eCwgbGF5ZXIpO1xuXHR9LFxuXG5cdF9maWxsU3Ryb2tlOiBmdW5jdGlvbiAoY3R4LCBsYXllcikge1xuXHRcdHZhciBvcHRpb25zID0gbGF5ZXIub3B0aW9ucztcblxuXHRcdGlmIChvcHRpb25zLmZpbGwpIHtcblx0XHRcdGN0eC5nbG9iYWxBbHBoYSA9IG9wdGlvbnMuZmlsbE9wYWNpdHk7XG5cdFx0XHRjdHguZmlsbFN0eWxlID0gb3B0aW9ucy5maWxsQ29sb3IgfHwgb3B0aW9ucy5jb2xvcjtcblx0XHRcdGN0eC5maWxsKG9wdGlvbnMuZmlsbFJ1bGUgfHwgJ2V2ZW5vZGQnKTtcblx0XHR9XG5cblx0XHRpZiAob3B0aW9ucy5zdHJva2UgJiYgb3B0aW9ucy53ZWlnaHQgIT09IDApIHtcblx0XHRcdGlmIChjdHguc2V0TGluZURhc2gpIHtcblx0XHRcdFx0Y3R4LnNldExpbmVEYXNoKGxheWVyLm9wdGlvbnMgJiYgbGF5ZXIub3B0aW9ucy5fZGFzaEFycmF5IHx8IFtdKTtcblx0XHRcdH1cblx0XHRcdGN0eC5nbG9iYWxBbHBoYSA9IG9wdGlvbnMub3BhY2l0eTtcblx0XHRcdGN0eC5saW5lV2lkdGggPSBvcHRpb25zLndlaWdodDtcblx0XHRcdGN0eC5zdHJva2VTdHlsZSA9IG9wdGlvbnMuY29sb3I7XG5cdFx0XHRjdHgubGluZUNhcCA9IG9wdGlvbnMubGluZUNhcDtcblx0XHRcdGN0eC5saW5lSm9pbiA9IG9wdGlvbnMubGluZUpvaW47XG5cdFx0XHRjdHguc3Ryb2tlKCk7XG5cdFx0fVxuXHR9LFxuXG5cdC8vIENhbnZhcyBvYnZpb3VzbHkgZG9lc24ndCBoYXZlIG1vdXNlIGV2ZW50cyBmb3IgaW5kaXZpZHVhbCBkcmF3biBvYmplY3RzLFxuXHQvLyBzbyB3ZSBlbXVsYXRlIHRoYXQgYnkgY2FsY3VsYXRpbmcgd2hhdCdzIHVuZGVyIHRoZSBtb3VzZSBvbiBtb3VzZW1vdmUvY2xpY2sgbWFudWFsbHlcblxuXHRfb25DbGljazogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgcG9pbnQgPSB0aGlzLl9tYXAubW91c2VFdmVudFRvTGF5ZXJQb2ludChlKSwgbGF5ZXIsIGNsaWNrZWRMYXllcjtcblxuXHRcdGZvciAodmFyIG9yZGVyID0gdGhpcy5fZHJhd0ZpcnN0OyBvcmRlcjsgb3JkZXIgPSBvcmRlci5uZXh0KSB7XG5cdFx0XHRsYXllciA9IG9yZGVyLmxheWVyO1xuXHRcdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUgJiYgbGF5ZXIuX2NvbnRhaW5zUG9pbnQocG9pbnQpICYmICF0aGlzLl9tYXAuX2RyYWdnYWJsZU1vdmVkKGxheWVyKSkge1xuXHRcdFx0XHRjbGlja2VkTGF5ZXIgPSBsYXllcjtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKGNsaWNrZWRMYXllcikgIHtcblx0XHRcdGZha2VTdG9wKGUpO1xuXHRcdFx0dGhpcy5fZmlyZUV2ZW50KFtjbGlja2VkTGF5ZXJdLCBlKTtcblx0XHR9XG5cdH0sXG5cblx0X29uTW91c2VNb3ZlOiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmICghdGhpcy5fbWFwIHx8IHRoaXMuX21hcC5kcmFnZ2luZy5tb3ZpbmcoKSB8fCB0aGlzLl9tYXAuX2FuaW1hdGluZ1pvb20pIHsgcmV0dXJuOyB9XG5cblx0XHR2YXIgcG9pbnQgPSB0aGlzLl9tYXAubW91c2VFdmVudFRvTGF5ZXJQb2ludChlKTtcblx0XHR0aGlzLl9oYW5kbGVNb3VzZUhvdmVyKGUsIHBvaW50KTtcblx0fSxcblxuXG5cdF9oYW5kbGVNb3VzZU91dDogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgbGF5ZXIgPSB0aGlzLl9ob3ZlcmVkTGF5ZXI7XG5cdFx0aWYgKGxheWVyKSB7XG5cdFx0XHQvLyBpZiB3ZSdyZSBsZWF2aW5nIHRoZSBsYXllciwgZmlyZSBtb3VzZW91dFxuXHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC1pbnRlcmFjdGl2ZScpO1xuXHRcdFx0dGhpcy5fZmlyZUV2ZW50KFtsYXllcl0sIGUsICdtb3VzZW91dCcpO1xuXHRcdFx0dGhpcy5faG92ZXJlZExheWVyID0gbnVsbDtcblx0XHR9XG5cdH0sXG5cblx0X2hhbmRsZU1vdXNlSG92ZXI6IGZ1bmN0aW9uIChlLCBwb2ludCkge1xuXHRcdHZhciBsYXllciwgY2FuZGlkYXRlSG92ZXJlZExheWVyO1xuXG5cdFx0Zm9yICh2YXIgb3JkZXIgPSB0aGlzLl9kcmF3Rmlyc3Q7IG9yZGVyOyBvcmRlciA9IG9yZGVyLm5leHQpIHtcblx0XHRcdGxheWVyID0gb3JkZXIubGF5ZXI7XG5cdFx0XHRpZiAobGF5ZXIub3B0aW9ucy5pbnRlcmFjdGl2ZSAmJiBsYXllci5fY29udGFpbnNQb2ludChwb2ludCkpIHtcblx0XHRcdFx0Y2FuZGlkYXRlSG92ZXJlZExheWVyID0gbGF5ZXI7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGNhbmRpZGF0ZUhvdmVyZWRMYXllciAhPT0gdGhpcy5faG92ZXJlZExheWVyKSB7XG5cdFx0XHR0aGlzLl9oYW5kbGVNb3VzZU91dChlKTtcblxuXHRcdFx0aWYgKGNhbmRpZGF0ZUhvdmVyZWRMYXllcikge1xuXHRcdFx0XHRhZGRDbGFzcyh0aGlzLl9jb250YWluZXIsICdsZWFmbGV0LWludGVyYWN0aXZlJyk7IC8vIGNoYW5nZSBjdXJzb3Jcblx0XHRcdFx0dGhpcy5fZmlyZUV2ZW50KFtjYW5kaWRhdGVIb3ZlcmVkTGF5ZXJdLCBlLCAnbW91c2VvdmVyJyk7XG5cdFx0XHRcdHRoaXMuX2hvdmVyZWRMYXllciA9IGNhbmRpZGF0ZUhvdmVyZWRMYXllcjtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAodGhpcy5faG92ZXJlZExheWVyKSB7XG5cdFx0XHR0aGlzLl9maXJlRXZlbnQoW3RoaXMuX2hvdmVyZWRMYXllcl0sIGUpO1xuXHRcdH1cblx0fSxcblxuXHRfZmlyZUV2ZW50OiBmdW5jdGlvbiAobGF5ZXJzLCBlLCB0eXBlKSB7XG5cdFx0dGhpcy5fbWFwLl9maXJlRE9NRXZlbnQoZSwgdHlwZSB8fCBlLnR5cGUsIGxheWVycyk7XG5cdH0sXG5cblx0X2JyaW5nVG9Gcm9udDogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dmFyIG9yZGVyID0gbGF5ZXIuX29yZGVyO1xuXG5cdFx0aWYgKCFvcmRlcikgeyByZXR1cm47IH1cblxuXHRcdHZhciBuZXh0ID0gb3JkZXIubmV4dDtcblx0XHR2YXIgcHJldiA9IG9yZGVyLnByZXY7XG5cblx0XHRpZiAobmV4dCkge1xuXHRcdFx0bmV4dC5wcmV2ID0gcHJldjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gQWxyZWFkeSBsYXN0XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGlmIChwcmV2KSB7XG5cdFx0XHRwcmV2Lm5leHQgPSBuZXh0O1xuXHRcdH0gZWxzZSBpZiAobmV4dCkge1xuXHRcdFx0Ly8gVXBkYXRlIGZpcnN0IGVudHJ5IHVubGVzcyB0aGlzIGlzIHRoZVxuXHRcdFx0Ly8gc2luZ2xlIGVudHJ5XG5cdFx0XHR0aGlzLl9kcmF3Rmlyc3QgPSBuZXh0O1xuXHRcdH1cblxuXHRcdG9yZGVyLnByZXYgPSB0aGlzLl9kcmF3TGFzdDtcblx0XHR0aGlzLl9kcmF3TGFzdC5uZXh0ID0gb3JkZXI7XG5cblx0XHRvcmRlci5uZXh0ID0gbnVsbDtcblx0XHR0aGlzLl9kcmF3TGFzdCA9IG9yZGVyO1xuXG5cdFx0dGhpcy5fcmVxdWVzdFJlZHJhdyhsYXllcik7XG5cdH0sXG5cblx0X2JyaW5nVG9CYWNrOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR2YXIgb3JkZXIgPSBsYXllci5fb3JkZXI7XG5cblx0XHRpZiAoIW9yZGVyKSB7IHJldHVybjsgfVxuXG5cdFx0dmFyIG5leHQgPSBvcmRlci5uZXh0O1xuXHRcdHZhciBwcmV2ID0gb3JkZXIucHJldjtcblxuXHRcdGlmIChwcmV2KSB7XG5cdFx0XHRwcmV2Lm5leHQgPSBuZXh0O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBBbHJlYWR5IGZpcnN0XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGlmIChuZXh0KSB7XG5cdFx0XHRuZXh0LnByZXYgPSBwcmV2O1xuXHRcdH0gZWxzZSBpZiAocHJldikge1xuXHRcdFx0Ly8gVXBkYXRlIGxhc3QgZW50cnkgdW5sZXNzIHRoaXMgaXMgdGhlXG5cdFx0XHQvLyBzaW5nbGUgZW50cnlcblx0XHRcdHRoaXMuX2RyYXdMYXN0ID0gcHJldjtcblx0XHR9XG5cblx0XHRvcmRlci5wcmV2ID0gbnVsbDtcblxuXHRcdG9yZGVyLm5leHQgPSB0aGlzLl9kcmF3Rmlyc3Q7XG5cdFx0dGhpcy5fZHJhd0ZpcnN0LnByZXYgPSBvcmRlcjtcblx0XHR0aGlzLl9kcmF3Rmlyc3QgPSBvcmRlcjtcblxuXHRcdHRoaXMuX3JlcXVlc3RSZWRyYXcobGF5ZXIpO1xuXHR9XG59KTtcblxuLy8gQGZhY3RvcnkgTC5jYW52YXMob3B0aW9ucz86IFJlbmRlcmVyIG9wdGlvbnMpXG4vLyBDcmVhdGVzIGEgQ2FudmFzIHJlbmRlcmVyIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG5mdW5jdGlvbiBjYW52YXMkMShvcHRpb25zKSB7XG5cdHJldHVybiBjYW52YXMgPyBuZXcgQ2FudmFzKG9wdGlvbnMpIDogbnVsbDtcbn1cblxuLypcbiAqIFRoYW5rcyB0byBEbWl0cnkgQmFyYW5vdnNreSBhbmQgaGlzIFJhcGhhZWwgbGlicmFyeSBmb3IgaW5zcGlyYXRpb24hXG4gKi9cblxuXG52YXIgdm1sQ3JlYXRlID0gKGZ1bmN0aW9uICgpIHtcblx0dHJ5IHtcblx0XHRkb2N1bWVudC5uYW1lc3BhY2VzLmFkZCgnbHZtbCcsICd1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOnZtbCcpO1xuXHRcdHJldHVybiBmdW5jdGlvbiAobmFtZSkge1xuXHRcdFx0cmV0dXJuIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJzxsdm1sOicgKyBuYW1lICsgJyBjbGFzcz1cImx2bWxcIj4nKTtcblx0XHR9O1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uIChuYW1lKSB7XG5cdFx0XHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnPCcgKyBuYW1lICsgJyB4bWxucz1cInVybjpzY2hlbWFzLW1pY3Jvc29mdC5jb206dm1sXCIgY2xhc3M9XCJsdm1sXCI+Jyk7XG5cdFx0fTtcblx0fVxufSkoKTtcblxuXG4vKlxuICogQGNsYXNzIFNWR1xuICpcbiAqXG4gKiBWTUwgd2FzIGRlcHJlY2F0ZWQgaW4gMjAxMiwgd2hpY2ggbWVhbnMgVk1MIGZ1bmN0aW9uYWxpdHkgZXhpc3RzIG9ubHkgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5XG4gKiB3aXRoIG9sZCB2ZXJzaW9ucyBvZiBJbnRlcm5ldCBFeHBsb3Jlci5cbiAqL1xuXG4vLyBtaXhpbiB0byByZWRlZmluZSBzb21lIFNWRyBtZXRob2RzIHRvIGhhbmRsZSBWTUwgc3ludGF4IHdoaWNoIGlzIHNpbWlsYXIgYnV0IHdpdGggc29tZSBkaWZmZXJlbmNlc1xudmFyIHZtbE1peGluID0ge1xuXG5cdF9pbml0Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5fY29udGFpbmVyID0gY3JlYXRlJDEoJ2RpdicsICdsZWFmbGV0LXZtbC1jb250YWluZXInKTtcblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm47IH1cblx0XHRSZW5kZXJlci5wcm90b3R5cGUuX3VwZGF0ZS5jYWxsKHRoaXMpO1xuXHRcdHRoaXMuZmlyZSgndXBkYXRlJyk7XG5cdH0sXG5cblx0X2luaXRQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR2YXIgY29udGFpbmVyID0gbGF5ZXIuX2NvbnRhaW5lciA9IHZtbENyZWF0ZSgnc2hhcGUnKTtcblxuXHRcdGFkZENsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdm1sLXNoYXBlICcgKyAodGhpcy5vcHRpb25zLmNsYXNzTmFtZSB8fCAnJykpO1xuXG5cdFx0Y29udGFpbmVyLmNvb3Jkc2l6ZSA9ICcxIDEnO1xuXG5cdFx0bGF5ZXIuX3BhdGggPSB2bWxDcmVhdGUoJ3BhdGgnKTtcblx0XHRjb250YWluZXIuYXBwZW5kQ2hpbGQobGF5ZXIuX3BhdGgpO1xuXG5cdFx0dGhpcy5fdXBkYXRlU3R5bGUobGF5ZXIpO1xuXHRcdHRoaXMuX2xheWVyc1tzdGFtcChsYXllcildID0gbGF5ZXI7XG5cdH0sXG5cblx0X2FkZFBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHZhciBjb250YWluZXIgPSBsYXllci5fY29udGFpbmVyO1xuXHRcdHRoaXMuX2NvbnRhaW5lci5hcHBlbmRDaGlsZChjb250YWluZXIpO1xuXG5cdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHtcblx0XHRcdGxheWVyLmFkZEludGVyYWN0aXZlVGFyZ2V0KGNvbnRhaW5lcik7XG5cdFx0fVxuXHR9LFxuXG5cdF9yZW1vdmVQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR2YXIgY29udGFpbmVyID0gbGF5ZXIuX2NvbnRhaW5lcjtcblx0XHRyZW1vdmUoY29udGFpbmVyKTtcblx0XHRsYXllci5yZW1vdmVJbnRlcmFjdGl2ZVRhcmdldChjb250YWluZXIpO1xuXHRcdGRlbGV0ZSB0aGlzLl9sYXllcnNbc3RhbXAobGF5ZXIpXTtcblx0fSxcblxuXHRfdXBkYXRlU3R5bGU6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHZhciBzdHJva2UgPSBsYXllci5fc3Ryb2tlLFxuXHRcdCAgICBmaWxsID0gbGF5ZXIuX2ZpbGwsXG5cdFx0ICAgIG9wdGlvbnMgPSBsYXllci5vcHRpb25zLFxuXHRcdCAgICBjb250YWluZXIgPSBsYXllci5fY29udGFpbmVyO1xuXG5cdFx0Y29udGFpbmVyLnN0cm9rZWQgPSAhIW9wdGlvbnMuc3Ryb2tlO1xuXHRcdGNvbnRhaW5lci5maWxsZWQgPSAhIW9wdGlvbnMuZmlsbDtcblxuXHRcdGlmIChvcHRpb25zLnN0cm9rZSkge1xuXHRcdFx0aWYgKCFzdHJva2UpIHtcblx0XHRcdFx0c3Ryb2tlID0gbGF5ZXIuX3N0cm9rZSA9IHZtbENyZWF0ZSgnc3Ryb2tlJyk7XG5cdFx0XHR9XG5cdFx0XHRjb250YWluZXIuYXBwZW5kQ2hpbGQoc3Ryb2tlKTtcblx0XHRcdHN0cm9rZS53ZWlnaHQgPSBvcHRpb25zLndlaWdodCArICdweCc7XG5cdFx0XHRzdHJva2UuY29sb3IgPSBvcHRpb25zLmNvbG9yO1xuXHRcdFx0c3Ryb2tlLm9wYWNpdHkgPSBvcHRpb25zLm9wYWNpdHk7XG5cblx0XHRcdGlmIChvcHRpb25zLmRhc2hBcnJheSkge1xuXHRcdFx0XHRzdHJva2UuZGFzaFN0eWxlID0gaXNBcnJheShvcHRpb25zLmRhc2hBcnJheSkgP1xuXHRcdFx0XHQgICAgb3B0aW9ucy5kYXNoQXJyYXkuam9pbignICcpIDpcblx0XHRcdFx0ICAgIG9wdGlvbnMuZGFzaEFycmF5LnJlcGxhY2UoLyggKiwgKikvZywgJyAnKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHN0cm9rZS5kYXNoU3R5bGUgPSAnJztcblx0XHRcdH1cblx0XHRcdHN0cm9rZS5lbmRjYXAgPSBvcHRpb25zLmxpbmVDYXAucmVwbGFjZSgnYnV0dCcsICdmbGF0Jyk7XG5cdFx0XHRzdHJva2Uuam9pbnN0eWxlID0gb3B0aW9ucy5saW5lSm9pbjtcblxuXHRcdH0gZWxzZSBpZiAoc3Ryb2tlKSB7XG5cdFx0XHRjb250YWluZXIucmVtb3ZlQ2hpbGQoc3Ryb2tlKTtcblx0XHRcdGxheWVyLl9zdHJva2UgPSBudWxsO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLmZpbGwpIHtcblx0XHRcdGlmICghZmlsbCkge1xuXHRcdFx0XHRmaWxsID0gbGF5ZXIuX2ZpbGwgPSB2bWxDcmVhdGUoJ2ZpbGwnKTtcblx0XHRcdH1cblx0XHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZChmaWxsKTtcblx0XHRcdGZpbGwuY29sb3IgPSBvcHRpb25zLmZpbGxDb2xvciB8fCBvcHRpb25zLmNvbG9yO1xuXHRcdFx0ZmlsbC5vcGFjaXR5ID0gb3B0aW9ucy5maWxsT3BhY2l0eTtcblxuXHRcdH0gZWxzZSBpZiAoZmlsbCkge1xuXHRcdFx0Y29udGFpbmVyLnJlbW92ZUNoaWxkKGZpbGwpO1xuXHRcdFx0bGF5ZXIuX2ZpbGwgPSBudWxsO1xuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlQ2lyY2xlOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR2YXIgcCA9IGxheWVyLl9wb2ludC5yb3VuZCgpLFxuXHRcdCAgICByID0gTWF0aC5yb3VuZChsYXllci5fcmFkaXVzKSxcblx0XHQgICAgcjIgPSBNYXRoLnJvdW5kKGxheWVyLl9yYWRpdXNZIHx8IHIpO1xuXG5cdFx0dGhpcy5fc2V0UGF0aChsYXllciwgbGF5ZXIuX2VtcHR5KCkgPyAnTTAgMCcgOlxuXHRcdFx0J0FMICcgKyBwLnggKyAnLCcgKyBwLnkgKyAnICcgKyByICsgJywnICsgcjIgKyAnIDAsJyArICg2NTUzNSAqIDM2MCkpO1xuXHR9LFxuXG5cdF9zZXRQYXRoOiBmdW5jdGlvbiAobGF5ZXIsIHBhdGgpIHtcblx0XHRsYXllci5fcGF0aC52ID0gcGF0aDtcblx0fSxcblxuXHRfYnJpbmdUb0Zyb250OiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR0b0Zyb250KGxheWVyLl9jb250YWluZXIpO1xuXHR9LFxuXG5cdF9icmluZ1RvQmFjazogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dG9CYWNrKGxheWVyLl9jb250YWluZXIpO1xuXHR9XG59O1xuXG52YXIgY3JlYXRlJDIgPSB2bWwgPyB2bWxDcmVhdGUgOiBzdmdDcmVhdGU7XG5cbi8qXG4gKiBAY2xhc3MgU1ZHXG4gKiBAaW5oZXJpdHMgUmVuZGVyZXJcbiAqIEBha2EgTC5TVkdcbiAqXG4gKiBBbGxvd3MgdmVjdG9yIGxheWVycyB0byBiZSBkaXNwbGF5ZWQgd2l0aCBbU1ZHXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcpLlxuICogSW5oZXJpdHMgYFJlbmRlcmVyYC5cbiAqXG4gKiBEdWUgdG8gW3RlY2huaWNhbCBsaW1pdGF0aW9uc10oaHR0cDovL2Nhbml1c2UuY29tLyNzZWFyY2g9c3ZnKSwgU1ZHIGlzIG5vdFxuICogYXZhaWxhYmxlIGluIGFsbCB3ZWIgYnJvd3NlcnMsIG5vdGFibHkgQW5kcm9pZCAyLnggYW5kIDMueC5cbiAqXG4gKiBBbHRob3VnaCBTVkcgaXMgbm90IGF2YWlsYWJsZSBvbiBJRTcgYW5kIElFOCwgdGhlc2UgYnJvd3NlcnMgc3VwcG9ydFxuICogW1ZNTF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVmVjdG9yX01hcmt1cF9MYW5ndWFnZSlcbiAqIChhIG5vdyBkZXByZWNhdGVkIHRlY2hub2xvZ3kpLCBhbmQgdGhlIFNWRyByZW5kZXJlciB3aWxsIGZhbGwgYmFjayB0byBWTUwgaW5cbiAqIHRoaXMgY2FzZS5cbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIFVzZSBTVkcgYnkgZGVmYXVsdCBmb3IgYWxsIHBhdGhzIGluIHRoZSBtYXA6XG4gKlxuICogYGBganNcbiAqIHZhciBtYXAgPSBMLm1hcCgnbWFwJywge1xuICogXHRyZW5kZXJlcjogTC5zdmcoKVxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBVc2UgYSBTVkcgcmVuZGVyZXIgd2l0aCBleHRyYSBwYWRkaW5nIGZvciBzcGVjaWZpYyB2ZWN0b3IgZ2VvbWV0cmllczpcbiAqXG4gKiBgYGBqc1xuICogdmFyIG1hcCA9IEwubWFwKCdtYXAnKTtcbiAqIHZhciBteVJlbmRlcmVyID0gTC5zdmcoeyBwYWRkaW5nOiAwLjUgfSk7XG4gKiB2YXIgbGluZSA9IEwucG9seWxpbmUoIGNvb3JkaW5hdGVzLCB7IHJlbmRlcmVyOiBteVJlbmRlcmVyIH0gKTtcbiAqIHZhciBjaXJjbGUgPSBMLmNpcmNsZSggY2VudGVyLCB7IHJlbmRlcmVyOiBteVJlbmRlcmVyIH0gKTtcbiAqIGBgYFxuICovXG5cbnZhciBTVkcgPSBSZW5kZXJlci5leHRlbmQoe1xuXG5cdGdldEV2ZW50czogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBldmVudHMgPSBSZW5kZXJlci5wcm90b3R5cGUuZ2V0RXZlbnRzLmNhbGwodGhpcyk7XG5cdFx0ZXZlbnRzLnpvb21zdGFydCA9IHRoaXMuX29uWm9vbVN0YXJ0O1xuXHRcdHJldHVybiBldmVudHM7XG5cdH0sXG5cblx0X2luaXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMignc3ZnJyk7XG5cblx0XHQvLyBtYWtlcyBpdCBwb3NzaWJsZSB0byBjbGljayB0aHJvdWdoIHN2ZyByb290OyB3ZSdsbCByZXNldCBpdCBiYWNrIGluIGluZGl2aWR1YWwgcGF0aHNcblx0XHR0aGlzLl9jb250YWluZXIuc2V0QXR0cmlidXRlKCdwb2ludGVyLWV2ZW50cycsICdub25lJyk7XG5cblx0XHR0aGlzLl9yb290R3JvdXAgPSBjcmVhdGUkMignZycpO1xuXHRcdHRoaXMuX2NvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLl9yb290R3JvdXApO1xuXHR9LFxuXG5cdF9kZXN0cm95Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XG5cdFx0b2ZmKHRoaXMuX2NvbnRhaW5lcik7XG5cdFx0ZGVsZXRlIHRoaXMuX2NvbnRhaW5lcjtcblx0XHRkZWxldGUgdGhpcy5fcm9vdEdyb3VwO1xuXHRcdGRlbGV0ZSB0aGlzLl9zdmdTaXplO1xuXHR9LFxuXG5cdF9vblpvb21TdGFydDogZnVuY3Rpb24gKCkge1xuXHRcdC8vIERyYWctdGhlbi1waW5jaCBpbnRlcmFjdGlvbnMgbWlnaHQgbWVzcyB1cCB0aGUgY2VudGVyIGFuZCB6b29tLlxuXHRcdC8vIEluIHRoaXMgY2FzZSwgdGhlIGVhc2llc3Qgd2F5IHRvIHByZXZlbnQgdGhpcyBpcyByZS1kbyB0aGUgcmVuZGVyZXJcblx0XHQvLyAgIGJvdW5kcyBhbmQgcGFkZGluZyB3aGVuIHRoZSB6b29taW5nIHN0YXJ0cy5cblx0XHR0aGlzLl91cGRhdGUoKTtcblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSAmJiB0aGlzLl9ib3VuZHMpIHsgcmV0dXJuOyB9XG5cblx0XHRSZW5kZXJlci5wcm90b3R5cGUuX3VwZGF0ZS5jYWxsKHRoaXMpO1xuXG5cdFx0dmFyIGIgPSB0aGlzLl9ib3VuZHMsXG5cdFx0ICAgIHNpemUgPSBiLmdldFNpemUoKSxcblx0XHQgICAgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyO1xuXG5cdFx0Ly8gc2V0IHNpemUgb2Ygc3ZnLWNvbnRhaW5lciBpZiBjaGFuZ2VkXG5cdFx0aWYgKCF0aGlzLl9zdmdTaXplIHx8ICF0aGlzLl9zdmdTaXplLmVxdWFscyhzaXplKSkge1xuXHRcdFx0dGhpcy5fc3ZnU2l6ZSA9IHNpemU7XG5cdFx0XHRjb250YWluZXIuc2V0QXR0cmlidXRlKCd3aWR0aCcsIHNpemUueCk7XG5cdFx0XHRjb250YWluZXIuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCBzaXplLnkpO1xuXHRcdH1cblxuXHRcdC8vIG1vdmVtZW50OiB1cGRhdGUgY29udGFpbmVyIHZpZXdCb3ggc28gdGhhdCB3ZSBkb24ndCBoYXZlIHRvIGNoYW5nZSBjb29yZGluYXRlcyBvZiBpbmRpdmlkdWFsIGxheWVyc1xuXHRcdHNldFBvc2l0aW9uKGNvbnRhaW5lciwgYi5taW4pO1xuXHRcdGNvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCBbYi5taW4ueCwgYi5taW4ueSwgc2l6ZS54LCBzaXplLnldLmpvaW4oJyAnKSk7XG5cblx0XHR0aGlzLmZpcmUoJ3VwZGF0ZScpO1xuXHR9LFxuXG5cdC8vIG1ldGhvZHMgYmVsb3cgYXJlIGNhbGxlZCBieSB2ZWN0b3IgbGF5ZXJzIGltcGxlbWVudGF0aW9uc1xuXG5cdF9pbml0UGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dmFyIHBhdGggPSBsYXllci5fcGF0aCA9IGNyZWF0ZSQyKCdwYXRoJyk7XG5cblx0XHQvLyBAbmFtZXNwYWNlIFBhdGhcblx0XHQvLyBAb3B0aW9uIGNsYXNzTmFtZTogU3RyaW5nID0gbnVsbFxuXHRcdC8vIEN1c3RvbSBjbGFzcyBuYW1lIHNldCBvbiBhbiBlbGVtZW50LiBPbmx5IGZvciBTVkcgcmVuZGVyZXIuXG5cdFx0aWYgKGxheWVyLm9wdGlvbnMuY2xhc3NOYW1lKSB7XG5cdFx0XHRhZGRDbGFzcyhwYXRoLCBsYXllci5vcHRpb25zLmNsYXNzTmFtZSk7XG5cdFx0fVxuXG5cdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHtcblx0XHRcdGFkZENsYXNzKHBhdGgsICdsZWFmbGV0LWludGVyYWN0aXZlJyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fdXBkYXRlU3R5bGUobGF5ZXIpO1xuXHRcdHRoaXMuX2xheWVyc1tzdGFtcChsYXllcildID0gbGF5ZXI7XG5cdH0sXG5cblx0X2FkZFBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdGlmICghdGhpcy5fcm9vdEdyb3VwKSB7IHRoaXMuX2luaXRDb250YWluZXIoKTsgfVxuXHRcdHRoaXMuX3Jvb3RHcm91cC5hcHBlbmRDaGlsZChsYXllci5fcGF0aCk7XG5cdFx0bGF5ZXIuYWRkSW50ZXJhY3RpdmVUYXJnZXQobGF5ZXIuX3BhdGgpO1xuXHR9LFxuXG5cdF9yZW1vdmVQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHRyZW1vdmUobGF5ZXIuX3BhdGgpO1xuXHRcdGxheWVyLnJlbW92ZUludGVyYWN0aXZlVGFyZ2V0KGxheWVyLl9wYXRoKTtcblx0XHRkZWxldGUgdGhpcy5fbGF5ZXJzW3N0YW1wKGxheWVyKV07XG5cdH0sXG5cblx0X3VwZGF0ZVBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdGxheWVyLl9wcm9qZWN0KCk7XG5cdFx0bGF5ZXIuX3VwZGF0ZSgpO1xuXHR9LFxuXG5cdF91cGRhdGVTdHlsZTogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dmFyIHBhdGggPSBsYXllci5fcGF0aCxcblx0XHQgICAgb3B0aW9ucyA9IGxheWVyLm9wdGlvbnM7XG5cblx0XHRpZiAoIXBhdGgpIHsgcmV0dXJuOyB9XG5cblx0XHRpZiAob3B0aW9ucy5zdHJva2UpIHtcblx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UnLCBvcHRpb25zLmNvbG9yKTtcblx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2Utb3BhY2l0eScsIG9wdGlvbnMub3BhY2l0eSk7XG5cdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLXdpZHRoJywgb3B0aW9ucy53ZWlnaHQpO1xuXHRcdFx0cGF0aC5zZXRBdHRyaWJ1dGUoJ3N0cm9rZS1saW5lY2FwJywgb3B0aW9ucy5saW5lQ2FwKTtcblx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UtbGluZWpvaW4nLCBvcHRpb25zLmxpbmVKb2luKTtcblxuXHRcdFx0aWYgKG9wdGlvbnMuZGFzaEFycmF5KSB7XG5cdFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UtZGFzaGFycmF5Jywgb3B0aW9ucy5kYXNoQXJyYXkpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cGF0aC5yZW1vdmVBdHRyaWJ1dGUoJ3N0cm9rZS1kYXNoYXJyYXknKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKG9wdGlvbnMuZGFzaE9mZnNldCkge1xuXHRcdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLWRhc2hvZmZzZXQnLCBvcHRpb25zLmRhc2hPZmZzZXQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cGF0aC5yZW1vdmVBdHRyaWJ1dGUoJ3N0cm9rZS1kYXNob2Zmc2V0Jyk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UnLCAnbm9uZScpO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLmZpbGwpIHtcblx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdmaWxsJywgb3B0aW9ucy5maWxsQ29sb3IgfHwgb3B0aW9ucy5jb2xvcik7XG5cdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnZmlsbC1vcGFjaXR5Jywgb3B0aW9ucy5maWxsT3BhY2l0eSk7XG5cdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnZmlsbC1ydWxlJywgb3B0aW9ucy5maWxsUnVsZSB8fCAnZXZlbm9kZCcpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnZmlsbCcsICdub25lJyk7XG5cdFx0fVxuXHR9LFxuXG5cdF91cGRhdGVQb2x5OiBmdW5jdGlvbiAobGF5ZXIsIGNsb3NlZCkge1xuXHRcdHRoaXMuX3NldFBhdGgobGF5ZXIsIHBvaW50c1RvUGF0aChsYXllci5fcGFydHMsIGNsb3NlZCkpO1xuXHR9LFxuXG5cdF91cGRhdGVDaXJjbGU6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHZhciBwID0gbGF5ZXIuX3BvaW50LFxuXHRcdCAgICByID0gTWF0aC5tYXgoTWF0aC5yb3VuZChsYXllci5fcmFkaXVzKSwgMSksXG5cdFx0ICAgIHIyID0gTWF0aC5tYXgoTWF0aC5yb3VuZChsYXllci5fcmFkaXVzWSksIDEpIHx8IHIsXG5cdFx0ICAgIGFyYyA9ICdhJyArIHIgKyAnLCcgKyByMiArICcgMCAxLDAgJztcblxuXHRcdC8vIGRyYXdpbmcgYSBjaXJjbGUgd2l0aCB0d28gaGFsZi1hcmNzXG5cdFx0dmFyIGQgPSBsYXllci5fZW1wdHkoKSA/ICdNMCAwJyA6XG5cdFx0XHQnTScgKyAocC54IC0gcikgKyAnLCcgKyBwLnkgK1xuXHRcdFx0YXJjICsgKHIgKiAyKSArICcsMCAnICtcblx0XHRcdGFyYyArICgtciAqIDIpICsgJywwICc7XG5cblx0XHR0aGlzLl9zZXRQYXRoKGxheWVyLCBkKTtcblx0fSxcblxuXHRfc2V0UGF0aDogZnVuY3Rpb24gKGxheWVyLCBwYXRoKSB7XG5cdFx0bGF5ZXIuX3BhdGguc2V0QXR0cmlidXRlKCdkJywgcGF0aCk7XG5cdH0sXG5cblx0Ly8gU1ZHIGRvZXMgbm90IGhhdmUgdGhlIGNvbmNlcHQgb2YgekluZGV4IHNvIHdlIHJlc29ydCB0byBjaGFuZ2luZyB0aGUgRE9NIG9yZGVyIG9mIGVsZW1lbnRzXG5cdF9icmluZ1RvRnJvbnQ6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHRvRnJvbnQobGF5ZXIuX3BhdGgpO1xuXHR9LFxuXG5cdF9icmluZ1RvQmFjazogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dG9CYWNrKGxheWVyLl9wYXRoKTtcblx0fVxufSk7XG5cbmlmICh2bWwpIHtcblx0U1ZHLmluY2x1ZGUodm1sTWl4aW4pO1xufVxuXG4vLyBAbmFtZXNwYWNlIFNWR1xuLy8gQGZhY3RvcnkgTC5zdmcob3B0aW9ucz86IFJlbmRlcmVyIG9wdGlvbnMpXG4vLyBDcmVhdGVzIGEgU1ZHIHJlbmRlcmVyIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG5mdW5jdGlvbiBzdmckMShvcHRpb25zKSB7XG5cdHJldHVybiBzdmcgfHwgdm1sID8gbmV3IFNWRyhvcHRpb25zKSA6IG51bGw7XG59XG5cbk1hcC5pbmNsdWRlKHtcblx0Ly8gQG5hbWVzcGFjZSBNYXA7IEBtZXRob2QgZ2V0UmVuZGVyZXIobGF5ZXI6IFBhdGgpOiBSZW5kZXJlclxuXHQvLyBSZXR1cm5zIHRoZSBpbnN0YW5jZSBvZiBgUmVuZGVyZXJgIHRoYXQgc2hvdWxkIGJlIHVzZWQgdG8gcmVuZGVyIHRoZSBnaXZlblxuXHQvLyBgUGF0aGAuIEl0IHdpbGwgZW5zdXJlIHRoYXQgdGhlIGByZW5kZXJlcmAgb3B0aW9ucyBvZiB0aGUgbWFwIGFuZCBwYXRoc1xuXHQvLyBhcmUgcmVzcGVjdGVkLCBhbmQgdGhhdCB0aGUgcmVuZGVyZXJzIGRvIGV4aXN0IG9uIHRoZSBtYXAuXG5cdGdldFJlbmRlcmVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHQvLyBAbmFtZXNwYWNlIFBhdGg7IEBvcHRpb24gcmVuZGVyZXI6IFJlbmRlcmVyXG5cdFx0Ly8gVXNlIHRoaXMgc3BlY2lmaWMgaW5zdGFuY2Ugb2YgYFJlbmRlcmVyYCBmb3IgdGhpcyBwYXRoLiBUYWtlc1xuXHRcdC8vIHByZWNlZGVuY2Ugb3ZlciB0aGUgbWFwJ3MgW2RlZmF1bHQgcmVuZGVyZXJdKCNtYXAtcmVuZGVyZXIpLlxuXHRcdHZhciByZW5kZXJlciA9IGxheWVyLm9wdGlvbnMucmVuZGVyZXIgfHwgdGhpcy5fZ2V0UGFuZVJlbmRlcmVyKGxheWVyLm9wdGlvbnMucGFuZSkgfHwgdGhpcy5vcHRpb25zLnJlbmRlcmVyIHx8IHRoaXMuX3JlbmRlcmVyO1xuXG5cdFx0aWYgKCFyZW5kZXJlcikge1xuXHRcdFx0cmVuZGVyZXIgPSB0aGlzLl9yZW5kZXJlciA9IHRoaXMuX2NyZWF0ZVJlbmRlcmVyKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCF0aGlzLmhhc0xheWVyKHJlbmRlcmVyKSkge1xuXHRcdFx0dGhpcy5hZGRMYXllcihyZW5kZXJlcik7XG5cdFx0fVxuXHRcdHJldHVybiByZW5kZXJlcjtcblx0fSxcblxuXHRfZ2V0UGFuZVJlbmRlcmVyOiBmdW5jdGlvbiAobmFtZSkge1xuXHRcdGlmIChuYW1lID09PSAnb3ZlcmxheVBhbmUnIHx8IG5hbWUgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdHZhciByZW5kZXJlciA9IHRoaXMuX3BhbmVSZW5kZXJlcnNbbmFtZV07XG5cdFx0aWYgKHJlbmRlcmVyID09PSB1bmRlZmluZWQpIHtcblx0XHRcdHJlbmRlcmVyID0gdGhpcy5fY3JlYXRlUmVuZGVyZXIoe3BhbmU6IG5hbWV9KTtcblx0XHRcdHRoaXMuX3BhbmVSZW5kZXJlcnNbbmFtZV0gPSByZW5kZXJlcjtcblx0XHR9XG5cdFx0cmV0dXJuIHJlbmRlcmVyO1xuXHR9LFxuXG5cdF9jcmVhdGVSZW5kZXJlcjogZnVuY3Rpb24gKG9wdGlvbnMpIHtcblx0XHQvLyBAbmFtZXNwYWNlIE1hcDsgQG9wdGlvbiBwcmVmZXJDYW52YXM6IEJvb2xlYW4gPSBmYWxzZVxuXHRcdC8vIFdoZXRoZXIgYFBhdGhgcyBzaG91bGQgYmUgcmVuZGVyZWQgb24gYSBgQ2FudmFzYCByZW5kZXJlci5cblx0XHQvLyBCeSBkZWZhdWx0LCBhbGwgYFBhdGhgcyBhcmUgcmVuZGVyZWQgaW4gYSBgU1ZHYCByZW5kZXJlci5cblx0XHRyZXR1cm4gKHRoaXMub3B0aW9ucy5wcmVmZXJDYW52YXMgJiYgY2FudmFzJDEob3B0aW9ucykpIHx8IHN2ZyQxKG9wdGlvbnMpO1xuXHR9XG59KTtcblxuLypcbiAqIEwuUmVjdGFuZ2xlIGV4dGVuZHMgUG9seWdvbiBhbmQgY3JlYXRlcyBhIHJlY3RhbmdsZSB3aGVuIHBhc3NlZCBhIExhdExuZ0JvdW5kcyBvYmplY3QuXG4gKi9cblxuLypcbiAqIEBjbGFzcyBSZWN0YW5nbGVcbiAqIEBha2EgTC5SZWN0YW5nbGVcbiAqIEBpbmhlcml0cyBQb2x5Z29uXG4gKlxuICogQSBjbGFzcyBmb3IgZHJhd2luZyByZWN0YW5nbGUgb3ZlcmxheXMgb24gYSBtYXAuIEV4dGVuZHMgYFBvbHlnb25gLlxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBganNcbiAqIC8vIGRlZmluZSByZWN0YW5nbGUgZ2VvZ3JhcGhpY2FsIGJvdW5kc1xuICogdmFyIGJvdW5kcyA9IFtbNTQuNTU5MzIyLCAtNS43Njc4MjJdLCBbNTYuMTIxMDYwNCwgLTMuMDIxMjQwXV07XG4gKlxuICogLy8gY3JlYXRlIGFuIG9yYW5nZSByZWN0YW5nbGVcbiAqIEwucmVjdGFuZ2xlKGJvdW5kcywge2NvbG9yOiBcIiNmZjc4MDBcIiwgd2VpZ2h0OiAxfSkuYWRkVG8obWFwKTtcbiAqXG4gKiAvLyB6b29tIHRoZSBtYXAgdG8gdGhlIHJlY3RhbmdsZSBib3VuZHNcbiAqIG1hcC5maXRCb3VuZHMoYm91bmRzKTtcbiAqIGBgYFxuICpcbiAqL1xuXG5cbnZhciBSZWN0YW5nbGUgPSBQb2x5Z29uLmV4dGVuZCh7XG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChsYXRMbmdCb3VuZHMsIG9wdGlvbnMpIHtcblx0XHRQb2x5Z29uLnByb3RvdHlwZS5pbml0aWFsaXplLmNhbGwodGhpcywgdGhpcy5fYm91bmRzVG9MYXRMbmdzKGxhdExuZ0JvdW5kcyksIG9wdGlvbnMpO1xuXHR9LFxuXG5cdC8vIEBtZXRob2Qgc2V0Qm91bmRzKGxhdExuZ0JvdW5kczogTGF0TG5nQm91bmRzKTogdGhpc1xuXHQvLyBSZWRyYXdzIHRoZSByZWN0YW5nbGUgd2l0aCB0aGUgcGFzc2VkIGJvdW5kcy5cblx0c2V0Qm91bmRzOiBmdW5jdGlvbiAobGF0TG5nQm91bmRzKSB7XG5cdFx0cmV0dXJuIHRoaXMuc2V0TGF0TG5ncyh0aGlzLl9ib3VuZHNUb0xhdExuZ3MobGF0TG5nQm91bmRzKSk7XG5cdH0sXG5cblx0X2JvdW5kc1RvTGF0TG5nczogZnVuY3Rpb24gKGxhdExuZ0JvdW5kcykge1xuXHRcdGxhdExuZ0JvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGxhdExuZ0JvdW5kcyk7XG5cdFx0cmV0dXJuIFtcblx0XHRcdGxhdExuZ0JvdW5kcy5nZXRTb3V0aFdlc3QoKSxcblx0XHRcdGxhdExuZ0JvdW5kcy5nZXROb3J0aFdlc3QoKSxcblx0XHRcdGxhdExuZ0JvdW5kcy5nZXROb3J0aEVhc3QoKSxcblx0XHRcdGxhdExuZ0JvdW5kcy5nZXRTb3V0aEVhc3QoKVxuXHRcdF07XG5cdH1cbn0pO1xuXG5cbi8vIEBmYWN0b3J5IEwucmVjdGFuZ2xlKGxhdExuZ0JvdW5kczogTGF0TG5nQm91bmRzLCBvcHRpb25zPzogUG9seWxpbmUgb3B0aW9ucylcbmZ1bmN0aW9uIHJlY3RhbmdsZShsYXRMbmdCb3VuZHMsIG9wdGlvbnMpIHtcblx0cmV0dXJuIG5ldyBSZWN0YW5nbGUobGF0TG5nQm91bmRzLCBvcHRpb25zKTtcbn1cblxuU1ZHLmNyZWF0ZSA9IGNyZWF0ZSQyO1xuU1ZHLnBvaW50c1RvUGF0aCA9IHBvaW50c1RvUGF0aDtcblxuR2VvSlNPTi5nZW9tZXRyeVRvTGF5ZXIgPSBnZW9tZXRyeVRvTGF5ZXI7XG5HZW9KU09OLmNvb3Jkc1RvTGF0TG5nID0gY29vcmRzVG9MYXRMbmc7XG5HZW9KU09OLmNvb3Jkc1RvTGF0TG5ncyA9IGNvb3Jkc1RvTGF0TG5ncztcbkdlb0pTT04ubGF0TG5nVG9Db29yZHMgPSBsYXRMbmdUb0Nvb3Jkcztcbkdlb0pTT04ubGF0TG5nc1RvQ29vcmRzID0gbGF0TG5nc1RvQ29vcmRzO1xuR2VvSlNPTi5nZXRGZWF0dXJlID0gZ2V0RmVhdHVyZTtcbkdlb0pTT04uYXNGZWF0dXJlID0gYXNGZWF0dXJlO1xuXG4vKlxuICogTC5IYW5kbGVyLkJveFpvb20gaXMgdXNlZCB0byBhZGQgc2hpZnQtZHJhZyB6b29tIGludGVyYWN0aW9uIHRvIHRoZSBtYXBcbiAqICh6b29tIHRvIGEgc2VsZWN0ZWQgYm91bmRpbmcgYm94KSwgZW5hYmxlZCBieSBkZWZhdWx0LlxuICovXG5cbi8vIEBuYW1lc3BhY2UgTWFwXG4vLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG5NYXAubWVyZ2VPcHRpb25zKHtcblx0Ly8gQG9wdGlvbiBib3hab29tOiBCb29sZWFuID0gdHJ1ZVxuXHQvLyBXaGV0aGVyIHRoZSBtYXAgY2FuIGJlIHpvb21lZCB0byBhIHJlY3Rhbmd1bGFyIGFyZWEgc3BlY2lmaWVkIGJ5XG5cdC8vIGRyYWdnaW5nIHRoZSBtb3VzZSB3aGlsZSBwcmVzc2luZyB0aGUgc2hpZnQga2V5LlxuXHRib3hab29tOiB0cnVlXG59KTtcblxudmFyIEJveFpvb20gPSBIYW5kbGVyLmV4dGVuZCh7XG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChtYXApIHtcblx0XHR0aGlzLl9tYXAgPSBtYXA7XG5cdFx0dGhpcy5fY29udGFpbmVyID0gbWFwLl9jb250YWluZXI7XG5cdFx0dGhpcy5fcGFuZSA9IG1hcC5fcGFuZXMub3ZlcmxheVBhbmU7XG5cdFx0dGhpcy5fcmVzZXRTdGF0ZVRpbWVvdXQgPSAwO1xuXHRcdG1hcC5vbigndW5sb2FkJywgdGhpcy5fZGVzdHJveSwgdGhpcyk7XG5cdH0sXG5cblx0YWRkSG9va3M6IGZ1bmN0aW9uICgpIHtcblx0XHRvbih0aGlzLl9jb250YWluZXIsICdtb3VzZWRvd24nLCB0aGlzLl9vbk1vdXNlRG93biwgdGhpcyk7XG5cdH0sXG5cblx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcblx0XHRvZmYodGhpcy5fY29udGFpbmVyLCAnbW91c2Vkb3duJywgdGhpcy5fb25Nb3VzZURvd24sIHRoaXMpO1xuXHR9LFxuXG5cdG1vdmVkOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX21vdmVkO1xuXHR9LFxuXG5cdF9kZXN0cm95OiBmdW5jdGlvbiAoKSB7XG5cdFx0cmVtb3ZlKHRoaXMuX3BhbmUpO1xuXHRcdGRlbGV0ZSB0aGlzLl9wYW5lO1xuXHR9LFxuXG5cdF9yZXNldFN0YXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5fcmVzZXRTdGF0ZVRpbWVvdXQgPSAwO1xuXHRcdHRoaXMuX21vdmVkID0gZmFsc2U7XG5cdH0sXG5cblx0X2NsZWFyRGVmZXJyZWRSZXNldFN0YXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX3Jlc2V0U3RhdGVUaW1lb3V0ICE9PSAwKSB7XG5cdFx0XHRjbGVhclRpbWVvdXQodGhpcy5fcmVzZXRTdGF0ZVRpbWVvdXQpO1xuXHRcdFx0dGhpcy5fcmVzZXRTdGF0ZVRpbWVvdXQgPSAwO1xuXHRcdH1cblx0fSxcblxuXHRfb25Nb3VzZURvd246IGZ1bmN0aW9uIChlKSB7XG5cdFx0aWYgKCFlLnNoaWZ0S2V5IHx8ICgoZS53aGljaCAhPT0gMSkgJiYgKGUuYnV0dG9uICE9PSAxKSkpIHsgcmV0dXJuIGZhbHNlOyB9XG5cblx0XHQvLyBDbGVhciB0aGUgZGVmZXJyZWQgcmVzZXRTdGF0ZSBpZiBpdCBoYXNuJ3QgZXhlY3V0ZWQgeWV0LCBvdGhlcndpc2UgaXRcblx0XHQvLyB3aWxsIGludGVycnVwdCB0aGUgaW50ZXJhY3Rpb24gYW5kIG9ycGhhbiBhIGJveCBlbGVtZW50IGluIHRoZSBjb250YWluZXIuXG5cdFx0dGhpcy5fY2xlYXJEZWZlcnJlZFJlc2V0U3RhdGUoKTtcblx0XHR0aGlzLl9yZXNldFN0YXRlKCk7XG5cblx0XHRkaXNhYmxlVGV4dFNlbGVjdGlvbigpO1xuXHRcdGRpc2FibGVJbWFnZURyYWcoKTtcblxuXHRcdHRoaXMuX3N0YXJ0UG9pbnQgPSB0aGlzLl9tYXAubW91c2VFdmVudFRvQ29udGFpbmVyUG9pbnQoZSk7XG5cblx0XHRvbihkb2N1bWVudCwge1xuXHRcdFx0Y29udGV4dG1lbnU6IHN0b3AsXG5cdFx0XHRtb3VzZW1vdmU6IHRoaXMuX29uTW91c2VNb3ZlLFxuXHRcdFx0bW91c2V1cDogdGhpcy5fb25Nb3VzZVVwLFxuXHRcdFx0a2V5ZG93bjogdGhpcy5fb25LZXlEb3duXG5cdFx0fSwgdGhpcyk7XG5cdH0sXG5cblx0X29uTW91c2VNb3ZlOiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmICghdGhpcy5fbW92ZWQpIHtcblx0XHRcdHRoaXMuX21vdmVkID0gdHJ1ZTtcblxuXHRcdFx0dGhpcy5fYm94ID0gY3JlYXRlJDEoJ2RpdicsICdsZWFmbGV0LXpvb20tYm94JywgdGhpcy5fY29udGFpbmVyKTtcblx0XHRcdGFkZENsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY3Jvc3NoYWlyJyk7XG5cblx0XHRcdHRoaXMuX21hcC5maXJlKCdib3h6b29tc3RhcnQnKTtcblx0XHR9XG5cblx0XHR0aGlzLl9wb2ludCA9IHRoaXMuX21hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKTtcblxuXHRcdHZhciBib3VuZHMgPSBuZXcgQm91bmRzKHRoaXMuX3BvaW50LCB0aGlzLl9zdGFydFBvaW50KSxcblx0XHQgICAgc2l6ZSA9IGJvdW5kcy5nZXRTaXplKCk7XG5cblx0XHRzZXRQb3NpdGlvbih0aGlzLl9ib3gsIGJvdW5kcy5taW4pO1xuXG5cdFx0dGhpcy5fYm94LnN0eWxlLndpZHRoICA9IHNpemUueCArICdweCc7XG5cdFx0dGhpcy5fYm94LnN0eWxlLmhlaWdodCA9IHNpemUueSArICdweCc7XG5cdH0sXG5cblx0X2ZpbmlzaDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9tb3ZlZCkge1xuXHRcdFx0cmVtb3ZlKHRoaXMuX2JveCk7XG5cdFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9jb250YWluZXIsICdsZWFmbGV0LWNyb3NzaGFpcicpO1xuXHRcdH1cblxuXHRcdGVuYWJsZVRleHRTZWxlY3Rpb24oKTtcblx0XHRlbmFibGVJbWFnZURyYWcoKTtcblxuXHRcdG9mZihkb2N1bWVudCwge1xuXHRcdFx0Y29udGV4dG1lbnU6IHN0b3AsXG5cdFx0XHRtb3VzZW1vdmU6IHRoaXMuX29uTW91c2VNb3ZlLFxuXHRcdFx0bW91c2V1cDogdGhpcy5fb25Nb3VzZVVwLFxuXHRcdFx0a2V5ZG93bjogdGhpcy5fb25LZXlEb3duXG5cdFx0fSwgdGhpcyk7XG5cdH0sXG5cblx0X29uTW91c2VVcDogZnVuY3Rpb24gKGUpIHtcblx0XHRpZiAoKGUud2hpY2ggIT09IDEpICYmIChlLmJ1dHRvbiAhPT0gMSkpIHsgcmV0dXJuOyB9XG5cblx0XHR0aGlzLl9maW5pc2goKTtcblxuXHRcdGlmICghdGhpcy5fbW92ZWQpIHsgcmV0dXJuOyB9XG5cdFx0Ly8gUG9zdHBvbmUgdG8gbmV4dCBKUyB0aWNrIHNvIGludGVybmFsIGNsaWNrIGV2ZW50IGhhbmRsaW5nXG5cdFx0Ly8gc3RpbGwgc2VlIGl0IGFzIFwibW92ZWRcIi5cblx0XHR0aGlzLl9jbGVhckRlZmVycmVkUmVzZXRTdGF0ZSgpO1xuXHRcdHRoaXMuX3Jlc2V0U3RhdGVUaW1lb3V0ID0gc2V0VGltZW91dChiaW5kKHRoaXMuX3Jlc2V0U3RhdGUsIHRoaXMpLCAwKTtcblxuXHRcdHZhciBib3VuZHMgPSBuZXcgTGF0TG5nQm91bmRzKFxuXHRcdCAgICAgICAgdGhpcy5fbWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcodGhpcy5fc3RhcnRQb2ludCksXG5cdFx0ICAgICAgICB0aGlzLl9tYXAuY29udGFpbmVyUG9pbnRUb0xhdExuZyh0aGlzLl9wb2ludCkpO1xuXG5cdFx0dGhpcy5fbWFwXG5cdFx0XHQuZml0Qm91bmRzKGJvdW5kcylcblx0XHRcdC5maXJlKCdib3h6b29tZW5kJywge2JveFpvb21Cb3VuZHM6IGJvdW5kc30pO1xuXHR9LFxuXG5cdF9vbktleURvd246IGZ1bmN0aW9uIChlKSB7XG5cdFx0aWYgKGUua2V5Q29kZSA9PT0gMjcpIHtcblx0XHRcdHRoaXMuX2ZpbmlzaCgpO1xuXHRcdH1cblx0fVxufSk7XG5cbi8vIEBzZWN0aW9uIEhhbmRsZXJzXG4vLyBAcHJvcGVydHkgYm94Wm9vbTogSGFuZGxlclxuLy8gQm94IChzaGlmdC1kcmFnIHdpdGggbW91c2UpIHpvb20gaGFuZGxlci5cbk1hcC5hZGRJbml0SG9vaygnYWRkSGFuZGxlcicsICdib3hab29tJywgQm94Wm9vbSk7XG5cbi8qXG4gKiBMLkhhbmRsZXIuRG91YmxlQ2xpY2tab29tIGlzIHVzZWQgdG8gaGFuZGxlIGRvdWJsZS1jbGljayB6b29tIG9uIHRoZSBtYXAsIGVuYWJsZWQgYnkgZGVmYXVsdC5cbiAqL1xuXG4vLyBAbmFtZXNwYWNlIE1hcFxuLy8gQHNlY3Rpb24gSW50ZXJhY3Rpb24gT3B0aW9uc1xuXG5NYXAubWVyZ2VPcHRpb25zKHtcblx0Ly8gQG9wdGlvbiBkb3VibGVDbGlja1pvb206IEJvb2xlYW58U3RyaW5nID0gdHJ1ZVxuXHQvLyBXaGV0aGVyIHRoZSBtYXAgY2FuIGJlIHpvb21lZCBpbiBieSBkb3VibGUgY2xpY2tpbmcgb24gaXQgYW5kXG5cdC8vIHpvb21lZCBvdXQgYnkgZG91YmxlIGNsaWNraW5nIHdoaWxlIGhvbGRpbmcgc2hpZnQuIElmIHBhc3NlZFxuXHQvLyBgJ2NlbnRlcidgLCBkb3VibGUtY2xpY2sgem9vbSB3aWxsIHpvb20gdG8gdGhlIGNlbnRlciBvZiB0aGVcblx0Ly8gIHZpZXcgcmVnYXJkbGVzcyBvZiB3aGVyZSB0aGUgbW91c2Ugd2FzLlxuXHRkb3VibGVDbGlja1pvb206IHRydWVcbn0pO1xuXG52YXIgRG91YmxlQ2xpY2tab29tID0gSGFuZGxlci5leHRlbmQoe1xuXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX21hcC5vbignZGJsY2xpY2snLCB0aGlzLl9vbkRvdWJsZUNsaWNrLCB0aGlzKTtcblx0fSxcblxuXHRyZW1vdmVIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX21hcC5vZmYoJ2RibGNsaWNrJywgdGhpcy5fb25Eb3VibGVDbGljaywgdGhpcyk7XG5cdH0sXG5cblx0X29uRG91YmxlQ2xpY2s6IGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcblx0XHQgICAgb2xkWm9vbSA9IG1hcC5nZXRab29tKCksXG5cdFx0ICAgIGRlbHRhID0gbWFwLm9wdGlvbnMuem9vbURlbHRhLFxuXHRcdCAgICB6b29tID0gZS5vcmlnaW5hbEV2ZW50LnNoaWZ0S2V5ID8gb2xkWm9vbSAtIGRlbHRhIDogb2xkWm9vbSArIGRlbHRhO1xuXG5cdFx0aWYgKG1hcC5vcHRpb25zLmRvdWJsZUNsaWNrWm9vbSA9PT0gJ2NlbnRlcicpIHtcblx0XHRcdG1hcC5zZXRab29tKHpvb20pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRtYXAuc2V0Wm9vbUFyb3VuZChlLmNvbnRhaW5lclBvaW50LCB6b29tKTtcblx0XHR9XG5cdH1cbn0pO1xuXG4vLyBAc2VjdGlvbiBIYW5kbGVyc1xuLy9cbi8vIE1hcCBwcm9wZXJ0aWVzIGluY2x1ZGUgaW50ZXJhY3Rpb24gaGFuZGxlcnMgdGhhdCBhbGxvdyB5b3UgdG8gY29udHJvbFxuLy8gaW50ZXJhY3Rpb24gYmVoYXZpb3IgaW4gcnVudGltZSwgZW5hYmxpbmcgb3IgZGlzYWJsaW5nIGNlcnRhaW4gZmVhdHVyZXMgc3VjaFxuLy8gYXMgZHJhZ2dpbmcgb3IgdG91Y2ggem9vbSAoc2VlIGBIYW5kbGVyYCBtZXRob2RzKS4gRm9yIGV4YW1wbGU6XG4vL1xuLy8gYGBganNcbi8vIG1hcC5kb3VibGVDbGlja1pvb20uZGlzYWJsZSgpO1xuLy8gYGBgXG4vL1xuLy8gQHByb3BlcnR5IGRvdWJsZUNsaWNrWm9vbTogSGFuZGxlclxuLy8gRG91YmxlIGNsaWNrIHpvb20gaGFuZGxlci5cbk1hcC5hZGRJbml0SG9vaygnYWRkSGFuZGxlcicsICdkb3VibGVDbGlja1pvb20nLCBEb3VibGVDbGlja1pvb20pO1xuXG4vKlxuICogTC5IYW5kbGVyLk1hcERyYWcgaXMgdXNlZCB0byBtYWtlIHRoZSBtYXAgZHJhZ2dhYmxlICh3aXRoIHBhbm5pbmcgaW5lcnRpYSksIGVuYWJsZWQgYnkgZGVmYXVsdC5cbiAqL1xuXG4vLyBAbmFtZXNwYWNlIE1hcFxuLy8gQHNlY3Rpb24gSW50ZXJhY3Rpb24gT3B0aW9uc1xuTWFwLm1lcmdlT3B0aW9ucyh7XG5cdC8vIEBvcHRpb24gZHJhZ2dpbmc6IEJvb2xlYW4gPSB0cnVlXG5cdC8vIFdoZXRoZXIgdGhlIG1hcCBiZSBkcmFnZ2FibGUgd2l0aCBtb3VzZS90b3VjaCBvciBub3QuXG5cdGRyYWdnaW5nOiB0cnVlLFxuXG5cdC8vIEBzZWN0aW9uIFBhbm5pbmcgSW5lcnRpYSBPcHRpb25zXG5cdC8vIEBvcHRpb24gaW5lcnRpYTogQm9vbGVhbiA9ICpcblx0Ly8gSWYgZW5hYmxlZCwgcGFubmluZyBvZiB0aGUgbWFwIHdpbGwgaGF2ZSBhbiBpbmVydGlhIGVmZmVjdCB3aGVyZVxuXHQvLyB0aGUgbWFwIGJ1aWxkcyBtb21lbnR1bSB3aGlsZSBkcmFnZ2luZyBhbmQgY29udGludWVzIG1vdmluZyBpblxuXHQvLyB0aGUgc2FtZSBkaXJlY3Rpb24gZm9yIHNvbWUgdGltZS4gRmVlbHMgZXNwZWNpYWxseSBuaWNlIG9uIHRvdWNoXG5cdC8vIGRldmljZXMuIEVuYWJsZWQgYnkgZGVmYXVsdCB1bmxlc3MgcnVubmluZyBvbiBvbGQgQW5kcm9pZCBkZXZpY2VzLlxuXHRpbmVydGlhOiAhYW5kcm9pZDIzLFxuXG5cdC8vIEBvcHRpb24gaW5lcnRpYURlY2VsZXJhdGlvbjogTnVtYmVyID0gMzAwMFxuXHQvLyBUaGUgcmF0ZSB3aXRoIHdoaWNoIHRoZSBpbmVydGlhbCBtb3ZlbWVudCBzbG93cyBkb3duLCBpbiBwaXhlbHMvc2Vjb25kwrIuXG5cdGluZXJ0aWFEZWNlbGVyYXRpb246IDM0MDAsIC8vIHB4L3NeMlxuXG5cdC8vIEBvcHRpb24gaW5lcnRpYU1heFNwZWVkOiBOdW1iZXIgPSBJbmZpbml0eVxuXHQvLyBNYXggc3BlZWQgb2YgdGhlIGluZXJ0aWFsIG1vdmVtZW50LCBpbiBwaXhlbHMvc2Vjb25kLlxuXHRpbmVydGlhTWF4U3BlZWQ6IEluZmluaXR5LCAvLyBweC9zXG5cblx0Ly8gQG9wdGlvbiBlYXNlTGluZWFyaXR5OiBOdW1iZXIgPSAwLjJcblx0ZWFzZUxpbmVhcml0eTogMC4yLFxuXG5cdC8vIFRPRE8gcmVmYWN0b3IsIG1vdmUgdG8gQ1JTXG5cdC8vIEBvcHRpb24gd29ybGRDb3B5SnVtcDogQm9vbGVhbiA9IGZhbHNlXG5cdC8vIFdpdGggdGhpcyBvcHRpb24gZW5hYmxlZCwgdGhlIG1hcCB0cmFja3Mgd2hlbiB5b3UgcGFuIHRvIGFub3RoZXIgXCJjb3B5XCJcblx0Ly8gb2YgdGhlIHdvcmxkIGFuZCBzZWFtbGVzc2x5IGp1bXBzIHRvIHRoZSBvcmlnaW5hbCBvbmUgc28gdGhhdCBhbGwgb3ZlcmxheXNcblx0Ly8gbGlrZSBtYXJrZXJzIGFuZCB2ZWN0b3IgbGF5ZXJzIGFyZSBzdGlsbCB2aXNpYmxlLlxuXHR3b3JsZENvcHlKdW1wOiBmYWxzZSxcblxuXHQvLyBAb3B0aW9uIG1heEJvdW5kc1Zpc2Nvc2l0eTogTnVtYmVyID0gMC4wXG5cdC8vIElmIGBtYXhCb3VuZHNgIGlzIHNldCwgdGhpcyBvcHRpb24gd2lsbCBjb250cm9sIGhvdyBzb2xpZCB0aGUgYm91bmRzXG5cdC8vIGFyZSB3aGVuIGRyYWdnaW5nIHRoZSBtYXAgYXJvdW5kLiBUaGUgZGVmYXVsdCB2YWx1ZSBvZiBgMC4wYCBhbGxvd3MgdGhlXG5cdC8vIHVzZXIgdG8gZHJhZyBvdXRzaWRlIHRoZSBib3VuZHMgYXQgbm9ybWFsIHNwZWVkLCBoaWdoZXIgdmFsdWVzIHdpbGxcblx0Ly8gc2xvdyBkb3duIG1hcCBkcmFnZ2luZyBvdXRzaWRlIGJvdW5kcywgYW5kIGAxLjBgIG1ha2VzIHRoZSBib3VuZHMgZnVsbHlcblx0Ly8gc29saWQsIHByZXZlbnRpbmcgdGhlIHVzZXIgZnJvbSBkcmFnZ2luZyBvdXRzaWRlIHRoZSBib3VuZHMuXG5cdG1heEJvdW5kc1Zpc2Nvc2l0eTogMC4wXG59KTtcblxudmFyIERyYWcgPSBIYW5kbGVyLmV4dGVuZCh7XG5cdGFkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKCF0aGlzLl9kcmFnZ2FibGUpIHtcblx0XHRcdHZhciBtYXAgPSB0aGlzLl9tYXA7XG5cblx0XHRcdHRoaXMuX2RyYWdnYWJsZSA9IG5ldyBEcmFnZ2FibGUobWFwLl9tYXBQYW5lLCBtYXAuX2NvbnRhaW5lcik7XG5cblx0XHRcdHRoaXMuX2RyYWdnYWJsZS5vbih7XG5cdFx0XHRcdGRyYWdzdGFydDogdGhpcy5fb25EcmFnU3RhcnQsXG5cdFx0XHRcdGRyYWc6IHRoaXMuX29uRHJhZyxcblx0XHRcdFx0ZHJhZ2VuZDogdGhpcy5fb25EcmFnRW5kXG5cdFx0XHR9LCB0aGlzKTtcblxuXHRcdFx0dGhpcy5fZHJhZ2dhYmxlLm9uKCdwcmVkcmFnJywgdGhpcy5fb25QcmVEcmFnTGltaXQsIHRoaXMpO1xuXHRcdFx0aWYgKG1hcC5vcHRpb25zLndvcmxkQ29weUp1bXApIHtcblx0XHRcdFx0dGhpcy5fZHJhZ2dhYmxlLm9uKCdwcmVkcmFnJywgdGhpcy5fb25QcmVEcmFnV3JhcCwgdGhpcyk7XG5cdFx0XHRcdG1hcC5vbignem9vbWVuZCcsIHRoaXMuX29uWm9vbUVuZCwgdGhpcyk7XG5cblx0XHRcdFx0bWFwLndoZW5SZWFkeSh0aGlzLl9vblpvb21FbmQsIHRoaXMpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRhZGRDbGFzcyh0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ2xlYWZsZXQtZ3JhYiBsZWFmbGV0LXRvdWNoLWRyYWcnKTtcblx0XHR0aGlzLl9kcmFnZ2FibGUuZW5hYmxlKCk7XG5cdFx0dGhpcy5fcG9zaXRpb25zID0gW107XG5cdFx0dGhpcy5fdGltZXMgPSBbXTtcblx0fSxcblxuXHRyZW1vdmVIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdHJlbW92ZUNsYXNzKHRoaXMuX21hcC5fY29udGFpbmVyLCAnbGVhZmxldC1ncmFiJyk7XG5cdFx0cmVtb3ZlQ2xhc3ModGhpcy5fbWFwLl9jb250YWluZXIsICdsZWFmbGV0LXRvdWNoLWRyYWcnKTtcblx0XHR0aGlzLl9kcmFnZ2FibGUuZGlzYWJsZSgpO1xuXHR9LFxuXG5cdG1vdmVkOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2RyYWdnYWJsZSAmJiB0aGlzLl9kcmFnZ2FibGUuX21vdmVkO1xuXHR9LFxuXG5cdG1vdmluZzogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLl9kcmFnZ2FibGUgJiYgdGhpcy5fZHJhZ2dhYmxlLl9tb3Zpbmc7XG5cdH0sXG5cblx0X29uRHJhZ1N0YXJ0OiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcblxuXHRcdG1hcC5fc3RvcCgpO1xuXHRcdGlmICh0aGlzLl9tYXAub3B0aW9ucy5tYXhCb3VuZHMgJiYgdGhpcy5fbWFwLm9wdGlvbnMubWF4Qm91bmRzVmlzY29zaXR5KSB7XG5cdFx0XHR2YXIgYm91bmRzID0gdG9MYXRMbmdCb3VuZHModGhpcy5fbWFwLm9wdGlvbnMubWF4Qm91bmRzKTtcblxuXHRcdFx0dGhpcy5fb2Zmc2V0TGltaXQgPSB0b0JvdW5kcyhcblx0XHRcdFx0dGhpcy5fbWFwLmxhdExuZ1RvQ29udGFpbmVyUG9pbnQoYm91bmRzLmdldE5vcnRoV2VzdCgpKS5tdWx0aXBseUJ5KC0xKSxcblx0XHRcdFx0dGhpcy5fbWFwLmxhdExuZ1RvQ29udGFpbmVyUG9pbnQoYm91bmRzLmdldFNvdXRoRWFzdCgpKS5tdWx0aXBseUJ5KC0xKVxuXHRcdFx0XHRcdC5hZGQodGhpcy5fbWFwLmdldFNpemUoKSkpO1xuXG5cdFx0XHR0aGlzLl92aXNjb3NpdHkgPSBNYXRoLm1pbigxLjAsIE1hdGgubWF4KDAuMCwgdGhpcy5fbWFwLm9wdGlvbnMubWF4Qm91bmRzVmlzY29zaXR5KSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX29mZnNldExpbWl0ID0gbnVsbDtcblx0XHR9XG5cblx0XHRtYXBcblx0XHQgICAgLmZpcmUoJ21vdmVzdGFydCcpXG5cdFx0ICAgIC5maXJlKCdkcmFnc3RhcnQnKTtcblxuXHRcdGlmIChtYXAub3B0aW9ucy5pbmVydGlhKSB7XG5cdFx0XHR0aGlzLl9wb3NpdGlvbnMgPSBbXTtcblx0XHRcdHRoaXMuX3RpbWVzID0gW107XG5cdFx0fVxuXHR9LFxuXG5cdF9vbkRyYWc6IGZ1bmN0aW9uIChlKSB7XG5cdFx0aWYgKHRoaXMuX21hcC5vcHRpb25zLmluZXJ0aWEpIHtcblx0XHRcdHZhciB0aW1lID0gdGhpcy5fbGFzdFRpbWUgPSArbmV3IERhdGUoKSxcblx0XHRcdCAgICBwb3MgPSB0aGlzLl9sYXN0UG9zID0gdGhpcy5fZHJhZ2dhYmxlLl9hYnNQb3MgfHwgdGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3M7XG5cblx0XHRcdHRoaXMuX3Bvc2l0aW9ucy5wdXNoKHBvcyk7XG5cdFx0XHR0aGlzLl90aW1lcy5wdXNoKHRpbWUpO1xuXG5cdFx0XHR0aGlzLl9wcnVuZVBvc2l0aW9ucyh0aW1lKTtcblx0XHR9XG5cblx0XHR0aGlzLl9tYXBcblx0XHQgICAgLmZpcmUoJ21vdmUnLCBlKVxuXHRcdCAgICAuZmlyZSgnZHJhZycsIGUpO1xuXHR9LFxuXG5cdF9wcnVuZVBvc2l0aW9uczogZnVuY3Rpb24gKHRpbWUpIHtcblx0XHR3aGlsZSAodGhpcy5fcG9zaXRpb25zLmxlbmd0aCA+IDEgJiYgdGltZSAtIHRoaXMuX3RpbWVzWzBdID4gNTApIHtcblx0XHRcdHRoaXMuX3Bvc2l0aW9ucy5zaGlmdCgpO1xuXHRcdFx0dGhpcy5fdGltZXMuc2hpZnQoKTtcblx0XHR9XG5cdH0sXG5cblx0X29uWm9vbUVuZDogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBweENlbnRlciA9IHRoaXMuX21hcC5nZXRTaXplKCkuZGl2aWRlQnkoMiksXG5cdFx0ICAgIHB4V29ybGRDZW50ZXIgPSB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KFswLCAwXSk7XG5cblx0XHR0aGlzLl9pbml0aWFsV29ybGRPZmZzZXQgPSBweFdvcmxkQ2VudGVyLnN1YnRyYWN0KHB4Q2VudGVyKS54O1xuXHRcdHRoaXMuX3dvcmxkV2lkdGggPSB0aGlzLl9tYXAuZ2V0UGl4ZWxXb3JsZEJvdW5kcygpLmdldFNpemUoKS54O1xuXHR9LFxuXG5cdF92aXNjb3VzTGltaXQ6IGZ1bmN0aW9uICh2YWx1ZSwgdGhyZXNob2xkKSB7XG5cdFx0cmV0dXJuIHZhbHVlIC0gKHZhbHVlIC0gdGhyZXNob2xkKSAqIHRoaXMuX3Zpc2Nvc2l0eTtcblx0fSxcblxuXHRfb25QcmVEcmFnTGltaXQ6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoIXRoaXMuX3Zpc2Nvc2l0eSB8fCAhdGhpcy5fb2Zmc2V0TGltaXQpIHsgcmV0dXJuOyB9XG5cblx0XHR2YXIgb2Zmc2V0ID0gdGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3Muc3VidHJhY3QodGhpcy5fZHJhZ2dhYmxlLl9zdGFydFBvcyk7XG5cblx0XHR2YXIgbGltaXQgPSB0aGlzLl9vZmZzZXRMaW1pdDtcblx0XHRpZiAob2Zmc2V0LnggPCBsaW1pdC5taW4ueCkgeyBvZmZzZXQueCA9IHRoaXMuX3Zpc2NvdXNMaW1pdChvZmZzZXQueCwgbGltaXQubWluLngpOyB9XG5cdFx0aWYgKG9mZnNldC55IDwgbGltaXQubWluLnkpIHsgb2Zmc2V0LnkgPSB0aGlzLl92aXNjb3VzTGltaXQob2Zmc2V0LnksIGxpbWl0Lm1pbi55KTsgfVxuXHRcdGlmIChvZmZzZXQueCA+IGxpbWl0Lm1heC54KSB7IG9mZnNldC54ID0gdGhpcy5fdmlzY291c0xpbWl0KG9mZnNldC54LCBsaW1pdC5tYXgueCk7IH1cblx0XHRpZiAob2Zmc2V0LnkgPiBsaW1pdC5tYXgueSkgeyBvZmZzZXQueSA9IHRoaXMuX3Zpc2NvdXNMaW1pdChvZmZzZXQueSwgbGltaXQubWF4LnkpOyB9XG5cblx0XHR0aGlzLl9kcmFnZ2FibGUuX25ld1BvcyA9IHRoaXMuX2RyYWdnYWJsZS5fc3RhcnRQb3MuYWRkKG9mZnNldCk7XG5cdH0sXG5cblx0X29uUHJlRHJhZ1dyYXA6IGZ1bmN0aW9uICgpIHtcblx0XHQvLyBUT0RPIHJlZmFjdG9yIHRvIGJlIGFibGUgdG8gYWRqdXN0IG1hcCBwYW5lIHBvc2l0aW9uIGFmdGVyIHpvb21cblx0XHR2YXIgd29ybGRXaWR0aCA9IHRoaXMuX3dvcmxkV2lkdGgsXG5cdFx0ICAgIGhhbGZXaWR0aCA9IE1hdGgucm91bmQod29ybGRXaWR0aCAvIDIpLFxuXHRcdCAgICBkeCA9IHRoaXMuX2luaXRpYWxXb3JsZE9mZnNldCxcblx0XHQgICAgeCA9IHRoaXMuX2RyYWdnYWJsZS5fbmV3UG9zLngsXG5cdFx0ICAgIG5ld1gxID0gKHggLSBoYWxmV2lkdGggKyBkeCkgJSB3b3JsZFdpZHRoICsgaGFsZldpZHRoIC0gZHgsXG5cdFx0ICAgIG5ld1gyID0gKHggKyBoYWxmV2lkdGggKyBkeCkgJSB3b3JsZFdpZHRoIC0gaGFsZldpZHRoIC0gZHgsXG5cdFx0ICAgIG5ld1ggPSBNYXRoLmFicyhuZXdYMSArIGR4KSA8IE1hdGguYWJzKG5ld1gyICsgZHgpID8gbmV3WDEgOiBuZXdYMjtcblxuXHRcdHRoaXMuX2RyYWdnYWJsZS5fYWJzUG9zID0gdGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3MuY2xvbmUoKTtcblx0XHR0aGlzLl9kcmFnZ2FibGUuX25ld1Bvcy54ID0gbmV3WDtcblx0fSxcblxuXHRfb25EcmFnRW5kOiBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBtYXAgPSB0aGlzLl9tYXAsXG5cdFx0ICAgIG9wdGlvbnMgPSBtYXAub3B0aW9ucyxcblxuXHRcdCAgICBub0luZXJ0aWEgPSAhb3B0aW9ucy5pbmVydGlhIHx8IHRoaXMuX3RpbWVzLmxlbmd0aCA8IDI7XG5cblx0XHRtYXAuZmlyZSgnZHJhZ2VuZCcsIGUpO1xuXG5cdFx0aWYgKG5vSW5lcnRpYSkge1xuXHRcdFx0bWFwLmZpcmUoJ21vdmVlbmQnKTtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLl9wcnVuZVBvc2l0aW9ucygrbmV3IERhdGUoKSk7XG5cblx0XHRcdHZhciBkaXJlY3Rpb24gPSB0aGlzLl9sYXN0UG9zLnN1YnRyYWN0KHRoaXMuX3Bvc2l0aW9uc1swXSksXG5cdFx0XHQgICAgZHVyYXRpb24gPSAodGhpcy5fbGFzdFRpbWUgLSB0aGlzLl90aW1lc1swXSkgLyAxMDAwLFxuXHRcdFx0ICAgIGVhc2UgPSBvcHRpb25zLmVhc2VMaW5lYXJpdHksXG5cblx0XHRcdCAgICBzcGVlZFZlY3RvciA9IGRpcmVjdGlvbi5tdWx0aXBseUJ5KGVhc2UgLyBkdXJhdGlvbiksXG5cdFx0XHQgICAgc3BlZWQgPSBzcGVlZFZlY3Rvci5kaXN0YW5jZVRvKFswLCAwXSksXG5cblx0XHRcdCAgICBsaW1pdGVkU3BlZWQgPSBNYXRoLm1pbihvcHRpb25zLmluZXJ0aWFNYXhTcGVlZCwgc3BlZWQpLFxuXHRcdFx0ICAgIGxpbWl0ZWRTcGVlZFZlY3RvciA9IHNwZWVkVmVjdG9yLm11bHRpcGx5QnkobGltaXRlZFNwZWVkIC8gc3BlZWQpLFxuXG5cdFx0XHQgICAgZGVjZWxlcmF0aW9uRHVyYXRpb24gPSBsaW1pdGVkU3BlZWQgLyAob3B0aW9ucy5pbmVydGlhRGVjZWxlcmF0aW9uICogZWFzZSksXG5cdFx0XHQgICAgb2Zmc2V0ID0gbGltaXRlZFNwZWVkVmVjdG9yLm11bHRpcGx5QnkoLWRlY2VsZXJhdGlvbkR1cmF0aW9uIC8gMikucm91bmQoKTtcblxuXHRcdFx0aWYgKCFvZmZzZXQueCAmJiAhb2Zmc2V0LnkpIHtcblx0XHRcdFx0bWFwLmZpcmUoJ21vdmVlbmQnKTtcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0b2Zmc2V0ID0gbWFwLl9saW1pdE9mZnNldChvZmZzZXQsIG1hcC5vcHRpb25zLm1heEJvdW5kcyk7XG5cblx0XHRcdFx0cmVxdWVzdEFuaW1GcmFtZShmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0bWFwLnBhbkJ5KG9mZnNldCwge1xuXHRcdFx0XHRcdFx0ZHVyYXRpb246IGRlY2VsZXJhdGlvbkR1cmF0aW9uLFxuXHRcdFx0XHRcdFx0ZWFzZUxpbmVhcml0eTogZWFzZSxcblx0XHRcdFx0XHRcdG5vTW92ZVN0YXJ0OiB0cnVlLFxuXHRcdFx0XHRcdFx0YW5pbWF0ZTogdHJ1ZVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn0pO1xuXG4vLyBAc2VjdGlvbiBIYW5kbGVyc1xuLy8gQHByb3BlcnR5IGRyYWdnaW5nOiBIYW5kbGVyXG4vLyBNYXAgZHJhZ2dpbmcgaGFuZGxlciAoYnkgYm90aCBtb3VzZSBhbmQgdG91Y2gpLlxuTWFwLmFkZEluaXRIb29rKCdhZGRIYW5kbGVyJywgJ2RyYWdnaW5nJywgRHJhZyk7XG5cbi8qXG4gKiBMLk1hcC5LZXlib2FyZCBpcyBoYW5kbGluZyBrZXlib2FyZCBpbnRlcmFjdGlvbiB3aXRoIHRoZSBtYXAsIGVuYWJsZWQgYnkgZGVmYXVsdC5cbiAqL1xuXG4vLyBAbmFtZXNwYWNlIE1hcFxuLy8gQHNlY3Rpb24gS2V5Ym9hcmQgTmF2aWdhdGlvbiBPcHRpb25zXG5NYXAubWVyZ2VPcHRpb25zKHtcblx0Ly8gQG9wdGlvbiBrZXlib2FyZDogQm9vbGVhbiA9IHRydWVcblx0Ly8gTWFrZXMgdGhlIG1hcCBmb2N1c2FibGUgYW5kIGFsbG93cyB1c2VycyB0byBuYXZpZ2F0ZSB0aGUgbWFwIHdpdGgga2V5Ym9hcmRcblx0Ly8gYXJyb3dzIGFuZCBgK2AvYC1gIGtleXMuXG5cdGtleWJvYXJkOiB0cnVlLFxuXG5cdC8vIEBvcHRpb24ga2V5Ym9hcmRQYW5EZWx0YTogTnVtYmVyID0gODBcblx0Ly8gQW1vdW50IG9mIHBpeGVscyB0byBwYW4gd2hlbiBwcmVzc2luZyBhbiBhcnJvdyBrZXkuXG5cdGtleWJvYXJkUGFuRGVsdGE6IDgwXG59KTtcblxudmFyIEtleWJvYXJkID0gSGFuZGxlci5leHRlbmQoe1xuXG5cdGtleUNvZGVzOiB7XG5cdFx0bGVmdDogICAgWzM3XSxcblx0XHRyaWdodDogICBbMzldLFxuXHRcdGRvd246ICAgIFs0MF0sXG5cdFx0dXA6ICAgICAgWzM4XSxcblx0XHR6b29tSW46ICBbMTg3LCAxMDcsIDYxLCAxNzFdLFxuXHRcdHpvb21PdXQ6IFsxODksIDEwOSwgNTQsIDE3M11cblx0fSxcblxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobWFwKSB7XG5cdFx0dGhpcy5fbWFwID0gbWFwO1xuXG5cdFx0dGhpcy5fc2V0UGFuRGVsdGEobWFwLm9wdGlvbnMua2V5Ym9hcmRQYW5EZWx0YSk7XG5cdFx0dGhpcy5fc2V0Wm9vbURlbHRhKG1hcC5vcHRpb25zLnpvb21EZWx0YSk7XG5cdH0sXG5cblx0YWRkSG9va3M6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgY29udGFpbmVyID0gdGhpcy5fbWFwLl9jb250YWluZXI7XG5cblx0XHQvLyBtYWtlIHRoZSBjb250YWluZXIgZm9jdXNhYmxlIGJ5IHRhYmJpbmdcblx0XHRpZiAoY29udGFpbmVyLnRhYkluZGV4IDw9IDApIHtcblx0XHRcdGNvbnRhaW5lci50YWJJbmRleCA9ICcwJztcblx0XHR9XG5cblx0XHRvbihjb250YWluZXIsIHtcblx0XHRcdGZvY3VzOiB0aGlzLl9vbkZvY3VzLFxuXHRcdFx0Ymx1cjogdGhpcy5fb25CbHVyLFxuXHRcdFx0bW91c2Vkb3duOiB0aGlzLl9vbk1vdXNlRG93blxuXHRcdH0sIHRoaXMpO1xuXG5cdFx0dGhpcy5fbWFwLm9uKHtcblx0XHRcdGZvY3VzOiB0aGlzLl9hZGRIb29rcyxcblx0XHRcdGJsdXI6IHRoaXMuX3JlbW92ZUhvb2tzXG5cdFx0fSwgdGhpcyk7XG5cdH0sXG5cblx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9yZW1vdmVIb29rcygpO1xuXG5cdFx0b2ZmKHRoaXMuX21hcC5fY29udGFpbmVyLCB7XG5cdFx0XHRmb2N1czogdGhpcy5fb25Gb2N1cyxcblx0XHRcdGJsdXI6IHRoaXMuX29uQmx1cixcblx0XHRcdG1vdXNlZG93bjogdGhpcy5fb25Nb3VzZURvd25cblx0XHR9LCB0aGlzKTtcblxuXHRcdHRoaXMuX21hcC5vZmYoe1xuXHRcdFx0Zm9jdXM6IHRoaXMuX2FkZEhvb2tzLFxuXHRcdFx0Ymx1cjogdGhpcy5fcmVtb3ZlSG9va3Ncblx0XHR9LCB0aGlzKTtcblx0fSxcblxuXHRfb25Nb3VzZURvd246IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAodGhpcy5fZm9jdXNlZCkgeyByZXR1cm47IH1cblxuXHRcdHZhciBib2R5ID0gZG9jdW1lbnQuYm9keSxcblx0XHQgICAgZG9jRWwgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsXG5cdFx0ICAgIHRvcCA9IGJvZHkuc2Nyb2xsVG9wIHx8IGRvY0VsLnNjcm9sbFRvcCxcblx0XHQgICAgbGVmdCA9IGJvZHkuc2Nyb2xsTGVmdCB8fCBkb2NFbC5zY3JvbGxMZWZ0O1xuXG5cdFx0dGhpcy5fbWFwLl9jb250YWluZXIuZm9jdXMoKTtcblxuXHRcdHdpbmRvdy5zY3JvbGxUbyhsZWZ0LCB0b3ApO1xuXHR9LFxuXG5cdF9vbkZvY3VzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5fZm9jdXNlZCA9IHRydWU7XG5cdFx0dGhpcy5fbWFwLmZpcmUoJ2ZvY3VzJyk7XG5cdH0sXG5cblx0X29uQmx1cjogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX2ZvY3VzZWQgPSBmYWxzZTtcblx0XHR0aGlzLl9tYXAuZmlyZSgnYmx1cicpO1xuXHR9LFxuXG5cdF9zZXRQYW5EZWx0YTogZnVuY3Rpb24gKHBhbkRlbHRhKSB7XG5cdFx0dmFyIGtleXMgPSB0aGlzLl9wYW5LZXlzID0ge30sXG5cdFx0ICAgIGNvZGVzID0gdGhpcy5rZXlDb2Rlcyxcblx0XHQgICAgaSwgbGVuO1xuXG5cdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMubGVmdC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0a2V5c1tjb2Rlcy5sZWZ0W2ldXSA9IFstMSAqIHBhbkRlbHRhLCAwXTtcblx0XHR9XG5cdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMucmlnaHQubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdGtleXNbY29kZXMucmlnaHRbaV1dID0gW3BhbkRlbHRhLCAwXTtcblx0XHR9XG5cdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMuZG93bi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0a2V5c1tjb2Rlcy5kb3duW2ldXSA9IFswLCBwYW5EZWx0YV07XG5cdFx0fVxuXHRcdGZvciAoaSA9IDAsIGxlbiA9IGNvZGVzLnVwLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRrZXlzW2NvZGVzLnVwW2ldXSA9IFswLCAtMSAqIHBhbkRlbHRhXTtcblx0XHR9XG5cdH0sXG5cblx0X3NldFpvb21EZWx0YTogZnVuY3Rpb24gKHpvb21EZWx0YSkge1xuXHRcdHZhciBrZXlzID0gdGhpcy5fem9vbUtleXMgPSB7fSxcblx0XHQgICAgY29kZXMgPSB0aGlzLmtleUNvZGVzLFxuXHRcdCAgICBpLCBsZW47XG5cblx0XHRmb3IgKGkgPSAwLCBsZW4gPSBjb2Rlcy56b29tSW4ubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdGtleXNbY29kZXMuem9vbUluW2ldXSA9IHpvb21EZWx0YTtcblx0XHR9XG5cdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMuem9vbU91dC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0a2V5c1tjb2Rlcy56b29tT3V0W2ldXSA9IC16b29tRGVsdGE7XG5cdFx0fVxuXHR9LFxuXG5cdF9hZGRIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdG9uKGRvY3VtZW50LCAna2V5ZG93bicsIHRoaXMuX29uS2V5RG93biwgdGhpcyk7XG5cdH0sXG5cblx0X3JlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0b2ZmKGRvY3VtZW50LCAna2V5ZG93bicsIHRoaXMuX29uS2V5RG93biwgdGhpcyk7XG5cdH0sXG5cblx0X29uS2V5RG93bjogZnVuY3Rpb24gKGUpIHtcblx0XHRpZiAoZS5hbHRLZXkgfHwgZS5jdHJsS2V5IHx8IGUubWV0YUtleSkgeyByZXR1cm47IH1cblxuXHRcdHZhciBrZXkgPSBlLmtleUNvZGUsXG5cdFx0ICAgIG1hcCA9IHRoaXMuX21hcCxcblx0XHQgICAgb2Zmc2V0O1xuXG5cdFx0aWYgKGtleSBpbiB0aGlzLl9wYW5LZXlzKSB7XG5cdFx0XHRpZiAoIW1hcC5fcGFuQW5pbSB8fCAhbWFwLl9wYW5BbmltLl9pblByb2dyZXNzKSB7XG5cdFx0XHRcdG9mZnNldCA9IHRoaXMuX3BhbktleXNba2V5XTtcblx0XHRcdFx0aWYgKGUuc2hpZnRLZXkpIHtcblx0XHRcdFx0XHRvZmZzZXQgPSB0b1BvaW50KG9mZnNldCkubXVsdGlwbHlCeSgzKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdG1hcC5wYW5CeShvZmZzZXQpO1xuXG5cdFx0XHRcdGlmIChtYXAub3B0aW9ucy5tYXhCb3VuZHMpIHtcblx0XHRcdFx0XHRtYXAucGFuSW5zaWRlQm91bmRzKG1hcC5vcHRpb25zLm1heEJvdW5kcyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKGtleSBpbiB0aGlzLl96b29tS2V5cykge1xuXHRcdFx0bWFwLnNldFpvb20obWFwLmdldFpvb20oKSArIChlLnNoaWZ0S2V5ID8gMyA6IDEpICogdGhpcy5fem9vbUtleXNba2V5XSk7XG5cblx0XHR9IGVsc2UgaWYgKGtleSA9PT0gMjcgJiYgbWFwLl9wb3B1cCAmJiBtYXAuX3BvcHVwLm9wdGlvbnMuY2xvc2VPbkVzY2FwZUtleSkge1xuXHRcdFx0bWFwLmNsb3NlUG9wdXAoKTtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0c3RvcChlKTtcblx0fVxufSk7XG5cbi8vIEBzZWN0aW9uIEhhbmRsZXJzXG4vLyBAc2VjdGlvbiBIYW5kbGVyc1xuLy8gQHByb3BlcnR5IGtleWJvYXJkOiBIYW5kbGVyXG4vLyBLZXlib2FyZCBuYXZpZ2F0aW9uIGhhbmRsZXIuXG5NYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAna2V5Ym9hcmQnLCBLZXlib2FyZCk7XG5cbi8qXG4gKiBMLkhhbmRsZXIuU2Nyb2xsV2hlZWxab29tIGlzIHVzZWQgYnkgTC5NYXAgdG8gZW5hYmxlIG1vdXNlIHNjcm9sbCB3aGVlbCB6b29tIG9uIHRoZSBtYXAuXG4gKi9cblxuLy8gQG5hbWVzcGFjZSBNYXBcbi8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcbk1hcC5tZXJnZU9wdGlvbnMoe1xuXHQvLyBAc2VjdGlvbiBNb3VzZXdoZWVsIG9wdGlvbnNcblx0Ly8gQG9wdGlvbiBzY3JvbGxXaGVlbFpvb206IEJvb2xlYW58U3RyaW5nID0gdHJ1ZVxuXHQvLyBXaGV0aGVyIHRoZSBtYXAgY2FuIGJlIHpvb21lZCBieSB1c2luZyB0aGUgbW91c2Ugd2hlZWwuIElmIHBhc3NlZCBgJ2NlbnRlcidgLFxuXHQvLyBpdCB3aWxsIHpvb20gdG8gdGhlIGNlbnRlciBvZiB0aGUgdmlldyByZWdhcmRsZXNzIG9mIHdoZXJlIHRoZSBtb3VzZSB3YXMuXG5cdHNjcm9sbFdoZWVsWm9vbTogdHJ1ZSxcblxuXHQvLyBAb3B0aW9uIHdoZWVsRGVib3VuY2VUaW1lOiBOdW1iZXIgPSA0MFxuXHQvLyBMaW1pdHMgdGhlIHJhdGUgYXQgd2hpY2ggYSB3aGVlbCBjYW4gZmlyZSAoaW4gbWlsbGlzZWNvbmRzKS4gQnkgZGVmYXVsdFxuXHQvLyB1c2VyIGNhbid0IHpvb20gdmlhIHdoZWVsIG1vcmUgb2Z0ZW4gdGhhbiBvbmNlIHBlciA0MCBtcy5cblx0d2hlZWxEZWJvdW5jZVRpbWU6IDQwLFxuXG5cdC8vIEBvcHRpb24gd2hlZWxQeFBlclpvb21MZXZlbDogTnVtYmVyID0gNjBcblx0Ly8gSG93IG1hbnkgc2Nyb2xsIHBpeGVscyAoYXMgcmVwb3J0ZWQgYnkgW0wuRG9tRXZlbnQuZ2V0V2hlZWxEZWx0YV0oI2RvbWV2ZW50LWdldHdoZWVsZGVsdGEpKVxuXHQvLyBtZWFuIGEgY2hhbmdlIG9mIG9uZSBmdWxsIHpvb20gbGV2ZWwuIFNtYWxsZXIgdmFsdWVzIHdpbGwgbWFrZSB3aGVlbC16b29taW5nXG5cdC8vIGZhc3RlciAoYW5kIHZpY2UgdmVyc2EpLlxuXHR3aGVlbFB4UGVyWm9vbUxldmVsOiA2MFxufSk7XG5cbnZhciBTY3JvbGxXaGVlbFpvb20gPSBIYW5kbGVyLmV4dGVuZCh7XG5cdGFkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0b24odGhpcy5fbWFwLl9jb250YWluZXIsICdtb3VzZXdoZWVsJywgdGhpcy5fb25XaGVlbFNjcm9sbCwgdGhpcyk7XG5cblx0XHR0aGlzLl9kZWx0YSA9IDA7XG5cdH0sXG5cblx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcblx0XHRvZmYodGhpcy5fbWFwLl9jb250YWluZXIsICdtb3VzZXdoZWVsJywgdGhpcy5fb25XaGVlbFNjcm9sbCwgdGhpcyk7XG5cdH0sXG5cblx0X29uV2hlZWxTY3JvbGw6IGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIGRlbHRhID0gZ2V0V2hlZWxEZWx0YShlKTtcblxuXHRcdHZhciBkZWJvdW5jZSA9IHRoaXMuX21hcC5vcHRpb25zLndoZWVsRGVib3VuY2VUaW1lO1xuXG5cdFx0dGhpcy5fZGVsdGEgKz0gZGVsdGE7XG5cdFx0dGhpcy5fbGFzdE1vdXNlUG9zID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUpO1xuXG5cdFx0aWYgKCF0aGlzLl9zdGFydFRpbWUpIHtcblx0XHRcdHRoaXMuX3N0YXJ0VGltZSA9ICtuZXcgRGF0ZSgpO1xuXHRcdH1cblxuXHRcdHZhciBsZWZ0ID0gTWF0aC5tYXgoZGVib3VuY2UgLSAoK25ldyBEYXRlKCkgLSB0aGlzLl9zdGFydFRpbWUpLCAwKTtcblxuXHRcdGNsZWFyVGltZW91dCh0aGlzLl90aW1lcik7XG5cdFx0dGhpcy5fdGltZXIgPSBzZXRUaW1lb3V0KGJpbmQodGhpcy5fcGVyZm9ybVpvb20sIHRoaXMpLCBsZWZ0KTtcblxuXHRcdHN0b3AoZSk7XG5cdH0sXG5cblx0X3BlcmZvcm1ab29tOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcblx0XHQgICAgem9vbSA9IG1hcC5nZXRab29tKCksXG5cdFx0ICAgIHNuYXAgPSB0aGlzLl9tYXAub3B0aW9ucy56b29tU25hcCB8fCAwO1xuXG5cdFx0bWFwLl9zdG9wKCk7IC8vIHN0b3AgcGFubmluZyBhbmQgZmx5IGFuaW1hdGlvbnMgaWYgYW55XG5cblx0XHQvLyBtYXAgdGhlIGRlbHRhIHdpdGggYSBzaWdtb2lkIGZ1bmN0aW9uIHRvIC00Li40IHJhbmdlIGxlYW5pbmcgb24gLTEuLjFcblx0XHR2YXIgZDIgPSB0aGlzLl9kZWx0YSAvICh0aGlzLl9tYXAub3B0aW9ucy53aGVlbFB4UGVyWm9vbUxldmVsICogNCksXG5cdFx0ICAgIGQzID0gNCAqIE1hdGgubG9nKDIgLyAoMSArIE1hdGguZXhwKC1NYXRoLmFicyhkMikpKSkgLyBNYXRoLkxOMixcblx0XHQgICAgZDQgPSBzbmFwID8gTWF0aC5jZWlsKGQzIC8gc25hcCkgKiBzbmFwIDogZDMsXG5cdFx0ICAgIGRlbHRhID0gbWFwLl9saW1pdFpvb20oem9vbSArICh0aGlzLl9kZWx0YSA+IDAgPyBkNCA6IC1kNCkpIC0gem9vbTtcblxuXHRcdHRoaXMuX2RlbHRhID0gMDtcblx0XHR0aGlzLl9zdGFydFRpbWUgPSBudWxsO1xuXG5cdFx0aWYgKCFkZWx0YSkgeyByZXR1cm47IH1cblxuXHRcdGlmIChtYXAub3B0aW9ucy5zY3JvbGxXaGVlbFpvb20gPT09ICdjZW50ZXInKSB7XG5cdFx0XHRtYXAuc2V0Wm9vbSh6b29tICsgZGVsdGEpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRtYXAuc2V0Wm9vbUFyb3VuZCh0aGlzLl9sYXN0TW91c2VQb3MsIHpvb20gKyBkZWx0YSk7XG5cdFx0fVxuXHR9XG59KTtcblxuLy8gQHNlY3Rpb24gSGFuZGxlcnNcbi8vIEBwcm9wZXJ0eSBzY3JvbGxXaGVlbFpvb206IEhhbmRsZXJcbi8vIFNjcm9sbCB3aGVlbCB6b29tIGhhbmRsZXIuXG5NYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAnc2Nyb2xsV2hlZWxab29tJywgU2Nyb2xsV2hlZWxab29tKTtcblxuLypcbiAqIEwuTWFwLlRhcCBpcyB1c2VkIHRvIGVuYWJsZSBtb2JpbGUgaGFja3MgbGlrZSBxdWljayB0YXBzIGFuZCBsb25nIGhvbGQuXG4gKi9cblxuLy8gQG5hbWVzcGFjZSBNYXBcbi8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcbk1hcC5tZXJnZU9wdGlvbnMoe1xuXHQvLyBAc2VjdGlvbiBUb3VjaCBpbnRlcmFjdGlvbiBvcHRpb25zXG5cdC8vIEBvcHRpb24gdGFwOiBCb29sZWFuID0gdHJ1ZVxuXHQvLyBFbmFibGVzIG1vYmlsZSBoYWNrcyBmb3Igc3VwcG9ydGluZyBpbnN0YW50IHRhcHMgKGZpeGluZyAyMDBtcyBjbGlja1xuXHQvLyBkZWxheSBvbiBpT1MvQW5kcm9pZCkgYW5kIHRvdWNoIGhvbGRzIChmaXJlZCBhcyBgY29udGV4dG1lbnVgIGV2ZW50cykuXG5cdHRhcDogdHJ1ZSxcblxuXHQvLyBAb3B0aW9uIHRhcFRvbGVyYW5jZTogTnVtYmVyID0gMTVcblx0Ly8gVGhlIG1heCBudW1iZXIgb2YgcGl4ZWxzIGEgdXNlciBjYW4gc2hpZnQgaGlzIGZpbmdlciBkdXJpbmcgdG91Y2hcblx0Ly8gZm9yIGl0IHRvIGJlIGNvbnNpZGVyZWQgYSB2YWxpZCB0YXAuXG5cdHRhcFRvbGVyYW5jZTogMTVcbn0pO1xuXG52YXIgVGFwID0gSGFuZGxlci5leHRlbmQoe1xuXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdG9uKHRoaXMuX21hcC5fY29udGFpbmVyLCAndG91Y2hzdGFydCcsIHRoaXMuX29uRG93biwgdGhpcyk7XG5cdH0sXG5cblx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcblx0XHRvZmYodGhpcy5fbWFwLl9jb250YWluZXIsICd0b3VjaHN0YXJ0JywgdGhpcy5fb25Eb3duLCB0aGlzKTtcblx0fSxcblxuXHRfb25Eb3duOiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmICghZS50b3VjaGVzKSB7IHJldHVybjsgfVxuXG5cdFx0cHJldmVudERlZmF1bHQoZSk7XG5cblx0XHR0aGlzLl9maXJlQ2xpY2sgPSB0cnVlO1xuXG5cdFx0Ly8gZG9uJ3Qgc2ltdWxhdGUgY2xpY2sgb3IgdHJhY2sgbG9uZ3ByZXNzIGlmIG1vcmUgdGhhbiAxIHRvdWNoXG5cdFx0aWYgKGUudG91Y2hlcy5sZW5ndGggPiAxKSB7XG5cdFx0XHR0aGlzLl9maXJlQ2xpY2sgPSBmYWxzZTtcblx0XHRcdGNsZWFyVGltZW91dCh0aGlzLl9ob2xkVGltZW91dCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIGZpcnN0ID0gZS50b3VjaGVzWzBdLFxuXHRcdCAgICBlbCA9IGZpcnN0LnRhcmdldDtcblxuXHRcdHRoaXMuX3N0YXJ0UG9zID0gdGhpcy5fbmV3UG9zID0gbmV3IFBvaW50KGZpcnN0LmNsaWVudFgsIGZpcnN0LmNsaWVudFkpO1xuXG5cdFx0Ly8gaWYgdG91Y2hpbmcgYSBsaW5rLCBoaWdobGlnaHQgaXRcblx0XHRpZiAoZWwudGFnTmFtZSAmJiBlbC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdhJykge1xuXHRcdFx0YWRkQ2xhc3MoZWwsICdsZWFmbGV0LWFjdGl2ZScpO1xuXHRcdH1cblxuXHRcdC8vIHNpbXVsYXRlIGxvbmcgaG9sZCBidXQgc2V0dGluZyBhIHRpbWVvdXRcblx0XHR0aGlzLl9ob2xkVGltZW91dCA9IHNldFRpbWVvdXQoYmluZChmdW5jdGlvbiAoKSB7XG5cdFx0XHRpZiAodGhpcy5faXNUYXBWYWxpZCgpKSB7XG5cdFx0XHRcdHRoaXMuX2ZpcmVDbGljayA9IGZhbHNlO1xuXHRcdFx0XHR0aGlzLl9vblVwKCk7XG5cdFx0XHRcdHRoaXMuX3NpbXVsYXRlRXZlbnQoJ2NvbnRleHRtZW51JywgZmlyc3QpO1xuXHRcdFx0fVxuXHRcdH0sIHRoaXMpLCAxMDAwKTtcblxuXHRcdHRoaXMuX3NpbXVsYXRlRXZlbnQoJ21vdXNlZG93bicsIGZpcnN0KTtcblxuXHRcdG9uKGRvY3VtZW50LCB7XG5cdFx0XHR0b3VjaG1vdmU6IHRoaXMuX29uTW92ZSxcblx0XHRcdHRvdWNoZW5kOiB0aGlzLl9vblVwXG5cdFx0fSwgdGhpcyk7XG5cdH0sXG5cblx0X29uVXA6IGZ1bmN0aW9uIChlKSB7XG5cdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX2hvbGRUaW1lb3V0KTtcblxuXHRcdG9mZihkb2N1bWVudCwge1xuXHRcdFx0dG91Y2htb3ZlOiB0aGlzLl9vbk1vdmUsXG5cdFx0XHR0b3VjaGVuZDogdGhpcy5fb25VcFxuXHRcdH0sIHRoaXMpO1xuXG5cdFx0aWYgKHRoaXMuX2ZpcmVDbGljayAmJiBlICYmIGUuY2hhbmdlZFRvdWNoZXMpIHtcblxuXHRcdFx0dmFyIGZpcnN0ID0gZS5jaGFuZ2VkVG91Y2hlc1swXSxcblx0XHRcdCAgICBlbCA9IGZpcnN0LnRhcmdldDtcblxuXHRcdFx0aWYgKGVsICYmIGVsLnRhZ05hbWUgJiYgZWwudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnYScpIHtcblx0XHRcdFx0cmVtb3ZlQ2xhc3MoZWwsICdsZWFmbGV0LWFjdGl2ZScpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl9zaW11bGF0ZUV2ZW50KCdtb3VzZXVwJywgZmlyc3QpO1xuXG5cdFx0XHQvLyBzaW11bGF0ZSBjbGljayBpZiB0aGUgdG91Y2ggZGlkbid0IG1vdmUgdG9vIG11Y2hcblx0XHRcdGlmICh0aGlzLl9pc1RhcFZhbGlkKCkpIHtcblx0XHRcdFx0dGhpcy5fc2ltdWxhdGVFdmVudCgnY2xpY2snLCBmaXJzdCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdF9pc1RhcFZhbGlkOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX25ld1Bvcy5kaXN0YW5jZVRvKHRoaXMuX3N0YXJ0UG9zKSA8PSB0aGlzLl9tYXAub3B0aW9ucy50YXBUb2xlcmFuY2U7XG5cdH0sXG5cblx0X29uTW92ZTogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgZmlyc3QgPSBlLnRvdWNoZXNbMF07XG5cdFx0dGhpcy5fbmV3UG9zID0gbmV3IFBvaW50KGZpcnN0LmNsaWVudFgsIGZpcnN0LmNsaWVudFkpO1xuXHRcdHRoaXMuX3NpbXVsYXRlRXZlbnQoJ21vdXNlbW92ZScsIGZpcnN0KTtcblx0fSxcblxuXHRfc2ltdWxhdGVFdmVudDogZnVuY3Rpb24gKHR5cGUsIGUpIHtcblx0XHR2YXIgc2ltdWxhdGVkRXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnTW91c2VFdmVudHMnKTtcblxuXHRcdHNpbXVsYXRlZEV2ZW50Ll9zaW11bGF0ZWQgPSB0cnVlO1xuXHRcdGUudGFyZ2V0Ll9zaW11bGF0ZWRDbGljayA9IHRydWU7XG5cblx0XHRzaW11bGF0ZWRFdmVudC5pbml0TW91c2VFdmVudChcblx0XHQgICAgICAgIHR5cGUsIHRydWUsIHRydWUsIHdpbmRvdywgMSxcblx0XHQgICAgICAgIGUuc2NyZWVuWCwgZS5zY3JlZW5ZLFxuXHRcdCAgICAgICAgZS5jbGllbnRYLCBlLmNsaWVudFksXG5cdFx0ICAgICAgICBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgMCwgbnVsbCk7XG5cblx0XHRlLnRhcmdldC5kaXNwYXRjaEV2ZW50KHNpbXVsYXRlZEV2ZW50KTtcblx0fVxufSk7XG5cbi8vIEBzZWN0aW9uIEhhbmRsZXJzXG4vLyBAcHJvcGVydHkgdGFwOiBIYW5kbGVyXG4vLyBNb2JpbGUgdG91Y2ggaGFja3MgKHF1aWNrIHRhcCBhbmQgdG91Y2ggaG9sZCkgaGFuZGxlci5cbmlmICh0b3VjaCAmJiAhcG9pbnRlcikge1xuXHRNYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAndGFwJywgVGFwKTtcbn1cblxuLypcbiAqIEwuSGFuZGxlci5Ub3VjaFpvb20gaXMgdXNlZCBieSBMLk1hcCB0byBhZGQgcGluY2ggem9vbSBvbiBzdXBwb3J0ZWQgbW9iaWxlIGJyb3dzZXJzLlxuICovXG5cbi8vIEBuYW1lc3BhY2UgTWFwXG4vLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG5NYXAubWVyZ2VPcHRpb25zKHtcblx0Ly8gQHNlY3Rpb24gVG91Y2ggaW50ZXJhY3Rpb24gb3B0aW9uc1xuXHQvLyBAb3B0aW9uIHRvdWNoWm9vbTogQm9vbGVhbnxTdHJpbmcgPSAqXG5cdC8vIFdoZXRoZXIgdGhlIG1hcCBjYW4gYmUgem9vbWVkIGJ5IHRvdWNoLWRyYWdnaW5nIHdpdGggdHdvIGZpbmdlcnMuIElmXG5cdC8vIHBhc3NlZCBgJ2NlbnRlcidgLCBpdCB3aWxsIHpvb20gdG8gdGhlIGNlbnRlciBvZiB0aGUgdmlldyByZWdhcmRsZXNzIG9mXG5cdC8vIHdoZXJlIHRoZSB0b3VjaCBldmVudHMgKGZpbmdlcnMpIHdlcmUuIEVuYWJsZWQgZm9yIHRvdWNoLWNhcGFibGUgd2ViXG5cdC8vIGJyb3dzZXJzIGV4Y2VwdCBmb3Igb2xkIEFuZHJvaWRzLlxuXHR0b3VjaFpvb206IHRvdWNoICYmICFhbmRyb2lkMjMsXG5cblx0Ly8gQG9wdGlvbiBib3VuY2VBdFpvb21MaW1pdHM6IEJvb2xlYW4gPSB0cnVlXG5cdC8vIFNldCBpdCB0byBmYWxzZSBpZiB5b3UgZG9uJ3Qgd2FudCB0aGUgbWFwIHRvIHpvb20gYmV5b25kIG1pbi9tYXggem9vbVxuXHQvLyBhbmQgdGhlbiBib3VuY2UgYmFjayB3aGVuIHBpbmNoLXpvb21pbmcuXG5cdGJvdW5jZUF0Wm9vbUxpbWl0czogdHJ1ZVxufSk7XG5cbnZhciBUb3VjaFpvb20gPSBIYW5kbGVyLmV4dGVuZCh7XG5cdGFkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0YWRkQ2xhc3ModGhpcy5fbWFwLl9jb250YWluZXIsICdsZWFmbGV0LXRvdWNoLXpvb20nKTtcblx0XHRvbih0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ3RvdWNoc3RhcnQnLCB0aGlzLl9vblRvdWNoU3RhcnQsIHRoaXMpO1xuXHR9LFxuXG5cdHJlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmVtb3ZlQ2xhc3ModGhpcy5fbWFwLl9jb250YWluZXIsICdsZWFmbGV0LXRvdWNoLXpvb20nKTtcblx0XHRvZmYodGhpcy5fbWFwLl9jb250YWluZXIsICd0b3VjaHN0YXJ0JywgdGhpcy5fb25Ub3VjaFN0YXJ0LCB0aGlzKTtcblx0fSxcblxuXHRfb25Ub3VjaFN0YXJ0OiBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBtYXAgPSB0aGlzLl9tYXA7XG5cdFx0aWYgKCFlLnRvdWNoZXMgfHwgZS50b3VjaGVzLmxlbmd0aCAhPT0gMiB8fCBtYXAuX2FuaW1hdGluZ1pvb20gfHwgdGhpcy5fem9vbWluZykgeyByZXR1cm47IH1cblxuXHRcdHZhciBwMSA9IG1hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLnRvdWNoZXNbMF0pLFxuXHRcdCAgICBwMiA9IG1hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLnRvdWNoZXNbMV0pO1xuXG5cdFx0dGhpcy5fY2VudGVyUG9pbnQgPSBtYXAuZ2V0U2l6ZSgpLl9kaXZpZGVCeSgyKTtcblx0XHR0aGlzLl9zdGFydExhdExuZyA9IG1hcC5jb250YWluZXJQb2ludFRvTGF0TG5nKHRoaXMuX2NlbnRlclBvaW50KTtcblx0XHRpZiAobWFwLm9wdGlvbnMudG91Y2hab29tICE9PSAnY2VudGVyJykge1xuXHRcdFx0dGhpcy5fcGluY2hTdGFydExhdExuZyA9IG1hcC5jb250YWluZXJQb2ludFRvTGF0TG5nKHAxLmFkZChwMikuX2RpdmlkZUJ5KDIpKTtcblx0XHR9XG5cblx0XHR0aGlzLl9zdGFydERpc3QgPSBwMS5kaXN0YW5jZVRvKHAyKTtcblx0XHR0aGlzLl9zdGFydFpvb20gPSBtYXAuZ2V0Wm9vbSgpO1xuXG5cdFx0dGhpcy5fbW92ZWQgPSBmYWxzZTtcblx0XHR0aGlzLl96b29taW5nID0gdHJ1ZTtcblxuXHRcdG1hcC5fc3RvcCgpO1xuXG5cdFx0b24oZG9jdW1lbnQsICd0b3VjaG1vdmUnLCB0aGlzLl9vblRvdWNoTW92ZSwgdGhpcyk7XG5cdFx0b24oZG9jdW1lbnQsICd0b3VjaGVuZCcsIHRoaXMuX29uVG91Y2hFbmQsIHRoaXMpO1xuXG5cdFx0cHJldmVudERlZmF1bHQoZSk7XG5cdH0sXG5cblx0X29uVG91Y2hNb3ZlOiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmICghZS50b3VjaGVzIHx8IGUudG91Y2hlcy5sZW5ndGggIT09IDIgfHwgIXRoaXMuX3pvb21pbmcpIHsgcmV0dXJuOyB9XG5cblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuXHRcdCAgICBwMSA9IG1hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLnRvdWNoZXNbMF0pLFxuXHRcdCAgICBwMiA9IG1hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLnRvdWNoZXNbMV0pLFxuXHRcdCAgICBzY2FsZSA9IHAxLmRpc3RhbmNlVG8ocDIpIC8gdGhpcy5fc3RhcnREaXN0O1xuXG5cdFx0dGhpcy5fem9vbSA9IG1hcC5nZXRTY2FsZVpvb20oc2NhbGUsIHRoaXMuX3N0YXJ0Wm9vbSk7XG5cblx0XHRpZiAoIW1hcC5vcHRpb25zLmJvdW5jZUF0Wm9vbUxpbWl0cyAmJiAoXG5cdFx0XHQodGhpcy5fem9vbSA8IG1hcC5nZXRNaW5ab29tKCkgJiYgc2NhbGUgPCAxKSB8fFxuXHRcdFx0KHRoaXMuX3pvb20gPiBtYXAuZ2V0TWF4Wm9vbSgpICYmIHNjYWxlID4gMSkpKSB7XG5cdFx0XHR0aGlzLl96b29tID0gbWFwLl9saW1pdFpvb20odGhpcy5fem9vbSk7XG5cdFx0fVxuXG5cdFx0aWYgKG1hcC5vcHRpb25zLnRvdWNoWm9vbSA9PT0gJ2NlbnRlcicpIHtcblx0XHRcdHRoaXMuX2NlbnRlciA9IHRoaXMuX3N0YXJ0TGF0TG5nO1xuXHRcdFx0aWYgKHNjYWxlID09PSAxKSB7IHJldHVybjsgfVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBHZXQgZGVsdGEgZnJvbSBwaW5jaCB0byBjZW50ZXIsIHNvIGNlbnRlckxhdExuZyBpcyBkZWx0YSBhcHBsaWVkIHRvIGluaXRpYWwgcGluY2hMYXRMbmdcblx0XHRcdHZhciBkZWx0YSA9IHAxLl9hZGQocDIpLl9kaXZpZGVCeSgyKS5fc3VidHJhY3QodGhpcy5fY2VudGVyUG9pbnQpO1xuXHRcdFx0aWYgKHNjYWxlID09PSAxICYmIGRlbHRhLnggPT09IDAgJiYgZGVsdGEueSA9PT0gMCkgeyByZXR1cm47IH1cblx0XHRcdHRoaXMuX2NlbnRlciA9IG1hcC51bnByb2plY3QobWFwLnByb2plY3QodGhpcy5fcGluY2hTdGFydExhdExuZywgdGhpcy5fem9vbSkuc3VidHJhY3QoZGVsdGEpLCB0aGlzLl96b29tKTtcblx0XHR9XG5cblx0XHRpZiAoIXRoaXMuX21vdmVkKSB7XG5cdFx0XHRtYXAuX21vdmVTdGFydCh0cnVlLCBmYWxzZSk7XG5cdFx0XHR0aGlzLl9tb3ZlZCA9IHRydWU7XG5cdFx0fVxuXG5cdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2FuaW1SZXF1ZXN0KTtcblxuXHRcdHZhciBtb3ZlRm4gPSBiaW5kKG1hcC5fbW92ZSwgbWFwLCB0aGlzLl9jZW50ZXIsIHRoaXMuX3pvb20sIHtwaW5jaDogdHJ1ZSwgcm91bmQ6IGZhbHNlfSk7XG5cdFx0dGhpcy5fYW5pbVJlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lKG1vdmVGbiwgdGhpcywgdHJ1ZSk7XG5cblx0XHRwcmV2ZW50RGVmYXVsdChlKTtcblx0fSxcblxuXHRfb25Ub3VjaEVuZDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICghdGhpcy5fbW92ZWQgfHwgIXRoaXMuX3pvb21pbmcpIHtcblx0XHRcdHRoaXMuX3pvb21pbmcgPSBmYWxzZTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0aGlzLl96b29taW5nID0gZmFsc2U7XG5cdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2FuaW1SZXF1ZXN0KTtcblxuXHRcdG9mZihkb2N1bWVudCwgJ3RvdWNobW92ZScsIHRoaXMuX29uVG91Y2hNb3ZlKTtcblx0XHRvZmYoZG9jdW1lbnQsICd0b3VjaGVuZCcsIHRoaXMuX29uVG91Y2hFbmQpO1xuXG5cdFx0Ly8gUGluY2ggdXBkYXRlcyBHcmlkTGF5ZXJzJyBsZXZlbHMgb25seSB3aGVuIHpvb21TbmFwIGlzIG9mZiwgc28gem9vbVNuYXAgYmVjb21lcyBub1VwZGF0ZS5cblx0XHRpZiAodGhpcy5fbWFwLm9wdGlvbnMuem9vbUFuaW1hdGlvbikge1xuXHRcdFx0dGhpcy5fbWFwLl9hbmltYXRlWm9vbSh0aGlzLl9jZW50ZXIsIHRoaXMuX21hcC5fbGltaXRab29tKHRoaXMuX3pvb20pLCB0cnVlLCB0aGlzLl9tYXAub3B0aW9ucy56b29tU25hcCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX21hcC5fcmVzZXRWaWV3KHRoaXMuX2NlbnRlciwgdGhpcy5fbWFwLl9saW1pdFpvb20odGhpcy5fem9vbSkpO1xuXHRcdH1cblx0fVxufSk7XG5cbi8vIEBzZWN0aW9uIEhhbmRsZXJzXG4vLyBAcHJvcGVydHkgdG91Y2hab29tOiBIYW5kbGVyXG4vLyBUb3VjaCB6b29tIGhhbmRsZXIuXG5NYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAndG91Y2hab29tJywgVG91Y2hab29tKTtcblxuTWFwLkJveFpvb20gPSBCb3hab29tO1xuTWFwLkRvdWJsZUNsaWNrWm9vbSA9IERvdWJsZUNsaWNrWm9vbTtcbk1hcC5EcmFnID0gRHJhZztcbk1hcC5LZXlib2FyZCA9IEtleWJvYXJkO1xuTWFwLlNjcm9sbFdoZWVsWm9vbSA9IFNjcm9sbFdoZWVsWm9vbTtcbk1hcC5UYXAgPSBUYXA7XG5NYXAuVG91Y2hab29tID0gVG91Y2hab29tO1xuXG5PYmplY3QuZnJlZXplID0gZnJlZXplO1xuXG5leHBvcnRzLnZlcnNpb24gPSB2ZXJzaW9uO1xuZXhwb3J0cy5Db250cm9sID0gQ29udHJvbDtcbmV4cG9ydHMuY29udHJvbCA9IGNvbnRyb2w7XG5leHBvcnRzLkJyb3dzZXIgPSBCcm93c2VyO1xuZXhwb3J0cy5FdmVudGVkID0gRXZlbnRlZDtcbmV4cG9ydHMuTWl4aW4gPSBNaXhpbjtcbmV4cG9ydHMuVXRpbCA9IFV0aWw7XG5leHBvcnRzLkNsYXNzID0gQ2xhc3M7XG5leHBvcnRzLkhhbmRsZXIgPSBIYW5kbGVyO1xuZXhwb3J0cy5leHRlbmQgPSBleHRlbmQ7XG5leHBvcnRzLmJpbmQgPSBiaW5kO1xuZXhwb3J0cy5zdGFtcCA9IHN0YW1wO1xuZXhwb3J0cy5zZXRPcHRpb25zID0gc2V0T3B0aW9ucztcbmV4cG9ydHMuRG9tRXZlbnQgPSBEb21FdmVudDtcbmV4cG9ydHMuRG9tVXRpbCA9IERvbVV0aWw7XG5leHBvcnRzLlBvc0FuaW1hdGlvbiA9IFBvc0FuaW1hdGlvbjtcbmV4cG9ydHMuRHJhZ2dhYmxlID0gRHJhZ2dhYmxlO1xuZXhwb3J0cy5MaW5lVXRpbCA9IExpbmVVdGlsO1xuZXhwb3J0cy5Qb2x5VXRpbCA9IFBvbHlVdGlsO1xuZXhwb3J0cy5Qb2ludCA9IFBvaW50O1xuZXhwb3J0cy5wb2ludCA9IHRvUG9pbnQ7XG5leHBvcnRzLkJvdW5kcyA9IEJvdW5kcztcbmV4cG9ydHMuYm91bmRzID0gdG9Cb3VuZHM7XG5leHBvcnRzLlRyYW5zZm9ybWF0aW9uID0gVHJhbnNmb3JtYXRpb247XG5leHBvcnRzLnRyYW5zZm9ybWF0aW9uID0gdG9UcmFuc2Zvcm1hdGlvbjtcbmV4cG9ydHMuUHJvamVjdGlvbiA9IGluZGV4O1xuZXhwb3J0cy5MYXRMbmcgPSBMYXRMbmc7XG5leHBvcnRzLmxhdExuZyA9IHRvTGF0TG5nO1xuZXhwb3J0cy5MYXRMbmdCb3VuZHMgPSBMYXRMbmdCb3VuZHM7XG5leHBvcnRzLmxhdExuZ0JvdW5kcyA9IHRvTGF0TG5nQm91bmRzO1xuZXhwb3J0cy5DUlMgPSBDUlM7XG5leHBvcnRzLkdlb0pTT04gPSBHZW9KU09OO1xuZXhwb3J0cy5nZW9KU09OID0gZ2VvSlNPTjtcbmV4cG9ydHMuZ2VvSnNvbiA9IGdlb0pzb247XG5leHBvcnRzLkxheWVyID0gTGF5ZXI7XG5leHBvcnRzLkxheWVyR3JvdXAgPSBMYXllckdyb3VwO1xuZXhwb3J0cy5sYXllckdyb3VwID0gbGF5ZXJHcm91cDtcbmV4cG9ydHMuRmVhdHVyZUdyb3VwID0gRmVhdHVyZUdyb3VwO1xuZXhwb3J0cy5mZWF0dXJlR3JvdXAgPSBmZWF0dXJlR3JvdXA7XG5leHBvcnRzLkltYWdlT3ZlcmxheSA9IEltYWdlT3ZlcmxheTtcbmV4cG9ydHMuaW1hZ2VPdmVybGF5ID0gaW1hZ2VPdmVybGF5O1xuZXhwb3J0cy5WaWRlb092ZXJsYXkgPSBWaWRlb092ZXJsYXk7XG5leHBvcnRzLnZpZGVvT3ZlcmxheSA9IHZpZGVvT3ZlcmxheTtcbmV4cG9ydHMuU1ZHT3ZlcmxheSA9IFNWR092ZXJsYXk7XG5leHBvcnRzLnN2Z092ZXJsYXkgPSBzdmdPdmVybGF5O1xuZXhwb3J0cy5EaXZPdmVybGF5ID0gRGl2T3ZlcmxheTtcbmV4cG9ydHMuUG9wdXAgPSBQb3B1cDtcbmV4cG9ydHMucG9wdXAgPSBwb3B1cDtcbmV4cG9ydHMuVG9vbHRpcCA9IFRvb2x0aXA7XG5leHBvcnRzLnRvb2x0aXAgPSB0b29sdGlwO1xuZXhwb3J0cy5JY29uID0gSWNvbjtcbmV4cG9ydHMuaWNvbiA9IGljb247XG5leHBvcnRzLkRpdkljb24gPSBEaXZJY29uO1xuZXhwb3J0cy5kaXZJY29uID0gZGl2SWNvbjtcbmV4cG9ydHMuTWFya2VyID0gTWFya2VyO1xuZXhwb3J0cy5tYXJrZXIgPSBtYXJrZXI7XG5leHBvcnRzLlRpbGVMYXllciA9IFRpbGVMYXllcjtcbmV4cG9ydHMudGlsZUxheWVyID0gdGlsZUxheWVyO1xuZXhwb3J0cy5HcmlkTGF5ZXIgPSBHcmlkTGF5ZXI7XG5leHBvcnRzLmdyaWRMYXllciA9IGdyaWRMYXllcjtcbmV4cG9ydHMuU1ZHID0gU1ZHO1xuZXhwb3J0cy5zdmcgPSBzdmckMTtcbmV4cG9ydHMuUmVuZGVyZXIgPSBSZW5kZXJlcjtcbmV4cG9ydHMuQ2FudmFzID0gQ2FudmFzO1xuZXhwb3J0cy5jYW52YXMgPSBjYW52YXMkMTtcbmV4cG9ydHMuUGF0aCA9IFBhdGg7XG5leHBvcnRzLkNpcmNsZU1hcmtlciA9IENpcmNsZU1hcmtlcjtcbmV4cG9ydHMuY2lyY2xlTWFya2VyID0gY2lyY2xlTWFya2VyO1xuZXhwb3J0cy5DaXJjbGUgPSBDaXJjbGU7XG5leHBvcnRzLmNpcmNsZSA9IGNpcmNsZTtcbmV4cG9ydHMuUG9seWxpbmUgPSBQb2x5bGluZTtcbmV4cG9ydHMucG9seWxpbmUgPSBwb2x5bGluZTtcbmV4cG9ydHMuUG9seWdvbiA9IFBvbHlnb247XG5leHBvcnRzLnBvbHlnb24gPSBwb2x5Z29uO1xuZXhwb3J0cy5SZWN0YW5nbGUgPSBSZWN0YW5nbGU7XG5leHBvcnRzLnJlY3RhbmdsZSA9IHJlY3RhbmdsZTtcbmV4cG9ydHMuTWFwID0gTWFwO1xuZXhwb3J0cy5tYXAgPSBjcmVhdGVNYXA7XG5cbnZhciBvbGRMID0gd2luZG93Lkw7XG5leHBvcnRzLm5vQ29uZmxpY3QgPSBmdW5jdGlvbigpIHtcblx0d2luZG93LkwgPSBvbGRMO1xuXHRyZXR1cm4gdGhpcztcbn1cblxuLy8gQWx3YXlzIGV4cG9ydCB1cyB0byB3aW5kb3cgZ2xvYmFsIChzZWUgIzIzNjQpXG53aW5kb3cuTCA9IGV4cG9ydHM7XG5cbn0pKSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1sZWFmbGV0LXNyYy5qcy5tYXBcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2xlYWZsZXQvZGlzdC9sZWFmbGV0LXNyYy5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvbGVhZmxldC9kaXN0L2xlYWZsZXQtc3JjLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js\n");
/***/ }),
/***/ "./node_modules/process/browser.js":
/***/ (function(module, exports) {
eval("// shim for using process in browser\nvar process = module.exports = {};\n\n// cached from whatever global is present so that test runners that stub it\n// don't break things. But we need to wrap it in a try catch in case it is\n// wrapped in strict mode code which doesn't define any globals. It's inside a\n// function because try/catches deoptimize in certain engines.\n\nvar cachedSetTimeout;\nvar cachedClearTimeout;\n\nfunction defaultSetTimout() {\n throw new Error('setTimeout has not been defined');\n}\nfunction defaultClearTimeout () {\n throw new Error('clearTimeout has not been defined');\n}\n(function () {\n try {\n if (typeof setTimeout === 'function') {\n cachedSetTimeout = setTimeout;\n } else {\n cachedSetTimeout = defaultSetTimout;\n }\n } catch (e) {\n cachedSetTimeout = defaultSetTimout;\n }\n try {\n if (typeof clearTimeout === 'function') {\n cachedClearTimeout = clearTimeout;\n } else {\n cachedClearTimeout = defaultClearTimeout;\n }\n } catch (e) {\n cachedClearTimeout = defaultClearTimeout;\n }\n} ())\nfunction runTimeout(fun) {\n if (cachedSetTimeout === setTimeout) {\n //normal enviroments in sane situations\n return setTimeout(fun, 0);\n }\n // if setTimeout wasn't available but was latter defined\n if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {\n cachedSetTimeout = setTimeout;\n return setTimeout(fun, 0);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedSetTimeout(fun, 0);\n } catch(e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedSetTimeout.call(null, fun, 0);\n } catch(e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error\n return cachedSetTimeout.call(this, fun, 0);\n }\n }\n\n\n}\nfunction runClearTimeout(marker) {\n if (cachedClearTimeout === clearTimeout) {\n //normal enviroments in sane situations\n return clearTimeout(marker);\n }\n // if clearTimeout wasn't available but was latter defined\n if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {\n cachedClearTimeout = clearTimeout;\n return clearTimeout(marker);\n }\n try {\n // when when somebody has screwed with setTimeout but no I.E. maddness\n return cachedClearTimeout(marker);\n } catch (e){\n try {\n // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally\n return cachedClearTimeout.call(null, marker);\n } catch (e){\n // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.\n // Some versions of I.E. have different rules for clearTimeout vs setTimeout\n return cachedClearTimeout.call(this, marker);\n }\n }\n\n\n\n}\nvar queue = [];\nvar draining = false;\nvar currentQueue;\nvar queueIndex = -1;\n\nfunction cleanUpNextTick() {\n if (!draining || !currentQueue) {\n return;\n }\n draining = false;\n if (currentQueue.length) {\n queue = currentQueue.concat(queue);\n } else {\n queueIndex = -1;\n }\n if (queue.length) {\n drainQueue();\n }\n}\n\nfunction drainQueue() {\n if (draining) {\n return;\n }\n var timeout = runTimeout(cleanUpNextTick);\n draining = true;\n\n var len = queue.length;\n while(len) {\n currentQueue = queue;\n queue = [];\n while (++queueIndex < len) {\n if (currentQueue) {\n currentQueue[queueIndex].run();\n }\n }\n queueIndex = -1;\n len = queue.length;\n }\n currentQueue = null;\n draining = false;\n runClearTimeout(timeout);\n}\n\nprocess.nextTick = function (fun) {\n var args = new Array(arguments.length - 1);\n if (arguments.length > 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n runTimeout(drainQueue);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\nprocess.prependListener = noop;\nprocess.prependOnceListener = noop;\n\nprocess.listeners = function (name) { return [] }\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzPzViNjkiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixzQkFBc0I7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHFDQUFxQzs7QUFFckM7QUFDQTtBQUNBOztBQUVBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7QUFDQSw0QkFBNEIsVUFBVSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLy8gY2FjaGVkIGZyb20gd2hhdGV2ZXIgZ2xvYmFsIGlzIHByZXNlbnQgc28gdGhhdCB0ZXN0IHJ1bm5lcnMgdGhhdCBzdHViIGl0XG4vLyBkb24ndCBicmVhayB0aGluZ3MuICBCdXQgd2UgbmVlZCB0byB3cmFwIGl0IGluIGEgdHJ5IGNhdGNoIGluIGNhc2UgaXQgaXNcbi8vIHdyYXBwZWQgaW4gc3RyaWN0IG1vZGUgY29kZSB3aGljaCBkb2Vzbid0IGRlZmluZSBhbnkgZ2xvYmFscy4gIEl0J3MgaW5zaWRlIGFcbi8vIGZ1bmN0aW9uIGJlY2F1c2UgdHJ5L2NhdGNoZXMgZGVvcHRpbWl6ZSBpbiBjZXJ0YWluIGVuZ2luZXMuXG5cbnZhciBjYWNoZWRTZXRUaW1lb3V0O1xudmFyIGNhY2hlZENsZWFyVGltZW91dDtcblxuZnVuY3Rpb24gZGVmYXVsdFNldFRpbW91dCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NldFRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGVhclRpbWVvdXQgKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2xlYXJUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG4oZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgY2xlYXJUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgIH1cbn0gKCkpXG5mdW5jdGlvbiBydW5UaW1lb3V0KGZ1bikge1xuICAgIGlmIChjYWNoZWRTZXRUaW1lb3V0ID09PSBzZXRUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICAvLyBpZiBzZXRUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkU2V0VGltZW91dCA9PT0gZGVmYXVsdFNldFRpbW91dCB8fCAhY2FjaGVkU2V0VGltZW91dCkgJiYgc2V0VGltZW91dCkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dChmdW4sIDApO1xuICAgIH0gY2F0Y2goZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwobnVsbCwgZnVuLCAwKTtcbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yXG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKHRoaXMsIGZ1biwgMCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxufVxuZnVuY3Rpb24gcnVuQ2xlYXJUaW1lb3V0KG1hcmtlcikge1xuICAgIGlmIChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGNsZWFyVGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICAvLyBpZiBjbGVhclRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGRlZmF1bHRDbGVhclRpbWVvdXQgfHwgIWNhY2hlZENsZWFyVGltZW91dCkgJiYgY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCAgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbChudWxsLCBtYXJrZXIpO1xuICAgICAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yLlxuICAgICAgICAgICAgLy8gU29tZSB2ZXJzaW9ucyBvZiBJLkUuIGhhdmUgZGlmZmVyZW50IHJ1bGVzIGZvciBjbGVhclRpbWVvdXQgdnMgc2V0VGltZW91dFxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKHRoaXMsIG1hcmtlcik7XG4gICAgICAgIH1cbiAgICB9XG5cblxuXG59XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBpZiAoIWRyYWluaW5nIHx8ICFjdXJyZW50UXVldWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBydW5UaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50UXVldWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UXVldWVbcXVldWVJbmRleF0ucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGN1cnJlbnRRdWV1ZSA9IG51bGw7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBydW5DbGVhclRpbWVvdXQodGltZW91dCk7XG59XG5cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVldWUucHVzaChuZXcgSXRlbShmdW4sIGFyZ3MpKTtcbiAgICBpZiAocXVldWUubGVuZ3RoID09PSAxICYmICFkcmFpbmluZykge1xuICAgICAgICBydW5UaW1lb3V0KGRyYWluUXVldWUpO1xuICAgIH1cbn07XG5cbi8vIHY4IGxpa2VzIHByZWRpY3RpYmxlIG9iamVjdHNcbmZ1bmN0aW9uIEl0ZW0oZnVuLCBhcnJheSkge1xuICAgIHRoaXMuZnVuID0gZnVuO1xuICAgIHRoaXMuYXJyYXkgPSBhcnJheTtcbn1cbkl0ZW0ucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZ1bi5hcHBseShudWxsLCB0aGlzLmFycmF5KTtcbn07XG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRPbmNlTGlzdGVuZXIgPSBub29wO1xuXG5wcm9jZXNzLmxpc3RlbmVycyA9IGZ1bmN0aW9uIChuYW1lKSB7IHJldHVybiBbXSB9XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/process/browser.js\n");
/***/ }),
/***/ "./node_modules/rivets/dist/rivets.js":
/***/ (function(module, exports, __webpack_require__) {
eval("/* WEBPACK VAR INJECTION */(function(module) {var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;// Rivets.js\n// version: 0.9.6\n// author: Michael Richards\n// license: MIT\n(function() {\n var Rivets, bindMethod, jQuery, unbindMethod, _ref,\n __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },\n __slice = [].slice,\n __hasProp = {}.hasOwnProperty,\n __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },\n __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\n\n Rivets = {\n options: ['prefix', 'templateDelimiters', 'rootInterface', 'preloadData', 'handler', 'executeFunctions'],\n extensions: ['binders', 'formatters', 'components', 'adapters'],\n \"public\": {\n binders: {},\n components: {},\n formatters: {},\n adapters: {},\n prefix: 'rv',\n templateDelimiters: ['{', '}'],\n rootInterface: '.',\n preloadData: true,\n executeFunctions: false,\n iterationAlias: function(modelName) {\n return '%' + modelName + '%';\n },\n handler: function(context, ev, binding) {\n return this.call(context, ev, binding.view.models);\n },\n configure: function(options) {\n var descriptor, key, option, value;\n if (options == null) {\n options = {};\n }\n for (option in options) {\n value = options[option];\n if (option === 'binders' || option === 'components' || option === 'formatters' || option === 'adapters') {\n for (key in value) {\n descriptor = value[key];\n Rivets[option][key] = descriptor;\n }\n } else {\n Rivets[\"public\"][option] = value;\n }\n }\n },\n bind: function(el, models, options) {\n var view;\n if (models == null) {\n models = {};\n }\n if (options == null) {\n options = {};\n }\n view = new Rivets.View(el, models, options);\n view.bind();\n return view;\n },\n init: function(component, el, data) {\n var scope, template, view;\n if (data == null) {\n data = {};\n }\n if (el == null) {\n el = document.createElement('div');\n }\n component = Rivets[\"public\"].components[component];\n template = component.template.call(this, el);\n if (template instanceof HTMLElement) {\n while (el.firstChild) {\n el.removeChild(el.firstChild);\n }\n el.appendChild(template);\n } else {\n el.innerHTML = template;\n }\n scope = component.initialize.call(this, el, data);\n view = new Rivets.View(el, scope);\n view.bind();\n return view;\n }\n }\n };\n\n if (window['jQuery'] || window['$']) {\n jQuery = window['jQuery'] || window['$'];\n _ref = 'on' in jQuery.prototype ? ['on', 'off'] : ['bind', 'unbind'], bindMethod = _ref[0], unbindMethod = _ref[1];\n Rivets.Util = {\n bindEvent: function(el, event, handler) {\n return jQuery(el)[bindMethod](event, handler);\n },\n unbindEvent: function(el, event, handler) {\n return jQuery(el)[unbindMethod](event, handler);\n },\n getInputValue: function(el) {\n var $el;\n $el = jQuery(el);\n if ($el.attr('type') === 'checkbox') {\n return $el.is(':checked');\n } else {\n return $el.val();\n }\n }\n };\n } else {\n Rivets.Util = {\n bindEvent: (function() {\n if ('addEventListener' in window) {\n return function(el, event, handler) {\n return el.addEventListener(event, handler, false);\n };\n }\n return function(el, event, handler) {\n return el.attachEvent('on' + event, handler);\n };\n })(),\n unbindEvent: (function() {\n if ('removeEventListener' in window) {\n return function(el, event, handler) {\n return el.removeEventListener(event, handler, false);\n };\n }\n return function(el, event, handler) {\n return el.detachEvent('on' + event, handler);\n };\n })(),\n getInputValue: function(el) {\n var o, _i, _len, _results;\n if (el.type === 'checkbox') {\n return el.checked;\n } else if (el.type === 'select-multiple') {\n _results = [];\n for (_i = 0, _len = el.length; _i < _len; _i++) {\n o = el[_i];\n if (o.selected) {\n _results.push(o.value);\n }\n }\n return _results;\n } else {\n return el.value;\n }\n }\n };\n }\n\n Rivets.TypeParser = (function() {\n function TypeParser() {}\n\n TypeParser.types = {\n primitive: 0,\n keypath: 1\n };\n\n TypeParser.parse = function(string) {\n if (/^'.*'$|^\".*\"$/.test(string)) {\n return {\n type: this.types.primitive,\n value: string.slice(1, -1)\n };\n } else if (string === 'true') {\n return {\n type: this.types.primitive,\n value: true\n };\n } else if (string === 'false') {\n return {\n type: this.types.primitive,\n value: false\n };\n } else if (string === 'null') {\n return {\n type: this.types.primitive,\n value: null\n };\n } else if (string === 'undefined') {\n return {\n type: this.types.primitive,\n value: void 0\n };\n } else if (string === '') {\n return {\n type: this.types.primitive,\n value: void 0\n };\n } else if (isNaN(Number(string)) === false) {\n return {\n type: this.types.primitive,\n value: Number(string)\n };\n } else {\n return {\n type: this.types.keypath,\n value: string\n };\n }\n };\n\n return TypeParser;\n\n })();\n\n Rivets.TextTemplateParser = (function() {\n function TextTemplateParser() {}\n\n TextTemplateParser.types = {\n text: 0,\n binding: 1\n };\n\n TextTemplateParser.parse = function(template, delimiters) {\n var index, lastIndex, lastToken, length, substring, tokens, value;\n tokens = [];\n length = template.length;\n index = 0;\n lastIndex = 0;\n while (lastIndex < length) {\n index = template.indexOf(delimiters[0], lastIndex);\n if (index < 0) {\n tokens.push({\n type: this.types.text,\n value: template.slice(lastIndex)\n });\n break;\n } else {\n if (index > 0 && lastIndex < index) {\n tokens.push({\n type: this.types.text,\n value: template.slice(lastIndex, index)\n });\n }\n lastIndex = index + delimiters[0].length;\n index = template.indexOf(delimiters[1], lastIndex);\n if (index < 0) {\n substring = template.slice(lastIndex - delimiters[1].length);\n lastToken = tokens[tokens.length - 1];\n if ((lastToken != null ? lastToken.type : void 0) === this.types.text) {\n lastToken.value += substring;\n } else {\n tokens.push({\n type: this.types.text,\n value: substring\n });\n }\n break;\n }\n value = template.slice(lastIndex, index).trim();\n tokens.push({\n type: this.types.binding,\n value: value\n });\n lastIndex = index + delimiters[1].length;\n }\n }\n return tokens;\n };\n\n return TextTemplateParser;\n\n })();\n\n Rivets.View = (function() {\n function View(els, models, options) {\n var k, option, v, _base, _i, _j, _len, _len1, _ref1, _ref2, _ref3, _ref4, _ref5;\n this.els = els;\n this.models = models;\n if (options == null) {\n options = {};\n }\n this.update = __bind(this.update, this);\n this.publish = __bind(this.publish, this);\n this.sync = __bind(this.sync, this);\n this.unbind = __bind(this.unbind, this);\n this.bind = __bind(this.bind, this);\n this.select = __bind(this.select, this);\n this.traverse = __bind(this.traverse, this);\n this.build = __bind(this.build, this);\n this.buildBinding = __bind(this.buildBinding, this);\n this.bindingRegExp = __bind(this.bindingRegExp, this);\n this.options = __bind(this.options, this);\n if (!(this.els.jquery || this.els instanceof Array)) {\n this.els = [this.els];\n }\n _ref1 = Rivets.extensions;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n option = _ref1[_i];\n this[option] = {};\n if (options[option]) {\n _ref2 = options[option];\n for (k in _ref2) {\n v = _ref2[k];\n this[option][k] = v;\n }\n }\n _ref3 = Rivets[\"public\"][option];\n for (k in _ref3) {\n v = _ref3[k];\n if ((_base = this[option])[k] == null) {\n _base[k] = v;\n }\n }\n }\n _ref4 = Rivets.options;\n for (_j = 0, _len1 = _ref4.length; _j < _len1; _j++) {\n option = _ref4[_j];\n this[option] = (_ref5 = options[option]) != null ? _ref5 : Rivets[\"public\"][option];\n }\n this.build();\n }\n\n View.prototype.options = function() {\n var option, options, _i, _len, _ref1;\n options = {};\n _ref1 = Rivets.extensions.concat(Rivets.options);\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n option = _ref1[_i];\n options[option] = this[option];\n }\n return options;\n };\n\n View.prototype.bindingRegExp = function() {\n return new RegExp(\"^\" + this.prefix + \"-\");\n };\n\n View.prototype.buildBinding = function(binding, node, type, declaration) {\n var context, ctx, dependencies, keypath, options, pipe, pipes;\n options = {};\n pipes = (function() {\n var _i, _len, _ref1, _results;\n _ref1 = declaration.match(/((?:'[^']*')*(?:(?:[^\\|']*(?:'[^']*')+[^\\|']*)+|[^\\|]+))|^$/g);\n _results = [];\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n pipe = _ref1[_i];\n _results.push(pipe.trim());\n }\n return _results;\n })();\n context = (function() {\n var _i, _len, _ref1, _results;\n _ref1 = pipes.shift().split('<');\n _results = [];\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n ctx = _ref1[_i];\n _results.push(ctx.trim());\n }\n return _results;\n })();\n keypath = context.shift();\n options.formatters = pipes;\n if (dependencies = context.shift()) {\n options.dependencies = dependencies.split(/\\s+/);\n }\n return this.bindings.push(new Rivets[binding](this, node, type, keypath, options));\n };\n\n View.prototype.build = function() {\n var el, parse, _i, _len, _ref1;\n this.bindings = [];\n parse = (function(_this) {\n return function(node) {\n var block, childNode, delimiters, n, parser, text, token, tokens, _i, _j, _len, _len1, _ref1;\n if (node.nodeType === 3) {\n parser = Rivets.TextTemplateParser;\n if (delimiters = _this.templateDelimiters) {\n if ((tokens = parser.parse(node.data, delimiters)).length) {\n if (!(tokens.length === 1 && tokens[0].type === parser.types.text)) {\n for (_i = 0, _len = tokens.length; _i < _len; _i++) {\n token = tokens[_i];\n text = document.createTextNode(token.value);\n node.parentNode.insertBefore(text, node);\n if (token.type === 1) {\n _this.buildBinding('TextBinding', text, null, token.value);\n }\n }\n node.parentNode.removeChild(node);\n }\n }\n }\n } else if (node.nodeType === 1) {\n block = _this.traverse(node);\n }\n if (!block) {\n _ref1 = (function() {\n var _k, _len1, _ref1, _results;\n _ref1 = node.childNodes;\n _results = [];\n for (_k = 0, _len1 = _ref1.length; _k < _len1; _k++) {\n n = _ref1[_k];\n _results.push(n);\n }\n return _results;\n })();\n for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n childNode = _ref1[_j];\n parse(childNode);\n }\n }\n };\n })(this);\n _ref1 = this.els;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n el = _ref1[_i];\n parse(el);\n }\n this.bindings.sort(function(a, b) {\n var _ref2, _ref3;\n return (((_ref2 = b.binder) != null ? _ref2.priority : void 0) || 0) - (((_ref3 = a.binder) != null ? _ref3.priority : void 0) || 0);\n });\n };\n\n View.prototype.traverse = function(node) {\n var attribute, attributes, binder, bindingRegExp, block, identifier, regexp, type, value, _i, _j, _len, _len1, _ref1, _ref2, _ref3;\n bindingRegExp = this.bindingRegExp();\n block = node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE';\n _ref1 = node.attributes;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n attribute = _ref1[_i];\n if (bindingRegExp.test(attribute.name)) {\n type = attribute.name.replace(bindingRegExp, '');\n if (!(binder = this.binders[type])) {\n _ref2 = this.binders;\n for (identifier in _ref2) {\n value = _ref2[identifier];\n if (identifier !== '*' && identifier.indexOf('*') !== -1) {\n regexp = new RegExp(\"^\" + (identifier.replace(/\\*/g, '.+')) + \"$\");\n if (regexp.test(type)) {\n binder = value;\n }\n }\n }\n }\n binder || (binder = this.binders['*']);\n if (binder.block) {\n block = true;\n attributes = [attribute];\n }\n }\n }\n _ref3 = attributes || node.attributes;\n for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {\n attribute = _ref3[_j];\n if (bindingRegExp.test(attribute.name)) {\n type = attribute.name.replace(bindingRegExp, '');\n this.buildBinding('Binding', node, type, attribute.value);\n }\n }\n if (!block) {\n type = node.nodeName.toLowerCase();\n if (this.components[type] && !node._bound) {\n this.bindings.push(new Rivets.ComponentBinding(this, node, type));\n block = true;\n }\n }\n return block;\n };\n\n View.prototype.select = function(fn) {\n var binding, _i, _len, _ref1, _results;\n _ref1 = this.bindings;\n _results = [];\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n binding = _ref1[_i];\n if (fn(binding)) {\n _results.push(binding);\n }\n }\n return _results;\n };\n\n View.prototype.bind = function() {\n var binding, _i, _len, _ref1;\n _ref1 = this.bindings;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n binding = _ref1[_i];\n binding.bind();\n }\n };\n\n View.prototype.unbind = function() {\n var binding, _i, _len, _ref1;\n _ref1 = this.bindings;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n binding = _ref1[_i];\n binding.unbind();\n }\n };\n\n View.prototype.sync = function() {\n var binding, _i, _len, _ref1;\n _ref1 = this.bindings;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n binding = _ref1[_i];\n if (typeof binding.sync === \"function\") {\n binding.sync();\n }\n }\n };\n\n View.prototype.publish = function() {\n var binding, _i, _len, _ref1;\n _ref1 = this.select(function(b) {\n var _ref1;\n return (_ref1 = b.binder) != null ? _ref1.publishes : void 0;\n });\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n binding = _ref1[_i];\n binding.publish();\n }\n };\n\n View.prototype.update = function(models) {\n var binding, key, model, _i, _len, _ref1;\n if (models == null) {\n models = {};\n }\n for (key in models) {\n model = models[key];\n this.models[key] = model;\n }\n _ref1 = this.bindings;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n binding = _ref1[_i];\n if (typeof binding.update === \"function\") {\n binding.update(models);\n }\n }\n };\n\n return View;\n\n })();\n\n Rivets.Binding = (function() {\n function Binding(view, el, type, keypath, options) {\n this.view = view;\n this.el = el;\n this.type = type;\n this.keypath = keypath;\n this.options = options != null ? options : {};\n this.getValue = __bind(this.getValue, this);\n this.update = __bind(this.update, this);\n this.unbind = __bind(this.unbind, this);\n this.bind = __bind(this.bind, this);\n this.publish = __bind(this.publish, this);\n this.sync = __bind(this.sync, this);\n this.set = __bind(this.set, this);\n this.eventHandler = __bind(this.eventHandler, this);\n this.formattedValue = __bind(this.formattedValue, this);\n this.parseFormatterArguments = __bind(this.parseFormatterArguments, this);\n this.parseTarget = __bind(this.parseTarget, this);\n this.observe = __bind(this.observe, this);\n this.setBinder = __bind(this.setBinder, this);\n this.formatters = this.options.formatters || [];\n this.dependencies = [];\n this.formatterObservers = {};\n this.model = void 0;\n this.setBinder();\n }\n\n Binding.prototype.setBinder = function() {\n var identifier, regexp, value, _ref1;\n if (!(this.binder = this.view.binders[this.type])) {\n _ref1 = this.view.binders;\n for (identifier in _ref1) {\n value = _ref1[identifier];\n if (identifier !== '*' && identifier.indexOf('*') !== -1) {\n regexp = new RegExp(\"^\" + (identifier.replace(/\\*/g, '.+')) + \"$\");\n if (regexp.test(this.type)) {\n this.binder = value;\n this.args = new RegExp(\"^\" + (identifier.replace(/\\*/g, '(.+)')) + \"$\").exec(this.type);\n this.args.shift();\n }\n }\n }\n }\n this.binder || (this.binder = this.view.binders['*']);\n if (this.binder instanceof Function) {\n return this.binder = {\n routine: this.binder\n };\n }\n };\n\n Binding.prototype.observe = function(obj, keypath, callback) {\n return Rivets.sightglass(obj, keypath, callback, {\n root: this.view.rootInterface,\n adapters: this.view.adapters\n });\n };\n\n Binding.prototype.parseTarget = function() {\n var token;\n token = Rivets.TypeParser.parse(this.keypath);\n if (token.type === Rivets.TypeParser.types.primitive) {\n return this.value = token.value;\n } else {\n this.observer = this.observe(this.view.models, this.keypath, this.sync);\n return this.model = this.observer.target;\n }\n };\n\n Binding.prototype.parseFormatterArguments = function(args, formatterIndex) {\n var ai, arg, observer, processedArgs, _base, _i, _len;\n args = (function() {\n var _i, _len, _results;\n _results = [];\n for (_i = 0, _len = args.length; _i < _len; _i++) {\n arg = args[_i];\n _results.push(Rivets.TypeParser.parse(arg));\n }\n return _results;\n })();\n processedArgs = [];\n for (ai = _i = 0, _len = args.length; _i < _len; ai = ++_i) {\n arg = args[ai];\n processedArgs.push(arg.type === Rivets.TypeParser.types.primitive ? arg.value : ((_base = this.formatterObservers)[formatterIndex] || (_base[formatterIndex] = {}), !(observer = this.formatterObservers[formatterIndex][ai]) ? (observer = this.observe(this.view.models, arg.value, this.sync), this.formatterObservers[formatterIndex][ai] = observer) : void 0, observer.value()));\n }\n return processedArgs;\n };\n\n Binding.prototype.formattedValue = function(value) {\n var args, fi, formatter, id, processedArgs, _i, _len, _ref1, _ref2;\n _ref1 = this.formatters;\n for (fi = _i = 0, _len = _ref1.length; _i < _len; fi = ++_i) {\n formatter = _ref1[fi];\n args = formatter.match(/[^\\s']+|'([^']|'[^\\s])*'|\"([^\"]|\"[^\\s])*\"/g);\n id = args.shift();\n formatter = this.view.formatters[id];\n processedArgs = this.parseFormatterArguments(args, fi);\n if ((formatter != null ? formatter.read : void 0) instanceof Function) {\n value = (_ref2 = formatter.read).call.apply(_ref2, [this.model, value].concat(__slice.call(processedArgs)));\n } else if (formatter instanceof Function) {\n value = formatter.call.apply(formatter, [this.model, value].concat(__slice.call(processedArgs)));\n }\n }\n return value;\n };\n\n Binding.prototype.eventHandler = function(fn) {\n var binding, handler;\n handler = (binding = this).view.handler;\n return function(ev) {\n return handler.call(fn, this, ev, binding);\n };\n };\n\n Binding.prototype.set = function(value) {\n var _ref1;\n value = value instanceof Function && !this.binder[\"function\"] && Rivets[\"public\"].executeFunctions ? this.formattedValue(value.call(this.model)) : this.formattedValue(value);\n return (_ref1 = this.binder.routine) != null ? _ref1.call(this, this.el, value) : void 0;\n };\n\n Binding.prototype.sync = function() {\n var dependency, observer;\n return this.set((function() {\n var _i, _j, _len, _len1, _ref1, _ref2, _ref3;\n if (this.observer) {\n if (this.model !== this.observer.target) {\n _ref1 = this.dependencies;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n observer = _ref1[_i];\n observer.unobserve();\n }\n this.dependencies = [];\n if (((this.model = this.observer.target) != null) && ((_ref2 = this.options.dependencies) != null ? _ref2.length : void 0)) {\n _ref3 = this.options.dependencies;\n for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {\n dependency = _ref3[_j];\n observer = this.observe(this.model, dependency, this.sync);\n this.dependencies.push(observer);\n }\n }\n }\n return this.observer.value();\n } else {\n return this.value;\n }\n }).call(this));\n };\n\n Binding.prototype.publish = function() {\n var args, fi, fiReversed, formatter, id, lastformatterIndex, processedArgs, value, _i, _len, _ref1, _ref2, _ref3;\n if (this.observer) {\n value = this.getValue(this.el);\n lastformatterIndex = this.formatters.length - 1;\n _ref1 = this.formatters.slice(0).reverse();\n for (fiReversed = _i = 0, _len = _ref1.length; _i < _len; fiReversed = ++_i) {\n formatter = _ref1[fiReversed];\n fi = lastformatterIndex - fiReversed;\n args = formatter.split(/\\s+/);\n id = args.shift();\n processedArgs = this.parseFormatterArguments(args, fi);\n if ((_ref2 = this.view.formatters[id]) != null ? _ref2.publish : void 0) {\n value = (_ref3 = this.view.formatters[id]).publish.apply(_ref3, [value].concat(__slice.call(processedArgs)));\n }\n }\n return this.observer.setValue(value);\n }\n };\n\n Binding.prototype.bind = function() {\n var dependency, observer, _i, _len, _ref1, _ref2, _ref3;\n this.parseTarget();\n if ((_ref1 = this.binder.bind) != null) {\n _ref1.call(this, this.el);\n }\n if ((this.model != null) && ((_ref2 = this.options.dependencies) != null ? _ref2.length : void 0)) {\n _ref3 = this.options.dependencies;\n for (_i = 0, _len = _ref3.length; _i < _len; _i++) {\n dependency = _ref3[_i];\n observer = this.observe(this.model, dependency, this.sync);\n this.dependencies.push(observer);\n }\n }\n if (this.view.preloadData) {\n return this.sync();\n }\n };\n\n Binding.prototype.unbind = function() {\n var ai, args, fi, observer, _i, _len, _ref1, _ref2, _ref3, _ref4;\n if ((_ref1 = this.binder.unbind) != null) {\n _ref1.call(this, this.el);\n }\n if ((_ref2 = this.observer) != null) {\n _ref2.unobserve();\n }\n _ref3 = this.dependencies;\n for (_i = 0, _len = _ref3.length; _i < _len; _i++) {\n observer = _ref3[_i];\n observer.unobserve();\n }\n this.dependencies = [];\n _ref4 = this.formatterObservers;\n for (fi in _ref4) {\n args = _ref4[fi];\n for (ai in args) {\n observer = args[ai];\n observer.unobserve();\n }\n }\n return this.formatterObservers = {};\n };\n\n Binding.prototype.update = function(models) {\n var _ref1, _ref2;\n if (models == null) {\n models = {};\n }\n this.model = (_ref1 = this.observer) != null ? _ref1.target : void 0;\n return (_ref2 = this.binder.update) != null ? _ref2.call(this, models) : void 0;\n };\n\n Binding.prototype.getValue = function(el) {\n if (this.binder && (this.binder.getValue != null)) {\n return this.binder.getValue.call(this, el);\n } else {\n return Rivets.Util.getInputValue(el);\n }\n };\n\n return Binding;\n\n })();\n\n Rivets.ComponentBinding = (function(_super) {\n __extends(ComponentBinding, _super);\n\n function ComponentBinding(view, el, type) {\n var attribute, bindingRegExp, propertyName, token, _i, _len, _ref1, _ref2;\n this.view = view;\n this.el = el;\n this.type = type;\n this.unbind = __bind(this.unbind, this);\n this.bind = __bind(this.bind, this);\n this.locals = __bind(this.locals, this);\n this.component = this.view.components[this.type];\n this[\"static\"] = {};\n this.observers = {};\n this.upstreamObservers = {};\n bindingRegExp = view.bindingRegExp();\n _ref1 = this.el.attributes || [];\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n attribute = _ref1[_i];\n if (!bindingRegExp.test(attribute.name)) {\n propertyName = this.camelCase(attribute.name);\n token = Rivets.TypeParser.parse(attribute.value);\n if (__indexOf.call((_ref2 = this.component[\"static\"]) != null ? _ref2 : [], propertyName) >= 0) {\n this[\"static\"][propertyName] = attribute.value;\n } else if (token.type === Rivets.TypeParser.types.primitive) {\n this[\"static\"][propertyName] = token.value;\n } else {\n this.observers[propertyName] = attribute.value;\n }\n }\n }\n }\n\n ComponentBinding.prototype.sync = function() {};\n\n ComponentBinding.prototype.update = function() {};\n\n ComponentBinding.prototype.publish = function() {};\n\n ComponentBinding.prototype.locals = function() {\n var key, observer, result, value, _ref1, _ref2;\n result = {};\n _ref1 = this[\"static\"];\n for (key in _ref1) {\n value = _ref1[key];\n result[key] = value;\n }\n _ref2 = this.observers;\n for (key in _ref2) {\n observer = _ref2[key];\n result[key] = observer.value();\n }\n return result;\n };\n\n ComponentBinding.prototype.camelCase = function(string) {\n return string.replace(/-([a-z])/g, function(grouped) {\n return grouped[1].toUpperCase();\n });\n };\n\n ComponentBinding.prototype.bind = function() {\n var k, key, keypath, observer, option, options, scope, v, _base, _i, _j, _len, _len1, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;\n if (!this.bound) {\n _ref1 = this.observers;\n for (key in _ref1) {\n keypath = _ref1[key];\n this.observers[key] = this.observe(this.view.models, keypath, ((function(_this) {\n return function(key) {\n return function() {\n return _this.componentView.models[key] = _this.observers[key].value();\n };\n };\n })(this)).call(this, key));\n }\n this.bound = true;\n }\n if (this.componentView != null) {\n this.componentView.bind();\n } else {\n this.el.innerHTML = this.component.template.call(this);\n scope = this.component.initialize.call(this, this.el, this.locals());\n this.el._bound = true;\n options = {};\n _ref2 = Rivets.extensions;\n for (_i = 0, _len = _ref2.length; _i < _len; _i++) {\n option = _ref2[_i];\n options[option] = {};\n if (this.component[option]) {\n _ref3 = this.component[option];\n for (k in _ref3) {\n v = _ref3[k];\n options[option][k] = v;\n }\n }\n _ref4 = this.view[option];\n for (k in _ref4) {\n v = _ref4[k];\n if ((_base = options[option])[k] == null) {\n _base[k] = v;\n }\n }\n }\n _ref5 = Rivets.options;\n for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) {\n option = _ref5[_j];\n options[option] = (_ref6 = this.component[option]) != null ? _ref6 : this.view[option];\n }\n this.componentView = new Rivets.View(Array.prototype.slice.call(this.el.childNodes), scope, options);\n this.componentView.bind();\n _ref7 = this.observers;\n for (key in _ref7) {\n observer = _ref7[key];\n this.upstreamObservers[key] = this.observe(this.componentView.models, key, ((function(_this) {\n return function(key, observer) {\n return function() {\n return observer.setValue(_this.componentView.models[key]);\n };\n };\n })(this)).call(this, key, observer));\n }\n }\n };\n\n ComponentBinding.prototype.unbind = function() {\n var key, observer, _ref1, _ref2, _ref3;\n _ref1 = this.upstreamObservers;\n for (key in _ref1) {\n observer = _ref1[key];\n observer.unobserve();\n }\n _ref2 = this.observers;\n for (key in _ref2) {\n observer = _ref2[key];\n observer.unobserve();\n }\n return (_ref3 = this.componentView) != null ? _ref3.unbind.call(this) : void 0;\n };\n\n return ComponentBinding;\n\n })(Rivets.Binding);\n\n Rivets.TextBinding = (function(_super) {\n __extends(TextBinding, _super);\n\n function TextBinding(view, el, type, keypath, options) {\n this.view = view;\n this.el = el;\n this.type = type;\n this.keypath = keypath;\n this.options = options != null ? options : {};\n this.sync = __bind(this.sync, this);\n this.formatters = this.options.formatters || [];\n this.dependencies = [];\n this.formatterObservers = {};\n }\n\n TextBinding.prototype.binder = {\n routine: function(node, value) {\n return node.data = value != null ? value : '';\n }\n };\n\n TextBinding.prototype.sync = function() {\n return TextBinding.__super__.sync.apply(this, arguments);\n };\n\n return TextBinding;\n\n })(Rivets.Binding);\n\n Rivets[\"public\"].binders.text = function(el, value) {\n if (el.textContent != null) {\n return el.textContent = value != null ? value : '';\n } else {\n return el.innerText = value != null ? value : '';\n }\n };\n\n Rivets[\"public\"].binders.html = function(el, value) {\n return el.innerHTML = value != null ? value : '';\n };\n\n Rivets[\"public\"].binders.show = function(el, value) {\n return el.style.display = value ? '' : 'none';\n };\n\n Rivets[\"public\"].binders.hide = function(el, value) {\n return el.style.display = value ? 'none' : '';\n };\n\n Rivets[\"public\"].binders.enabled = function(el, value) {\n return el.disabled = !value;\n };\n\n Rivets[\"public\"].binders.disabled = function(el, value) {\n return el.disabled = !!value;\n };\n\n Rivets[\"public\"].binders.checked = {\n publishes: true,\n priority: 2000,\n bind: function(el) {\n return Rivets.Util.bindEvent(el, 'change', this.publish);\n },\n unbind: function(el) {\n return Rivets.Util.unbindEvent(el, 'change', this.publish);\n },\n routine: function(el, value) {\n var _ref1;\n if (el.type === 'radio') {\n return el.checked = ((_ref1 = el.value) != null ? _ref1.toString() : void 0) === (value != null ? value.toString() : void 0);\n } else {\n return el.checked = !!value;\n }\n }\n };\n\n Rivets[\"public\"].binders.unchecked = {\n publishes: true,\n priority: 2000,\n bind: function(el) {\n return Rivets.Util.bindEvent(el, 'change', this.publish);\n },\n unbind: function(el) {\n return Rivets.Util.unbindEvent(el, 'change', this.publish);\n },\n routine: function(el, value) {\n var _ref1;\n if (el.type === 'radio') {\n return el.checked = ((_ref1 = el.value) != null ? _ref1.toString() : void 0) !== (value != null ? value.toString() : void 0);\n } else {\n return el.checked = !value;\n }\n }\n };\n\n Rivets[\"public\"].binders.value = {\n publishes: true,\n priority: 3000,\n bind: function(el) {\n if (!(el.tagName === 'INPUT' && el.type === 'radio')) {\n this.event = el.tagName === 'SELECT' ? 'change' : 'input';\n return Rivets.Util.bindEvent(el, this.event, this.publish);\n }\n },\n unbind: function(el) {\n if (!(el.tagName === 'INPUT' && el.type === 'radio')) {\n return Rivets.Util.unbindEvent(el, this.event, this.publish);\n }\n },\n routine: function(el, value) {\n var o, _i, _len, _ref1, _ref2, _ref3, _results;\n if (el.tagName === 'INPUT' && el.type === 'radio') {\n return el.setAttribute('value', value);\n } else if (window.jQuery != null) {\n el = jQuery(el);\n if ((value != null ? value.toString() : void 0) !== ((_ref1 = el.val()) != null ? _ref1.toString() : void 0)) {\n return el.val(value != null ? value : '');\n }\n } else {\n if (el.type === 'select-multiple') {\n if (value != null) {\n _results = [];\n for (_i = 0, _len = el.length; _i < _len; _i++) {\n o = el[_i];\n _results.push(o.selected = (_ref2 = o.value, __indexOf.call(value, _ref2) >= 0));\n }\n return _results;\n }\n } else if ((value != null ? value.toString() : void 0) !== ((_ref3 = el.value) != null ? _ref3.toString() : void 0)) {\n return el.value = value != null ? value : '';\n }\n }\n }\n };\n\n Rivets[\"public\"].binders[\"if\"] = {\n block: true,\n priority: 4000,\n bind: function(el) {\n var attr, declaration;\n if (this.marker == null) {\n attr = [this.view.prefix, this.type].join('-').replace('--', '-');\n declaration = el.getAttribute(attr);\n this.marker = document.createComment(\" rivets: \" + this.type + \" \" + declaration + \" \");\n this.bound = false;\n el.removeAttribute(attr);\n el.parentNode.insertBefore(this.marker, el);\n return el.parentNode.removeChild(el);\n }\n },\n unbind: function() {\n if (this.nested) {\n this.nested.unbind();\n return this.bound = false;\n }\n },\n routine: function(el, value) {\n var key, model, models, _ref1;\n if (!!value === !this.bound) {\n if (value) {\n models = {};\n _ref1 = this.view.models;\n for (key in _ref1) {\n model = _ref1[key];\n models[key] = model;\n }\n (this.nested || (this.nested = new Rivets.View(el, models, this.view.options()))).bind();\n this.marker.parentNode.insertBefore(el, this.marker.nextSibling);\n return this.bound = true;\n } else {\n el.parentNode.removeChild(el);\n this.nested.unbind();\n return this.bound = false;\n }\n }\n },\n update: function(models) {\n var _ref1;\n return (_ref1 = this.nested) != null ? _ref1.update(models) : void 0;\n }\n };\n\n Rivets[\"public\"].binders.unless = {\n block: true,\n priority: 4000,\n bind: function(el) {\n return Rivets[\"public\"].binders[\"if\"].bind.call(this, el);\n },\n unbind: function() {\n return Rivets[\"public\"].binders[\"if\"].unbind.call(this);\n },\n routine: function(el, value) {\n return Rivets[\"public\"].binders[\"if\"].routine.call(this, el, !value);\n },\n update: function(models) {\n return Rivets[\"public\"].binders[\"if\"].update.call(this, models);\n }\n };\n\n Rivets[\"public\"].binders['on-*'] = {\n \"function\": true,\n priority: 1000,\n unbind: function(el) {\n if (this.handler) {\n return Rivets.Util.unbindEvent(el, this.args[0], this.handler);\n }\n },\n routine: function(el, value) {\n if (this.handler) {\n Rivets.Util.unbindEvent(el, this.args[0], this.handler);\n }\n return Rivets.Util.bindEvent(el, this.args[0], this.handler = this.eventHandler(value));\n }\n };\n\n Rivets[\"public\"].binders['each-*'] = {\n block: true,\n priority: 4000,\n bind: function(el) {\n var attr, view, _i, _len, _ref1;\n if (this.marker == null) {\n attr = [this.view.prefix, this.type].join('-').replace('--', '-');\n this.marker = document.createComment(\" rivets: \" + this.type + \" \");\n this.iterated = [];\n el.removeAttribute(attr);\n el.parentNode.insertBefore(this.marker, el);\n el.parentNode.removeChild(el);\n } else {\n _ref1 = this.iterated;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n view = _ref1[_i];\n view.bind();\n }\n }\n },\n unbind: function(el) {\n var view, _i, _len, _ref1;\n if (this.iterated != null) {\n _ref1 = this.iterated;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n view = _ref1[_i];\n view.unbind();\n }\n }\n },\n routine: function(el, collection) {\n var binding, data, i, index, key, model, modelName, options, previous, template, view, _i, _j, _k, _len, _len1, _len2, _ref1, _ref2, _ref3;\n modelName = this.args[0];\n collection = collection || [];\n if (this.iterated.length > collection.length) {\n _ref1 = Array(this.iterated.length - collection.length);\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n i = _ref1[_i];\n view = this.iterated.pop();\n view.unbind();\n this.marker.parentNode.removeChild(view.els[0]);\n }\n }\n for (index = _j = 0, _len1 = collection.length; _j < _len1; index = ++_j) {\n model = collection[index];\n data = {\n index: index\n };\n data[Rivets[\"public\"].iterationAlias(modelName)] = index;\n data[modelName] = model;\n if (this.iterated[index] == null) {\n _ref2 = this.view.models;\n for (key in _ref2) {\n model = _ref2[key];\n if (data[key] == null) {\n data[key] = model;\n }\n }\n previous = this.iterated.length ? this.iterated[this.iterated.length - 1].els[0] : this.marker;\n options = this.view.options();\n options.preloadData = true;\n template = el.cloneNode(true);\n view = new Rivets.View(template, data, options);\n view.bind();\n this.iterated.push(view);\n this.marker.parentNode.insertBefore(template, previous.nextSibling);\n } else if (this.iterated[index].models[modelName] !== model) {\n this.iterated[index].update(data);\n }\n }\n if (el.nodeName === 'OPTION') {\n _ref3 = this.view.bindings;\n for (_k = 0, _len2 = _ref3.length; _k < _len2; _k++) {\n binding = _ref3[_k];\n if (binding.el === this.marker.parentNode && binding.type === 'value') {\n binding.sync();\n }\n }\n }\n },\n update: function(models) {\n var data, key, model, view, _i, _len, _ref1;\n data = {};\n for (key in models) {\n model = models[key];\n if (key !== this.args[0]) {\n data[key] = model;\n }\n }\n _ref1 = this.iterated;\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n view = _ref1[_i];\n view.update(data);\n }\n }\n };\n\n Rivets[\"public\"].binders['class-*'] = function(el, value) {\n var elClass;\n elClass = \" \" + el.className + \" \";\n if (!value === (elClass.indexOf(\" \" + this.args[0] + \" \") !== -1)) {\n return el.className = value ? \"\" + el.className + \" \" + this.args[0] : elClass.replace(\" \" + this.args[0] + \" \", ' ').trim();\n }\n };\n\n Rivets[\"public\"].binders['*'] = function(el, value) {\n if (value != null) {\n return el.setAttribute(this.type, value);\n } else {\n return el.removeAttribute(this.type);\n }\n };\n\n Rivets[\"public\"].formatters['call'] = function() {\n var args, value;\n value = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];\n return value.call.apply(value, [this].concat(__slice.call(args)));\n };\n\n Rivets[\"public\"].adapters['.'] = {\n id: '_rv',\n counter: 0,\n weakmap: {},\n weakReference: function(obj) {\n var id, _base, _name;\n if (!obj.hasOwnProperty(this.id)) {\n id = this.counter++;\n Object.defineProperty(obj, this.id, {\n value: id\n });\n }\n return (_base = this.weakmap)[_name = obj[this.id]] || (_base[_name] = {\n callbacks: {}\n });\n },\n cleanupWeakReference: function(ref, id) {\n if (!Object.keys(ref.callbacks).length) {\n if (!(ref.pointers && Object.keys(ref.pointers).length)) {\n return delete this.weakmap[id];\n }\n }\n },\n stubFunction: function(obj, fn) {\n var map, original, weakmap;\n original = obj[fn];\n map = this.weakReference(obj);\n weakmap = this.weakmap;\n return obj[fn] = function() {\n var callback, k, r, response, _i, _len, _ref1, _ref2, _ref3, _ref4;\n response = original.apply(obj, arguments);\n _ref1 = map.pointers;\n for (r in _ref1) {\n k = _ref1[r];\n _ref4 = (_ref2 = (_ref3 = weakmap[r]) != null ? _ref3.callbacks[k] : void 0) != null ? _ref2 : [];\n for (_i = 0, _len = _ref4.length; _i < _len; _i++) {\n callback = _ref4[_i];\n callback();\n }\n }\n return response;\n };\n },\n observeMutations: function(obj, ref, keypath) {\n var fn, functions, map, _base, _i, _len;\n if (Array.isArray(obj)) {\n map = this.weakReference(obj);\n if (map.pointers == null) {\n map.pointers = {};\n functions = ['push', 'pop', 'shift', 'unshift', 'sort', 'reverse', 'splice'];\n for (_i = 0, _len = functions.length; _i < _len; _i++) {\n fn = functions[_i];\n this.stubFunction(obj, fn);\n }\n }\n if ((_base = map.pointers)[ref] == null) {\n _base[ref] = [];\n }\n if (__indexOf.call(map.pointers[ref], keypath) < 0) {\n return map.pointers[ref].push(keypath);\n }\n }\n },\n unobserveMutations: function(obj, ref, keypath) {\n var idx, map, pointers;\n if (Array.isArray(obj) && (obj[this.id] != null)) {\n if (map = this.weakmap[obj[this.id]]) {\n if (pointers = map.pointers[ref]) {\n if ((idx = pointers.indexOf(keypath)) >= 0) {\n pointers.splice(idx, 1);\n }\n if (!pointers.length) {\n delete map.pointers[ref];\n }\n return this.cleanupWeakReference(map, obj[this.id]);\n }\n }\n }\n },\n observe: function(obj, keypath, callback) {\n var callbacks, desc, value;\n callbacks = this.weakReference(obj).callbacks;\n if (callbacks[keypath] == null) {\n callbacks[keypath] = [];\n desc = Object.getOwnPropertyDescriptor(obj, keypath);\n if (!((desc != null ? desc.get : void 0) || (desc != null ? desc.set : void 0))) {\n value = obj[keypath];\n Object.defineProperty(obj, keypath, {\n enumerable: true,\n get: function() {\n return value;\n },\n set: (function(_this) {\n return function(newValue) {\n var cb, map, _i, _len, _ref1;\n if (newValue !== value) {\n _this.unobserveMutations(value, obj[_this.id], keypath);\n value = newValue;\n if (map = _this.weakmap[obj[_this.id]]) {\n callbacks = map.callbacks;\n if (callbacks[keypath]) {\n _ref1 = callbacks[keypath].slice();\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n cb = _ref1[_i];\n if (__indexOf.call(callbacks[keypath], cb) >= 0) {\n cb();\n }\n }\n }\n return _this.observeMutations(newValue, obj[_this.id], keypath);\n }\n }\n };\n })(this)\n });\n }\n }\n if (__indexOf.call(callbacks[keypath], callback) < 0) {\n callbacks[keypath].push(callback);\n }\n return this.observeMutations(obj[keypath], obj[this.id], keypath);\n },\n unobserve: function(obj, keypath, callback) {\n var callbacks, idx, map;\n if (map = this.weakmap[obj[this.id]]) {\n if (callbacks = map.callbacks[keypath]) {\n if ((idx = callbacks.indexOf(callback)) >= 0) {\n callbacks.splice(idx, 1);\n if (!callbacks.length) {\n delete map.callbacks[keypath];\n this.unobserveMutations(obj[keypath], obj[this.id], keypath);\n }\n }\n return this.cleanupWeakReference(map, obj[this.id]);\n }\n }\n },\n get: function(obj, keypath) {\n return obj[keypath];\n },\n set: function(obj, keypath, value) {\n return obj[keypath] = value;\n }\n };\n\n Rivets.factory = function(sightglass) {\n Rivets.sightglass = sightglass;\n Rivets[\"public\"]._ = Rivets;\n return Rivets[\"public\"];\n };\n\n if (typeof (typeof module !== \"undefined\" && module !== null ? module.exports : void 0) === 'object') {\n module.exports = Rivets.factory(__webpack_require__(\"./node_modules/sightglass/index.js\"));\n } else if (true) {\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(\"./node_modules/sightglass/index.js\")], __WEBPACK_AMD_DEFINE_RESULT__ = (function(sightglass) {\n return this.rivets = Rivets.factory(sightglass);\n }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n } else {\n this.rivets = Rivets.factory(sightglass);\n }\n\n}).call(this);\n\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(\"./node_modules/webpack/buildin/module.js\")(module)))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvcml2ZXRzL2Rpc3Qvcml2ZXRzLmpzP2ViMWIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCLG1CQUFtQixnQ0FBZ0MsR0FBRyxFQUFFO0FBQ3RGO0FBQ0Esa0JBQWtCO0FBQ2xCLHlDQUF5QywwQkFBMEIsMkRBQTJELEVBQUUsa0JBQWtCLDBCQUEwQixFQUFFLG1DQUFtQyw4QkFBOEIsb0NBQW9DLGNBQWMsRUFBRTtBQUNuUyw4Q0FBOEMsaUNBQWlDLE9BQU8sT0FBTyw2Q0FBNkMsRUFBRSxXQUFXOztBQUV2SjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQixvQkFBb0I7QUFDcEIsb0JBQW9CO0FBQ3BCLGtCQUFrQjtBQUNsQjtBQUNBLDZCQUE2QixLQUFLO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLHdDQUF3QyxXQUFXO0FBQ25EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDLFlBQVk7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxXQUFXO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDLFdBQVc7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUMsV0FBVztBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0RBQW9ELFdBQVc7QUFDL0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdEQUFnRCxZQUFZO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLDhDQUE4QyxZQUFZO0FBQzFEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSx1Q0FBdUMsV0FBVztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxXQUFXO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0MsWUFBWTtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsV0FBVztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsV0FBVztBQUNsRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsV0FBVztBQUNsRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsV0FBVztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCx1Q0FBdUMsV0FBVztBQUNsRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxXQUFXO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0MsV0FBVztBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLDJDQUEyQyxXQUFXO0FBQ3REO0FBQ0EseUtBQXlLO0FBQ3pLO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw0Q0FBNEMsV0FBVztBQUN2RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkMsV0FBVztBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0QsWUFBWTtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNEQUFzRCxXQUFXO0FBQ2pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDLFdBQVc7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxXQUFXO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBOztBQUVBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDLFdBQVc7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLFlBQVk7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLFdBQVc7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EseUNBQXlDLFdBQVc7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUMsV0FBVztBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUMsV0FBVztBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxREFBcUQsWUFBWTtBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLFlBQVk7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkMsV0FBVztBQUN0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsV0FBVztBQUMxRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1REFBdUQsV0FBVztBQUNsRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esb0NBQW9DLG1CQUFPLENBQUMsb0NBQVk7QUFDeEQsR0FBRyxVQUFVLElBQTBDO0FBQ3ZELElBQUksaUNBQU8sQ0FBQyx5REFBWSxDQUFDLG1DQUFFO0FBQzNCO0FBQ0EsS0FBSztBQUFBLG9HQUFDO0FBQ04sR0FBRztBQUNIO0FBQ0E7O0FBRUEsQ0FBQyIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9yaXZldHMvZGlzdC9yaXZldHMuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBSaXZldHMuanNcbi8vIHZlcnNpb246IDAuOS42XG4vLyBhdXRob3I6IE1pY2hhZWwgUmljaGFyZHNcbi8vIGxpY2Vuc2U6IE1JVFxuKGZ1bmN0aW9uKCkge1xuICB2YXIgUml2ZXRzLCBiaW5kTWV0aG9kLCBqUXVlcnksIHVuYmluZE1ldGhvZCwgX3JlZixcbiAgICBfX2JpbmQgPSBmdW5jdGlvbihmbiwgbWUpeyByZXR1cm4gZnVuY3Rpb24oKXsgcmV0dXJuIGZuLmFwcGx5KG1lLCBhcmd1bWVudHMpOyB9OyB9LFxuICAgIF9fc2xpY2UgPSBbXS5zbGljZSxcbiAgICBfX2hhc1Byb3AgPSB7fS5oYXNPd25Qcm9wZXJ0eSxcbiAgICBfX2V4dGVuZHMgPSBmdW5jdGlvbihjaGlsZCwgcGFyZW50KSB7IGZvciAodmFyIGtleSBpbiBwYXJlbnQpIHsgaWYgKF9faGFzUHJvcC5jYWxsKHBhcmVudCwga2V5KSkgY2hpbGRba2V5XSA9IHBhcmVudFtrZXldOyB9IGZ1bmN0aW9uIGN0b3IoKSB7IHRoaXMuY29uc3RydWN0b3IgPSBjaGlsZDsgfSBjdG9yLnByb3RvdHlwZSA9IHBhcmVudC5wcm90b3R5cGU7IGNoaWxkLnByb3RvdHlwZSA9IG5ldyBjdG9yKCk7IGNoaWxkLl9fc3VwZXJfXyA9IHBhcmVudC5wcm90b3R5cGU7IHJldHVybiBjaGlsZDsgfSxcbiAgICBfX2luZGV4T2YgPSBbXS5pbmRleE9mIHx8IGZ1bmN0aW9uKGl0ZW0pIHsgZm9yICh2YXIgaSA9IDAsIGwgPSB0aGlzLmxlbmd0aDsgaSA8IGw7IGkrKykgeyBpZiAoaSBpbiB0aGlzICYmIHRoaXNbaV0gPT09IGl0ZW0pIHJldHVybiBpOyB9IHJldHVybiAtMTsgfTtcblxuICBSaXZldHMgPSB7XG4gICAgb3B0aW9uczogWydwcmVmaXgnLCAndGVtcGxhdGVEZWxpbWl0ZXJzJywgJ3Jvb3RJbnRlcmZhY2UnLCAncHJlbG9hZERhdGEnLCAnaGFuZGxlcicsICdleGVjdXRlRnVuY3Rpb25zJ10sXG4gICAgZXh0ZW5zaW9uczogWydiaW5kZXJzJywgJ2Zvcm1hdHRlcnMnLCAnY29tcG9uZW50cycsICdhZGFwdGVycyddLFxuICAgIFwicHVibGljXCI6IHtcbiAgICAgIGJpbmRlcnM6IHt9LFxuICAgICAgY29tcG9uZW50czoge30sXG4gICAgICBmb3JtYXR0ZXJzOiB7fSxcbiAgICAgIGFkYXB0ZXJzOiB7fSxcbiAgICAgIHByZWZpeDogJ3J2JyxcbiAgICAgIHRlbXBsYXRlRGVsaW1pdGVyczogWyd7JywgJ30nXSxcbiAgICAgIHJvb3RJbnRlcmZhY2U6ICcuJyxcbiAgICAgIHByZWxvYWREYXRhOiB0cnVlLFxuICAgICAgZXhlY3V0ZUZ1bmN0aW9uczogZmFsc2UsXG4gICAgICBpdGVyYXRpb25BbGlhczogZnVuY3Rpb24obW9kZWxOYW1lKSB7XG4gICAgICAgIHJldHVybiAnJScgKyBtb2RlbE5hbWUgKyAnJSc7XG4gICAgICB9LFxuICAgICAgaGFuZGxlcjogZnVuY3Rpb24oY29udGV4dCwgZXYsIGJpbmRpbmcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsbChjb250ZXh0LCBldiwgYmluZGluZy52aWV3Lm1vZGVscyk7XG4gICAgICB9LFxuICAgICAgY29uZmlndXJlOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgIHZhciBkZXNjcmlwdG9yLCBrZXksIG9wdGlvbiwgdmFsdWU7XG4gICAgICAgIGlmIChvcHRpb25zID09IG51bGwpIHtcbiAgICAgICAgICBvcHRpb25zID0ge307XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChvcHRpb24gaW4gb3B0aW9ucykge1xuICAgICAgICAgIHZhbHVlID0gb3B0aW9uc1tvcHRpb25dO1xuICAgICAgICAgIGlmIChvcHRpb24gPT09ICdiaW5kZXJzJyB8fCBvcHRpb24gPT09ICdjb21wb25lbnRzJyB8fCBvcHRpb24gPT09ICdmb3JtYXR0ZXJzJyB8fCBvcHRpb24gPT09ICdhZGFwdGVycycpIHtcbiAgICAgICAgICAgIGZvciAoa2V5IGluIHZhbHVlKSB7XG4gICAgICAgICAgICAgIGRlc2NyaXB0b3IgPSB2YWx1ZVtrZXldO1xuICAgICAgICAgICAgICBSaXZldHNbb3B0aW9uXVtrZXldID0gZGVzY3JpcHRvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgUml2ZXRzW1wicHVibGljXCJdW29wdGlvbl0gPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBiaW5kOiBmdW5jdGlvbihlbCwgbW9kZWxzLCBvcHRpb25zKSB7XG4gICAgICAgIHZhciB2aWV3O1xuICAgICAgICBpZiAobW9kZWxzID09IG51bGwpIHtcbiAgICAgICAgICBtb2RlbHMgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3B0aW9ucyA9PSBudWxsKSB7XG4gICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIHZpZXcgPSBuZXcgUml2ZXRzLlZpZXcoZWwsIG1vZGVscywgb3B0aW9ucyk7XG4gICAgICAgIHZpZXcuYmluZCgpO1xuICAgICAgICByZXR1cm4gdmlldztcbiAgICAgIH0sXG4gICAgICBpbml0OiBmdW5jdGlvbihjb21wb25lbnQsIGVsLCBkYXRhKSB7XG4gICAgICAgIHZhciBzY29wZSwgdGVtcGxhdGUsIHZpZXc7XG4gICAgICAgIGlmIChkYXRhID09IG51bGwpIHtcbiAgICAgICAgICBkYXRhID0ge307XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGVsID09IG51bGwpIHtcbiAgICAgICAgICBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICB9XG4gICAgICAgIGNvbXBvbmVudCA9IFJpdmV0c1tcInB1YmxpY1wiXS5jb21wb25lbnRzW2NvbXBvbmVudF07XG4gICAgICAgIHRlbXBsYXRlID0gY29tcG9uZW50LnRlbXBsYXRlLmNhbGwodGhpcywgZWwpO1xuICAgICAgICBpZiAodGVtcGxhdGUgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgICAgICAgIHdoaWxlIChlbC5maXJzdENoaWxkKSB7XG4gICAgICAgICAgICBlbC5yZW1vdmVDaGlsZChlbC5maXJzdENoaWxkKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWwuYXBwZW5kQ2hpbGQodGVtcGxhdGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVsLmlubmVySFRNTCA9IHRlbXBsYXRlO1xuICAgICAgICB9XG4gICAgICAgIHNjb3BlID0gY29tcG9uZW50LmluaXRpYWxpemUuY2FsbCh0aGlzLCBlbCwgZGF0YSk7XG4gICAgICAgIHZpZXcgPSBuZXcgUml2ZXRzLlZpZXcoZWwsIHNjb3BlKTtcbiAgICAgICAgdmlldy5iaW5kKCk7XG4gICAgICAgIHJldHVybiB2aWV3O1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBpZiAod2luZG93WydqUXVlcnknXSB8fCB3aW5kb3dbJyQnXSkge1xuICAgIGpRdWVyeSA9IHdpbmRvd1snalF1ZXJ5J10gfHwgd2luZG93WyckJ107XG4gICAgX3JlZiA9ICdvbicgaW4galF1ZXJ5LnByb3RvdHlwZSA/IFsnb24nLCAnb2ZmJ10gOiBbJ2JpbmQnLCAndW5iaW5kJ10sIGJpbmRNZXRob2QgPSBfcmVmWzBdLCB1bmJpbmRNZXRob2QgPSBfcmVmWzFdO1xuICAgIFJpdmV0cy5VdGlsID0ge1xuICAgICAgYmluZEV2ZW50OiBmdW5jdGlvbihlbCwgZXZlbnQsIGhhbmRsZXIpIHtcbiAgICAgICAgcmV0dXJuIGpRdWVyeShlbClbYmluZE1ldGhvZF0oZXZlbnQsIGhhbmRsZXIpO1xuICAgICAgfSxcbiAgICAgIHVuYmluZEV2ZW50OiBmdW5jdGlvbihlbCwgZXZlbnQsIGhhbmRsZXIpIHtcbiAgICAgICAgcmV0dXJuIGpRdWVyeShlbClbdW5iaW5kTWV0aG9kXShldmVudCwgaGFuZGxlcik7XG4gICAgICB9LFxuICAgICAgZ2V0SW5wdXRWYWx1ZTogZnVuY3Rpb24oZWwpIHtcbiAgICAgICAgdmFyICRlbDtcbiAgICAgICAgJGVsID0galF1ZXJ5KGVsKTtcbiAgICAgICAgaWYgKCRlbC5hdHRyKCd0eXBlJykgPT09ICdjaGVja2JveCcpIHtcbiAgICAgICAgICByZXR1cm4gJGVsLmlzKCc6Y2hlY2tlZCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiAkZWwudmFsKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIFJpdmV0cy5VdGlsID0ge1xuICAgICAgYmluZEV2ZW50OiAoZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICgnYWRkRXZlbnRMaXN0ZW5lcicgaW4gd2luZG93KSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVsLCBldmVudCwgaGFuZGxlcikge1xuICAgICAgICAgICAgcmV0dXJuIGVsLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZXIsIGZhbHNlKTtcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihlbCwgZXZlbnQsIGhhbmRsZXIpIHtcbiAgICAgICAgICByZXR1cm4gZWwuYXR0YWNoRXZlbnQoJ29uJyArIGV2ZW50LCBoYW5kbGVyKTtcbiAgICAgICAgfTtcbiAgICAgIH0pKCksXG4gICAgICB1bmJpbmRFdmVudDogKGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoJ3JlbW92ZUV2ZW50TGlzdGVuZXInIGluIHdpbmRvdykge1xuICAgICAgICAgIHJldHVybiBmdW5jdGlvbihlbCwgZXZlbnQsIGhhbmRsZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBlbC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVyLCBmYWxzZSk7XG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZnVuY3Rpb24oZWwsIGV2ZW50LCBoYW5kbGVyKSB7XG4gICAgICAgICAgcmV0dXJuIGVsLmRldGFjaEV2ZW50KCdvbicgKyBldmVudCwgaGFuZGxlcik7XG4gICAgICAgIH07XG4gICAgICB9KSgpLFxuICAgICAgZ2V0SW5wdXRWYWx1ZTogZnVuY3Rpb24oZWwpIHtcbiAgICAgICAgdmFyIG8sIF9pLCBfbGVuLCBfcmVzdWx0cztcbiAgICAgICAgaWYgKGVsLnR5cGUgPT09ICdjaGVja2JveCcpIHtcbiAgICAgICAgICByZXR1cm4gZWwuY2hlY2tlZDtcbiAgICAgICAgfSBlbHNlIGlmIChlbC50eXBlID09PSAnc2VsZWN0LW11bHRpcGxlJykge1xuICAgICAgICAgIF9yZXN1bHRzID0gW107XG4gICAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBlbC5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgICAgbyA9IGVsW19pXTtcbiAgICAgICAgICAgIGlmIChvLnNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgIF9yZXN1bHRzLnB1c2goby52YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBfcmVzdWx0cztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gZWwudmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgUml2ZXRzLlR5cGVQYXJzZXIgPSAoZnVuY3Rpb24oKSB7XG4gICAgZnVuY3Rpb24gVHlwZVBhcnNlcigpIHt9XG5cbiAgICBUeXBlUGFyc2VyLnR5cGVzID0ge1xuICAgICAgcHJpbWl0aXZlOiAwLFxuICAgICAga2V5cGF0aDogMVxuICAgIH07XG5cbiAgICBUeXBlUGFyc2VyLnBhcnNlID0gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICBpZiAoL14nLionJHxeXCIuKlwiJC8udGVzdChzdHJpbmcpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogdGhpcy50eXBlcy5wcmltaXRpdmUsXG4gICAgICAgICAgdmFsdWU6IHN0cmluZy5zbGljZSgxLCAtMSlcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSBpZiAoc3RyaW5nID09PSAndHJ1ZScpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiB0aGlzLnR5cGVzLnByaW1pdGl2ZSxcbiAgICAgICAgICB2YWx1ZTogdHJ1ZVxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmIChzdHJpbmcgPT09ICdmYWxzZScpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiB0aGlzLnR5cGVzLnByaW1pdGl2ZSxcbiAgICAgICAgICB2YWx1ZTogZmFsc2VcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSBpZiAoc3RyaW5nID09PSAnbnVsbCcpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiB0aGlzLnR5cGVzLnByaW1pdGl2ZSxcbiAgICAgICAgICB2YWx1ZTogbnVsbFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmIChzdHJpbmcgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogdGhpcy50eXBlcy5wcmltaXRpdmUsXG4gICAgICAgICAgdmFsdWU6IHZvaWQgMFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmIChzdHJpbmcgPT09ICcnKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogdGhpcy50eXBlcy5wcmltaXRpdmUsXG4gICAgICAgICAgdmFsdWU6IHZvaWQgMFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmIChpc05hTihOdW1iZXIoc3RyaW5nKSkgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogdGhpcy50eXBlcy5wcmltaXRpdmUsXG4gICAgICAgICAgdmFsdWU6IE51bWJlcihzdHJpbmcpXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IHRoaXMudHlwZXMua2V5cGF0aCxcbiAgICAgICAgICB2YWx1ZTogc3RyaW5nXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBUeXBlUGFyc2VyO1xuXG4gIH0pKCk7XG5cbiAgUml2ZXRzLlRleHRUZW1wbGF0ZVBhcnNlciA9IChmdW5jdGlvbigpIHtcbiAgICBmdW5jdGlvbiBUZXh0VGVtcGxhdGVQYXJzZXIoKSB7fVxuXG4gICAgVGV4dFRlbXBsYXRlUGFyc2VyLnR5cGVzID0ge1xuICAgICAgdGV4dDogMCxcbiAgICAgIGJpbmRpbmc6IDFcbiAgICB9O1xuXG4gICAgVGV4dFRlbXBsYXRlUGFyc2VyLnBhcnNlID0gZnVuY3Rpb24odGVtcGxhdGUsIGRlbGltaXRlcnMpIHtcbiAgICAgIHZhciBpbmRleCwgbGFzdEluZGV4LCBsYXN0VG9rZW4sIGxlbmd0aCwgc3Vic3RyaW5nLCB0b2tlbnMsIHZhbHVlO1xuICAgICAgdG9rZW5zID0gW107XG4gICAgICBsZW5ndGggPSB0ZW1wbGF0ZS5sZW5ndGg7XG4gICAgICBpbmRleCA9IDA7XG4gICAgICBsYXN0SW5kZXggPSAwO1xuICAgICAgd2hpbGUgKGxhc3RJbmRleCA8IGxlbmd0aCkge1xuICAgICAgICBpbmRleCA9IHRlbXBsYXRlLmluZGV4T2YoZGVsaW1pdGVyc1swXSwgbGFzdEluZGV4KTtcbiAgICAgICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgICAgIHRva2Vucy5wdXNoKHtcbiAgICAgICAgICAgIHR5cGU6IHRoaXMudHlwZXMudGV4dCxcbiAgICAgICAgICAgIHZhbHVlOiB0ZW1wbGF0ZS5zbGljZShsYXN0SW5kZXgpXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGluZGV4ID4gMCAmJiBsYXN0SW5kZXggPCBpbmRleCkge1xuICAgICAgICAgICAgdG9rZW5zLnB1c2goe1xuICAgICAgICAgICAgICB0eXBlOiB0aGlzLnR5cGVzLnRleHQsXG4gICAgICAgICAgICAgIHZhbHVlOiB0ZW1wbGF0ZS5zbGljZShsYXN0SW5kZXgsIGluZGV4KVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGxhc3RJbmRleCA9IGluZGV4ICsgZGVsaW1pdGVyc1swXS5sZW5ndGg7XG4gICAgICAgICAgaW5kZXggPSB0ZW1wbGF0ZS5pbmRleE9mKGRlbGltaXRlcnNbMV0sIGxhc3RJbmRleCk7XG4gICAgICAgICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgICAgICAgc3Vic3RyaW5nID0gdGVtcGxhdGUuc2xpY2UobGFzdEluZGV4IC0gZGVsaW1pdGVyc1sxXS5sZW5ndGgpO1xuICAgICAgICAgICAgbGFzdFRva2VuID0gdG9rZW5zW3Rva2Vucy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgIGlmICgobGFzdFRva2VuICE9IG51bGwgPyBsYXN0VG9rZW4udHlwZSA6IHZvaWQgMCkgPT09IHRoaXMudHlwZXMudGV4dCkge1xuICAgICAgICAgICAgICBsYXN0VG9rZW4udmFsdWUgKz0gc3Vic3RyaW5nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgdG9rZW5zLnB1c2goe1xuICAgICAgICAgICAgICAgIHR5cGU6IHRoaXMudHlwZXMudGV4dCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogc3Vic3RyaW5nXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhbHVlID0gdGVtcGxhdGUuc2xpY2UobGFzdEluZGV4LCBpbmRleCkudHJpbSgpO1xuICAgICAgICAgIHRva2Vucy5wdXNoKHtcbiAgICAgICAgICAgIHR5cGU6IHRoaXMudHlwZXMuYmluZGluZyxcbiAgICAgICAgICAgIHZhbHVlOiB2YWx1ZVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIGxhc3RJbmRleCA9IGluZGV4ICsgZGVsaW1pdGVyc1sxXS5sZW5ndGg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0b2tlbnM7XG4gICAgfTtcblxuICAgIHJldHVybiBUZXh0VGVtcGxhdGVQYXJzZXI7XG5cbiAgfSkoKTtcblxuICBSaXZldHMuVmlldyA9IChmdW5jdGlvbigpIHtcbiAgICBmdW5jdGlvbiBWaWV3KGVscywgbW9kZWxzLCBvcHRpb25zKSB7XG4gICAgICB2YXIgaywgb3B0aW9uLCB2LCBfYmFzZSwgX2ksIF9qLCBfbGVuLCBfbGVuMSwgX3JlZjEsIF9yZWYyLCBfcmVmMywgX3JlZjQsIF9yZWY1O1xuICAgICAgdGhpcy5lbHMgPSBlbHM7XG4gICAgICB0aGlzLm1vZGVscyA9IG1vZGVscztcbiAgICAgIGlmIChvcHRpb25zID09IG51bGwpIHtcbiAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgfVxuICAgICAgdGhpcy51cGRhdGUgPSBfX2JpbmQodGhpcy51cGRhdGUsIHRoaXMpO1xuICAgICAgdGhpcy5wdWJsaXNoID0gX19iaW5kKHRoaXMucHVibGlzaCwgdGhpcyk7XG4gICAgICB0aGlzLnN5bmMgPSBfX2JpbmQodGhpcy5zeW5jLCB0aGlzKTtcbiAgICAgIHRoaXMudW5iaW5kID0gX19iaW5kKHRoaXMudW5iaW5kLCB0aGlzKTtcbiAgICAgIHRoaXMuYmluZCA9IF9fYmluZCh0aGlzLmJpbmQsIHRoaXMpO1xuICAgICAgdGhpcy5zZWxlY3QgPSBfX2JpbmQodGhpcy5zZWxlY3QsIHRoaXMpO1xuICAgICAgdGhpcy50cmF2ZXJzZSA9IF9fYmluZCh0aGlzLnRyYXZlcnNlLCB0aGlzKTtcbiAgICAgIHRoaXMuYnVpbGQgPSBfX2JpbmQodGhpcy5idWlsZCwgdGhpcyk7XG4gICAgICB0aGlzLmJ1aWxkQmluZGluZyA9IF9fYmluZCh0aGlzLmJ1aWxkQmluZGluZywgdGhpcyk7XG4gICAgICB0aGlzLmJpbmRpbmdSZWdFeHAgPSBfX2JpbmQodGhpcy5iaW5kaW5nUmVnRXhwLCB0aGlzKTtcbiAgICAgIHRoaXMub3B0aW9ucyA9IF9fYmluZCh0aGlzLm9wdGlvbnMsIHRoaXMpO1xuICAgICAgaWYgKCEodGhpcy5lbHMuanF1ZXJ5IHx8IHRoaXMuZWxzIGluc3RhbmNlb2YgQXJyYXkpKSB7XG4gICAgICAgIHRoaXMuZWxzID0gW3RoaXMuZWxzXTtcbiAgICAgIH1cbiAgICAgIF9yZWYxID0gUml2ZXRzLmV4dGVuc2lvbnM7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIG9wdGlvbiA9IF9yZWYxW19pXTtcbiAgICAgICAgdGhpc1tvcHRpb25dID0ge307XG4gICAgICAgIGlmIChvcHRpb25zW29wdGlvbl0pIHtcbiAgICAgICAgICBfcmVmMiA9IG9wdGlvbnNbb3B0aW9uXTtcbiAgICAgICAgICBmb3IgKGsgaW4gX3JlZjIpIHtcbiAgICAgICAgICAgIHYgPSBfcmVmMltrXTtcbiAgICAgICAgICAgIHRoaXNbb3B0aW9uXVtrXSA9IHY7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIF9yZWYzID0gUml2ZXRzW1wicHVibGljXCJdW29wdGlvbl07XG4gICAgICAgIGZvciAoayBpbiBfcmVmMykge1xuICAgICAgICAgIHYgPSBfcmVmM1trXTtcbiAgICAgICAgICBpZiAoKF9iYXNlID0gdGhpc1tvcHRpb25dKVtrXSA9PSBudWxsKSB7XG4gICAgICAgICAgICBfYmFzZVtrXSA9IHY7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBfcmVmNCA9IFJpdmV0cy5vcHRpb25zO1xuICAgICAgZm9yIChfaiA9IDAsIF9sZW4xID0gX3JlZjQubGVuZ3RoOyBfaiA8IF9sZW4xOyBfaisrKSB7XG4gICAgICAgIG9wdGlvbiA9IF9yZWY0W19qXTtcbiAgICAgICAgdGhpc1tvcHRpb25dID0gKF9yZWY1ID0gb3B0aW9uc1tvcHRpb25dKSAhPSBudWxsID8gX3JlZjUgOiBSaXZldHNbXCJwdWJsaWNcIl1bb3B0aW9uXTtcbiAgICAgIH1cbiAgICAgIHRoaXMuYnVpbGQoKTtcbiAgICB9XG5cbiAgICBWaWV3LnByb3RvdHlwZS5vcHRpb25zID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgb3B0aW9uLCBvcHRpb25zLCBfaSwgX2xlbiwgX3JlZjE7XG4gICAgICBvcHRpb25zID0ge307XG4gICAgICBfcmVmMSA9IFJpdmV0cy5leHRlbnNpb25zLmNvbmNhdChSaXZldHMub3B0aW9ucyk7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIG9wdGlvbiA9IF9yZWYxW19pXTtcbiAgICAgICAgb3B0aW9uc1tvcHRpb25dID0gdGhpc1tvcHRpb25dO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG9wdGlvbnM7XG4gICAgfTtcblxuICAgIFZpZXcucHJvdG90eXBlLmJpbmRpbmdSZWdFeHAgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBuZXcgUmVnRXhwKFwiXlwiICsgdGhpcy5wcmVmaXggKyBcIi1cIik7XG4gICAgfTtcblxuICAgIFZpZXcucHJvdG90eXBlLmJ1aWxkQmluZGluZyA9IGZ1bmN0aW9uKGJpbmRpbmcsIG5vZGUsIHR5cGUsIGRlY2xhcmF0aW9uKSB7XG4gICAgICB2YXIgY29udGV4dCwgY3R4LCBkZXBlbmRlbmNpZXMsIGtleXBhdGgsIG9wdGlvbnMsIHBpcGUsIHBpcGVzO1xuICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgcGlwZXMgPSAoZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBfaSwgX2xlbiwgX3JlZjEsIF9yZXN1bHRzO1xuICAgICAgICBfcmVmMSA9IGRlY2xhcmF0aW9uLm1hdGNoKC8oKD86J1teJ10qJykqKD86KD86W15cXHwnXSooPzonW14nXSonKStbXlxcfCddKikrfFteXFx8XSspKXxeJC9nKTtcbiAgICAgICAgX3Jlc3VsdHMgPSBbXTtcbiAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgIHBpcGUgPSBfcmVmMVtfaV07XG4gICAgICAgICAgX3Jlc3VsdHMucHVzaChwaXBlLnRyaW0oKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9yZXN1bHRzO1xuICAgICAgfSkoKTtcbiAgICAgIGNvbnRleHQgPSAoZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBfaSwgX2xlbiwgX3JlZjEsIF9yZXN1bHRzO1xuICAgICAgICBfcmVmMSA9IHBpcGVzLnNoaWZ0KCkuc3BsaXQoJzwnKTtcbiAgICAgICAgX3Jlc3VsdHMgPSBbXTtcbiAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgIGN0eCA9IF9yZWYxW19pXTtcbiAgICAgICAgICBfcmVzdWx0cy5wdXNoKGN0eC50cmltKCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfcmVzdWx0cztcbiAgICAgIH0pKCk7XG4gICAgICBrZXlwYXRoID0gY29udGV4dC5zaGlmdCgpO1xuICAgICAgb3B0aW9ucy5mb3JtYXR0ZXJzID0gcGlwZXM7XG4gICAgICBpZiAoZGVwZW5kZW5jaWVzID0gY29udGV4dC5zaGlmdCgpKSB7XG4gICAgICAgIG9wdGlvbnMuZGVwZW5kZW5jaWVzID0gZGVwZW5kZW5jaWVzLnNwbGl0KC9cXHMrLyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5iaW5kaW5ncy5wdXNoKG5ldyBSaXZldHNbYmluZGluZ10odGhpcywgbm9kZSwgdHlwZSwga2V5cGF0aCwgb3B0aW9ucykpO1xuICAgIH07XG5cbiAgICBWaWV3LnByb3RvdHlwZS5idWlsZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGVsLCBwYXJzZSwgX2ksIF9sZW4sIF9yZWYxO1xuICAgICAgdGhpcy5iaW5kaW5ncyA9IFtdO1xuICAgICAgcGFyc2UgPSAoZnVuY3Rpb24oX3RoaXMpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgICB2YXIgYmxvY2ssIGNoaWxkTm9kZSwgZGVsaW1pdGVycywgbiwgcGFyc2VyLCB0ZXh0LCB0b2tlbiwgdG9rZW5zLCBfaSwgX2osIF9sZW4sIF9sZW4xLCBfcmVmMTtcbiAgICAgICAgICBpZiAobm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgcGFyc2VyID0gUml2ZXRzLlRleHRUZW1wbGF0ZVBhcnNlcjtcbiAgICAgICAgICAgIGlmIChkZWxpbWl0ZXJzID0gX3RoaXMudGVtcGxhdGVEZWxpbWl0ZXJzKSB7XG4gICAgICAgICAgICAgIGlmICgodG9rZW5zID0gcGFyc2VyLnBhcnNlKG5vZGUuZGF0YSwgZGVsaW1pdGVycykpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGlmICghKHRva2Vucy5sZW5ndGggPT09IDEgJiYgdG9rZW5zWzBdLnR5cGUgPT09IHBhcnNlci50eXBlcy50ZXh0KSkge1xuICAgICAgICAgICAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSB0b2tlbnMubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdG9rZW4gPSB0b2tlbnNbX2ldO1xuICAgICAgICAgICAgICAgICAgICB0ZXh0ID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUodG9rZW4udmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBub2RlLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRleHQsIG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodG9rZW4udHlwZSA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgIF90aGlzLmJ1aWxkQmluZGluZygnVGV4dEJpbmRpbmcnLCB0ZXh0LCBudWxsLCB0b2tlbi52YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIG5vZGUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKG5vZGUubm9kZVR5cGUgPT09IDEpIHtcbiAgICAgICAgICAgIGJsb2NrID0gX3RoaXMudHJhdmVyc2Uobm9kZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghYmxvY2spIHtcbiAgICAgICAgICAgIF9yZWYxID0gKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICB2YXIgX2ssIF9sZW4xLCBfcmVmMSwgX3Jlc3VsdHM7XG4gICAgICAgICAgICAgIF9yZWYxID0gbm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICBfcmVzdWx0cyA9IFtdO1xuICAgICAgICAgICAgICBmb3IgKF9rID0gMCwgX2xlbjEgPSBfcmVmMS5sZW5ndGg7IF9rIDwgX2xlbjE7IF9rKyspIHtcbiAgICAgICAgICAgICAgICBuID0gX3JlZjFbX2tdO1xuICAgICAgICAgICAgICAgIF9yZXN1bHRzLnB1c2gobik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmV0dXJuIF9yZXN1bHRzO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgICAgIGZvciAoX2ogPSAwLCBfbGVuMSA9IF9yZWYxLmxlbmd0aDsgX2ogPCBfbGVuMTsgX2orKykge1xuICAgICAgICAgICAgICBjaGlsZE5vZGUgPSBfcmVmMVtfal07XG4gICAgICAgICAgICAgIHBhcnNlKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfSkodGhpcyk7XG4gICAgICBfcmVmMSA9IHRoaXMuZWxzO1xuICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICBlbCA9IF9yZWYxW19pXTtcbiAgICAgICAgcGFyc2UoZWwpO1xuICAgICAgfVxuICAgICAgdGhpcy5iaW5kaW5ncy5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgdmFyIF9yZWYyLCBfcmVmMztcbiAgICAgICAgcmV0dXJuICgoKF9yZWYyID0gYi5iaW5kZXIpICE9IG51bGwgPyBfcmVmMi5wcmlvcml0eSA6IHZvaWQgMCkgfHwgMCkgLSAoKChfcmVmMyA9IGEuYmluZGVyKSAhPSBudWxsID8gX3JlZjMucHJpb3JpdHkgOiB2b2lkIDApIHx8IDApO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIFZpZXcucHJvdG90eXBlLnRyYXZlcnNlID0gZnVuY3Rpb24obm9kZSkge1xuICAgICAgdmFyIGF0dHJpYnV0ZSwgYXR0cmlidXRlcywgYmluZGVyLCBiaW5kaW5nUmVnRXhwLCBibG9jaywgaWRlbnRpZmllciwgcmVnZXhwLCB0eXBlLCB2YWx1ZSwgX2ksIF9qLCBfbGVuLCBfbGVuMSwgX3JlZjEsIF9yZWYyLCBfcmVmMztcbiAgICAgIGJpbmRpbmdSZWdFeHAgPSB0aGlzLmJpbmRpbmdSZWdFeHAoKTtcbiAgICAgIGJsb2NrID0gbm9kZS5ub2RlTmFtZSA9PT0gJ1NDUklQVCcgfHwgbm9kZS5ub2RlTmFtZSA9PT0gJ1NUWUxFJztcbiAgICAgIF9yZWYxID0gbm9kZS5hdHRyaWJ1dGVzO1xuICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICBhdHRyaWJ1dGUgPSBfcmVmMVtfaV07XG4gICAgICAgIGlmIChiaW5kaW5nUmVnRXhwLnRlc3QoYXR0cmlidXRlLm5hbWUpKSB7XG4gICAgICAgICAgdHlwZSA9IGF0dHJpYnV0ZS5uYW1lLnJlcGxhY2UoYmluZGluZ1JlZ0V4cCwgJycpO1xuICAgICAgICAgIGlmICghKGJpbmRlciA9IHRoaXMuYmluZGVyc1t0eXBlXSkpIHtcbiAgICAgICAgICAgIF9yZWYyID0gdGhpcy5iaW5kZXJzO1xuICAgICAgICAgICAgZm9yIChpZGVudGlmaWVyIGluIF9yZWYyKSB7XG4gICAgICAgICAgICAgIHZhbHVlID0gX3JlZjJbaWRlbnRpZmllcl07XG4gICAgICAgICAgICAgIGlmIChpZGVudGlmaWVyICE9PSAnKicgJiYgaWRlbnRpZmllci5pbmRleE9mKCcqJykgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmVnZXhwID0gbmV3IFJlZ0V4cChcIl5cIiArIChpZGVudGlmaWVyLnJlcGxhY2UoL1xcKi9nLCAnLisnKSkgKyBcIiRcIik7XG4gICAgICAgICAgICAgICAgaWYgKHJlZ2V4cC50ZXN0KHR5cGUpKSB7XG4gICAgICAgICAgICAgICAgICBiaW5kZXIgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYmluZGVyIHx8IChiaW5kZXIgPSB0aGlzLmJpbmRlcnNbJyonXSk7XG4gICAgICAgICAgaWYgKGJpbmRlci5ibG9jaykge1xuICAgICAgICAgICAgYmxvY2sgPSB0cnVlO1xuICAgICAgICAgICAgYXR0cmlidXRlcyA9IFthdHRyaWJ1dGVdO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgX3JlZjMgPSBhdHRyaWJ1dGVzIHx8IG5vZGUuYXR0cmlidXRlcztcbiAgICAgIGZvciAoX2ogPSAwLCBfbGVuMSA9IF9yZWYzLmxlbmd0aDsgX2ogPCBfbGVuMTsgX2orKykge1xuICAgICAgICBhdHRyaWJ1dGUgPSBfcmVmM1tfal07XG4gICAgICAgIGlmIChiaW5kaW5nUmVnRXhwLnRlc3QoYXR0cmlidXRlLm5hbWUpKSB7XG4gICAgICAgICAgdHlwZSA9IGF0dHJpYnV0ZS5uYW1lLnJlcGxhY2UoYmluZGluZ1JlZ0V4cCwgJycpO1xuICAgICAgICAgIHRoaXMuYnVpbGRCaW5kaW5nKCdCaW5kaW5nJywgbm9kZSwgdHlwZSwgYXR0cmlidXRlLnZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFibG9jaykge1xuICAgICAgICB0eXBlID0gbm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAodGhpcy5jb21wb25lbnRzW3R5cGVdICYmICFub2RlLl9ib3VuZCkge1xuICAgICAgICAgIHRoaXMuYmluZGluZ3MucHVzaChuZXcgUml2ZXRzLkNvbXBvbmVudEJpbmRpbmcodGhpcywgbm9kZSwgdHlwZSkpO1xuICAgICAgICAgIGJsb2NrID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIGJsb2NrO1xuICAgIH07XG5cbiAgICBWaWV3LnByb3RvdHlwZS5zZWxlY3QgPSBmdW5jdGlvbihmbikge1xuICAgICAgdmFyIGJpbmRpbmcsIF9pLCBfbGVuLCBfcmVmMSwgX3Jlc3VsdHM7XG4gICAgICBfcmVmMSA9IHRoaXMuYmluZGluZ3M7XG4gICAgICBfcmVzdWx0cyA9IFtdO1xuICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICBiaW5kaW5nID0gX3JlZjFbX2ldO1xuICAgICAgICBpZiAoZm4oYmluZGluZykpIHtcbiAgICAgICAgICBfcmVzdWx0cy5wdXNoKGJpbmRpbmcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gX3Jlc3VsdHM7XG4gICAgfTtcblxuICAgIFZpZXcucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBiaW5kaW5nLCBfaSwgX2xlbiwgX3JlZjE7XG4gICAgICBfcmVmMSA9IHRoaXMuYmluZGluZ3M7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGJpbmRpbmcgPSBfcmVmMVtfaV07XG4gICAgICAgIGJpbmRpbmcuYmluZCgpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBWaWV3LnByb3RvdHlwZS51bmJpbmQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBiaW5kaW5nLCBfaSwgX2xlbiwgX3JlZjE7XG4gICAgICBfcmVmMSA9IHRoaXMuYmluZGluZ3M7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGJpbmRpbmcgPSBfcmVmMVtfaV07XG4gICAgICAgIGJpbmRpbmcudW5iaW5kKCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIFZpZXcucHJvdG90eXBlLnN5bmMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBiaW5kaW5nLCBfaSwgX2xlbiwgX3JlZjE7XG4gICAgICBfcmVmMSA9IHRoaXMuYmluZGluZ3M7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGJpbmRpbmcgPSBfcmVmMVtfaV07XG4gICAgICAgIGlmICh0eXBlb2YgYmluZGluZy5zeW5jID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICBiaW5kaW5nLnN5bmMoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBWaWV3LnByb3RvdHlwZS5wdWJsaXNoID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYmluZGluZywgX2ksIF9sZW4sIF9yZWYxO1xuICAgICAgX3JlZjEgPSB0aGlzLnNlbGVjdChmdW5jdGlvbihiKSB7XG4gICAgICAgIHZhciBfcmVmMTtcbiAgICAgICAgcmV0dXJuIChfcmVmMSA9IGIuYmluZGVyKSAhPSBudWxsID8gX3JlZjEucHVibGlzaGVzIDogdm9pZCAwO1xuICAgICAgfSk7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGJpbmRpbmcgPSBfcmVmMVtfaV07XG4gICAgICAgIGJpbmRpbmcucHVibGlzaCgpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBWaWV3LnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbihtb2RlbHMpIHtcbiAgICAgIHZhciBiaW5kaW5nLCBrZXksIG1vZGVsLCBfaSwgX2xlbiwgX3JlZjE7XG4gICAgICBpZiAobW9kZWxzID09IG51bGwpIHtcbiAgICAgICAgbW9kZWxzID0ge307XG4gICAgICB9XG4gICAgICBmb3IgKGtleSBpbiBtb2RlbHMpIHtcbiAgICAgICAgbW9kZWwgPSBtb2RlbHNba2V5XTtcbiAgICAgICAgdGhpcy5tb2RlbHNba2V5XSA9IG1vZGVsO1xuICAgICAgfVxuICAgICAgX3JlZjEgPSB0aGlzLmJpbmRpbmdzO1xuICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICBiaW5kaW5nID0gX3JlZjFbX2ldO1xuICAgICAgICBpZiAodHlwZW9mIGJpbmRpbmcudXBkYXRlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICBiaW5kaW5nLnVwZGF0ZShtb2RlbHMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBWaWV3O1xuXG4gIH0pKCk7XG5cbiAgUml2ZXRzLkJpbmRpbmcgPSAoZnVuY3Rpb24oKSB7XG4gICAgZnVuY3Rpb24gQmluZGluZyh2aWV3LCBlbCwgdHlwZSwga2V5cGF0aCwgb3B0aW9ucykge1xuICAgICAgdGhpcy52aWV3ID0gdmlldztcbiAgICAgIHRoaXMuZWwgPSBlbDtcbiAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICB0aGlzLmtleXBhdGggPSBrZXlwYXRoO1xuICAgICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucyAhPSBudWxsID8gb3B0aW9ucyA6IHt9O1xuICAgICAgdGhpcy5nZXRWYWx1ZSA9IF9fYmluZCh0aGlzLmdldFZhbHVlLCB0aGlzKTtcbiAgICAgIHRoaXMudXBkYXRlID0gX19iaW5kKHRoaXMudXBkYXRlLCB0aGlzKTtcbiAgICAgIHRoaXMudW5iaW5kID0gX19iaW5kKHRoaXMudW5iaW5kLCB0aGlzKTtcbiAgICAgIHRoaXMuYmluZCA9IF9fYmluZCh0aGlzLmJpbmQsIHRoaXMpO1xuICAgICAgdGhpcy5wdWJsaXNoID0gX19iaW5kKHRoaXMucHVibGlzaCwgdGhpcyk7XG4gICAgICB0aGlzLnN5bmMgPSBfX2JpbmQodGhpcy5zeW5jLCB0aGlzKTtcbiAgICAgIHRoaXMuc2V0ID0gX19iaW5kKHRoaXMuc2V0LCB0aGlzKTtcbiAgICAgIHRoaXMuZXZlbnRIYW5kbGVyID0gX19iaW5kKHRoaXMuZXZlbnRIYW5kbGVyLCB0aGlzKTtcbiAgICAgIHRoaXMuZm9ybWF0dGVkVmFsdWUgPSBfX2JpbmQodGhpcy5mb3JtYXR0ZWRWYWx1ZSwgdGhpcyk7XG4gICAgICB0aGlzLnBhcnNlRm9ybWF0dGVyQXJndW1lbnRzID0gX19iaW5kKHRoaXMucGFyc2VGb3JtYXR0ZXJBcmd1bWVudHMsIHRoaXMpO1xuICAgICAgdGhpcy5wYXJzZVRhcmdldCA9IF9fYmluZCh0aGlzLnBhcnNlVGFyZ2V0LCB0aGlzKTtcbiAgICAgIHRoaXMub2JzZXJ2ZSA9IF9fYmluZCh0aGlzLm9ic2VydmUsIHRoaXMpO1xuICAgICAgdGhpcy5zZXRCaW5kZXIgPSBfX2JpbmQodGhpcy5zZXRCaW5kZXIsIHRoaXMpO1xuICAgICAgdGhpcy5mb3JtYXR0ZXJzID0gdGhpcy5vcHRpb25zLmZvcm1hdHRlcnMgfHwgW107XG4gICAgICB0aGlzLmRlcGVuZGVuY2llcyA9IFtdO1xuICAgICAgdGhpcy5mb3JtYXR0ZXJPYnNlcnZlcnMgPSB7fTtcbiAgICAgIHRoaXMubW9kZWwgPSB2b2lkIDA7XG4gICAgICB0aGlzLnNldEJpbmRlcigpO1xuICAgIH1cblxuICAgIEJpbmRpbmcucHJvdG90eXBlLnNldEJpbmRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGlkZW50aWZpZXIsIHJlZ2V4cCwgdmFsdWUsIF9yZWYxO1xuICAgICAgaWYgKCEodGhpcy5iaW5kZXIgPSB0aGlzLnZpZXcuYmluZGVyc1t0aGlzLnR5cGVdKSkge1xuICAgICAgICBfcmVmMSA9IHRoaXMudmlldy5iaW5kZXJzO1xuICAgICAgICBmb3IgKGlkZW50aWZpZXIgaW4gX3JlZjEpIHtcbiAgICAgICAgICB2YWx1ZSA9IF9yZWYxW2lkZW50aWZpZXJdO1xuICAgICAgICAgIGlmIChpZGVudGlmaWVyICE9PSAnKicgJiYgaWRlbnRpZmllci5pbmRleE9mKCcqJykgIT09IC0xKSB7XG4gICAgICAgICAgICByZWdleHAgPSBuZXcgUmVnRXhwKFwiXlwiICsgKGlkZW50aWZpZXIucmVwbGFjZSgvXFwqL2csICcuKycpKSArIFwiJFwiKTtcbiAgICAgICAgICAgIGlmIChyZWdleHAudGVzdCh0aGlzLnR5cGUpKSB7XG4gICAgICAgICAgICAgIHRoaXMuYmluZGVyID0gdmFsdWU7XG4gICAgICAgICAgICAgIHRoaXMuYXJncyA9IG5ldyBSZWdFeHAoXCJeXCIgKyAoaWRlbnRpZmllci5yZXBsYWNlKC9cXCovZywgJyguKyknKSkgKyBcIiRcIikuZXhlYyh0aGlzLnR5cGUpO1xuICAgICAgICAgICAgICB0aGlzLmFyZ3Muc2hpZnQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMuYmluZGVyIHx8ICh0aGlzLmJpbmRlciA9IHRoaXMudmlldy5iaW5kZXJzWycqJ10pO1xuICAgICAgaWYgKHRoaXMuYmluZGVyIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYmluZGVyID0ge1xuICAgICAgICAgIHJvdXRpbmU6IHRoaXMuYmluZGVyXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfTtcblxuICAgIEJpbmRpbmcucHJvdG90eXBlLm9ic2VydmUgPSBmdW5jdGlvbihvYmosIGtleXBhdGgsIGNhbGxiYWNrKSB7XG4gICAgICByZXR1cm4gUml2ZXRzLnNpZ2h0Z2xhc3Mob2JqLCBrZXlwYXRoLCBjYWxsYmFjaywge1xuICAgICAgICByb290OiB0aGlzLnZpZXcucm9vdEludGVyZmFjZSxcbiAgICAgICAgYWRhcHRlcnM6IHRoaXMudmlldy5hZGFwdGVyc1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIEJpbmRpbmcucHJvdG90eXBlLnBhcnNlVGFyZ2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgdG9rZW47XG4gICAgICB0b2tlbiA9IFJpdmV0cy5UeXBlUGFyc2VyLnBhcnNlKHRoaXMua2V5cGF0aCk7XG4gICAgICBpZiAodG9rZW4udHlwZSA9PT0gUml2ZXRzLlR5cGVQYXJzZXIudHlwZXMucHJpbWl0aXZlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlID0gdG9rZW4udmFsdWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm9ic2VydmVyID0gdGhpcy5vYnNlcnZlKHRoaXMudmlldy5tb2RlbHMsIHRoaXMua2V5cGF0aCwgdGhpcy5zeW5jKTtcbiAgICAgICAgcmV0dXJuIHRoaXMubW9kZWwgPSB0aGlzLm9ic2VydmVyLnRhcmdldDtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgQmluZGluZy5wcm90b3R5cGUucGFyc2VGb3JtYXR0ZXJBcmd1bWVudHMgPSBmdW5jdGlvbihhcmdzLCBmb3JtYXR0ZXJJbmRleCkge1xuICAgICAgdmFyIGFpLCBhcmcsIG9ic2VydmVyLCBwcm9jZXNzZWRBcmdzLCBfYmFzZSwgX2ksIF9sZW47XG4gICAgICBhcmdzID0gKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgX2ksIF9sZW4sIF9yZXN1bHRzO1xuICAgICAgICBfcmVzdWx0cyA9IFtdO1xuICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IGFyZ3MubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgICBhcmcgPSBhcmdzW19pXTtcbiAgICAgICAgICBfcmVzdWx0cy5wdXNoKFJpdmV0cy5UeXBlUGFyc2VyLnBhcnNlKGFyZykpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfcmVzdWx0cztcbiAgICAgIH0pKCk7XG4gICAgICBwcm9jZXNzZWRBcmdzID0gW107XG4gICAgICBmb3IgKGFpID0gX2kgPSAwLCBfbGVuID0gYXJncy5sZW5ndGg7IF9pIDwgX2xlbjsgYWkgPSArK19pKSB7XG4gICAgICAgIGFyZyA9IGFyZ3NbYWldO1xuICAgICAgICBwcm9jZXNzZWRBcmdzLnB1c2goYXJnLnR5cGUgPT09IFJpdmV0cy5UeXBlUGFyc2VyLnR5cGVzLnByaW1pdGl2ZSA/IGFyZy52YWx1ZSA6ICgoX2Jhc2UgPSB0aGlzLmZvcm1hdHRlck9ic2VydmVycylbZm9ybWF0dGVySW5kZXhdIHx8IChfYmFzZVtmb3JtYXR0ZXJJbmRleF0gPSB7fSksICEob2JzZXJ2ZXIgPSB0aGlzLmZvcm1hdHRlck9ic2VydmVyc1tmb3JtYXR0ZXJJbmRleF1bYWldKSA/IChvYnNlcnZlciA9IHRoaXMub2JzZXJ2ZSh0aGlzLnZpZXcubW9kZWxzLCBhcmcudmFsdWUsIHRoaXMuc3luYyksIHRoaXMuZm9ybWF0dGVyT2JzZXJ2ZXJzW2Zvcm1hdHRlckluZGV4XVthaV0gPSBvYnNlcnZlcikgOiB2b2lkIDAsIG9ic2VydmVyLnZhbHVlKCkpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwcm9jZXNzZWRBcmdzO1xuICAgIH07XG5cbiAgICBCaW5kaW5nLnByb3RvdHlwZS5mb3JtYXR0ZWRWYWx1ZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICB2YXIgYXJncywgZmksIGZvcm1hdHRlciwgaWQsIHByb2Nlc3NlZEFyZ3MsIF9pLCBfbGVuLCBfcmVmMSwgX3JlZjI7XG4gICAgICBfcmVmMSA9IHRoaXMuZm9ybWF0dGVycztcbiAgICAgIGZvciAoZmkgPSBfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgZmkgPSArK19pKSB7XG4gICAgICAgIGZvcm1hdHRlciA9IF9yZWYxW2ZpXTtcbiAgICAgICAgYXJncyA9IGZvcm1hdHRlci5tYXRjaCgvW15cXHMnXSt8JyhbXiddfCdbXlxcc10pKid8XCIoW15cIl18XCJbXlxcc10pKlwiL2cpO1xuICAgICAgICBpZCA9IGFyZ3Muc2hpZnQoKTtcbiAgICAgICAgZm9ybWF0dGVyID0gdGhpcy52aWV3LmZvcm1hdHRlcnNbaWRdO1xuICAgICAgICBwcm9jZXNzZWRBcmdzID0gdGhpcy5wYXJzZUZvcm1hdHRlckFyZ3VtZW50cyhhcmdzLCBmaSk7XG4gICAgICAgIGlmICgoZm9ybWF0dGVyICE9IG51bGwgPyBmb3JtYXR0ZXIucmVhZCA6IHZvaWQgMCkgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgIHZhbHVlID0gKF9yZWYyID0gZm9ybWF0dGVyLnJlYWQpLmNhbGwuYXBwbHkoX3JlZjIsIFt0aGlzLm1vZGVsLCB2YWx1ZV0uY29uY2F0KF9fc2xpY2UuY2FsbChwcm9jZXNzZWRBcmdzKSkpO1xuICAgICAgICB9IGVsc2UgaWYgKGZvcm1hdHRlciBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICAgICAgdmFsdWUgPSBmb3JtYXR0ZXIuY2FsbC5hcHBseShmb3JtYXR0ZXIsIFt0aGlzLm1vZGVsLCB2YWx1ZV0uY29uY2F0KF9fc2xpY2UuY2FsbChwcm9jZXNzZWRBcmdzKSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfTtcblxuICAgIEJpbmRpbmcucHJvdG90eXBlLmV2ZW50SGFuZGxlciA9IGZ1bmN0aW9uKGZuKSB7XG4gICAgICB2YXIgYmluZGluZywgaGFuZGxlcjtcbiAgICAgIGhhbmRsZXIgPSAoYmluZGluZyA9IHRoaXMpLnZpZXcuaGFuZGxlcjtcbiAgICAgIHJldHVybiBmdW5jdGlvbihldikge1xuICAgICAgICByZXR1cm4gaGFuZGxlci5jYWxsKGZuLCB0aGlzLCBldiwgYmluZGluZyk7XG4gICAgICB9O1xuICAgIH07XG5cbiAgICBCaW5kaW5nLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgdmFyIF9yZWYxO1xuICAgICAgdmFsdWUgPSB2YWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uICYmICF0aGlzLmJpbmRlcltcImZ1bmN0aW9uXCJdICYmIFJpdmV0c1tcInB1YmxpY1wiXS5leGVjdXRlRnVuY3Rpb25zID8gdGhpcy5mb3JtYXR0ZWRWYWx1ZSh2YWx1ZS5jYWxsKHRoaXMubW9kZWwpKSA6IHRoaXMuZm9ybWF0dGVkVmFsdWUodmFsdWUpO1xuICAgICAgcmV0dXJuIChfcmVmMSA9IHRoaXMuYmluZGVyLnJvdXRpbmUpICE9IG51bGwgPyBfcmVmMS5jYWxsKHRoaXMsIHRoaXMuZWwsIHZhbHVlKSA6IHZvaWQgMDtcbiAgICB9O1xuXG4gICAgQmluZGluZy5wcm90b3R5cGUuc3luYyA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGRlcGVuZGVuY3ksIG9ic2VydmVyO1xuICAgICAgcmV0dXJuIHRoaXMuc2V0KChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIF9pLCBfaiwgX2xlbiwgX2xlbjEsIF9yZWYxLCBfcmVmMiwgX3JlZjM7XG4gICAgICAgIGlmICh0aGlzLm9ic2VydmVyKSB7XG4gICAgICAgICAgaWYgKHRoaXMubW9kZWwgIT09IHRoaXMub2JzZXJ2ZXIudGFyZ2V0KSB7XG4gICAgICAgICAgICBfcmVmMSA9IHRoaXMuZGVwZW5kZW5jaWVzO1xuICAgICAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgICAgICBvYnNlcnZlciA9IF9yZWYxW19pXTtcbiAgICAgICAgICAgICAgb2JzZXJ2ZXIudW5vYnNlcnZlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmRlcGVuZGVuY2llcyA9IFtdO1xuICAgICAgICAgICAgaWYgKCgodGhpcy5tb2RlbCA9IHRoaXMub2JzZXJ2ZXIudGFyZ2V0KSAhPSBudWxsKSAmJiAoKF9yZWYyID0gdGhpcy5vcHRpb25zLmRlcGVuZGVuY2llcykgIT0gbnVsbCA/IF9yZWYyLmxlbmd0aCA6IHZvaWQgMCkpIHtcbiAgICAgICAgICAgICAgX3JlZjMgPSB0aGlzLm9wdGlvbnMuZGVwZW5kZW5jaWVzO1xuICAgICAgICAgICAgICBmb3IgKF9qID0gMCwgX2xlbjEgPSBfcmVmMy5sZW5ndGg7IF9qIDwgX2xlbjE7IF9qKyspIHtcbiAgICAgICAgICAgICAgICBkZXBlbmRlbmN5ID0gX3JlZjNbX2pdO1xuICAgICAgICAgICAgICAgIG9ic2VydmVyID0gdGhpcy5vYnNlcnZlKHRoaXMubW9kZWwsIGRlcGVuZGVuY3ksIHRoaXMuc3luYyk7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXBlbmRlbmNpZXMucHVzaChvYnNlcnZlcik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRoaXMub2JzZXJ2ZXIudmFsdWUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfSkuY2FsbCh0aGlzKSk7XG4gICAgfTtcblxuICAgIEJpbmRpbmcucHJvdG90eXBlLnB1Ymxpc2ggPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBhcmdzLCBmaSwgZmlSZXZlcnNlZCwgZm9ybWF0dGVyLCBpZCwgbGFzdGZvcm1hdHRlckluZGV4LCBwcm9jZXNzZWRBcmdzLCB2YWx1ZSwgX2ksIF9sZW4sIF9yZWYxLCBfcmVmMiwgX3JlZjM7XG4gICAgICBpZiAodGhpcy5vYnNlcnZlcikge1xuICAgICAgICB2YWx1ZSA9IHRoaXMuZ2V0VmFsdWUodGhpcy5lbCk7XG4gICAgICAgIGxhc3Rmb3JtYXR0ZXJJbmRleCA9IHRoaXMuZm9ybWF0dGVycy5sZW5ndGggLSAxO1xuICAgICAgICBfcmVmMSA9IHRoaXMuZm9ybWF0dGVycy5zbGljZSgwKS5yZXZlcnNlKCk7XG4gICAgICAgIGZvciAoZmlSZXZlcnNlZCA9IF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBmaVJldmVyc2VkID0gKytfaSkge1xuICAgICAgICAgIGZvcm1hdHRlciA9IF9yZWYxW2ZpUmV2ZXJzZWRdO1xuICAgICAgICAgIGZpID0gbGFzdGZvcm1hdHRlckluZGV4IC0gZmlSZXZlcnNlZDtcbiAgICAgICAgICBhcmdzID0gZm9ybWF0dGVyLnNwbGl0KC9cXHMrLyk7XG4gICAgICAgICAgaWQgPSBhcmdzLnNoaWZ0KCk7XG4gICAgICAgICAgcHJvY2Vzc2VkQXJncyA9IHRoaXMucGFyc2VGb3JtYXR0ZXJBcmd1bWVudHMoYXJncywgZmkpO1xuICAgICAgICAgIGlmICgoX3JlZjIgPSB0aGlzLnZpZXcuZm9ybWF0dGVyc1tpZF0pICE9IG51bGwgPyBfcmVmMi5wdWJsaXNoIDogdm9pZCAwKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IChfcmVmMyA9IHRoaXMudmlldy5mb3JtYXR0ZXJzW2lkXSkucHVibGlzaC5hcHBseShfcmVmMywgW3ZhbHVlXS5jb25jYXQoX19zbGljZS5jYWxsKHByb2Nlc3NlZEFyZ3MpKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLm9ic2VydmVyLnNldFZhbHVlKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgQmluZGluZy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGRlcGVuZGVuY3ksIG9ic2VydmVyLCBfaSwgX2xlbiwgX3JlZjEsIF9yZWYyLCBfcmVmMztcbiAgICAgIHRoaXMucGFyc2VUYXJnZXQoKTtcbiAgICAgIGlmICgoX3JlZjEgPSB0aGlzLmJpbmRlci5iaW5kKSAhPSBudWxsKSB7XG4gICAgICAgIF9yZWYxLmNhbGwodGhpcywgdGhpcy5lbCk7XG4gICAgICB9XG4gICAgICBpZiAoKHRoaXMubW9kZWwgIT0gbnVsbCkgJiYgKChfcmVmMiA9IHRoaXMub3B0aW9ucy5kZXBlbmRlbmNpZXMpICE9IG51bGwgPyBfcmVmMi5sZW5ndGggOiB2b2lkIDApKSB7XG4gICAgICAgIF9yZWYzID0gdGhpcy5vcHRpb25zLmRlcGVuZGVuY2llcztcbiAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMy5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgIGRlcGVuZGVuY3kgPSBfcmVmM1tfaV07XG4gICAgICAgICAgb2JzZXJ2ZXIgPSB0aGlzLm9ic2VydmUodGhpcy5tb2RlbCwgZGVwZW5kZW5jeSwgdGhpcy5zeW5jKTtcbiAgICAgICAgICB0aGlzLmRlcGVuZGVuY2llcy5wdXNoKG9ic2VydmVyKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHRoaXMudmlldy5wcmVsb2FkRGF0YSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zeW5jKCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIEJpbmRpbmcucHJvdG90eXBlLnVuYmluZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGFpLCBhcmdzLCBmaSwgb2JzZXJ2ZXIsIF9pLCBfbGVuLCBfcmVmMSwgX3JlZjIsIF9yZWYzLCBfcmVmNDtcbiAgICAgIGlmICgoX3JlZjEgPSB0aGlzLmJpbmRlci51bmJpbmQpICE9IG51bGwpIHtcbiAgICAgICAgX3JlZjEuY2FsbCh0aGlzLCB0aGlzLmVsKTtcbiAgICAgIH1cbiAgICAgIGlmICgoX3JlZjIgPSB0aGlzLm9ic2VydmVyKSAhPSBudWxsKSB7XG4gICAgICAgIF9yZWYyLnVub2JzZXJ2ZSgpO1xuICAgICAgfVxuICAgICAgX3JlZjMgPSB0aGlzLmRlcGVuZGVuY2llcztcbiAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjMubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgb2JzZXJ2ZXIgPSBfcmVmM1tfaV07XG4gICAgICAgIG9ic2VydmVyLnVub2JzZXJ2ZSgpO1xuICAgICAgfVxuICAgICAgdGhpcy5kZXBlbmRlbmNpZXMgPSBbXTtcbiAgICAgIF9yZWY0ID0gdGhpcy5mb3JtYXR0ZXJPYnNlcnZlcnM7XG4gICAgICBmb3IgKGZpIGluIF9yZWY0KSB7XG4gICAgICAgIGFyZ3MgPSBfcmVmNFtmaV07XG4gICAgICAgIGZvciAoYWkgaW4gYXJncykge1xuICAgICAgICAgIG9ic2VydmVyID0gYXJnc1thaV07XG4gICAgICAgICAgb2JzZXJ2ZXIudW5vYnNlcnZlKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLmZvcm1hdHRlck9ic2VydmVycyA9IHt9O1xuICAgIH07XG5cbiAgICBCaW5kaW5nLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbihtb2RlbHMpIHtcbiAgICAgIHZhciBfcmVmMSwgX3JlZjI7XG4gICAgICBpZiAobW9kZWxzID09IG51bGwpIHtcbiAgICAgICAgbW9kZWxzID0ge307XG4gICAgICB9XG4gICAgICB0aGlzLm1vZGVsID0gKF9yZWYxID0gdGhpcy5vYnNlcnZlcikgIT0gbnVsbCA/IF9yZWYxLnRhcmdldCA6IHZvaWQgMDtcbiAgICAgIHJldHVybiAoX3JlZjIgPSB0aGlzLmJpbmRlci51cGRhdGUpICE9IG51bGwgPyBfcmVmMi5jYWxsKHRoaXMsIG1vZGVscykgOiB2b2lkIDA7XG4gICAgfTtcblxuICAgIEJpbmRpbmcucHJvdG90eXBlLmdldFZhbHVlID0gZnVuY3Rpb24oZWwpIHtcbiAgICAgIGlmICh0aGlzLmJpbmRlciAmJiAodGhpcy5iaW5kZXIuZ2V0VmFsdWUgIT0gbnVsbCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYmluZGVyLmdldFZhbHVlLmNhbGwodGhpcywgZWwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFJpdmV0cy5VdGlsLmdldElucHV0VmFsdWUoZWwpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gQmluZGluZztcblxuICB9KSgpO1xuXG4gIFJpdmV0cy5Db21wb25lbnRCaW5kaW5nID0gKGZ1bmN0aW9uKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhDb21wb25lbnRCaW5kaW5nLCBfc3VwZXIpO1xuXG4gICAgZnVuY3Rpb24gQ29tcG9uZW50QmluZGluZyh2aWV3LCBlbCwgdHlwZSkge1xuICAgICAgdmFyIGF0dHJpYnV0ZSwgYmluZGluZ1JlZ0V4cCwgcHJvcGVydHlOYW1lLCB0b2tlbiwgX2ksIF9sZW4sIF9yZWYxLCBfcmVmMjtcbiAgICAgIHRoaXMudmlldyA9IHZpZXc7XG4gICAgICB0aGlzLmVsID0gZWw7XG4gICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgdGhpcy51bmJpbmQgPSBfX2JpbmQodGhpcy51bmJpbmQsIHRoaXMpO1xuICAgICAgdGhpcy5iaW5kID0gX19iaW5kKHRoaXMuYmluZCwgdGhpcyk7XG4gICAgICB0aGlzLmxvY2FscyA9IF9fYmluZCh0aGlzLmxvY2FscywgdGhpcyk7XG4gICAgICB0aGlzLmNvbXBvbmVudCA9IHRoaXMudmlldy5jb21wb25lbnRzW3RoaXMudHlwZV07XG4gICAgICB0aGlzW1wic3RhdGljXCJdID0ge307XG4gICAgICB0aGlzLm9ic2VydmVycyA9IHt9O1xuICAgICAgdGhpcy51cHN0cmVhbU9ic2VydmVycyA9IHt9O1xuICAgICAgYmluZGluZ1JlZ0V4cCA9IHZpZXcuYmluZGluZ1JlZ0V4cCgpO1xuICAgICAgX3JlZjEgPSB0aGlzLmVsLmF0dHJpYnV0ZXMgfHwgW107XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGF0dHJpYnV0ZSA9IF9yZWYxW19pXTtcbiAgICAgICAgaWYgKCFiaW5kaW5nUmVnRXhwLnRlc3QoYXR0cmlidXRlLm5hbWUpKSB7XG4gICAgICAgICAgcHJvcGVydHlOYW1lID0gdGhpcy5jYW1lbENhc2UoYXR0cmlidXRlLm5hbWUpO1xuICAgICAgICAgIHRva2VuID0gUml2ZXRzLlR5cGVQYXJzZXIucGFyc2UoYXR0cmlidXRlLnZhbHVlKTtcbiAgICAgICAgICBpZiAoX19pbmRleE9mLmNhbGwoKF9yZWYyID0gdGhpcy5jb21wb25lbnRbXCJzdGF0aWNcIl0pICE9IG51bGwgPyBfcmVmMiA6IFtdLCBwcm9wZXJ0eU5hbWUpID49IDApIHtcbiAgICAgICAgICAgIHRoaXNbXCJzdGF0aWNcIl1bcHJvcGVydHlOYW1lXSA9IGF0dHJpYnV0ZS52YWx1ZTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHRva2VuLnR5cGUgPT09IFJpdmV0cy5UeXBlUGFyc2VyLnR5cGVzLnByaW1pdGl2ZSkge1xuICAgICAgICAgICAgdGhpc1tcInN0YXRpY1wiXVtwcm9wZXJ0eU5hbWVdID0gdG9rZW4udmFsdWU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMub2JzZXJ2ZXJzW3Byb3BlcnR5TmFtZV0gPSBhdHRyaWJ1dGUudmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgQ29tcG9uZW50QmluZGluZy5wcm90b3R5cGUuc3luYyA9IGZ1bmN0aW9uKCkge307XG5cbiAgICBDb21wb25lbnRCaW5kaW5nLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbigpIHt9O1xuXG4gICAgQ29tcG9uZW50QmluZGluZy5wcm90b3R5cGUucHVibGlzaCA9IGZ1bmN0aW9uKCkge307XG5cbiAgICBDb21wb25lbnRCaW5kaW5nLnByb3RvdHlwZS5sb2NhbHMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBrZXksIG9ic2VydmVyLCByZXN1bHQsIHZhbHVlLCBfcmVmMSwgX3JlZjI7XG4gICAgICByZXN1bHQgPSB7fTtcbiAgICAgIF9yZWYxID0gdGhpc1tcInN0YXRpY1wiXTtcbiAgICAgIGZvciAoa2V5IGluIF9yZWYxKSB7XG4gICAgICAgIHZhbHVlID0gX3JlZjFba2V5XTtcbiAgICAgICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIF9yZWYyID0gdGhpcy5vYnNlcnZlcnM7XG4gICAgICBmb3IgKGtleSBpbiBfcmVmMikge1xuICAgICAgICBvYnNlcnZlciA9IF9yZWYyW2tleV07XG4gICAgICAgIHJlc3VsdFtrZXldID0gb2JzZXJ2ZXIudmFsdWUoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcblxuICAgIENvbXBvbmVudEJpbmRpbmcucHJvdG90eXBlLmNhbWVsQ2FzZSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC8tKFthLXpdKS9nLCBmdW5jdGlvbihncm91cGVkKSB7XG4gICAgICAgIHJldHVybiBncm91cGVkWzFdLnRvVXBwZXJDYXNlKCk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgQ29tcG9uZW50QmluZGluZy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGssIGtleSwga2V5cGF0aCwgb2JzZXJ2ZXIsIG9wdGlvbiwgb3B0aW9ucywgc2NvcGUsIHYsIF9iYXNlLCBfaSwgX2osIF9sZW4sIF9sZW4xLCBfcmVmMSwgX3JlZjIsIF9yZWYzLCBfcmVmNCwgX3JlZjUsIF9yZWY2LCBfcmVmNztcbiAgICAgIGlmICghdGhpcy5ib3VuZCkge1xuICAgICAgICBfcmVmMSA9IHRoaXMub2JzZXJ2ZXJzO1xuICAgICAgICBmb3IgKGtleSBpbiBfcmVmMSkge1xuICAgICAgICAgIGtleXBhdGggPSBfcmVmMVtrZXldO1xuICAgICAgICAgIHRoaXMub2JzZXJ2ZXJzW2tleV0gPSB0aGlzLm9ic2VydmUodGhpcy52aWV3Lm1vZGVscywga2V5cGF0aCwgKChmdW5jdGlvbihfdGhpcykge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGtleSkge1xuICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzLmNvbXBvbmVudFZpZXcubW9kZWxzW2tleV0gPSBfdGhpcy5vYnNlcnZlcnNba2V5XS52YWx1ZSgpO1xuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KSh0aGlzKSkuY2FsbCh0aGlzLCBrZXkpKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmJvdW5kID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmNvbXBvbmVudFZpZXcgIT0gbnVsbCkge1xuICAgICAgICB0aGlzLmNvbXBvbmVudFZpZXcuYmluZCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5lbC5pbm5lckhUTUwgPSB0aGlzLmNvbXBvbmVudC50ZW1wbGF0ZS5jYWxsKHRoaXMpO1xuICAgICAgICBzY29wZSA9IHRoaXMuY29tcG9uZW50LmluaXRpYWxpemUuY2FsbCh0aGlzLCB0aGlzLmVsLCB0aGlzLmxvY2FscygpKTtcbiAgICAgICAgdGhpcy5lbC5fYm91bmQgPSB0cnVlO1xuICAgICAgICBvcHRpb25zID0ge307XG4gICAgICAgIF9yZWYyID0gUml2ZXRzLmV4dGVuc2lvbnM7XG4gICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjIubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgICBvcHRpb24gPSBfcmVmMltfaV07XG4gICAgICAgICAgb3B0aW9uc1tvcHRpb25dID0ge307XG4gICAgICAgICAgaWYgKHRoaXMuY29tcG9uZW50W29wdGlvbl0pIHtcbiAgICAgICAgICAgIF9yZWYzID0gdGhpcy5jb21wb25lbnRbb3B0aW9uXTtcbiAgICAgICAgICAgIGZvciAoayBpbiBfcmVmMykge1xuICAgICAgICAgICAgICB2ID0gX3JlZjNba107XG4gICAgICAgICAgICAgIG9wdGlvbnNbb3B0aW9uXVtrXSA9IHY7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIF9yZWY0ID0gdGhpcy52aWV3W29wdGlvbl07XG4gICAgICAgICAgZm9yIChrIGluIF9yZWY0KSB7XG4gICAgICAgICAgICB2ID0gX3JlZjRba107XG4gICAgICAgICAgICBpZiAoKF9iYXNlID0gb3B0aW9uc1tvcHRpb25dKVtrXSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgIF9iYXNlW2tdID0gdjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgX3JlZjUgPSBSaXZldHMub3B0aW9ucztcbiAgICAgICAgZm9yIChfaiA9IDAsIF9sZW4xID0gX3JlZjUubGVuZ3RoOyBfaiA8IF9sZW4xOyBfaisrKSB7XG4gICAgICAgICAgb3B0aW9uID0gX3JlZjVbX2pdO1xuICAgICAgICAgIG9wdGlvbnNbb3B0aW9uXSA9IChfcmVmNiA9IHRoaXMuY29tcG9uZW50W29wdGlvbl0pICE9IG51bGwgPyBfcmVmNiA6IHRoaXMudmlld1tvcHRpb25dO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29tcG9uZW50VmlldyA9IG5ldyBSaXZldHMuVmlldyhBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLmVsLmNoaWxkTm9kZXMpLCBzY29wZSwgb3B0aW9ucyk7XG4gICAgICAgIHRoaXMuY29tcG9uZW50Vmlldy5iaW5kKCk7XG4gICAgICAgIF9yZWY3ID0gdGhpcy5vYnNlcnZlcnM7XG4gICAgICAgIGZvciAoa2V5IGluIF9yZWY3KSB7XG4gICAgICAgICAgb2JzZXJ2ZXIgPSBfcmVmN1trZXldO1xuICAgICAgICAgIHRoaXMudXBzdHJlYW1PYnNlcnZlcnNba2V5XSA9IHRoaXMub2JzZXJ2ZSh0aGlzLmNvbXBvbmVudFZpZXcubW9kZWxzLCBrZXksICgoZnVuY3Rpb24oX3RoaXMpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbihrZXksIG9ic2VydmVyKSB7XG4gICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JzZXJ2ZXIuc2V0VmFsdWUoX3RoaXMuY29tcG9uZW50Vmlldy5tb2RlbHNba2V5XSk7XG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pKHRoaXMpKS5jYWxsKHRoaXMsIGtleSwgb2JzZXJ2ZXIpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBDb21wb25lbnRCaW5kaW5nLnByb3RvdHlwZS51bmJpbmQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBrZXksIG9ic2VydmVyLCBfcmVmMSwgX3JlZjIsIF9yZWYzO1xuICAgICAgX3JlZjEgPSB0aGlzLnVwc3RyZWFtT2JzZXJ2ZXJzO1xuICAgICAgZm9yIChrZXkgaW4gX3JlZjEpIHtcbiAgICAgICAgb2JzZXJ2ZXIgPSBfcmVmMVtrZXldO1xuICAgICAgICBvYnNlcnZlci51bm9ic2VydmUoKTtcbiAgICAgIH1cbiAgICAgIF9yZWYyID0gdGhpcy5vYnNlcnZlcnM7XG4gICAgICBmb3IgKGtleSBpbiBfcmVmMikge1xuICAgICAgICBvYnNlcnZlciA9IF9yZWYyW2tleV07XG4gICAgICAgIG9ic2VydmVyLnVub2JzZXJ2ZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIChfcmVmMyA9IHRoaXMuY29tcG9uZW50VmlldykgIT0gbnVsbCA/IF9yZWYzLnVuYmluZC5jYWxsKHRoaXMpIDogdm9pZCAwO1xuICAgIH07XG5cbiAgICByZXR1cm4gQ29tcG9uZW50QmluZGluZztcblxuICB9KShSaXZldHMuQmluZGluZyk7XG5cbiAgUml2ZXRzLlRleHRCaW5kaW5nID0gKGZ1bmN0aW9uKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhUZXh0QmluZGluZywgX3N1cGVyKTtcblxuICAgIGZ1bmN0aW9uIFRleHRCaW5kaW5nKHZpZXcsIGVsLCB0eXBlLCBrZXlwYXRoLCBvcHRpb25zKSB7XG4gICAgICB0aGlzLnZpZXcgPSB2aWV3O1xuICAgICAgdGhpcy5lbCA9IGVsO1xuICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgIHRoaXMua2V5cGF0aCA9IGtleXBhdGg7XG4gICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zICE9IG51bGwgPyBvcHRpb25zIDoge307XG4gICAgICB0aGlzLnN5bmMgPSBfX2JpbmQodGhpcy5zeW5jLCB0aGlzKTtcbiAgICAgIHRoaXMuZm9ybWF0dGVycyA9IHRoaXMub3B0aW9ucy5mb3JtYXR0ZXJzIHx8IFtdO1xuICAgICAgdGhpcy5kZXBlbmRlbmNpZXMgPSBbXTtcbiAgICAgIHRoaXMuZm9ybWF0dGVyT2JzZXJ2ZXJzID0ge307XG4gICAgfVxuXG4gICAgVGV4dEJpbmRpbmcucHJvdG90eXBlLmJpbmRlciA9IHtcbiAgICAgIHJvdXRpbmU6IGZ1bmN0aW9uKG5vZGUsIHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBub2RlLmRhdGEgPSB2YWx1ZSAhPSBudWxsID8gdmFsdWUgOiAnJztcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgVGV4dEJpbmRpbmcucHJvdG90eXBlLnN5bmMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBUZXh0QmluZGluZy5fX3N1cGVyX18uc3luYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG5cbiAgICByZXR1cm4gVGV4dEJpbmRpbmc7XG5cbiAgfSkoUml2ZXRzLkJpbmRpbmcpO1xuXG4gIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzLnRleHQgPSBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICBpZiAoZWwudGV4dENvbnRlbnQgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGVsLnRleHRDb250ZW50ID0gdmFsdWUgIT0gbnVsbCA/IHZhbHVlIDogJyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBlbC5pbm5lclRleHQgPSB2YWx1ZSAhPSBudWxsID8gdmFsdWUgOiAnJztcbiAgICB9XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnMuaHRtbCA9IGZ1bmN0aW9uKGVsLCB2YWx1ZSkge1xuICAgIHJldHVybiBlbC5pbm5lckhUTUwgPSB2YWx1ZSAhPSBudWxsID8gdmFsdWUgOiAnJztcbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVycy5zaG93ID0gZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGVsLnN0eWxlLmRpc3BsYXkgPSB2YWx1ZSA/ICcnIDogJ25vbmUnO1xuICB9O1xuXG4gIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzLmhpZGUgPSBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICByZXR1cm4gZWwuc3R5bGUuZGlzcGxheSA9IHZhbHVlID8gJ25vbmUnIDogJyc7XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnMuZW5hYmxlZCA9IGZ1bmN0aW9uKGVsLCB2YWx1ZSkge1xuICAgIHJldHVybiBlbC5kaXNhYmxlZCA9ICF2YWx1ZTtcbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVycy5kaXNhYmxlZCA9IGZ1bmN0aW9uKGVsLCB2YWx1ZSkge1xuICAgIHJldHVybiBlbC5kaXNhYmxlZCA9ICEhdmFsdWU7XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnMuY2hlY2tlZCA9IHtcbiAgICBwdWJsaXNoZXM6IHRydWUsXG4gICAgcHJpb3JpdHk6IDIwMDAsXG4gICAgYmluZDogZnVuY3Rpb24oZWwpIHtcbiAgICAgIHJldHVybiBSaXZldHMuVXRpbC5iaW5kRXZlbnQoZWwsICdjaGFuZ2UnLCB0aGlzLnB1Ymxpc2gpO1xuICAgIH0sXG4gICAgdW5iaW5kOiBmdW5jdGlvbihlbCkge1xuICAgICAgcmV0dXJuIFJpdmV0cy5VdGlsLnVuYmluZEV2ZW50KGVsLCAnY2hhbmdlJywgdGhpcy5wdWJsaXNoKTtcbiAgICB9LFxuICAgIHJvdXRpbmU6IGZ1bmN0aW9uKGVsLCB2YWx1ZSkge1xuICAgICAgdmFyIF9yZWYxO1xuICAgICAgaWYgKGVsLnR5cGUgPT09ICdyYWRpbycpIHtcbiAgICAgICAgcmV0dXJuIGVsLmNoZWNrZWQgPSAoKF9yZWYxID0gZWwudmFsdWUpICE9IG51bGwgPyBfcmVmMS50b1N0cmluZygpIDogdm9pZCAwKSA9PT0gKHZhbHVlICE9IG51bGwgPyB2YWx1ZS50b1N0cmluZygpIDogdm9pZCAwKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBlbC5jaGVja2VkID0gISF2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnMudW5jaGVja2VkID0ge1xuICAgIHB1Ymxpc2hlczogdHJ1ZSxcbiAgICBwcmlvcml0eTogMjAwMCxcbiAgICBiaW5kOiBmdW5jdGlvbihlbCkge1xuICAgICAgcmV0dXJuIFJpdmV0cy5VdGlsLmJpbmRFdmVudChlbCwgJ2NoYW5nZScsIHRoaXMucHVibGlzaCk7XG4gICAgfSxcbiAgICB1bmJpbmQ6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICByZXR1cm4gUml2ZXRzLlV0aWwudW5iaW5kRXZlbnQoZWwsICdjaGFuZ2UnLCB0aGlzLnB1Ymxpc2gpO1xuICAgIH0sXG4gICAgcm91dGluZTogZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgICB2YXIgX3JlZjE7XG4gICAgICBpZiAoZWwudHlwZSA9PT0gJ3JhZGlvJykge1xuICAgICAgICByZXR1cm4gZWwuY2hlY2tlZCA9ICgoX3JlZjEgPSBlbC52YWx1ZSkgIT0gbnVsbCA/IF9yZWYxLnRvU3RyaW5nKCkgOiB2b2lkIDApICE9PSAodmFsdWUgIT0gbnVsbCA/IHZhbHVlLnRvU3RyaW5nKCkgOiB2b2lkIDApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGVsLmNoZWNrZWQgPSAhdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzLnZhbHVlID0ge1xuICAgIHB1Ymxpc2hlczogdHJ1ZSxcbiAgICBwcmlvcml0eTogMzAwMCxcbiAgICBiaW5kOiBmdW5jdGlvbihlbCkge1xuICAgICAgaWYgKCEoZWwudGFnTmFtZSA9PT0gJ0lOUFVUJyAmJiBlbC50eXBlID09PSAncmFkaW8nKSkge1xuICAgICAgICB0aGlzLmV2ZW50ID0gZWwudGFnTmFtZSA9PT0gJ1NFTEVDVCcgPyAnY2hhbmdlJyA6ICdpbnB1dCc7XG4gICAgICAgIHJldHVybiBSaXZldHMuVXRpbC5iaW5kRXZlbnQoZWwsIHRoaXMuZXZlbnQsIHRoaXMucHVibGlzaCk7XG4gICAgICB9XG4gICAgfSxcbiAgICB1bmJpbmQ6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICBpZiAoIShlbC50YWdOYW1lID09PSAnSU5QVVQnICYmIGVsLnR5cGUgPT09ICdyYWRpbycpKSB7XG4gICAgICAgIHJldHVybiBSaXZldHMuVXRpbC51bmJpbmRFdmVudChlbCwgdGhpcy5ldmVudCwgdGhpcy5wdWJsaXNoKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHJvdXRpbmU6IGZ1bmN0aW9uKGVsLCB2YWx1ZSkge1xuICAgICAgdmFyIG8sIF9pLCBfbGVuLCBfcmVmMSwgX3JlZjIsIF9yZWYzLCBfcmVzdWx0cztcbiAgICAgIGlmIChlbC50YWdOYW1lID09PSAnSU5QVVQnICYmIGVsLnR5cGUgPT09ICdyYWRpbycpIHtcbiAgICAgICAgcmV0dXJuIGVsLnNldEF0dHJpYnV0ZSgndmFsdWUnLCB2YWx1ZSk7XG4gICAgICB9IGVsc2UgaWYgKHdpbmRvdy5qUXVlcnkgIT0gbnVsbCkge1xuICAgICAgICBlbCA9IGpRdWVyeShlbCk7XG4gICAgICAgIGlmICgodmFsdWUgIT0gbnVsbCA/IHZhbHVlLnRvU3RyaW5nKCkgOiB2b2lkIDApICE9PSAoKF9yZWYxID0gZWwudmFsKCkpICE9IG51bGwgPyBfcmVmMS50b1N0cmluZygpIDogdm9pZCAwKSkge1xuICAgICAgICAgIHJldHVybiBlbC52YWwodmFsdWUgIT0gbnVsbCA/IHZhbHVlIDogJycpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZWwudHlwZSA9PT0gJ3NlbGVjdC1tdWx0aXBsZScpIHtcbiAgICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgX3Jlc3VsdHMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gZWwubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgICAgICAgbyA9IGVsW19pXTtcbiAgICAgICAgICAgICAgX3Jlc3VsdHMucHVzaChvLnNlbGVjdGVkID0gKF9yZWYyID0gby52YWx1ZSwgX19pbmRleE9mLmNhbGwodmFsdWUsIF9yZWYyKSA+PSAwKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gX3Jlc3VsdHM7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCh2YWx1ZSAhPSBudWxsID8gdmFsdWUudG9TdHJpbmcoKSA6IHZvaWQgMCkgIT09ICgoX3JlZjMgPSBlbC52YWx1ZSkgIT0gbnVsbCA/IF9yZWYzLnRvU3RyaW5nKCkgOiB2b2lkIDApKSB7XG4gICAgICAgICAgcmV0dXJuIGVsLnZhbHVlID0gdmFsdWUgIT0gbnVsbCA/IHZhbHVlIDogJyc7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnNbXCJpZlwiXSA9IHtcbiAgICBibG9jazogdHJ1ZSxcbiAgICBwcmlvcml0eTogNDAwMCxcbiAgICBiaW5kOiBmdW5jdGlvbihlbCkge1xuICAgICAgdmFyIGF0dHIsIGRlY2xhcmF0aW9uO1xuICAgICAgaWYgKHRoaXMubWFya2VyID09IG51bGwpIHtcbiAgICAgICAgYXR0ciA9IFt0aGlzLnZpZXcucHJlZml4LCB0aGlzLnR5cGVdLmpvaW4oJy0nKS5yZXBsYWNlKCctLScsICctJyk7XG4gICAgICAgIGRlY2xhcmF0aW9uID0gZWwuZ2V0QXR0cmlidXRlKGF0dHIpO1xuICAgICAgICB0aGlzLm1hcmtlciA9IGRvY3VtZW50LmNyZWF0ZUNvbW1lbnQoXCIgcml2ZXRzOiBcIiArIHRoaXMudHlwZSArIFwiIFwiICsgZGVjbGFyYXRpb24gKyBcIiBcIik7XG4gICAgICAgIHRoaXMuYm91bmQgPSBmYWxzZTtcbiAgICAgICAgZWwucmVtb3ZlQXR0cmlidXRlKGF0dHIpO1xuICAgICAgICBlbC5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLm1hcmtlciwgZWwpO1xuICAgICAgICByZXR1cm4gZWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChlbCk7XG4gICAgICB9XG4gICAgfSxcbiAgICB1bmJpbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHRoaXMubmVzdGVkKSB7XG4gICAgICAgIHRoaXMubmVzdGVkLnVuYmluZCgpO1xuICAgICAgICByZXR1cm4gdGhpcy5ib3VuZCA9IGZhbHNlO1xuICAgICAgfVxuICAgIH0sXG4gICAgcm91dGluZTogZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgICB2YXIga2V5LCBtb2RlbCwgbW9kZWxzLCBfcmVmMTtcbiAgICAgIGlmICghIXZhbHVlID09PSAhdGhpcy5ib3VuZCkge1xuICAgICAgICBpZiAodmFsdWUpIHtcbiAgICAgICAgICBtb2RlbHMgPSB7fTtcbiAgICAgICAgICBfcmVmMSA9IHRoaXMudmlldy5tb2RlbHM7XG4gICAgICAgICAgZm9yIChrZXkgaW4gX3JlZjEpIHtcbiAgICAgICAgICAgIG1vZGVsID0gX3JlZjFba2V5XTtcbiAgICAgICAgICAgIG1vZGVsc1trZXldID0gbW9kZWw7XG4gICAgICAgICAgfVxuICAgICAgICAgICh0aGlzLm5lc3RlZCB8fCAodGhpcy5uZXN0ZWQgPSBuZXcgUml2ZXRzLlZpZXcoZWwsIG1vZGVscywgdGhpcy52aWV3Lm9wdGlvbnMoKSkpKS5iaW5kKCk7XG4gICAgICAgICAgdGhpcy5tYXJrZXIucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoZWwsIHRoaXMubWFya2VyLm5leHRTaWJsaW5nKTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5ib3VuZCA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChlbCk7XG4gICAgICAgICAgdGhpcy5uZXN0ZWQudW5iaW5kKCk7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYm91bmQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgdXBkYXRlOiBmdW5jdGlvbihtb2RlbHMpIHtcbiAgICAgIHZhciBfcmVmMTtcbiAgICAgIHJldHVybiAoX3JlZjEgPSB0aGlzLm5lc3RlZCkgIT0gbnVsbCA/IF9yZWYxLnVwZGF0ZShtb2RlbHMpIDogdm9pZCAwO1xuICAgIH1cbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVycy51bmxlc3MgPSB7XG4gICAgYmxvY2s6IHRydWUsXG4gICAgcHJpb3JpdHk6IDQwMDAsXG4gICAgYmluZDogZnVuY3Rpb24oZWwpIHtcbiAgICAgIHJldHVybiBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVyc1tcImlmXCJdLmJpbmQuY2FsbCh0aGlzLCBlbCk7XG4gICAgfSxcbiAgICB1bmJpbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzW1wiaWZcIl0udW5iaW5kLmNhbGwodGhpcyk7XG4gICAgfSxcbiAgICByb3V0aW5lOiBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICAgIHJldHVybiBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVyc1tcImlmXCJdLnJvdXRpbmUuY2FsbCh0aGlzLCBlbCwgIXZhbHVlKTtcbiAgICB9LFxuICAgIHVwZGF0ZTogZnVuY3Rpb24obW9kZWxzKSB7XG4gICAgICByZXR1cm4gUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnNbXCJpZlwiXS51cGRhdGUuY2FsbCh0aGlzLCBtb2RlbHMpO1xuICAgIH1cbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVyc1snb24tKiddID0ge1xuICAgIFwiZnVuY3Rpb25cIjogdHJ1ZSxcbiAgICBwcmlvcml0eTogMTAwMCxcbiAgICB1bmJpbmQ6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICBpZiAodGhpcy5oYW5kbGVyKSB7XG4gICAgICAgIHJldHVybiBSaXZldHMuVXRpbC51bmJpbmRFdmVudChlbCwgdGhpcy5hcmdzWzBdLCB0aGlzLmhhbmRsZXIpO1xuICAgICAgfVxuICAgIH0sXG4gICAgcm91dGluZTogZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgICBpZiAodGhpcy5oYW5kbGVyKSB7XG4gICAgICAgIFJpdmV0cy5VdGlsLnVuYmluZEV2ZW50KGVsLCB0aGlzLmFyZ3NbMF0sIHRoaXMuaGFuZGxlcik7XG4gICAgICB9XG4gICAgICByZXR1cm4gUml2ZXRzLlV0aWwuYmluZEV2ZW50KGVsLCB0aGlzLmFyZ3NbMF0sIHRoaXMuaGFuZGxlciA9IHRoaXMuZXZlbnRIYW5kbGVyKHZhbHVlKSk7XG4gICAgfVxuICB9O1xuXG4gIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzWydlYWNoLSonXSA9IHtcbiAgICBibG9jazogdHJ1ZSxcbiAgICBwcmlvcml0eTogNDAwMCxcbiAgICBiaW5kOiBmdW5jdGlvbihlbCkge1xuICAgICAgdmFyIGF0dHIsIHZpZXcsIF9pLCBfbGVuLCBfcmVmMTtcbiAgICAgIGlmICh0aGlzLm1hcmtlciA9PSBudWxsKSB7XG4gICAgICAgIGF0dHIgPSBbdGhpcy52aWV3LnByZWZpeCwgdGhpcy50eXBlXS5qb2luKCctJykucmVwbGFjZSgnLS0nLCAnLScpO1xuICAgICAgICB0aGlzLm1hcmtlciA9IGRvY3VtZW50LmNyZWF0ZUNvbW1lbnQoXCIgcml2ZXRzOiBcIiArIHRoaXMudHlwZSArIFwiIFwiKTtcbiAgICAgICAgdGhpcy5pdGVyYXRlZCA9IFtdO1xuICAgICAgICBlbC5yZW1vdmVBdHRyaWJ1dGUoYXR0cik7XG4gICAgICAgIGVsLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMubWFya2VyLCBlbCk7XG4gICAgICAgIGVsLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZWwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgX3JlZjEgPSB0aGlzLml0ZXJhdGVkO1xuICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgdmlldyA9IF9yZWYxW19pXTtcbiAgICAgICAgICB2aWV3LmJpbmQoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgdW5iaW5kOiBmdW5jdGlvbihlbCkge1xuICAgICAgdmFyIHZpZXcsIF9pLCBfbGVuLCBfcmVmMTtcbiAgICAgIGlmICh0aGlzLml0ZXJhdGVkICE9IG51bGwpIHtcbiAgICAgICAgX3JlZjEgPSB0aGlzLml0ZXJhdGVkO1xuICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgdmlldyA9IF9yZWYxW19pXTtcbiAgICAgICAgICB2aWV3LnVuYmluZCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICByb3V0aW5lOiBmdW5jdGlvbihlbCwgY29sbGVjdGlvbikge1xuICAgICAgdmFyIGJpbmRpbmcsIGRhdGEsIGksIGluZGV4LCBrZXksIG1vZGVsLCBtb2RlbE5hbWUsIG9wdGlvbnMsIHByZXZpb3VzLCB0ZW1wbGF0ZSwgdmlldywgX2ksIF9qLCBfaywgX2xlbiwgX2xlbjEsIF9sZW4yLCBfcmVmMSwgX3JlZjIsIF9yZWYzO1xuICAgICAgbW9kZWxOYW1lID0gdGhpcy5hcmdzWzBdO1xuICAgICAgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb24gfHwgW107XG4gICAgICBpZiAodGhpcy5pdGVyYXRlZC5sZW5ndGggPiBjb2xsZWN0aW9uLmxlbmd0aCkge1xuICAgICAgICBfcmVmMSA9IEFycmF5KHRoaXMuaXRlcmF0ZWQubGVuZ3RoIC0gY29sbGVjdGlvbi5sZW5ndGgpO1xuICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgaSA9IF9yZWYxW19pXTtcbiAgICAgICAgICB2aWV3ID0gdGhpcy5pdGVyYXRlZC5wb3AoKTtcbiAgICAgICAgICB2aWV3LnVuYmluZCgpO1xuICAgICAgICAgIHRoaXMubWFya2VyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodmlldy5lbHNbMF0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBmb3IgKGluZGV4ID0gX2ogPSAwLCBfbGVuMSA9IGNvbGxlY3Rpb24ubGVuZ3RoOyBfaiA8IF9sZW4xOyBpbmRleCA9ICsrX2opIHtcbiAgICAgICAgbW9kZWwgPSBjb2xsZWN0aW9uW2luZGV4XTtcbiAgICAgICAgZGF0YSA9IHtcbiAgICAgICAgICBpbmRleDogaW5kZXhcbiAgICAgICAgfTtcbiAgICAgICAgZGF0YVtSaXZldHNbXCJwdWJsaWNcIl0uaXRlcmF0aW9uQWxpYXMobW9kZWxOYW1lKV0gPSBpbmRleDtcbiAgICAgICAgZGF0YVttb2RlbE5hbWVdID0gbW9kZWw7XG4gICAgICAgIGlmICh0aGlzLml0ZXJhdGVkW2luZGV4XSA9PSBudWxsKSB7XG4gICAgICAgICAgX3JlZjIgPSB0aGlzLnZpZXcubW9kZWxzO1xuICAgICAgICAgIGZvciAoa2V5IGluIF9yZWYyKSB7XG4gICAgICAgICAgICBtb2RlbCA9IF9yZWYyW2tleV07XG4gICAgICAgICAgICBpZiAoZGF0YVtrZXldID09IG51bGwpIHtcbiAgICAgICAgICAgICAgZGF0YVtrZXldID0gbW9kZWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHByZXZpb3VzID0gdGhpcy5pdGVyYXRlZC5sZW5ndGggPyB0aGlzLml0ZXJhdGVkW3RoaXMuaXRlcmF0ZWQubGVuZ3RoIC0gMV0uZWxzWzBdIDogdGhpcy5tYXJrZXI7XG4gICAgICAgICAgb3B0aW9ucyA9IHRoaXMudmlldy5vcHRpb25zKCk7XG4gICAgICAgICAgb3B0aW9ucy5wcmVsb2FkRGF0YSA9IHRydWU7XG4gICAgICAgICAgdGVtcGxhdGUgPSBlbC5jbG9uZU5vZGUodHJ1ZSk7XG4gICAgICAgICAgdmlldyA9IG5ldyBSaXZldHMuVmlldyh0ZW1wbGF0ZSwgZGF0YSwgb3B0aW9ucyk7XG4gICAgICAgICAgdmlldy5iaW5kKCk7XG4gICAgICAgICAgdGhpcy5pdGVyYXRlZC5wdXNoKHZpZXcpO1xuICAgICAgICAgIHRoaXMubWFya2VyLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRlbXBsYXRlLCBwcmV2aW91cy5uZXh0U2libGluZyk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5pdGVyYXRlZFtpbmRleF0ubW9kZWxzW21vZGVsTmFtZV0gIT09IG1vZGVsKSB7XG4gICAgICAgICAgdGhpcy5pdGVyYXRlZFtpbmRleF0udXBkYXRlKGRhdGEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZWwubm9kZU5hbWUgPT09ICdPUFRJT04nKSB7XG4gICAgICAgIF9yZWYzID0gdGhpcy52aWV3LmJpbmRpbmdzO1xuICAgICAgICBmb3IgKF9rID0gMCwgX2xlbjIgPSBfcmVmMy5sZW5ndGg7IF9rIDwgX2xlbjI7IF9rKyspIHtcbiAgICAgICAgICBiaW5kaW5nID0gX3JlZjNbX2tdO1xuICAgICAgICAgIGlmIChiaW5kaW5nLmVsID09PSB0aGlzLm1hcmtlci5wYXJlbnROb2RlICYmIGJpbmRpbmcudHlwZSA9PT0gJ3ZhbHVlJykge1xuICAgICAgICAgICAgYmluZGluZy5zeW5jKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICB1cGRhdGU6IGZ1bmN0aW9uKG1vZGVscykge1xuICAgICAgdmFyIGRhdGEsIGtleSwgbW9kZWwsIHZpZXcsIF9pLCBfbGVuLCBfcmVmMTtcbiAgICAgIGRhdGEgPSB7fTtcbiAgICAgIGZvciAoa2V5IGluIG1vZGVscykge1xuICAgICAgICBtb2RlbCA9IG1vZGVsc1trZXldO1xuICAgICAgICBpZiAoa2V5ICE9PSB0aGlzLmFyZ3NbMF0pIHtcbiAgICAgICAgICBkYXRhW2tleV0gPSBtb2RlbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgX3JlZjEgPSB0aGlzLml0ZXJhdGVkO1xuICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICB2aWV3ID0gX3JlZjFbX2ldO1xuICAgICAgICB2aWV3LnVwZGF0ZShkYXRhKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnNbJ2NsYXNzLSonXSA9IGZ1bmN0aW9uKGVsLCB2YWx1ZSkge1xuICAgIHZhciBlbENsYXNzO1xuICAgIGVsQ2xhc3MgPSBcIiBcIiArIGVsLmNsYXNzTmFtZSArIFwiIFwiO1xuICAgIGlmICghdmFsdWUgPT09IChlbENsYXNzLmluZGV4T2YoXCIgXCIgKyB0aGlzLmFyZ3NbMF0gKyBcIiBcIikgIT09IC0xKSkge1xuICAgICAgcmV0dXJuIGVsLmNsYXNzTmFtZSA9IHZhbHVlID8gXCJcIiArIGVsLmNsYXNzTmFtZSArIFwiIFwiICsgdGhpcy5hcmdzWzBdIDogZWxDbGFzcy5yZXBsYWNlKFwiIFwiICsgdGhpcy5hcmdzWzBdICsgXCIgXCIsICcgJykudHJpbSgpO1xuICAgIH1cbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVyc1snKiddID0gZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBlbC5zZXRBdHRyaWJ1dGUodGhpcy50eXBlLCB2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBlbC5yZW1vdmVBdHRyaWJ1dGUodGhpcy50eXBlKTtcbiAgICB9XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmZvcm1hdHRlcnNbJ2NhbGwnXSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBhcmdzLCB2YWx1ZTtcbiAgICB2YWx1ZSA9IGFyZ3VtZW50c1swXSwgYXJncyA9IDIgPD0gYXJndW1lbnRzLmxlbmd0aCA/IF9fc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpIDogW107XG4gICAgcmV0dXJuIHZhbHVlLmNhbGwuYXBwbHkodmFsdWUsIFt0aGlzXS5jb25jYXQoX19zbGljZS5jYWxsKGFyZ3MpKSk7XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmFkYXB0ZXJzWycuJ10gPSB7XG4gICAgaWQ6ICdfcnYnLFxuICAgIGNvdW50ZXI6IDAsXG4gICAgd2Vha21hcDoge30sXG4gICAgd2Vha1JlZmVyZW5jZTogZnVuY3Rpb24ob2JqKSB7XG4gICAgICB2YXIgaWQsIF9iYXNlLCBfbmFtZTtcbiAgICAgIGlmICghb2JqLmhhc093blByb3BlcnR5KHRoaXMuaWQpKSB7XG4gICAgICAgIGlkID0gdGhpcy5jb3VudGVyKys7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIHRoaXMuaWQsIHtcbiAgICAgICAgICB2YWx1ZTogaWRcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gKF9iYXNlID0gdGhpcy53ZWFrbWFwKVtfbmFtZSA9IG9ialt0aGlzLmlkXV0gfHwgKF9iYXNlW19uYW1lXSA9IHtcbiAgICAgICAgY2FsbGJhY2tzOiB7fVxuICAgICAgfSk7XG4gICAgfSxcbiAgICBjbGVhbnVwV2Vha1JlZmVyZW5jZTogZnVuY3Rpb24ocmVmLCBpZCkge1xuICAgICAgaWYgKCFPYmplY3Qua2V5cyhyZWYuY2FsbGJhY2tzKS5sZW5ndGgpIHtcbiAgICAgICAgaWYgKCEocmVmLnBvaW50ZXJzICYmIE9iamVjdC5rZXlzKHJlZi5wb2ludGVycykubGVuZ3RoKSkge1xuICAgICAgICAgIHJldHVybiBkZWxldGUgdGhpcy53ZWFrbWFwW2lkXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgc3R1YkZ1bmN0aW9uOiBmdW5jdGlvbihvYmosIGZuKSB7XG4gICAgICB2YXIgbWFwLCBvcmlnaW5hbCwgd2Vha21hcDtcbiAgICAgIG9yaWdpbmFsID0gb2JqW2ZuXTtcbiAgICAgIG1hcCA9IHRoaXMud2Vha1JlZmVyZW5jZShvYmopO1xuICAgICAgd2Vha21hcCA9IHRoaXMud2Vha21hcDtcbiAgICAgIHJldHVybiBvYmpbZm5dID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBjYWxsYmFjaywgaywgciwgcmVzcG9uc2UsIF9pLCBfbGVuLCBfcmVmMSwgX3JlZjIsIF9yZWYzLCBfcmVmNDtcbiAgICAgICAgcmVzcG9uc2UgPSBvcmlnaW5hbC5hcHBseShvYmosIGFyZ3VtZW50cyk7XG4gICAgICAgIF9yZWYxID0gbWFwLnBvaW50ZXJzO1xuICAgICAgICBmb3IgKHIgaW4gX3JlZjEpIHtcbiAgICAgICAgICBrID0gX3JlZjFbcl07XG4gICAgICAgICAgX3JlZjQgPSAoX3JlZjIgPSAoX3JlZjMgPSB3ZWFrbWFwW3JdKSAhPSBudWxsID8gX3JlZjMuY2FsbGJhY2tzW2tdIDogdm9pZCAwKSAhPSBudWxsID8gX3JlZjIgOiBbXTtcbiAgICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWY0Lmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgICBjYWxsYmFjayA9IF9yZWY0W19pXTtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgIH07XG4gICAgfSxcbiAgICBvYnNlcnZlTXV0YXRpb25zOiBmdW5jdGlvbihvYmosIHJlZiwga2V5cGF0aCkge1xuICAgICAgdmFyIGZuLCBmdW5jdGlvbnMsIG1hcCwgX2Jhc2UsIF9pLCBfbGVuO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgICBtYXAgPSB0aGlzLndlYWtSZWZlcmVuY2Uob2JqKTtcbiAgICAgICAgaWYgKG1hcC5wb2ludGVycyA9PSBudWxsKSB7XG4gICAgICAgICAgbWFwLnBvaW50ZXJzID0ge307XG4gICAgICAgICAgZnVuY3Rpb25zID0gWydwdXNoJywgJ3BvcCcsICdzaGlmdCcsICd1bnNoaWZ0JywgJ3NvcnQnLCAncmV2ZXJzZScsICdzcGxpY2UnXTtcbiAgICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IGZ1bmN0aW9ucy5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgICAgZm4gPSBmdW5jdGlvbnNbX2ldO1xuICAgICAgICAgICAgdGhpcy5zdHViRnVuY3Rpb24ob2JqLCBmbik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICgoX2Jhc2UgPSBtYXAucG9pbnRlcnMpW3JlZl0gPT0gbnVsbCkge1xuICAgICAgICAgIF9iYXNlW3JlZl0gPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoX19pbmRleE9mLmNhbGwobWFwLnBvaW50ZXJzW3JlZl0sIGtleXBhdGgpIDwgMCkge1xuICAgICAgICAgIHJldHVybiBtYXAucG9pbnRlcnNbcmVmXS5wdXNoKGtleXBhdGgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICB1bm9ic2VydmVNdXRhdGlvbnM6IGZ1bmN0aW9uKG9iaiwgcmVmLCBrZXlwYXRoKSB7XG4gICAgICB2YXIgaWR4LCBtYXAsIHBvaW50ZXJzO1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSAmJiAob2JqW3RoaXMuaWRdICE9IG51bGwpKSB7XG4gICAgICAgIGlmIChtYXAgPSB0aGlzLndlYWttYXBbb2JqW3RoaXMuaWRdXSkge1xuICAgICAgICAgIGlmIChwb2ludGVycyA9IG1hcC5wb2ludGVyc1tyZWZdKSB7XG4gICAgICAgICAgICBpZiAoKGlkeCA9IHBvaW50ZXJzLmluZGV4T2Yoa2V5cGF0aCkpID49IDApIHtcbiAgICAgICAgICAgICAgcG9pbnRlcnMuc3BsaWNlKGlkeCwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXBvaW50ZXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgICBkZWxldGUgbWFwLnBvaW50ZXJzW3JlZl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jbGVhbnVwV2Vha1JlZmVyZW5jZShtYXAsIG9ialt0aGlzLmlkXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBvYnNlcnZlOiBmdW5jdGlvbihvYmosIGtleXBhdGgsIGNhbGxiYWNrKSB7XG4gICAgICB2YXIgY2FsbGJhY2tzLCBkZXNjLCB2YWx1ZTtcbiAgICAgIGNhbGxiYWNrcyA9IHRoaXMud2Vha1JlZmVyZW5jZShvYmopLmNhbGxiYWNrcztcbiAgICAgIGlmIChjYWxsYmFja3Nba2V5cGF0aF0gPT0gbnVsbCkge1xuICAgICAgICBjYWxsYmFja3Nba2V5cGF0aF0gPSBbXTtcbiAgICAgICAgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqLCBrZXlwYXRoKTtcbiAgICAgICAgaWYgKCEoKGRlc2MgIT0gbnVsbCA/IGRlc2MuZ2V0IDogdm9pZCAwKSB8fCAoZGVzYyAhPSBudWxsID8gZGVzYy5zZXQgOiB2b2lkIDApKSkge1xuICAgICAgICAgIHZhbHVlID0gb2JqW2tleXBhdGhdO1xuICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleXBhdGgsIHtcbiAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0OiAoZnVuY3Rpb24oX3RoaXMpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKG5ld1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNiLCBtYXAsIF9pLCBfbGVuLCBfcmVmMTtcbiAgICAgICAgICAgICAgICBpZiAobmV3VmFsdWUgIT09IHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICBfdGhpcy51bm9ic2VydmVNdXRhdGlvbnModmFsdWUsIG9ialtfdGhpcy5pZF0sIGtleXBhdGgpO1xuICAgICAgICAgICAgICAgICAgdmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAgIGlmIChtYXAgPSBfdGhpcy53ZWFrbWFwW29ialtfdGhpcy5pZF1dKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrcyA9IG1hcC5jYWxsYmFja3M7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjYWxsYmFja3Nba2V5cGF0aF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICBfcmVmMSA9IGNhbGxiYWNrc1trZXlwYXRoXS5zbGljZSgpO1xuICAgICAgICAgICAgICAgICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNiID0gX3JlZjFbX2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9faW5kZXhPZi5jYWxsKGNhbGxiYWNrc1trZXlwYXRoXSwgY2IpID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2IoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzLm9ic2VydmVNdXRhdGlvbnMobmV3VmFsdWUsIG9ialtfdGhpcy5pZF0sIGtleXBhdGgpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0pKHRoaXMpXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChfX2luZGV4T2YuY2FsbChjYWxsYmFja3Nba2V5cGF0aF0sIGNhbGxiYWNrKSA8IDApIHtcbiAgICAgICAgY2FsbGJhY2tzW2tleXBhdGhdLnB1c2goY2FsbGJhY2spO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMub2JzZXJ2ZU11dGF0aW9ucyhvYmpba2V5cGF0aF0sIG9ialt0aGlzLmlkXSwga2V5cGF0aCk7XG4gICAgfSxcbiAgICB1bm9ic2VydmU6IGZ1bmN0aW9uKG9iaiwga2V5cGF0aCwgY2FsbGJhY2spIHtcbiAgICAgIHZhciBjYWxsYmFja3MsIGlkeCwgbWFwO1xuICAgICAgaWYgKG1hcCA9IHRoaXMud2Vha21hcFtvYmpbdGhpcy5pZF1dKSB7XG4gICAgICAgIGlmIChjYWxsYmFja3MgPSBtYXAuY2FsbGJhY2tzW2tleXBhdGhdKSB7XG4gICAgICAgICAgaWYgKChpZHggPSBjYWxsYmFja3MuaW5kZXhPZihjYWxsYmFjaykpID49IDApIHtcbiAgICAgICAgICAgIGNhbGxiYWNrcy5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgIGlmICghY2FsbGJhY2tzLmxlbmd0aCkge1xuICAgICAgICAgICAgICBkZWxldGUgbWFwLmNhbGxiYWNrc1trZXlwYXRoXTtcbiAgICAgICAgICAgICAgdGhpcy51bm9ic2VydmVNdXRhdGlvbnMob2JqW2tleXBhdGhdLCBvYmpbdGhpcy5pZF0sIGtleXBhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdGhpcy5jbGVhbnVwV2Vha1JlZmVyZW5jZShtYXAsIG9ialt0aGlzLmlkXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIGdldDogZnVuY3Rpb24ob2JqLCBrZXlwYXRoKSB7XG4gICAgICByZXR1cm4gb2JqW2tleXBhdGhdO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbihvYmosIGtleXBhdGgsIHZhbHVlKSB7XG4gICAgICByZXR1cm4gb2JqW2tleXBhdGhdID0gdmFsdWU7XG4gICAgfVxuICB9O1xuXG4gIFJpdmV0cy5mYWN0b3J5ID0gZnVuY3Rpb24oc2lnaHRnbGFzcykge1xuICAgIFJpdmV0cy5zaWdodGdsYXNzID0gc2lnaHRnbGFzcztcbiAgICBSaXZldHNbXCJwdWJsaWNcIl0uXyA9IFJpdmV0cztcbiAgICByZXR1cm4gUml2ZXRzW1wicHVibGljXCJdO1xuICB9O1xuXG4gIGlmICh0eXBlb2YgKHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlICE9PSBudWxsID8gbW9kdWxlLmV4cG9ydHMgOiB2b2lkIDApID09PSAnb2JqZWN0Jykge1xuICAgIG1vZHVsZS5leHBvcnRzID0gUml2ZXRzLmZhY3RvcnkocmVxdWlyZSgnc2lnaHRnbGFzcycpKTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICBkZWZpbmUoWydzaWdodGdsYXNzJ10sIGZ1bmN0aW9uKHNpZ2h0Z2xhc3MpIHtcbiAgICAgIHJldHVybiB0aGlzLnJpdmV0cyA9IFJpdmV0cy5mYWN0b3J5KHNpZ2h0Z2xhc3MpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHRoaXMucml2ZXRzID0gUml2ZXRzLmZhY3Rvcnkoc2lnaHRnbGFzcyk7XG4gIH1cblxufSkuY2FsbCh0aGlzKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL3JpdmV0cy9kaXN0L3JpdmV0cy5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvcml2ZXRzL2Rpc3Qvcml2ZXRzLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/rivets/dist/rivets.js\n");
/***/ }),
/***/ "./node_modules/sightglass/index.js":
/***/ (function(module, exports, __webpack_require__) {
eval("var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function() {\n // Public sightglass interface.\n function sightglass(obj, keypath, callback, options) {\n return new Observer(obj, keypath, callback, options)\n }\n\n // Batteries not included.\n sightglass.adapters = {}\n\n // Constructs a new keypath observer and kicks things off.\n function Observer(obj, keypath, callback, options) {\n this.options = options || {}\n this.options.adapters = this.options.adapters || {}\n this.obj = obj\n this.keypath = keypath\n this.callback = callback\n this.objectPath = []\n this.update = this.update.bind(this)\n this.parse()\n\n if (isObject(this.target = this.realize())) {\n this.set(true, this.key, this.target, this.callback)\n }\n }\n\n // Tokenizes the provided keypath string into interface + path tokens for the\n // observer to work with.\n Observer.tokenize = function(keypath, interfaces, root) {\n var tokens = []\n var current = {i: root, path: ''}\n var index, chr\n\n for (index = 0; index < keypath.length; index++) {\n chr = keypath.charAt(index)\n\n if (!!~interfaces.indexOf(chr)) {\n tokens.push(current)\n current = {i: chr, path: ''}\n } else {\n current.path += chr\n }\n }\n\n tokens.push(current)\n return tokens\n }\n\n // Parses the keypath using the interfaces defined on the view. Sets variables\n // for the tokenized keypath as well as the end key.\n Observer.prototype.parse = function() {\n var interfaces = this.interfaces()\n var root, path\n\n if (!interfaces.length) {\n error('Must define at least one adapter interface.')\n }\n\n if (!!~interfaces.indexOf(this.keypath[0])) {\n root = this.keypath[0]\n path = this.keypath.substr(1)\n } else {\n if (typeof (root = this.options.root || sightglass.root) === 'undefined') {\n error('Must define a default root adapter.')\n }\n\n path = this.keypath\n }\n\n this.tokens = Observer.tokenize(path, interfaces, root)\n this.key = this.tokens.pop()\n }\n\n // Realizes the full keypath, attaching observers for every key and correcting\n // old observers to any changed objects in the keypath.\n Observer.prototype.realize = function() {\n var current = this.obj\n var unreached = false\n var prev\n\n this.tokens.forEach(function(token, index) {\n if (isObject(current)) {\n if (typeof this.objectPath[index] !== 'undefined') {\n if (current !== (prev = this.objectPath[index])) {\n this.set(false, token, prev, this.update)\n this.set(true, token, current, this.update)\n this.objectPath[index] = current\n }\n } else {\n this.set(true, token, current, this.update)\n this.objectPath[index] = current\n }\n\n current = this.get(token, current)\n } else {\n if (unreached === false) {\n unreached = index\n }\n\n if (prev = this.objectPath[index]) {\n this.set(false, token, prev, this.update)\n }\n }\n }, this)\n\n if (unreached !== false) {\n this.objectPath.splice(unreached)\n }\n\n return current\n }\n\n // Updates the keypath. This is called when any intermediary key is changed.\n Observer.prototype.update = function() {\n var next, oldValue\n\n if ((next = this.realize()) !== this.target) {\n if (isObject(this.target)) {\n this.set(false, this.key, this.target, this.callback)\n }\n\n if (isObject(next)) {\n this.set(true, this.key, next, this.callback)\n }\n\n oldValue = this.value()\n this.target = next\n\n // Always call callback if value is a function. If not a function, call callback only if value changed\n if (this.value() instanceof Function || this.value() !== oldValue) this.callback()\n }\n }\n\n // Reads the current end value of the observed keypath. Returns undefined if\n // the full keypath is unreachable.\n Observer.prototype.value = function() {\n if (isObject(this.target)) {\n return this.get(this.key, this.target)\n }\n }\n\n // Sets the current end value of the observed keypath. Calling setValue when\n // the full keypath is unreachable is a no-op.\n Observer.prototype.setValue = function(value) {\n if (isObject(this.target)) {\n this.adapter(this.key).set(this.target, this.key.path, value)\n }\n }\n\n // Gets the provided key on an object.\n Observer.prototype.get = function(key, obj) {\n return this.adapter(key).get(obj, key.path)\n }\n\n // Observes or unobserves a callback on the object using the provided key.\n Observer.prototype.set = function(active, key, obj, callback) {\n var action = active ? 'observe' : 'unobserve'\n this.adapter(key)[action](obj, key.path, callback)\n }\n\n // Returns an array of all unique adapter interfaces available.\n Observer.prototype.interfaces = function() {\n var interfaces = Object.keys(this.options.adapters)\n\n Object.keys(sightglass.adapters).forEach(function(i) {\n if (!~interfaces.indexOf(i)) {\n interfaces.push(i)\n }\n })\n\n return interfaces\n }\n\n // Convenience function to grab the adapter for a specific key.\n Observer.prototype.adapter = function(key) {\n return this.options.adapters[key.i] ||\n sightglass.adapters[key.i]\n }\n\n // Unobserves the entire keypath.\n Observer.prototype.unobserve = function() {\n var obj\n\n this.tokens.forEach(function(token, index) {\n if (obj = this.objectPath[index]) {\n this.set(false, token, obj, this.update)\n }\n }, this)\n\n if (isObject(this.target)) {\n this.set(false, this.key, this.target, this.callback)\n }\n }\n\n // Check if a value is an object than can be observed.\n function isObject(obj) {\n return typeof obj === 'object' && obj !== null\n }\n\n // Error thrower.\n function error(message) {\n throw new Error('[sightglass] ' + message)\n }\n\n // Export module for Node and the browser.\n if (typeof module !== 'undefined' && module.exports) {\n module.exports = sightglass\n } else if (true) {\n !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() {\n return this.sightglass = sightglass\n }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))\n } else {\n this.sightglass = sightglass\n }\n}).call(this);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvc2lnaHRnbGFzcy9pbmRleC5qcz85NjA1Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQjs7QUFFQSxtQkFBbUIsd0JBQXdCO0FBQzNDOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkIsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUcsVUFBVSxJQUEwQztBQUN2RCxJQUFJLGlDQUFPLEVBQUUsbUNBQUU7QUFDZjtBQUNBLEtBQUs7QUFBQSxvR0FBQztBQUNOLEdBQUc7QUFDSDtBQUNBO0FBQ0EsQ0FBQyIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9zaWdodGdsYXNzL2luZGV4LmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCkge1xuICAvLyBQdWJsaWMgc2lnaHRnbGFzcyBpbnRlcmZhY2UuXG4gIGZ1bmN0aW9uIHNpZ2h0Z2xhc3Mob2JqLCBrZXlwYXRoLCBjYWxsYmFjaywgb3B0aW9ucykge1xuICAgIHJldHVybiBuZXcgT2JzZXJ2ZXIob2JqLCBrZXlwYXRoLCBjYWxsYmFjaywgb3B0aW9ucylcbiAgfVxuXG4gIC8vIEJhdHRlcmllcyBub3QgaW5jbHVkZWQuXG4gIHNpZ2h0Z2xhc3MuYWRhcHRlcnMgPSB7fVxuXG4gIC8vIENvbnN0cnVjdHMgYSBuZXcga2V5cGF0aCBvYnNlcnZlciBhbmQga2lja3MgdGhpbmdzIG9mZi5cbiAgZnVuY3Rpb24gT2JzZXJ2ZXIob2JqLCBrZXlwYXRoLCBjYWxsYmFjaywgb3B0aW9ucykge1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgICB0aGlzLm9wdGlvbnMuYWRhcHRlcnMgPSB0aGlzLm9wdGlvbnMuYWRhcHRlcnMgfHwge31cbiAgICB0aGlzLm9iaiA9IG9ialxuICAgIHRoaXMua2V5cGF0aCA9IGtleXBhdGhcbiAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2tcbiAgICB0aGlzLm9iamVjdFBhdGggPSBbXVxuICAgIHRoaXMudXBkYXRlID0gdGhpcy51cGRhdGUuYmluZCh0aGlzKVxuICAgIHRoaXMucGFyc2UoKVxuXG4gICAgaWYgKGlzT2JqZWN0KHRoaXMudGFyZ2V0ID0gdGhpcy5yZWFsaXplKCkpKSB7XG4gICAgICB0aGlzLnNldCh0cnVlLCB0aGlzLmtleSwgdGhpcy50YXJnZXQsIHRoaXMuY2FsbGJhY2spXG4gICAgfVxuICB9XG5cbiAgLy8gVG9rZW5pemVzIHRoZSBwcm92aWRlZCBrZXlwYXRoIHN0cmluZyBpbnRvIGludGVyZmFjZSArIHBhdGggdG9rZW5zIGZvciB0aGVcbiAgLy8gb2JzZXJ2ZXIgdG8gd29yayB3aXRoLlxuICBPYnNlcnZlci50b2tlbml6ZSA9IGZ1bmN0aW9uKGtleXBhdGgsIGludGVyZmFjZXMsIHJvb3QpIHtcbiAgICB2YXIgdG9rZW5zID0gW11cbiAgICB2YXIgY3VycmVudCA9IHtpOiByb290LCBwYXRoOiAnJ31cbiAgICB2YXIgaW5kZXgsIGNoclxuXG4gICAgZm9yIChpbmRleCA9IDA7IGluZGV4IDwga2V5cGF0aC5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgIGNociA9IGtleXBhdGguY2hhckF0KGluZGV4KVxuXG4gICAgICBpZiAoISF+aW50ZXJmYWNlcy5pbmRleE9mKGNocikpIHtcbiAgICAgICAgdG9rZW5zLnB1c2goY3VycmVudClcbiAgICAgICAgY3VycmVudCA9IHtpOiBjaHIsIHBhdGg6ICcnfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3VycmVudC5wYXRoICs9IGNoclxuICAgICAgfVxuICAgIH1cblxuICAgIHRva2Vucy5wdXNoKGN1cnJlbnQpXG4gICAgcmV0dXJuIHRva2Vuc1xuICB9XG5cbiAgLy8gUGFyc2VzIHRoZSBrZXlwYXRoIHVzaW5nIHRoZSBpbnRlcmZhY2VzIGRlZmluZWQgb24gdGhlIHZpZXcuIFNldHMgdmFyaWFibGVzXG4gIC8vIGZvciB0aGUgdG9rZW5pemVkIGtleXBhdGggYXMgd2VsbCBhcyB0aGUgZW5kIGtleS5cbiAgT2JzZXJ2ZXIucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGludGVyZmFjZXMgPSB0aGlzLmludGVyZmFjZXMoKVxuICAgIHZhciByb290LCBwYXRoXG5cbiAgICBpZiAoIWludGVyZmFjZXMubGVuZ3RoKSB7XG4gICAgICBlcnJvcignTXVzdCBkZWZpbmUgYXQgbGVhc3Qgb25lIGFkYXB0ZXIgaW50ZXJmYWNlLicpXG4gICAgfVxuXG4gICAgaWYgKCEhfmludGVyZmFjZXMuaW5kZXhPZih0aGlzLmtleXBhdGhbMF0pKSB7XG4gICAgICByb290ID0gdGhpcy5rZXlwYXRoWzBdXG4gICAgICBwYXRoID0gdGhpcy5rZXlwYXRoLnN1YnN0cigxKVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodHlwZW9mIChyb290ID0gdGhpcy5vcHRpb25zLnJvb3QgfHwgc2lnaHRnbGFzcy5yb290KSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgZXJyb3IoJ011c3QgZGVmaW5lIGEgZGVmYXVsdCByb290IGFkYXB0ZXIuJylcbiAgICAgIH1cblxuICAgICAgcGF0aCA9IHRoaXMua2V5cGF0aFxuICAgIH1cblxuICAgIHRoaXMudG9rZW5zID0gT2JzZXJ2ZXIudG9rZW5pemUocGF0aCwgaW50ZXJmYWNlcywgcm9vdClcbiAgICB0aGlzLmtleSA9IHRoaXMudG9rZW5zLnBvcCgpXG4gIH1cblxuICAvLyBSZWFsaXplcyB0aGUgZnVsbCBrZXlwYXRoLCBhdHRhY2hpbmcgb2JzZXJ2ZXJzIGZvciBldmVyeSBrZXkgYW5kIGNvcnJlY3RpbmdcbiAgLy8gb2xkIG9ic2VydmVycyB0byBhbnkgY2hhbmdlZCBvYmplY3RzIGluIHRoZSBrZXlwYXRoLlxuICBPYnNlcnZlci5wcm90b3R5cGUucmVhbGl6ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBjdXJyZW50ID0gdGhpcy5vYmpcbiAgICB2YXIgdW5yZWFjaGVkID0gZmFsc2VcbiAgICB2YXIgcHJldlxuXG4gICAgdGhpcy50b2tlbnMuZm9yRWFjaChmdW5jdGlvbih0b2tlbiwgaW5kZXgpIHtcbiAgICAgIGlmIChpc09iamVjdChjdXJyZW50KSkge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMub2JqZWN0UGF0aFtpbmRleF0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgaWYgKGN1cnJlbnQgIT09IChwcmV2ID0gdGhpcy5vYmplY3RQYXRoW2luZGV4XSkpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0KGZhbHNlLCB0b2tlbiwgcHJldiwgdGhpcy51cGRhdGUpXG4gICAgICAgICAgICB0aGlzLnNldCh0cnVlLCB0b2tlbiwgY3VycmVudCwgdGhpcy51cGRhdGUpXG4gICAgICAgICAgICB0aGlzLm9iamVjdFBhdGhbaW5kZXhdID0gY3VycmVudFxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnNldCh0cnVlLCB0b2tlbiwgY3VycmVudCwgdGhpcy51cGRhdGUpXG4gICAgICAgICAgdGhpcy5vYmplY3RQYXRoW2luZGV4XSA9IGN1cnJlbnRcbiAgICAgICAgfVxuXG4gICAgICAgIGN1cnJlbnQgPSB0aGlzLmdldCh0b2tlbiwgY3VycmVudClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh1bnJlYWNoZWQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgdW5yZWFjaGVkID0gaW5kZXhcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwcmV2ID0gdGhpcy5vYmplY3RQYXRoW2luZGV4XSkge1xuICAgICAgICAgIHRoaXMuc2V0KGZhbHNlLCB0b2tlbiwgcHJldiwgdGhpcy51cGRhdGUpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LCB0aGlzKVxuXG4gICAgaWYgKHVucmVhY2hlZCAhPT0gZmFsc2UpIHtcbiAgICAgIHRoaXMub2JqZWN0UGF0aC5zcGxpY2UodW5yZWFjaGVkKVxuICAgIH1cblxuICAgIHJldHVybiBjdXJyZW50XG4gIH1cblxuICAvLyBVcGRhdGVzIHRoZSBrZXlwYXRoLiBUaGlzIGlzIGNhbGxlZCB3aGVuIGFueSBpbnRlcm1lZGlhcnkga2V5IGlzIGNoYW5nZWQuXG4gIE9ic2VydmVyLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbmV4dCwgb2xkVmFsdWVcblxuICAgIGlmICgobmV4dCA9IHRoaXMucmVhbGl6ZSgpKSAhPT0gdGhpcy50YXJnZXQpIHtcbiAgICAgIGlmIChpc09iamVjdCh0aGlzLnRhcmdldCkpIHtcbiAgICAgICAgdGhpcy5zZXQoZmFsc2UsIHRoaXMua2V5LCB0aGlzLnRhcmdldCwgdGhpcy5jYWxsYmFjaylcbiAgICAgIH1cblxuICAgICAgaWYgKGlzT2JqZWN0KG5leHQpKSB7XG4gICAgICAgIHRoaXMuc2V0KHRydWUsIHRoaXMua2V5LCBuZXh0LCB0aGlzLmNhbGxiYWNrKVxuICAgICAgfVxuXG4gICAgICBvbGRWYWx1ZSA9IHRoaXMudmFsdWUoKVxuICAgICAgdGhpcy50YXJnZXQgPSBuZXh0XG5cbiAgICAgIC8vIEFsd2F5cyBjYWxsIGNhbGxiYWNrIGlmIHZhbHVlIGlzIGEgZnVuY3Rpb24uIElmIG5vdCBhIGZ1bmN0aW9uLCBjYWxsIGNhbGxiYWNrIG9ubHkgaWYgdmFsdWUgY2hhbmdlZFxuICAgICAgaWYgKHRoaXMudmFsdWUoKSBpbnN0YW5jZW9mIEZ1bmN0aW9uIHx8IHRoaXMudmFsdWUoKSAhPT0gb2xkVmFsdWUpIHRoaXMuY2FsbGJhY2soKVxuICAgIH1cbiAgfVxuXG4gIC8vIFJlYWRzIHRoZSBjdXJyZW50IGVuZCB2YWx1ZSBvZiB0aGUgb2JzZXJ2ZWQga2V5cGF0aC4gUmV0dXJucyB1bmRlZmluZWQgaWZcbiAgLy8gdGhlIGZ1bGwga2V5cGF0aCBpcyB1bnJlYWNoYWJsZS5cbiAgT2JzZXJ2ZXIucHJvdG90eXBlLnZhbHVlID0gZnVuY3Rpb24oKSB7XG4gICAgaWYgKGlzT2JqZWN0KHRoaXMudGFyZ2V0KSkge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0KHRoaXMua2V5LCB0aGlzLnRhcmdldClcbiAgICB9XG4gIH1cblxuICAvLyBTZXRzIHRoZSBjdXJyZW50IGVuZCB2YWx1ZSBvZiB0aGUgb2JzZXJ2ZWQga2V5cGF0aC4gQ2FsbGluZyBzZXRWYWx1ZSB3aGVuXG4gIC8vIHRoZSBmdWxsIGtleXBhdGggaXMgdW5yZWFjaGFibGUgaXMgYSBuby1vcC5cbiAgT2JzZXJ2ZXIucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICBpZiAoaXNPYmplY3QodGhpcy50YXJnZXQpKSB7XG4gICAgICB0aGlzLmFkYXB0ZXIodGhpcy5rZXkpLnNldCh0aGlzLnRhcmdldCwgdGhpcy5rZXkucGF0aCwgdmFsdWUpXG4gICAgfVxuICB9XG5cbiAgLy8gR2V0cyB0aGUgcHJvdmlkZWQga2V5IG9uIGFuIG9iamVjdC5cbiAgT2JzZXJ2ZXIucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uKGtleSwgb2JqKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRhcHRlcihrZXkpLmdldChvYmosIGtleS5wYXRoKVxuICB9XG5cbiAgLy8gT2JzZXJ2ZXMgb3IgdW5vYnNlcnZlcyBhIGNhbGxiYWNrIG9uIHRoZSBvYmplY3QgdXNpbmcgdGhlIHByb3ZpZGVkIGtleS5cbiAgT2JzZXJ2ZXIucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uKGFjdGl2ZSwga2V5LCBvYmosIGNhbGxiYWNrKSB7XG4gICAgdmFyIGFjdGlvbiA9IGFjdGl2ZSA/ICdvYnNlcnZlJyA6ICd1bm9ic2VydmUnXG4gICAgdGhpcy5hZGFwdGVyKGtleSlbYWN0aW9uXShvYmosIGtleS5wYXRoLCBjYWxsYmFjaylcbiAgfVxuXG4gIC8vIFJldHVybnMgYW4gYXJyYXkgb2YgYWxsIHVuaXF1ZSBhZGFwdGVyIGludGVyZmFjZXMgYXZhaWxhYmxlLlxuICBPYnNlcnZlci5wcm90b3R5cGUuaW50ZXJmYWNlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBpbnRlcmZhY2VzID0gT2JqZWN0LmtleXModGhpcy5vcHRpb25zLmFkYXB0ZXJzKVxuXG4gICAgT2JqZWN0LmtleXMoc2lnaHRnbGFzcy5hZGFwdGVycykuZm9yRWFjaChmdW5jdGlvbihpKSB7XG4gICAgICBpZiAoIX5pbnRlcmZhY2VzLmluZGV4T2YoaSkpIHtcbiAgICAgICAgaW50ZXJmYWNlcy5wdXNoKGkpXG4gICAgICB9XG4gICAgfSlcblxuICAgIHJldHVybiBpbnRlcmZhY2VzXG4gIH1cblxuICAvLyBDb252ZW5pZW5jZSBmdW5jdGlvbiB0byBncmFiIHRoZSBhZGFwdGVyIGZvciBhIHNwZWNpZmljIGtleS5cbiAgT2JzZXJ2ZXIucHJvdG90eXBlLmFkYXB0ZXIgPSBmdW5jdGlvbihrZXkpIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmFkYXB0ZXJzW2tleS5pXSB8fFxuICAgICAgc2lnaHRnbGFzcy5hZGFwdGVyc1trZXkuaV1cbiAgfVxuXG4gIC8vIFVub2JzZXJ2ZXMgdGhlIGVudGlyZSBrZXlwYXRoLlxuICBPYnNlcnZlci5wcm90b3R5cGUudW5vYnNlcnZlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG9ialxuXG4gICAgdGhpcy50b2tlbnMuZm9yRWFjaChmdW5jdGlvbih0b2tlbiwgaW5kZXgpIHtcbiAgICAgIGlmIChvYmogPSB0aGlzLm9iamVjdFBhdGhbaW5kZXhdKSB7XG4gICAgICAgIHRoaXMuc2V0KGZhbHNlLCB0b2tlbiwgb2JqLCB0aGlzLnVwZGF0ZSlcbiAgICAgIH1cbiAgICB9LCB0aGlzKVxuXG4gICAgaWYgKGlzT2JqZWN0KHRoaXMudGFyZ2V0KSkge1xuICAgICAgdGhpcy5zZXQoZmFsc2UsIHRoaXMua2V5LCB0aGlzLnRhcmdldCwgdGhpcy5jYWxsYmFjaylcbiAgICB9XG4gIH1cblxuICAvLyBDaGVjayBpZiBhIHZhbHVlIGlzIGFuIG9iamVjdCB0aGFuIGNhbiBiZSBvYnNlcnZlZC5cbiAgZnVuY3Rpb24gaXNPYmplY3Qob2JqKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBvYmogPT09ICdvYmplY3QnICYmIG9iaiAhPT0gbnVsbFxuICB9XG5cbiAgLy8gRXJyb3IgdGhyb3dlci5cbiAgZnVuY3Rpb24gZXJyb3IobWVzc2FnZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignW3NpZ2h0Z2xhc3NdICcgKyBtZXNzYWdlKVxuICB9XG5cbiAgLy8gRXhwb3J0IG1vZHVsZSBmb3IgTm9kZSBhbmQgdGhlIGJyb3dzZXIuXG4gIGlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgIG1vZHVsZS5leHBvcnRzID0gc2lnaHRnbGFzc1xuICB9IGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgIGRlZmluZShbXSwgZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5zaWdodGdsYXNzID0gc2lnaHRnbGFzc1xuICAgIH0pXG4gIH0gZWxzZSB7XG4gICAgdGhpcy5zaWdodGdsYXNzID0gc2lnaHRnbGFzc1xuICB9XG59KS5jYWxsKHRoaXMpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvc2lnaHRnbGFzcy9pbmRleC5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvc2lnaHRnbGFzcy9pbmRleC5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/sightglass/index.js\n");
/***/ }),
/***/ "./node_modules/webpack/buildin/module.js":
/***/ (function(module, exports) {
eval("module.exports = function(module) {\r\n\tif(!module.webpackPolyfill) {\r\n\t\tmodule.deprecate = function() {};\r\n\t\tmodule.paths = [];\r\n\t\t// module.parent = undefined by default\r\n\t\tif(!module.children) module.children = [];\r\n\t\tObject.defineProperty(module, \"loaded\", {\r\n\t\t\tenumerable: true,\r\n\t\t\tget: function() {\r\n\t\t\t\treturn module.l;\r\n\t\t\t}\r\n\t\t});\r\n\t\tObject.defineProperty(module, \"id\", {\r\n\t\t\tenumerable: true,\r\n\t\t\tget: function() {\r\n\t\t\t\treturn module.i;\r\n\t\t\t}\r\n\t\t});\r\n\t\tmodule.webpackPolyfill = 1;\r\n\t}\r\n\treturn module;\r\n};\r\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vbW9kdWxlLmpzP2MzYzIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL3dlYnBhY2svYnVpbGRpbi9tb2R1bGUuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG1vZHVsZSkge1xyXG5cdGlmKCFtb2R1bGUud2VicGFja1BvbHlmaWxsKSB7XHJcblx0XHRtb2R1bGUuZGVwcmVjYXRlID0gZnVuY3Rpb24oKSB7fTtcclxuXHRcdG1vZHVsZS5wYXRocyA9IFtdO1xyXG5cdFx0Ly8gbW9kdWxlLnBhcmVudCA9IHVuZGVmaW5lZCBieSBkZWZhdWx0XHJcblx0XHRpZighbW9kdWxlLmNoaWxkcmVuKSBtb2R1bGUuY2hpbGRyZW4gPSBbXTtcclxuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGUsIFwibG9hZGVkXCIsIHtcclxuXHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcclxuXHRcdFx0Z2V0OiBmdW5jdGlvbigpIHtcclxuXHRcdFx0XHRyZXR1cm4gbW9kdWxlLmw7XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZHVsZSwgXCJpZFwiLCB7XHJcblx0XHRcdGVudW1lcmFibGU6IHRydWUsXHJcblx0XHRcdGdldDogZnVuY3Rpb24oKSB7XHJcblx0XHRcdFx0cmV0dXJuIG1vZHVsZS5pO1xyXG5cdFx0XHR9XHJcblx0XHR9KTtcclxuXHRcdG1vZHVsZS53ZWJwYWNrUG9seWZpbGwgPSAxO1xyXG5cdH1cclxuXHRyZXR1cm4gbW9kdWxlO1xyXG59O1xyXG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAod2VicGFjaykvYnVpbGRpbi9tb2R1bGUuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL3dlYnBhY2svYnVpbGRpbi9tb2R1bGUuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/webpack/buildin/module.js\n");
/***/ }),
/***/ "./resources/js/bootstrap.js":
/***/ (function(module, exports, __webpack_require__) {
eval("/**\n * Bootstrap any Javascript libraries required\n */\n\nwindow.axios = __webpack_require__(\"./node_modules/axios/index.js\");\n\n/**\n * Container for phpVMS specific functions\n */\nwindow.phpvms = {};\n\n/**\n * Configure Axios with both the csrf token and the API key\n */\n\nvar base_url = document.head.querySelector('meta[name=\"base-url\"]');\nif (base_url) {\n window.axios.default.baseURL = base_url;\n}\n\nwindow.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';\nvar token = document.head.querySelector('meta[name=\"csrf-token\"]');\n\nif (token) {\n window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;\n /*window.jquery.ajaxSetup({\n 'X-CSRF-TOKEN': token.content\n })*/\n} else {\n console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');\n}\n\nvar api_key = document.head.querySelector('meta[name=\"api-key\"]');\nif (api_key) {\n window.axios.defaults.headers.common['x-api-key'] = api_key.content;\n window.PHPVMS_USER_API_KEY = api_key.content;\n} else {\n window.PHPVMS_USER_API_KEY = false;\n console.error('API Key not found!');\n}\n\n__webpack_require__(\"./resources/js/common.js\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvYm9vdHN0cmFwLmpzPzBlNTgiXSwibmFtZXMiOlsid2luZG93IiwiYXhpb3MiLCJyZXF1aXJlIiwicGhwdm1zIiwiYmFzZV91cmwiLCJkb2N1bWVudCIsImhlYWQiLCJxdWVyeVNlbGVjdG9yIiwiZGVmYXVsdCIsImJhc2VVUkwiLCJkZWZhdWx0cyIsImhlYWRlcnMiLCJjb21tb24iLCJ0b2tlbiIsImNvbnRlbnQiLCJjb25zb2xlIiwiZXJyb3IiLCJhcGlfa2V5IiwiUEhQVk1TX1VTRVJfQVBJX0tFWSJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7QUFJQUEsT0FBT0MsS0FBUCxHQUFlQyxtQkFBT0EsQ0FBQywrQkFBUixDQUFmOztBQUVBOzs7QUFHQUYsT0FBT0csTUFBUCxHQUFnQixFQUFoQjs7QUFFQTs7OztBQUlBLElBQU1DLFdBQVdDLFNBQVNDLElBQVQsQ0FBY0MsYUFBZCxDQUE0Qix1QkFBNUIsQ0FBakI7QUFDQSxJQUFHSCxRQUFILEVBQWE7QUFDWEosU0FBT0MsS0FBUCxDQUFhTyxPQUFiLENBQXFCQyxPQUFyQixHQUErQkwsUUFBL0I7QUFDRDs7QUFFREosT0FBT0MsS0FBUCxDQUFhUyxRQUFiLENBQXNCQyxPQUF0QixDQUE4QkMsTUFBOUIsQ0FBcUMsa0JBQXJDLElBQTJELGdCQUEzRDtBQUNBLElBQU1DLFFBQVFSLFNBQVNDLElBQVQsQ0FBY0MsYUFBZCxDQUE0Qix5QkFBNUIsQ0FBZDs7QUFFQSxJQUFJTSxLQUFKLEVBQVc7QUFDVGIsU0FBT0MsS0FBUCxDQUFhUyxRQUFiLENBQXNCQyxPQUF0QixDQUE4QkMsTUFBOUIsQ0FBcUMsY0FBckMsSUFBdURDLE1BQU1DLE9BQTdEO0FBQ0E7OztBQUdELENBTEQsTUFLTztBQUNMQyxVQUFRQyxLQUFSLENBQWMsdUVBQWQ7QUFDRDs7QUFFRCxJQUFNQyxVQUFVWixTQUFTQyxJQUFULENBQWNDLGFBQWQsQ0FBNEIsc0JBQTVCLENBQWhCO0FBQ0EsSUFBSVUsT0FBSixFQUFhO0FBQ1hqQixTQUFPQyxLQUFQLENBQWFTLFFBQWIsQ0FBc0JDLE9BQXRCLENBQThCQyxNQUE5QixDQUFxQyxXQUFyQyxJQUFvREssUUFBUUgsT0FBNUQ7QUFDQWQsU0FBT2tCLG1CQUFQLEdBQTZCRCxRQUFRSCxPQUFyQztBQUNELENBSEQsTUFHTztBQUNMZCxTQUFPa0IsbUJBQVAsR0FBNkIsS0FBN0I7QUFDQUgsVUFBUUMsS0FBUixDQUFjLG9CQUFkO0FBQ0Q7O0FBRURkLG1CQUFPQSxDQUFDLDBCQUFSIiwiZmlsZSI6Ii4vcmVzb3VyY2VzL2pzL2Jvb3RzdHJhcC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQm9vdHN0cmFwIGFueSBKYXZhc2NyaXB0IGxpYnJhcmllcyByZXF1aXJlZFxuICovXG5cbndpbmRvdy5heGlvcyA9IHJlcXVpcmUoJ2F4aW9zJyk7XG5cbi8qKlxuICogQ29udGFpbmVyIGZvciBwaHBWTVMgc3BlY2lmaWMgZnVuY3Rpb25zXG4gKi9cbndpbmRvdy5waHB2bXMgPSB7fTtcblxuLyoqXG4gKiBDb25maWd1cmUgQXhpb3Mgd2l0aCBib3RoIHRoZSBjc3JmIHRva2VuIGFuZCB0aGUgQVBJIGtleVxuICovXG5cbmNvbnN0IGJhc2VfdXJsID0gZG9jdW1lbnQuaGVhZC5xdWVyeVNlbGVjdG9yKCdtZXRhW25hbWU9XCJiYXNlLXVybFwiXScpO1xuaWYoYmFzZV91cmwpIHtcbiAgd2luZG93LmF4aW9zLmRlZmF1bHQuYmFzZVVSTCA9IGJhc2VfdXJsO1xufVxuXG53aW5kb3cuYXhpb3MuZGVmYXVsdHMuaGVhZGVycy5jb21tb25bJ1gtUmVxdWVzdGVkLVdpdGgnXSA9ICdYTUxIdHRwUmVxdWVzdCc7XG5jb25zdCB0b2tlbiA9IGRvY3VtZW50LmhlYWQucXVlcnlTZWxlY3RvcignbWV0YVtuYW1lPVwiY3NyZi10b2tlblwiXScpO1xuXG5pZiAodG9rZW4pIHtcbiAgd2luZG93LmF4aW9zLmRlZmF1bHRzLmhlYWRlcnMuY29tbW9uWydYLUNTUkYtVE9LRU4nXSA9IHRva2VuLmNvbnRlbnRcbiAgLyp3aW5kb3cuanF1ZXJ5LmFqYXhTZXR1cCh7XG4gICAgJ1gtQ1NSRi1UT0tFTic6IHRva2VuLmNvbnRlbnRcbiAgfSkqL1xufSBlbHNlIHtcbiAgY29uc29sZS5lcnJvcignQ1NSRiB0b2tlbiBub3QgZm91bmQ6IGh0dHBzOi8vbGFyYXZlbC5jb20vZG9jcy9jc3JmI2NzcmYteC1jc3JmLXRva2VuJylcbn1cblxuY29uc3QgYXBpX2tleSA9IGRvY3VtZW50LmhlYWQucXVlcnlTZWxlY3RvcignbWV0YVtuYW1lPVwiYXBpLWtleVwiXScpO1xuaWYgKGFwaV9rZXkpIHtcbiAgd2luZG93LmF4aW9zLmRlZmF1bHRzLmhlYWRlcnMuY29tbW9uWyd4LWFwaS1rZXknXSA9IGFwaV9rZXkuY29udGVudDtcbiAgd2luZG93LlBIUFZNU19VU0VSX0FQSV9LRVkgPSBhcGlfa2V5LmNvbnRlbnRcbn0gZWxzZSB7XG4gIHdpbmRvdy5QSFBWTVNfVVNFUl9BUElfS0VZID0gZmFsc2U7XG4gIGNvbnNvbGUuZXJyb3IoJ0FQSSBLZXkgbm90IGZvdW5kIScpXG59XG5cbnJlcXVpcmUoJy4vY29tbW9uJyk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9yZXNvdXJjZXMvanMvYm9vdHN0cmFwLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./resources/js/bootstrap.js\n");
/***/ }),
/***/ "./resources/js/common.js":
/***/ (function(module, exports, __webpack_require__) {
eval("/**\n *\n */\n\nvar rivets = __webpack_require__(\"./node_modules/rivets/dist/rivets.js\");\n\n/**\n * Generic formatter to prepend\n * @param value\n * @param prepend\n * @returns {*}\n */\nrivets.formatters.prepend = function (value, prepend) {\n return prepend + value;\n};\n\n/**\n * Format minutes into HHh MMm\n * @param value\n * @returns {string}\n */\nrivets.formatters.time_hm = function (value) {\n var hours = Math.floor(value / 60);\n var mins = value % 60;\n return hours + 'h ' + mins + 'm';\n};\n\n/**\n *\n * @param value\n * @param len\n * @returns {boolean}\n */\nrivets.formatters.gt = function (value, len) {\n return value.length > len;\n};\n\n/**\n *\n * @param value\n * @param len\n * @returns {boolean}\n */\nrivets.formatters.lt = function (value, len) {\n return value.length < len;\n};\n\n/**\n *\n * @param value\n * @param len\n * @returns {boolean}\n */\nrivets.formatters.eq = function (value, len) {\n return value.length > len;\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvY29tbW9uLmpzPzVmZDUiXSwibmFtZXMiOlsicml2ZXRzIiwicmVxdWlyZSIsImZvcm1hdHRlcnMiLCJwcmVwZW5kIiwidmFsdWUiLCJ0aW1lX2htIiwiaG91cnMiLCJNYXRoIiwiZmxvb3IiLCJtaW5zIiwiZ3QiLCJsZW4iLCJsZW5ndGgiLCJsdCIsImVxIl0sIm1hcHBpbmdzIjoiQUFBQTs7OztBQUlBLElBQU1BLFNBQVNDLG1CQUFPQSxDQUFDLHNDQUFSLENBQWY7O0FBRUE7Ozs7OztBQU1BRCxPQUFPRSxVQUFQLENBQWtCQyxPQUFsQixHQUE0QixVQUFVQyxLQUFWLEVBQWlCRCxPQUFqQixFQUEwQjtBQUNsRCxTQUFPQSxVQUFVQyxLQUFqQjtBQUNILENBRkQ7O0FBSUE7Ozs7O0FBS0FKLE9BQU9FLFVBQVAsQ0FBa0JHLE9BQWxCLEdBQTRCLFVBQVNELEtBQVQsRUFBZ0I7QUFDeEMsTUFBTUUsUUFBUUMsS0FBS0MsS0FBTCxDQUFXSixRQUFRLEVBQW5CLENBQWQ7QUFDQSxNQUFNSyxPQUFPTCxRQUFRLEVBQXJCO0FBQ0EsU0FBT0UsUUFBUSxJQUFSLEdBQWVHLElBQWYsR0FBc0IsR0FBN0I7QUFDSCxDQUpEOztBQU1BOzs7Ozs7QUFNQVQsT0FBT0UsVUFBUCxDQUFrQlEsRUFBbEIsR0FBdUIsVUFBQ04sS0FBRCxFQUFRTyxHQUFSLEVBQWdCO0FBQ25DLFNBQU9QLE1BQU1RLE1BQU4sR0FBZUQsR0FBdEI7QUFDSCxDQUZEOztBQUlBOzs7Ozs7QUFNQVgsT0FBT0UsVUFBUCxDQUFrQlcsRUFBbEIsR0FBdUIsVUFBQ1QsS0FBRCxFQUFRTyxHQUFSLEVBQWdCO0FBQ25DLFNBQU9QLE1BQU1RLE1BQU4sR0FBZUQsR0FBdEI7QUFDSCxDQUZEOztBQUlBOzs7Ozs7QUFNQVgsT0FBT0UsVUFBUCxDQUFrQlksRUFBbEIsR0FBdUIsVUFBQ1YsS0FBRCxFQUFRTyxHQUFSLEVBQWdCO0FBQ25DLFNBQU9QLE1BQU1RLE1BQU4sR0FBZUQsR0FBdEI7QUFDSCxDQUZEIiwiZmlsZSI6Ii4vcmVzb3VyY2VzL2pzL2NvbW1vbi5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICpcbiAqL1xuXG5jb25zdCByaXZldHMgPSByZXF1aXJlKCdyaXZldHMnKTtcblxuLyoqXG4gKiBHZW5lcmljIGZvcm1hdHRlciB0byBwcmVwZW5kXG4gKiBAcGFyYW0gdmFsdWVcbiAqIEBwYXJhbSBwcmVwZW5kXG4gKiBAcmV0dXJucyB7Kn1cbiAqL1xucml2ZXRzLmZvcm1hdHRlcnMucHJlcGVuZCA9IGZ1bmN0aW9uICh2YWx1ZSwgcHJlcGVuZCkge1xuICAgIHJldHVybiBwcmVwZW5kICsgdmFsdWVcbn07XG5cbi8qKlxuICogRm9ybWF0IG1pbnV0ZXMgaW50byBISGggTU1tXG4gKiBAcGFyYW0gdmFsdWVcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbnJpdmV0cy5mb3JtYXR0ZXJzLnRpbWVfaG0gPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIGNvbnN0IGhvdXJzID0gTWF0aC5mbG9vcih2YWx1ZSAvIDYwKTtcbiAgICBjb25zdCBtaW5zID0gdmFsdWUgJSA2MDtcbiAgICByZXR1cm4gaG91cnMgKyAnaCAnICsgbWlucyArICdtJztcbn07XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB2YWx1ZVxuICogQHBhcmFtIGxlblxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbnJpdmV0cy5mb3JtYXR0ZXJzLmd0ID0gKHZhbHVlLCBsZW4pID0+IHtcbiAgICByZXR1cm4gdmFsdWUubGVuZ3RoID4gbGVuO1xufTtcblxuLyoqXG4gKlxuICogQHBhcmFtIHZhbHVlXG4gKiBAcGFyYW0gbGVuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xucml2ZXRzLmZvcm1hdHRlcnMubHQgPSAodmFsdWUsIGxlbikgPT4ge1xuICAgIHJldHVybiB2YWx1ZS5sZW5ndGggPCBsZW47XG59O1xuXG4vKipcbiAqXG4gKiBAcGFyYW0gdmFsdWVcbiAqIEBwYXJhbSBsZW5cbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5yaXZldHMuZm9ybWF0dGVycy5lcSA9ICh2YWx1ZSwgbGVuKSA9PiB7XG4gICAgcmV0dXJuIHZhbHVlLmxlbmd0aCA+IGxlbjtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9yZXNvdXJjZXMvanMvY29tbW9uLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./resources/js/common.js\n");
/***/ }),
/***/ "./resources/js/frontend/app.js":
/***/ (function(module, exports, __webpack_require__) {
eval("\n__webpack_require__(\"./resources/js/bootstrap.js\");\n\n// Import the mapping function\nwindow.phpvms.map = __webpack_require__(\"./resources/js/maps/index.js\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvZnJvbnRlbmQvYXBwLmpzPzYwZTgiXSwibmFtZXMiOlsicmVxdWlyZSIsIndpbmRvdyIsInBocHZtcyIsIm1hcCJdLCJtYXBwaW5ncyI6IjtBQUNBQSxtQkFBT0EsQ0FBQyw2QkFBUjs7QUFFQTtBQUNBQyxPQUFPQyxNQUFQLENBQWNDLEdBQWQsR0FBb0JILG1CQUFPQSxDQUFDLDhCQUFSLENBQXBCIiwiZmlsZSI6Ii4vcmVzb3VyY2VzL2pzL2Zyb250ZW5kL2FwcC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIlxucmVxdWlyZSgnLi8uLi9ib290c3RyYXAnKTtcblxuLy8gSW1wb3J0IHRoZSBtYXBwaW5nIGZ1bmN0aW9uXG53aW5kb3cucGhwdm1zLm1hcCA9IHJlcXVpcmUoJy4uL21hcHMvaW5kZXgnKTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3Jlc291cmNlcy9qcy9mcm9udGVuZC9hcHAuanMiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./resources/js/frontend/app.js\n");
/***/ }),
/***/ "./resources/js/maps/airspace_map.js":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__base_map__ = __webpack_require__(\"./resources/js/maps/base_map.js\");\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__helpers__ = __webpack_require__(\"./resources/js/maps/helpers.js\");\n\nvar leaflet = __webpack_require__(\"./node_modules/leaflet/dist/leaflet-src.js\");\n\n\n\n\n/**\n * Render a map with the airspace, etc around a given set of coords\n * e.g, the airport map\n * @param opts\n */\n/* harmony default export */ __webpack_exports__[\"a\"] = (function (opts) {\n opts = Object.assign({\n render_elem: 'map',\n overlay_elem: '',\n lat: 0,\n lon: 0,\n zoom: 12,\n layers: [],\n set_marker: true,\n marker_popup: '',\n\n // Passed from the config/maps.php file\n metar_wms: {\n url: '',\n params: {}\n }\n }, opts);\n\n var map = Object(__WEBPACK_IMPORTED_MODULE_0__base_map__[\"a\" /* default */])(opts);\n var coords = [opts.lat, opts.lon];\n console.log('Applying coords', coords);\n\n map.setView(coords, opts.zoom);\n if (opts.set_marker === true) {\n leaflet.marker(coords).addTo(map).bindPopup(opts.marker_popup);\n }\n\n if (opts.metar_wms.url !== '') {\n Object(__WEBPACK_IMPORTED_MODULE_1__helpers__[\"a\" /* addWMSLayer */])(map, opts.metar_wms);\n }\n\n return map;\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9haXJzcGFjZV9tYXAuanM/NGZiMCJdLCJuYW1lcyI6WyJsZWFmbGV0IiwicmVxdWlyZSIsIm9wdHMiLCJPYmplY3QiLCJhc3NpZ24iLCJyZW5kZXJfZWxlbSIsIm92ZXJsYXlfZWxlbSIsImxhdCIsImxvbiIsInpvb20iLCJsYXllcnMiLCJzZXRfbWFya2VyIiwibWFya2VyX3BvcHVwIiwibWV0YXJfd21zIiwidXJsIiwicGFyYW1zIiwibWFwIiwiZHJhd19iYXNlX21hcCIsImNvb3JkcyIsImNvbnNvbGUiLCJsb2ciLCJzZXRWaWV3IiwibWFya2VyIiwiYWRkVG8iLCJiaW5kUG9wdXAiLCJhZGRXTVNMYXllciJdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsSUFBTUEsVUFBVUMsbUJBQU9BLENBQUMsNENBQVIsQ0FBaEI7O0FBRUE7QUFDQTs7QUFFQTs7Ozs7QUFLZSxtRUFBQ0MsSUFBRCxFQUFVO0FBQ3ZCQSxTQUFPQyxPQUFPQyxNQUFQLENBQWM7QUFDbkJDLGlCQUFhLEtBRE07QUFFbkJDLGtCQUFjLEVBRks7QUFHbkJDLFNBQUssQ0FIYztBQUluQkMsU0FBSyxDQUpjO0FBS25CQyxVQUFNLEVBTGE7QUFNbkJDLFlBQVEsRUFOVztBQU9uQkMsZ0JBQVksSUFQTztBQVFuQkMsa0JBQWMsRUFSSzs7QUFVbkI7QUFDQUMsZUFBVztBQUNQQyxXQUFLLEVBREU7QUFFUEMsY0FBUTtBQUZEO0FBWFEsR0FBZCxFQWVKYixJQWZJLENBQVA7O0FBaUJBLE1BQUljLE1BQU1DLGtFQUFhQSxDQUFDZixJQUFkLENBQVY7QUFDQSxNQUFNZ0IsU0FBUyxDQUFDaEIsS0FBS0ssR0FBTixFQUFXTCxLQUFLTSxHQUFoQixDQUFmO0FBQ0FXLFVBQVFDLEdBQVIsQ0FBWSxpQkFBWixFQUErQkYsTUFBL0I7O0FBRUFGLE1BQUlLLE9BQUosQ0FBWUgsTUFBWixFQUFvQmhCLEtBQUtPLElBQXpCO0FBQ0EsTUFBSVAsS0FBS1MsVUFBTCxLQUFvQixJQUF4QixFQUE4QjtBQUM1QlgsWUFBUXNCLE1BQVIsQ0FBZUosTUFBZixFQUF1QkssS0FBdkIsQ0FBNkJQLEdBQTdCLEVBQWtDUSxTQUFsQyxDQUE0Q3RCLEtBQUtVLFlBQWpEO0FBQ0Q7O0FBRUQsTUFBR1YsS0FBS1csU0FBTCxDQUFlQyxHQUFmLEtBQXVCLEVBQTFCLEVBQThCO0FBQzFCVyx5RUFBV0EsQ0FBQ1QsR0FBWixFQUFpQmQsS0FBS1csU0FBdEI7QUFDSDs7QUFFRCxTQUFPRyxHQUFQO0FBQ0QsQ0FoQ0QiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvbWFwcy9haXJzcGFjZV9tYXAuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJcbmNvbnN0IGxlYWZsZXQgPSByZXF1aXJlKCdsZWFmbGV0Jyk7XG5cbmltcG9ydCBkcmF3X2Jhc2VfbWFwIGZyb20gJy4vYmFzZV9tYXAnXG5pbXBvcnQgeyBhZGRXTVNMYXllciB9IGZyb20gJy4vaGVscGVycyc7XG5cbi8qKlxuICogUmVuZGVyIGEgbWFwIHdpdGggdGhlIGFpcnNwYWNlLCBldGMgYXJvdW5kIGEgZ2l2ZW4gc2V0IG9mIGNvb3Jkc1xuICogZS5nLCB0aGUgYWlycG9ydCBtYXBcbiAqIEBwYXJhbSBvcHRzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IChvcHRzKSA9PiB7XG4gIG9wdHMgPSBPYmplY3QuYXNzaWduKHtcbiAgICByZW5kZXJfZWxlbTogJ21hcCcsXG4gICAgb3ZlcmxheV9lbGVtOiAnJyxcbiAgICBsYXQ6IDAsXG4gICAgbG9uOiAwLFxuICAgIHpvb206IDEyLFxuICAgIGxheWVyczogW10sXG4gICAgc2V0X21hcmtlcjogdHJ1ZSxcbiAgICBtYXJrZXJfcG9wdXA6ICcnLFxuXG4gICAgLy8gUGFzc2VkIGZyb20gdGhlIGNvbmZpZy9tYXBzLnBocCBmaWxlXG4gICAgbWV0YXJfd21zOiB7XG4gICAgICAgIHVybDogJycsXG4gICAgICAgIHBhcmFtczoge31cbiAgICB9LFxuICB9LCBvcHRzKTtcblxuICBsZXQgbWFwID0gZHJhd19iYXNlX21hcChvcHRzKTtcbiAgY29uc3QgY29vcmRzID0gW29wdHMubGF0LCBvcHRzLmxvbl07XG4gIGNvbnNvbGUubG9nKCdBcHBseWluZyBjb29yZHMnLCBjb29yZHMpO1xuXG4gIG1hcC5zZXRWaWV3KGNvb3Jkcywgb3B0cy56b29tKTtcbiAgaWYgKG9wdHMuc2V0X21hcmtlciA9PT0gdHJ1ZSkge1xuICAgIGxlYWZsZXQubWFya2VyKGNvb3JkcykuYWRkVG8obWFwKS5iaW5kUG9wdXAob3B0cy5tYXJrZXJfcG9wdXApO1xuICB9XG5cbiAgaWYob3B0cy5tZXRhcl93bXMudXJsICE9PSAnJykge1xuICAgICAgYWRkV01TTGF5ZXIobWFwLCBvcHRzLm1ldGFyX3dtcyk7XG4gIH1cblxuICByZXR1cm4gbWFwO1xufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3Jlc291cmNlcy9qcy9tYXBzL2FpcnNwYWNlX21hcC5qcyJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./resources/js/maps/airspace_map.js\n");
/***/ }),
/***/ "./resources/js/maps/base_map.js":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("//\n\nvar leaflet = __webpack_require__(\"./node_modules/leaflet/dist/leaflet-src.js\");\n__webpack_require__(\"./node_modules/leaflet-providers/leaflet-providers.js\");\n\n/* harmony default export */ __webpack_exports__[\"a\"] = (function (opts) {\n\n opts = Object.assign({\n render_elem: 'map',\n center: [29.98139, -95.33374],\n zoom: 5,\n maxZoom: 10,\n layers: [],\n set_marker: false,\n providers: ['Esri.WorldStreetMap'],\n tile_layers: []\n }, opts);\n\n /*\n let feature_groups = [];\n const openaip_airspace_labels = new leaflet.TileLayer.WMS(\n \"http://{s}.tile.maps.openaip.net/geowebcache/service/wms\", {\n maxZoom: 14,\n minZoom: 12,\n layers: 'openaip_approved_airspaces_labels',\n tileSize: 1024,\n detectRetina: true,\n subdomains: '12',\n format: 'image/png',\n transparent: true\n });\n openaip_airspace_labels.addTo(map);*/\n\n /*const openaip_cached_basemap = new leaflet.TileLayer(\"http://{s}.tile.maps.openaip.net/geowebcache/service/tms/1.0.0/openaip_basemap@EPSG%3A900913@png/{z}/{x}/{y}.png\", {\n maxZoom: 14,\n minZoom: 4,\n tms: true,\n detectRetina: true,\n subdomains: '12',\n format: 'image/png',\n transparent: true\n });\n feature_groups.push(openaip_cached_basemap);\n */\n\n var map = leaflet.map('map', {\n //layers: [openaip_basemap_phys_osm],\n center: opts.center,\n zoom: opts.zoom,\n scrollWheelZoom: false\n });\n\n for (var i in opts.providers) {\n leaflet.tileLayer.provider(opts.providers[i]).addTo(map);\n }\n\n return map;\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9iYXNlX21hcC5qcz80MzA3Il0sIm5hbWVzIjpbImxlYWZsZXQiLCJyZXF1aXJlIiwib3B0cyIsIk9iamVjdCIsImFzc2lnbiIsInJlbmRlcl9lbGVtIiwiY2VudGVyIiwiem9vbSIsIm1heFpvb20iLCJsYXllcnMiLCJzZXRfbWFya2VyIiwicHJvdmlkZXJzIiwidGlsZV9sYXllcnMiLCJtYXAiLCJzY3JvbGxXaGVlbFpvb20iLCJpIiwidGlsZUxheWVyIiwicHJvdmlkZXIiLCJhZGRUbyJdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUEsSUFBTUEsVUFBVUMsbUJBQU9BLENBQUMsNENBQVIsQ0FBaEI7QUFDQUEsbUJBQU9BLENBQUMsdURBQVI7O0FBRWUsbUVBQUNDLElBQUQsRUFBVTs7QUFFckJBLFdBQU9DLE9BQU9DLE1BQVAsQ0FBYztBQUNqQkMscUJBQWEsS0FESTtBQUVqQkMsZ0JBQVEsQ0FBQyxRQUFELEVBQVcsQ0FBQyxRQUFaLENBRlM7QUFHakJDLGNBQU0sQ0FIVztBQUlqQkMsaUJBQVMsRUFKUTtBQUtqQkMsZ0JBQVEsRUFMUztBQU1qQkMsb0JBQVksS0FOSztBQU9qQkMsbUJBQVcsQ0FDUCxxQkFETyxDQVBNO0FBVWpCQyxxQkFBYTtBQVZJLEtBQWQsRUFXSlYsSUFYSSxDQUFQOztBQWFBOzs7Ozs7Ozs7Ozs7Ozs7QUFnQkE7Ozs7Ozs7Ozs7OztBQWFBLFFBQUlXLE1BQU1iLFFBQVFhLEdBQVIsQ0FBWSxLQUFaLEVBQW1CO0FBQ3pCO0FBQ0FQLGdCQUFRSixLQUFLSSxNQUZZO0FBR3pCQyxjQUFNTCxLQUFLSyxJQUhjO0FBSXpCTyx5QkFBaUI7QUFKUSxLQUFuQixDQUFWOztBQU9BLFNBQUksSUFBTUMsQ0FBVixJQUFlYixLQUFLUyxTQUFwQixFQUErQjtBQUMzQlgsZ0JBQVFnQixTQUFSLENBQWtCQyxRQUFsQixDQUEyQmYsS0FBS1MsU0FBTCxDQUFlSSxDQUFmLENBQTNCLEVBQThDRyxLQUE5QyxDQUFvREwsR0FBcEQ7QUFDSDs7QUFFRCxXQUFPQSxHQUFQO0FBQ0gsQ0F4REQiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvbWFwcy9iYXNlX21hcC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vXG5cbmNvbnN0IGxlYWZsZXQgPSByZXF1aXJlKCdsZWFmbGV0Jyk7XG5yZXF1aXJlKCdsZWFmbGV0LXByb3ZpZGVycycpO1xuXG5leHBvcnQgZGVmYXVsdCAob3B0cykgPT4ge1xuXG4gICAgb3B0cyA9IE9iamVjdC5hc3NpZ24oe1xuICAgICAgICByZW5kZXJfZWxlbTogJ21hcCcsXG4gICAgICAgIGNlbnRlcjogWzI5Ljk4MTM5LCAtOTUuMzMzNzRdLFxuICAgICAgICB6b29tOiA1LFxuICAgICAgICBtYXhab29tOiAxMCxcbiAgICAgICAgbGF5ZXJzOiBbXSxcbiAgICAgICAgc2V0X21hcmtlcjogZmFsc2UsXG4gICAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICAgICAgJ0VzcmkuV29ybGRTdHJlZXRNYXAnLFxuICAgICAgICBdLFxuICAgICAgICB0aWxlX2xheWVyczogW10sXG4gICAgfSwgb3B0cyk7XG5cbiAgICAvKlxuICAgIGxldCBmZWF0dXJlX2dyb3VwcyA9IFtdO1xuICAgIGNvbnN0IG9wZW5haXBfYWlyc3BhY2VfbGFiZWxzID0gbmV3IGxlYWZsZXQuVGlsZUxheWVyLldNUyhcbiAgICAgICAgXCJodHRwOi8ve3N9LnRpbGUubWFwcy5vcGVuYWlwLm5ldC9nZW93ZWJjYWNoZS9zZXJ2aWNlL3dtc1wiLCB7XG4gICAgICAgICAgICBtYXhab29tOiAxNCxcbiAgICAgICAgICAgIG1pblpvb206IDEyLFxuICAgICAgICAgICAgbGF5ZXJzOiAnb3BlbmFpcF9hcHByb3ZlZF9haXJzcGFjZXNfbGFiZWxzJyxcbiAgICAgICAgICAgIHRpbGVTaXplOiAxMDI0LFxuICAgICAgICAgICAgZGV0ZWN0UmV0aW5hOiB0cnVlLFxuICAgICAgICAgICAgc3ViZG9tYWluczogJzEyJyxcbiAgICAgICAgICAgIGZvcm1hdDogJ2ltYWdlL3BuZycsXG4gICAgICAgICAgICB0cmFuc3BhcmVudDogdHJ1ZVxuICAgICAgICB9KTtcblxuICAgIG9wZW5haXBfYWlyc3BhY2VfbGFiZWxzLmFkZFRvKG1hcCk7Ki9cblxuICAgIC8qY29uc3Qgb3BlbmFpcF9jYWNoZWRfYmFzZW1hcCA9IG5ldyBsZWFmbGV0LlRpbGVMYXllcihcImh0dHA6Ly97c30udGlsZS5tYXBzLm9wZW5haXAubmV0L2dlb3dlYmNhY2hlL3NlcnZpY2UvdG1zLzEuMC4wL29wZW5haXBfYmFzZW1hcEBFUFNHJTNBOTAwOTEzQHBuZy97en0ve3h9L3t5fS5wbmdcIiwge1xuICAgICAgICBtYXhab29tOiAxNCxcbiAgICAgICAgbWluWm9vbTogNCxcbiAgICAgICAgdG1zOiB0cnVlLFxuICAgICAgICBkZXRlY3RSZXRpbmE6IHRydWUsXG4gICAgICAgIHN1YmRvbWFpbnM6ICcxMicsXG4gICAgICAgIGZvcm1hdDogJ2ltYWdlL3BuZycsXG4gICAgICAgIHRyYW5zcGFyZW50OiB0cnVlXG4gICAgfSk7XG5cbiAgICBmZWF0dXJlX2dyb3Vwcy5wdXNoKG9wZW5haXBfY2FjaGVkX2Jhc2VtYXApO1xuICAgICovXG5cbiAgICBsZXQgbWFwID0gbGVhZmxldC5tYXAoJ21hcCcsIHtcbiAgICAgICAgLy9sYXllcnM6IFtvcGVuYWlwX2Jhc2VtYXBfcGh5c19vc21dLFxuICAgICAgICBjZW50ZXI6IG9wdHMuY2VudGVyLFxuICAgICAgICB6b29tOiBvcHRzLnpvb20sXG4gICAgICAgIHNjcm9sbFdoZWVsWm9vbTogZmFsc2UsXG4gICAgfSk7XG5cbiAgICBmb3IoY29uc3QgaSBpbiBvcHRzLnByb3ZpZGVycykge1xuICAgICAgICBsZWFmbGV0LnRpbGVMYXllci5wcm92aWRlcihvcHRzLnByb3ZpZGVyc1tpXSkuYWRkVG8obWFwKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWFwO1xufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3Jlc291cmNlcy9qcy9tYXBzL2Jhc2VfbWFwLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./resources/js/maps/base_map.js\n");
/***/ }),
/***/ "./resources/js/maps/config.js":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"c\", function() { return PLAN_ROUTE_COLOR; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"a\", function() { return ACTUAL_ROUTE_COLOR; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"b\", function() { return CIRCLE_COLOR; });\nvar PLAN_ROUTE_COLOR = '#043758',\n ACTUAL_ROUTE_COLOR = '#067ec1',\n CIRCLE_COLOR = '#056093';//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9jb25maWcuanM/NzdmNyJdLCJuYW1lcyI6WyJQTEFOX1JPVVRFX0NPTE9SIiwiQUNUVUFMX1JPVVRFX0NPTE9SIiwiQ0lSQ0xFX0NPTE9SIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUFBO0FBQUE7QUFBTyxJQUNIQSxtQkFBbUIsU0FEaEI7QUFBQSxJQUVIQyxxQkFBcUIsU0FGbEI7QUFBQSxJQUdIQyxlQUFlLFNBSFoiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvbWFwcy9jb25maWcuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgbGV0XG4gICAgUExBTl9ST1VURV9DT0xPUiA9ICcjMDQzNzU4JyxcbiAgICBBQ1RVQUxfUk9VVEVfQ09MT1IgPSAnIzA2N2VjMScsXG4gICAgQ0lSQ0xFX0NPTE9SID0gJyMwNTYwOTMnO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vcmVzb3VyY2VzL2pzL21hcHMvY29uZmlnLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./resources/js/maps/config.js\n");
/***/ }),
/***/ "./resources/js/maps/helpers.js":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("/* harmony export (immutable) */ __webpack_exports__[\"a\"] = addWMSLayer;\n/* unused harmony export showFeaturePopup */\n\nvar leaflet = __webpack_require__(\"./node_modules/leaflet/dist/leaflet-src.js\");\n\n/**\n * Add a WMS layer to a map. opts must be:\n * {\n * url: '',\n * params: {}\n * }\n * @param map\n * @param opts\n */\nfunction addWMSLayer(map, opts) {\n\n if (opts.url === '') {\n return;\n }\n\n opts.params = Object.assign({\n format: 'image/png',\n transparent: true,\n maxZoom: 14,\n minZoom: 4\n }, opts.params);\n\n var mlayer = leaflet.tileLayer.wms(opts.url, opts.params);\n\n mlayer.addTo(map);\n\n return mlayer;\n}\n\n/**\n * Show a popup\n * @param feature\n * @param layer\n */\nfunction showFeaturePopup(feature, layer) {\n var popup_html = '';\n if (feature.properties && feature.properties.popup) {\n popup_html += feature.properties.popup;\n }\n\n layer.bindPopup(popup_html);\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9oZWxwZXJzLmpzPzNjZDUiXSwibmFtZXMiOlsibGVhZmxldCIsInJlcXVpcmUiLCJhZGRXTVNMYXllciIsIm1hcCIsIm9wdHMiLCJ1cmwiLCJwYXJhbXMiLCJPYmplY3QiLCJhc3NpZ24iLCJmb3JtYXQiLCJ0cmFuc3BhcmVudCIsIm1heFpvb20iLCJtaW5ab29tIiwibWxheWVyIiwidGlsZUxheWVyIiwid21zIiwiYWRkVG8iLCJzaG93RmVhdHVyZVBvcHVwIiwiZmVhdHVyZSIsImxheWVyIiwicG9wdXBfaHRtbCIsInByb3BlcnRpZXMiLCJwb3B1cCIsImJpbmRQb3B1cCJdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsSUFBTUEsVUFBVUMsbUJBQU9BLENBQUMsNENBQVIsQ0FBaEI7O0FBRUE7Ozs7Ozs7OztBQVNPLFNBQVNDLFdBQVQsQ0FBcUJDLEdBQXJCLEVBQTBCQyxJQUExQixFQUFnQzs7QUFFbkMsUUFBR0EsS0FBS0MsR0FBTCxLQUFhLEVBQWhCLEVBQW9CO0FBQ2hCO0FBQ0g7O0FBRURELFNBQUtFLE1BQUwsR0FBY0MsT0FBT0MsTUFBUCxDQUFjO0FBQ3hCQyxnQkFBUSxXQURnQjtBQUV4QkMscUJBQWEsSUFGVztBQUd4QkMsaUJBQVMsRUFIZTtBQUl4QkMsaUJBQVM7QUFKZSxLQUFkLEVBS1hSLEtBQUtFLE1BTE0sQ0FBZDs7QUFPQSxRQUFNTyxTQUFTYixRQUFRYyxTQUFSLENBQWtCQyxHQUFsQixDQUNYWCxLQUFLQyxHQURNLEVBQ0RELEtBQUtFLE1BREosQ0FBZjs7QUFJQU8sV0FBT0csS0FBUCxDQUFhYixHQUFiOztBQUVBLFdBQU9VLE1BQVA7QUFDSDs7QUFFRDs7Ozs7QUFLTyxTQUFTSSxnQkFBVCxDQUEwQkMsT0FBMUIsRUFBbUNDLEtBQW5DLEVBQTBDO0FBQzdDLFFBQUlDLGFBQWEsRUFBakI7QUFDQSxRQUFJRixRQUFRRyxVQUFSLElBQXNCSCxRQUFRRyxVQUFSLENBQW1CQyxLQUE3QyxFQUFvRDtBQUNoREYsc0JBQWNGLFFBQVFHLFVBQVIsQ0FBbUJDLEtBQWpDO0FBQ0g7O0FBRURILFVBQU1JLFNBQU4sQ0FBZ0JILFVBQWhCO0FBQ0giLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvbWFwcy9oZWxwZXJzLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiXG5jb25zdCBsZWFmbGV0ID0gcmVxdWlyZSgnbGVhZmxldCcpO1xuXG4vKipcbiAqIEFkZCBhIFdNUyBsYXllciB0byBhIG1hcC4gb3B0cyBtdXN0IGJlOlxuICoge1xuICogIHVybDogJycsXG4gKiAgcGFyYW1zOiB7fVxuICogIH1cbiAqIEBwYXJhbSBtYXBcbiAqIEBwYXJhbSBvcHRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGRXTVNMYXllcihtYXAsIG9wdHMpIHtcblxuICAgIGlmKG9wdHMudXJsID09PSAnJykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgb3B0cy5wYXJhbXMgPSBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgZm9ybWF0OiAnaW1hZ2UvcG5nJyxcbiAgICAgICAgdHJhbnNwYXJlbnQ6IHRydWUsXG4gICAgICAgIG1heFpvb206IDE0LFxuICAgICAgICBtaW5ab29tOiA0LFxuICAgIH0sIG9wdHMucGFyYW1zKTtcblxuICAgIGNvbnN0IG1sYXllciA9IGxlYWZsZXQudGlsZUxheWVyLndtcyhcbiAgICAgICAgb3B0cy51cmwsIG9wdHMucGFyYW1zXG4gICAgKTtcblxuICAgIG1sYXllci5hZGRUbyhtYXApO1xuXG4gICAgcmV0dXJuIG1sYXllcjtcbn1cblxuLyoqXG4gKiBTaG93IGEgcG9wdXBcbiAqIEBwYXJhbSBmZWF0dXJlXG4gKiBAcGFyYW0gbGF5ZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNob3dGZWF0dXJlUG9wdXAoZmVhdHVyZSwgbGF5ZXIpIHtcbiAgICBsZXQgcG9wdXBfaHRtbCA9ICcnO1xuICAgIGlmIChmZWF0dXJlLnByb3BlcnRpZXMgJiYgZmVhdHVyZS5wcm9wZXJ0aWVzLnBvcHVwKSB7XG4gICAgICAgIHBvcHVwX2h0bWwgKz0gZmVhdHVyZS5wcm9wZXJ0aWVzLnBvcHVwXG4gICAgfVxuXG4gICAgbGF5ZXIuYmluZFBvcHVwKHBvcHVwX2h0bWwpXG59XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9yZXNvdXJjZXMvanMvbWFwcy9oZWxwZXJzLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./resources/js/maps/helpers.js\n");
/***/ }),
/***/ "./resources/js/maps/index.js":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("Object.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__airspace_map__ = __webpack_require__(\"./resources/js/maps/airspace_map.js\");\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__live_map__ = __webpack_require__(\"./resources/js/maps/live_map.js\");\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__route_map__ = __webpack_require__(\"./resources/js/maps/route_map.js\");\n/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, \"render_airspace_map\", function() { return __WEBPACK_IMPORTED_MODULE_0__airspace_map__[\"a\"]; });\n/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, \"render_live_map\", function() { return __WEBPACK_IMPORTED_MODULE_1__live_map__[\"a\"]; });\n/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, \"render_route_map\", function() { return __WEBPACK_IMPORTED_MODULE_2__route_map__[\"a\"]; });\n/**\n * All of the functionality required for maps\n */\n\nwindow.L = __webpack_require__(\"./node_modules/leaflet/dist/leaflet-src.js\");\n__webpack_require__(\"./node_modules/Leaflet.Geodesic/Leaflet.Geodesic.js\");\n__webpack_require__(\"./node_modules/leaflet-rotatedmarker/leaflet.rotatedMarker.js\");\n\n\n\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9pbmRleC5qcz85MmYwIl0sIm5hbWVzIjpbIndpbmRvdyIsIkwiLCJyZXF1aXJlIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7O0FBSUFBLE9BQU9DLENBQVAsR0FBV0MsbUJBQU9BLENBQUMsNENBQVIsQ0FBWDtBQUNBQSxtQkFBT0EsQ0FBQyxxREFBUjtBQUNBQSxtQkFBT0EsQ0FBQywrREFBUjs7QUFFQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvbWFwcy9pbmRleC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQWxsIG9mIHRoZSBmdW5jdGlvbmFsaXR5IHJlcXVpcmVkIGZvciBtYXBzXG4gKi9cblxud2luZG93LkwgPSByZXF1aXJlKCdsZWFmbGV0Jyk7XG5yZXF1aXJlKCdMZWFmbGV0Lkdlb2Rlc2ljJyk7XG5yZXF1aXJlKCdsZWFmbGV0LXJvdGF0ZWRtYXJrZXInKTtcblxuaW1wb3J0IHJlbmRlcl9haXJzcGFjZV9tYXAgZnJvbSAnLi9haXJzcGFjZV9tYXAnXG5pbXBvcnQgcmVuZGVyX2xpdmVfbWFwIGZyb20gJy4vbGl2ZV9tYXAnXG5pbXBvcnQgcmVuZGVyX3JvdXRlX21hcCBmcm9tICcuL3JvdXRlX21hcCdcblxuZXhwb3J0IHtcbiAgcmVuZGVyX2FpcnNwYWNlX21hcCxcbiAgcmVuZGVyX2xpdmVfbWFwLFxuICByZW5kZXJfcm91dGVfbWFwLFxufVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vcmVzb3VyY2VzL2pzL21hcHMvaW5kZXguanMiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./resources/js/maps/index.js\n");
/***/ }),
/***/ "./resources/js/maps/live_map.js":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__base_map__ = __webpack_require__(\"./resources/js/maps/base_map.js\");\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__config__ = __webpack_require__(\"./resources/js/maps/config.js\");\n//\n\nvar geolib = __webpack_require__(\"./node_modules/geolib/dist/geolib.js\");\nvar leaflet = __webpack_require__(\"./node_modules/leaflet/dist/leaflet-src.js\");\nvar rivets = __webpack_require__(\"./node_modules/rivets/dist/rivets.js\");\n\n\n\n\n/**\n * Render the live map\n * @param opts\n * @private\n */\n/* harmony default export */ __webpack_exports__[\"a\"] = (function (opts) {\n\n opts = Object.assign({\n center: [29.98139, -95.33374],\n zoom: 5,\n update_uri: '/api/acars',\n pirep_uri: '/api/pireps/{id}',\n pirep_link_uri: '/pireps/{id}',\n positions: null,\n render_elem: 'map',\n aircraft_icon: '/assets/img/acars/aircraft.png',\n units: 'nmi'\n }, opts);\n\n var map = Object(__WEBPACK_IMPORTED_MODULE_0__base_map__[\"a\" /* default */])(opts);\n var aircraftIcon = leaflet.icon({\n iconUrl: opts.aircraft_icon,\n iconSize: [42, 42],\n iconAnchor: [21, 21]\n });\n\n /**\n * Hold the markers\n * @type {{}}\n */\n var markers_list = {};\n\n var pannedToCenter = false;\n\n var layerFlights = null;\n var layerSelFlight = null;\n var layerSelFlightFeature = null;\n var layerSelFlightLayer = null;\n var layerSelArr = null;\n var layerSelDep = null;\n\n /**\n * Controller for two-way bindings\n * @type {{focusMarker: focusMarker}}\n */\n var mapController = {\n /**\n * Focus on a specific marker\n * @param e\n * @param model\n */\n focusMarker: function focusMarker(e, model) {\n if (!(model.pirep.id in markers_list)) {\n console.log('marker not found in list');\n return;\n }\n\n var marker = markers_list[model.pirep.id];\n onFlightClick(marker[0], marker[1]);\n }\n };\n\n var r_map_view = rivets.bind($('#map-info-box'), { pirep: {}, controller: mapController });\n var r_table_view = rivets.bind($('#live_flights'), { pireps: [], controller: mapController });\n\n /**\n * When a flight is clicked on, show the path, etc for that flight\n * @param feature\n * @param layer\n */\n var onFlightClick = function onFlightClick(feature, layer) {\n\n var pirep_uri = opts.pirep_uri.replace('{id}', feature.properties.pirep_id);\n var geojson_uri = opts.pirep_uri.replace('{id}', feature.properties.pirep_id) + \"/acars/geojson\";\n\n var pirep_info = $.ajax({\n url: pirep_uri,\n dataType: 'json',\n error: console.log\n });\n\n var flight_route = $.ajax({\n url: geojson_uri,\n dataType: 'json',\n error: console.log\n });\n\n // Load up the PIREP info\n $.when(flight_route).done(function (rte) {\n if (layerSelFlight !== null) {\n map.removeLayer(layerSelFlight);\n //map.removeLayer(layerSelArr);\n //map.removeLayer(layerSelDep);\n }\n\n layerSelFlight = leaflet.geodesic([], {\n weight: 5,\n opacity: 0.9,\n color: __WEBPACK_IMPORTED_MODULE_1__config__[\"a\" /* ACTUAL_ROUTE_COLOR */],\n wrap: false\n }).addTo(map);\n\n layerSelFlight.geoJson(rte.line);\n layerSelFlightFeature = feature;\n layerSelFlightLayer = layer;\n\n /*const dptIcon = leaflet.divIcon({\n html: '<div class=\"map-info-label\"><h5>' + rte.airports.d.icao + '</h5></div>'\n });\n layerSelDep = leaflet.marker([rte.airports.d.lat, rte.airports.d.lon], {icon:dptIcon}).addTo(map);\n */\n\n // Center on it, but only do it once, in case the map is moved\n if (!pannedToCenter) {\n // find center\n var c = geolib.getCenter([{ latitude: rte.airports.a.lat, longitude: rte.airports.a.lon }, { latitude: rte.airports.d.lat, longitude: rte.airports.d.lon }]);\n\n //map.panTo({lat: c.latitude, lng: c.longitude});\n map.panTo({ lat: rte.position.lat, lng: rte.position.lon });\n pannedToCenter = true;\n }\n });\n\n //\n // When the PIREP info is done loading, show the bottom bar\n //\n $.when(pirep_info).done(function (pirep) {\n r_map_view.update({ pirep: pirep.data });\n $('#map-info-box').show();\n });\n };\n\n var updateMap = function updateMap() {\n\n console.log('reloading flights from acars...');\n\n /**\n * AJAX UPDATE\n */\n var pirep_uri = opts.pirep_uri.replace('{id}', '');\n var pireps = $.ajax({\n url: pirep_uri,\n dataType: 'json',\n error: console.log\n });\n\n var flights = $.ajax({\n url: opts.update_uri,\n dataType: 'json',\n error: console.log\n });\n\n $.when(flights).done(function (flightGeoJson) {\n\n if (layerFlights !== null) {\n layerFlights.clearLayers();\n }\n\n layerFlights = leaflet.geoJSON(flightGeoJson, {\n onEachFeature: function onEachFeature(feature, layer) {\n layer.on({\n click: function click(e) {\n pannedToCenter = false;\n onFlightClick(feature, layer);\n }\n });\n\n var popup_html = '';\n if (feature.properties && feature.properties.popup !== '' && feature.properties.popup !== undefined) {\n popup_html += feature.properties.popup;\n layer.bindPopup(popup_html);\n }\n\n // add to the list\n markers_list[feature.properties.pirep_id] = [feature, layer];\n },\n pointToLayer: function pointToLayer(feature, latlon) {\n return leaflet.marker(latlon, {\n icon: aircraftIcon,\n rotationAngle: feature.properties.heading\n });\n }\n });\n\n layerFlights.addTo(map);\n\n // Reload the clicked-flight information\n if (layerSelFlight !== null) {\n onFlightClick(layerSelFlightFeature, layerSelFlightLayer);\n }\n });\n\n $.when(pireps).done(function (pireps) {\n r_table_view.update({\n pireps: pireps.data,\n has_data: pireps.data.length > 0\n });\n });\n };\n\n updateMap();\n setInterval(updateMap, 10000);\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9saXZlX21hcC5qcz9lN2Y2Il0sIm5hbWVzIjpbImdlb2xpYiIsInJlcXVpcmUiLCJsZWFmbGV0Iiwicml2ZXRzIiwib3B0cyIsIk9iamVjdCIsImFzc2lnbiIsImNlbnRlciIsInpvb20iLCJ1cGRhdGVfdXJpIiwicGlyZXBfdXJpIiwicGlyZXBfbGlua191cmkiLCJwb3NpdGlvbnMiLCJyZW5kZXJfZWxlbSIsImFpcmNyYWZ0X2ljb24iLCJ1bml0cyIsIm1hcCIsImRyYXdfYmFzZV9tYXAiLCJhaXJjcmFmdEljb24iLCJpY29uIiwiaWNvblVybCIsImljb25TaXplIiwiaWNvbkFuY2hvciIsIm1hcmtlcnNfbGlzdCIsInBhbm5lZFRvQ2VudGVyIiwibGF5ZXJGbGlnaHRzIiwibGF5ZXJTZWxGbGlnaHQiLCJsYXllclNlbEZsaWdodEZlYXR1cmUiLCJsYXllclNlbEZsaWdodExheWVyIiwibGF5ZXJTZWxBcnIiLCJsYXllclNlbERlcCIsIm1hcENvbnRyb2xsZXIiLCJmb2N1c01hcmtlciIsImUiLCJtb2RlbCIsInBpcmVwIiwiaWQiLCJjb25zb2xlIiwibG9nIiwibWFya2VyIiwib25GbGlnaHRDbGljayIsInJfbWFwX3ZpZXciLCJiaW5kIiwiJCIsImNvbnRyb2xsZXIiLCJyX3RhYmxlX3ZpZXciLCJwaXJlcHMiLCJmZWF0dXJlIiwibGF5ZXIiLCJyZXBsYWNlIiwicHJvcGVydGllcyIsInBpcmVwX2lkIiwiZ2VvanNvbl91cmkiLCJwaXJlcF9pbmZvIiwiYWpheCIsInVybCIsImRhdGFUeXBlIiwiZXJyb3IiLCJmbGlnaHRfcm91dGUiLCJ3aGVuIiwiZG9uZSIsInJ0ZSIsInJlbW92ZUxheWVyIiwiZ2VvZGVzaWMiLCJ3ZWlnaHQiLCJvcGFjaXR5IiwiY29sb3IiLCJBQ1RVQUxfUk9VVEVfQ09MT1IiLCJ3cmFwIiwiYWRkVG8iLCJnZW9Kc29uIiwibGluZSIsImMiLCJnZXRDZW50ZXIiLCJsYXRpdHVkZSIsImFpcnBvcnRzIiwiYSIsImxhdCIsImxvbmdpdHVkZSIsImxvbiIsImQiLCJwYW5UbyIsInBvc2l0aW9uIiwibG5nIiwidXBkYXRlIiwiZGF0YSIsInNob3ciLCJ1cGRhdGVNYXAiLCJmbGlnaHRzIiwiY2xlYXJMYXllcnMiLCJnZW9KU09OIiwiZmxpZ2h0R2VvSnNvbiIsIm9uRWFjaEZlYXR1cmUiLCJvbiIsImNsaWNrIiwicG9wdXBfaHRtbCIsInBvcHVwIiwidW5kZWZpbmVkIiwiYmluZFBvcHVwIiwicG9pbnRUb0xheWVyIiwibGF0bG9uIiwicm90YXRpb25BbmdsZSIsImhlYWRpbmciLCJoYXNfZGF0YSIsImxlbmd0aCIsInNldEludGVydmFsIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUFBO0FBQUE7O0FBRUEsSUFBTUEsU0FBU0MsbUJBQU9BLENBQUMsc0NBQVIsQ0FBZjtBQUNBLElBQU1DLFVBQVVELG1CQUFPQSxDQUFDLDRDQUFSLENBQWhCO0FBQ0EsSUFBTUUsU0FBU0YsbUJBQU9BLENBQUMsc0NBQVIsQ0FBZjs7QUFFQTtBQUNBOztBQUVBOzs7OztBQUtlLG1FQUFDRyxJQUFELEVBQVU7O0FBRXJCQSxXQUFPQyxPQUFPQyxNQUFQLENBQWM7QUFDakJDLGdCQUFRLENBQUMsUUFBRCxFQUFXLENBQUMsUUFBWixDQURTO0FBRWpCQyxjQUFNLENBRlc7QUFHakJDLG9CQUFZLFlBSEs7QUFJakJDLG1CQUFXLGtCQUpNO0FBS2pCQyx3QkFBZ0IsY0FMQztBQU1qQkMsbUJBQVcsSUFOTTtBQU9qQkMscUJBQWEsS0FQSTtBQVFqQkMsdUJBQWUsZ0NBUkU7QUFTakJDLGVBQU87QUFUVSxLQUFkLEVBVUpYLElBVkksQ0FBUDs7QUFZQSxRQUFNWSxNQUFNQyxrRUFBYUEsQ0FBQ2IsSUFBZCxDQUFaO0FBQ0EsUUFBTWMsZUFBZWhCLFFBQVFpQixJQUFSLENBQWE7QUFDOUJDLGlCQUFTaEIsS0FBS1UsYUFEZ0I7QUFFOUJPLGtCQUFVLENBQUMsRUFBRCxFQUFLLEVBQUwsQ0FGb0I7QUFHOUJDLG9CQUFZLENBQUMsRUFBRCxFQUFLLEVBQUw7QUFIa0IsS0FBYixDQUFyQjs7QUFNQTs7OztBQUlBLFFBQUlDLGVBQWUsRUFBbkI7O0FBRUEsUUFBSUMsaUJBQWlCLEtBQXJCOztBQUVBLFFBQUlDLGVBQWUsSUFBbkI7QUFDQSxRQUFJQyxpQkFBaUIsSUFBckI7QUFDQSxRQUFJQyx3QkFBd0IsSUFBNUI7QUFDQSxRQUFJQyxzQkFBc0IsSUFBMUI7QUFDQSxRQUFJQyxjQUFjLElBQWxCO0FBQ0EsUUFBSUMsY0FBYyxJQUFsQjs7QUFFQTs7OztBQUlBLFFBQU1DLGdCQUFnQjtBQUNsQjs7Ozs7QUFLQUMscUJBQWEscUJBQUNDLENBQUQsRUFBSUMsS0FBSixFQUFjO0FBQ3ZCLGdCQUFHLEVBQUVBLE1BQU1DLEtBQU4sQ0FBWUMsRUFBWixJQUFrQmIsWUFBcEIsQ0FBSCxFQUFzQztBQUNsQ2Msd0JBQVFDLEdBQVIsQ0FBWSwwQkFBWjtBQUNBO0FBQ0g7O0FBRUQsZ0JBQU1DLFNBQVNoQixhQUFhVyxNQUFNQyxLQUFOLENBQVlDLEVBQXpCLENBQWY7QUFDQUksMEJBQWNELE9BQU8sQ0FBUCxDQUFkLEVBQXlCQSxPQUFPLENBQVAsQ0FBekI7QUFDSDtBQWRpQixLQUF0Qjs7QUFpQkEsUUFBTUUsYUFBYXRDLE9BQU91QyxJQUFQLENBQVlDLEVBQUUsZUFBRixDQUFaLEVBQWdDLEVBQUNSLE9BQU8sRUFBUixFQUFZUyxZQUFZYixhQUF4QixFQUFoQyxDQUFuQjtBQUNBLFFBQU1jLGVBQWUxQyxPQUFPdUMsSUFBUCxDQUFZQyxFQUFFLGVBQUYsQ0FBWixFQUFnQyxFQUFDRyxRQUFRLEVBQVQsRUFBYUYsWUFBWWIsYUFBekIsRUFBaEMsQ0FBckI7O0FBRUE7Ozs7O0FBS0EsUUFBTVMsZ0JBQWdCLFNBQWhCQSxhQUFnQixDQUFDTyxPQUFELEVBQVVDLEtBQVYsRUFBb0I7O0FBRXRDLFlBQU10QyxZQUFZTixLQUFLTSxTQUFMLENBQWV1QyxPQUFmLENBQXVCLE1BQXZCLEVBQStCRixRQUFRRyxVQUFSLENBQW1CQyxRQUFsRCxDQUFsQjtBQUNBLFlBQU1DLGNBQWNoRCxLQUFLTSxTQUFMLENBQWV1QyxPQUFmLENBQXVCLE1BQXZCLEVBQStCRixRQUFRRyxVQUFSLENBQW1CQyxRQUFsRCxJQUE4RCxnQkFBbEY7O0FBRUEsWUFBTUUsYUFBYVYsRUFBRVcsSUFBRixDQUFPO0FBQ3RCQyxpQkFBSzdDLFNBRGlCO0FBRXRCOEMsc0JBQVUsTUFGWTtBQUd0QkMsbUJBQU9wQixRQUFRQztBQUhPLFNBQVAsQ0FBbkI7O0FBTUEsWUFBTW9CLGVBQWVmLEVBQUVXLElBQUYsQ0FBTztBQUN4QkMsaUJBQUtILFdBRG1CO0FBRXhCSSxzQkFBVSxNQUZjO0FBR3hCQyxtQkFBT3BCLFFBQVFDO0FBSFMsU0FBUCxDQUFyQjs7QUFNQTtBQUNBSyxVQUFFZ0IsSUFBRixDQUFPRCxZQUFQLEVBQXFCRSxJQUFyQixDQUEwQixVQUFDQyxHQUFELEVBQVM7QUFDL0IsZ0JBQUluQyxtQkFBbUIsSUFBdkIsRUFBNkI7QUFDekJWLG9CQUFJOEMsV0FBSixDQUFnQnBDLGNBQWhCO0FBQ0E7QUFDQTtBQUNIOztBQUVEQSw2QkFBaUJ4QixRQUFRNkQsUUFBUixDQUFpQixFQUFqQixFQUFxQjtBQUNsQ0Msd0JBQVEsQ0FEMEI7QUFFbENDLHlCQUFTLEdBRnlCO0FBR2xDQyx1QkFBT0MsbUVBSDJCO0FBSWxDQyxzQkFBTTtBQUo0QixhQUFyQixFQUtkQyxLQUxjLENBS1JyRCxHQUxRLENBQWpCOztBQU9BVSwyQkFBZTRDLE9BQWYsQ0FBdUJULElBQUlVLElBQTNCO0FBQ0E1QyxvQ0FBd0JvQixPQUF4QjtBQUNBbkIsa0NBQXNCb0IsS0FBdEI7O0FBRUE7Ozs7OztBQU9BO0FBQ0EsZ0JBQUcsQ0FBQ3hCLGNBQUosRUFBb0I7QUFDaEI7QUFDQSxvQkFBTWdELElBQUl4RSxPQUFPeUUsU0FBUCxDQUFpQixDQUN2QixFQUFDQyxVQUFVYixJQUFJYyxRQUFKLENBQWFDLENBQWIsQ0FBZUMsR0FBMUIsRUFBK0JDLFdBQVdqQixJQUFJYyxRQUFKLENBQWFDLENBQWIsQ0FBZUcsR0FBekQsRUFEdUIsRUFFdkIsRUFBQ0wsVUFBVWIsSUFBSWMsUUFBSixDQUFhSyxDQUFiLENBQWVILEdBQTFCLEVBQStCQyxXQUFXakIsSUFBSWMsUUFBSixDQUFhSyxDQUFiLENBQWVELEdBQXpELEVBRnVCLENBQWpCLENBQVY7O0FBS0E7QUFDQS9ELG9CQUFJaUUsS0FBSixDQUFVLEVBQUNKLEtBQUtoQixJQUFJcUIsUUFBSixDQUFhTCxHQUFuQixFQUF3Qk0sS0FBS3RCLElBQUlxQixRQUFKLENBQWFILEdBQTFDLEVBQVY7QUFDQXZELGlDQUFpQixJQUFqQjtBQUNIO0FBQ0osU0FyQ0Q7O0FBdUNBO0FBQ0E7QUFDQTtBQUNBbUIsVUFBRWdCLElBQUYsQ0FBT04sVUFBUCxFQUFtQk8sSUFBbkIsQ0FBd0IsaUJBQVM7QUFDN0JuQix1QkFBVzJDLE1BQVgsQ0FBa0IsRUFBQ2pELE9BQU1BLE1BQU1rRCxJQUFiLEVBQWxCO0FBQ0ExQyxjQUFFLGVBQUYsRUFBbUIyQyxJQUFuQjtBQUNILFNBSEQ7QUFJSCxLQWhFRDs7QUFrRUEsUUFBTUMsWUFBWSxTQUFaQSxTQUFZLEdBQU07O0FBRXBCbEQsZ0JBQVFDLEdBQVIsQ0FBWSxpQ0FBWjs7QUFFQTs7O0FBR0EsWUFBTTVCLFlBQVlOLEtBQUtNLFNBQUwsQ0FBZXVDLE9BQWYsQ0FBdUIsTUFBdkIsRUFBK0IsRUFBL0IsQ0FBbEI7QUFDQSxZQUFJSCxTQUFTSCxFQUFFVyxJQUFGLENBQU87QUFDaEJDLGlCQUFLN0MsU0FEVztBQUVoQjhDLHNCQUFVLE1BRk07QUFHaEJDLG1CQUFPcEIsUUFBUUM7QUFIQyxTQUFQLENBQWI7O0FBTUEsWUFBSWtELFVBQVU3QyxFQUFFVyxJQUFGLENBQU87QUFDakJDLGlCQUFLbkQsS0FBS0ssVUFETztBQUVqQitDLHNCQUFVLE1BRk87QUFHakJDLG1CQUFPcEIsUUFBUUM7QUFIRSxTQUFQLENBQWQ7O0FBTUFLLFVBQUVnQixJQUFGLENBQU82QixPQUFQLEVBQWdCNUIsSUFBaEIsQ0FBcUIseUJBQWlCOztBQUVsQyxnQkFBSW5DLGlCQUFpQixJQUFyQixFQUEyQjtBQUN2QkEsNkJBQWFnRSxXQUFiO0FBQ0g7O0FBRURoRSwyQkFBZXZCLFFBQVF3RixPQUFSLENBQWdCQyxhQUFoQixFQUErQjtBQUMxQ0MsK0JBQWUsdUJBQUM3QyxPQUFELEVBQVVDLEtBQVYsRUFBb0I7QUFDL0JBLDBCQUFNNkMsRUFBTixDQUFTO0FBQ0xDLCtCQUFPLGVBQUM3RCxDQUFELEVBQU87QUFDVlQsNkNBQWlCLEtBQWpCO0FBQ0FnQiwwQ0FBY08sT0FBZCxFQUF1QkMsS0FBdkI7QUFDSDtBQUpJLHFCQUFUOztBQU9BLHdCQUFJK0MsYUFBYSxFQUFqQjtBQUNBLHdCQUFJaEQsUUFBUUcsVUFBUixJQUF1QkgsUUFBUUcsVUFBUixDQUFtQjhDLEtBQW5CLEtBQTZCLEVBQTdCLElBQW1DakQsUUFBUUcsVUFBUixDQUFtQjhDLEtBQW5CLEtBQTZCQyxTQUEzRixFQUF1RztBQUNuR0Ysc0NBQWNoRCxRQUFRRyxVQUFSLENBQW1COEMsS0FBakM7QUFDQWhELDhCQUFNa0QsU0FBTixDQUFnQkgsVUFBaEI7QUFDSDs7QUFFRDtBQUNBeEUsaUNBQWF3QixRQUFRRyxVQUFSLENBQW1CQyxRQUFoQyxJQUE0QyxDQUFDSixPQUFELEVBQVVDLEtBQVYsQ0FBNUM7QUFDSCxpQkFqQnlDO0FBa0IxQ21ELDhCQUFjLHNCQUFVcEQsT0FBVixFQUFtQnFELE1BQW5CLEVBQTJCO0FBQ3JDLDJCQUFPbEcsUUFBUXFDLE1BQVIsQ0FBZTZELE1BQWYsRUFBdUI7QUFDMUJqRiw4QkFBTUQsWUFEb0I7QUFFMUJtRix1Q0FBZXRELFFBQVFHLFVBQVIsQ0FBbUJvRDtBQUZSLHFCQUF2QixDQUFQO0FBSUg7QUF2QnlDLGFBQS9CLENBQWY7O0FBMEJBN0UseUJBQWE0QyxLQUFiLENBQW1CckQsR0FBbkI7O0FBRUE7QUFDQSxnQkFBSVUsbUJBQW1CLElBQXZCLEVBQTZCO0FBQ3pCYyw4QkFBY2IscUJBQWQsRUFBcUNDLG1CQUFyQztBQUNIO0FBQ0osU0F0Q0Q7O0FBd0NBZSxVQUFFZ0IsSUFBRixDQUFPYixNQUFQLEVBQWVjLElBQWYsQ0FBb0Isa0JBQVU7QUFDMUJmLHlCQUFhdUMsTUFBYixDQUFvQjtBQUNoQnRDLHdCQUFRQSxPQUFPdUMsSUFEQztBQUVoQmtCLDBCQUFXekQsT0FBT3VDLElBQVAsQ0FBWW1CLE1BQVosR0FBcUI7QUFGaEIsYUFBcEI7QUFJSCxTQUxEO0FBTUgsS0FsRUQ7O0FBb0VBakI7QUFDQWtCLGdCQUFZbEIsU0FBWixFQUF1QixLQUF2QjtBQUNILENBek1EIiwiZmlsZSI6Ii4vcmVzb3VyY2VzL2pzL21hcHMvbGl2ZV9tYXAuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvL1xuXG5jb25zdCBnZW9saWIgPSByZXF1aXJlKCdnZW9saWInKTtcbmNvbnN0IGxlYWZsZXQgPSByZXF1aXJlKCdsZWFmbGV0Jyk7XG5jb25zdCByaXZldHMgPSByZXF1aXJlKCdyaXZldHMnKTtcblxuaW1wb3J0IGRyYXdfYmFzZV9tYXAgZnJvbSAnLi9iYXNlX21hcCdcbmltcG9ydCB7IEFDVFVBTF9ST1VURV9DT0xPUiB9IGZyb20gJy4vY29uZmlnJ1xuXG4vKipcbiAqIFJlbmRlciB0aGUgbGl2ZSBtYXBcbiAqIEBwYXJhbSBvcHRzXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgZGVmYXVsdCAob3B0cykgPT4ge1xuXG4gICAgb3B0cyA9IE9iamVjdC5hc3NpZ24oe1xuICAgICAgICBjZW50ZXI6IFsyOS45ODEzOSwgLTk1LjMzMzc0XSxcbiAgICAgICAgem9vbTogNSxcbiAgICAgICAgdXBkYXRlX3VyaTogJy9hcGkvYWNhcnMnLFxuICAgICAgICBwaXJlcF91cmk6ICcvYXBpL3BpcmVwcy97aWR9JyxcbiAgICAgICAgcGlyZXBfbGlua191cmk6ICcvcGlyZXBzL3tpZH0nLFxuICAgICAgICBwb3NpdGlvbnM6IG51bGwsXG4gICAgICAgIHJlbmRlcl9lbGVtOiAnbWFwJyxcbiAgICAgICAgYWlyY3JhZnRfaWNvbjogJy9hc3NldHMvaW1nL2FjYXJzL2FpcmNyYWZ0LnBuZycsXG4gICAgICAgIHVuaXRzOiAnbm1pJyxcbiAgICB9LCBvcHRzKTtcblxuICAgIGNvbnN0IG1hcCA9IGRyYXdfYmFzZV9tYXAob3B0cyk7XG4gICAgY29uc3QgYWlyY3JhZnRJY29uID0gbGVhZmxldC5pY29uKHtcbiAgICAgICAgaWNvblVybDogb3B0cy5haXJjcmFmdF9pY29uLFxuICAgICAgICBpY29uU2l6ZTogWzQyLCA0Ml0sXG4gICAgICAgIGljb25BbmNob3I6IFsyMSwgMjFdLFxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICogSG9sZCB0aGUgbWFya2Vyc1xuICAgICAqIEB0eXBlIHt7fX1cbiAgICAgKi9cbiAgICBsZXQgbWFya2Vyc19saXN0ID0ge307XG5cbiAgICBsZXQgcGFubmVkVG9DZW50ZXIgPSBmYWxzZTtcblxuICAgIGxldCBsYXllckZsaWdodHMgPSBudWxsO1xuICAgIGxldCBsYXllclNlbEZsaWdodCA9IG51bGw7XG4gICAgbGV0IGxheWVyU2VsRmxpZ2h0RmVhdHVyZSA9IG51bGw7XG4gICAgbGV0IGxheWVyU2VsRmxpZ2h0TGF5ZXIgPSBudWxsO1xuICAgIGxldCBsYXllclNlbEFyciA9IG51bGw7XG4gICAgbGV0IGxheWVyU2VsRGVwID0gbnVsbDtcblxuICAgIC8qKlxuICAgICAqIENvbnRyb2xsZXIgZm9yIHR3by13YXkgYmluZGluZ3NcbiAgICAgKiBAdHlwZSB7e2ZvY3VzTWFya2VyOiBmb2N1c01hcmtlcn19XG4gICAgICovXG4gICAgY29uc3QgbWFwQ29udHJvbGxlciA9IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZvY3VzIG9uIGEgc3BlY2lmaWMgbWFya2VyXG4gICAgICAgICAqIEBwYXJhbSBlXG4gICAgICAgICAqIEBwYXJhbSBtb2RlbFxuICAgICAgICAgKi9cbiAgICAgICAgZm9jdXNNYXJrZXI6IChlLCBtb2RlbCkgPT4ge1xuICAgICAgICAgICAgaWYoIShtb2RlbC5waXJlcC5pZCBpbiBtYXJrZXJzX2xpc3QpKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ21hcmtlciBub3QgZm91bmQgaW4gbGlzdCcpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgbWFya2VyID0gbWFya2Vyc19saXN0W21vZGVsLnBpcmVwLmlkXTtcbiAgICAgICAgICAgIG9uRmxpZ2h0Q2xpY2sobWFya2VyWzBdLCBtYXJrZXJbMV0pO1xuICAgICAgICB9LFxuICAgIH07XG5cbiAgICBjb25zdCByX21hcF92aWV3ID0gcml2ZXRzLmJpbmQoJCgnI21hcC1pbmZvLWJveCcpLCB7cGlyZXA6IHt9LCBjb250cm9sbGVyOiBtYXBDb250cm9sbGVyfSk7XG4gICAgY29uc3Qgcl90YWJsZV92aWV3ID0gcml2ZXRzLmJpbmQoJCgnI2xpdmVfZmxpZ2h0cycpLCB7cGlyZXBzOiBbXSwgY29udHJvbGxlcjogbWFwQ29udHJvbGxlcn0pO1xuXG4gICAgLyoqXG4gICAgICogV2hlbiBhIGZsaWdodCBpcyBjbGlja2VkIG9uLCBzaG93IHRoZSBwYXRoLCBldGMgZm9yIHRoYXQgZmxpZ2h0XG4gICAgICogQHBhcmFtIGZlYXR1cmVcbiAgICAgKiBAcGFyYW0gbGF5ZXJcbiAgICAgKi9cbiAgICBjb25zdCBvbkZsaWdodENsaWNrID0gKGZlYXR1cmUsIGxheWVyKSA9PiB7XG5cbiAgICAgICAgY29uc3QgcGlyZXBfdXJpID0gb3B0cy5waXJlcF91cmkucmVwbGFjZSgne2lkfScsIGZlYXR1cmUucHJvcGVydGllcy5waXJlcF9pZCk7XG4gICAgICAgIGNvbnN0IGdlb2pzb25fdXJpID0gb3B0cy5waXJlcF91cmkucmVwbGFjZSgne2lkfScsIGZlYXR1cmUucHJvcGVydGllcy5waXJlcF9pZCkgKyBcIi9hY2Fycy9nZW9qc29uXCI7XG5cbiAgICAgICAgY29uc3QgcGlyZXBfaW5mbyA9ICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IHBpcmVwX3VyaSxcbiAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICBlcnJvcjogY29uc29sZS5sb2dcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgZmxpZ2h0X3JvdXRlID0gJC5hamF4KHtcbiAgICAgICAgICAgIHVybDogZ2VvanNvbl91cmksXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgZXJyb3I6IGNvbnNvbGUubG9nXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIExvYWQgdXAgdGhlIFBJUkVQIGluZm9cbiAgICAgICAgJC53aGVuKGZsaWdodF9yb3V0ZSkuZG9uZSgocnRlKSA9PiB7XG4gICAgICAgICAgICBpZiAobGF5ZXJTZWxGbGlnaHQgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBtYXAucmVtb3ZlTGF5ZXIobGF5ZXJTZWxGbGlnaHQpO1xuICAgICAgICAgICAgICAgIC8vbWFwLnJlbW92ZUxheWVyKGxheWVyU2VsQXJyKTtcbiAgICAgICAgICAgICAgICAvL21hcC5yZW1vdmVMYXllcihsYXllclNlbERlcCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxheWVyU2VsRmxpZ2h0ID0gbGVhZmxldC5nZW9kZXNpYyhbXSwge1xuICAgICAgICAgICAgICAgIHdlaWdodDogNSxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAwLjksXG4gICAgICAgICAgICAgICAgY29sb3I6IEFDVFVBTF9ST1VURV9DT0xPUixcbiAgICAgICAgICAgICAgICB3cmFwOiBmYWxzZSxcbiAgICAgICAgICAgIH0pLmFkZFRvKG1hcCk7XG5cbiAgICAgICAgICAgIGxheWVyU2VsRmxpZ2h0Lmdlb0pzb24ocnRlLmxpbmUpO1xuICAgICAgICAgICAgbGF5ZXJTZWxGbGlnaHRGZWF0dXJlID0gZmVhdHVyZTtcbiAgICAgICAgICAgIGxheWVyU2VsRmxpZ2h0TGF5ZXIgPSBsYXllcjtcblxuICAgICAgICAgICAgLypjb25zdCBkcHRJY29uID0gbGVhZmxldC5kaXZJY29uKHtcbiAgICAgICAgICAgICAgICBodG1sOiAnPGRpdiBjbGFzcz1cIm1hcC1pbmZvLWxhYmVsXCI+PGg1PicgKyBydGUuYWlycG9ydHMuZC5pY2FvICsgJzwvaDU+PC9kaXY+J1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGxheWVyU2VsRGVwID0gbGVhZmxldC5tYXJrZXIoW3J0ZS5haXJwb3J0cy5kLmxhdCwgcnRlLmFpcnBvcnRzLmQubG9uXSwge2ljb246ZHB0SWNvbn0pLmFkZFRvKG1hcCk7XG4gICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvLyBDZW50ZXIgb24gaXQsIGJ1dCBvbmx5IGRvIGl0IG9uY2UsIGluIGNhc2UgdGhlIG1hcCBpcyBtb3ZlZFxuICAgICAgICAgICAgaWYoIXBhbm5lZFRvQ2VudGVyKSB7XG4gICAgICAgICAgICAgICAgLy8gZmluZCBjZW50ZXJcbiAgICAgICAgICAgICAgICBjb25zdCBjID0gZ2VvbGliLmdldENlbnRlcihbXG4gICAgICAgICAgICAgICAgICAgIHtsYXRpdHVkZTogcnRlLmFpcnBvcnRzLmEubGF0LCBsb25naXR1ZGU6IHJ0ZS5haXJwb3J0cy5hLmxvbn0sXG4gICAgICAgICAgICAgICAgICAgIHtsYXRpdHVkZTogcnRlLmFpcnBvcnRzLmQubGF0LCBsb25naXR1ZGU6IHJ0ZS5haXJwb3J0cy5kLmxvbn0sXG4gICAgICAgICAgICAgICAgXSk7XG5cbiAgICAgICAgICAgICAgICAvL21hcC5wYW5Ubyh7bGF0OiBjLmxhdGl0dWRlLCBsbmc6IGMubG9uZ2l0dWRlfSk7XG4gICAgICAgICAgICAgICAgbWFwLnBhblRvKHtsYXQ6IHJ0ZS5wb3NpdGlvbi5sYXQsIGxuZzogcnRlLnBvc2l0aW9uLmxvbn0pO1xuICAgICAgICAgICAgICAgIHBhbm5lZFRvQ2VudGVyID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy9cbiAgICAgICAgLy8gV2hlbiB0aGUgUElSRVAgaW5mbyBpcyBkb25lIGxvYWRpbmcsIHNob3cgdGhlIGJvdHRvbSBiYXJcbiAgICAgICAgLy9cbiAgICAgICAgJC53aGVuKHBpcmVwX2luZm8pLmRvbmUocGlyZXAgPT4ge1xuICAgICAgICAgICAgcl9tYXBfdmlldy51cGRhdGUoe3BpcmVwOnBpcmVwLmRhdGF9KTtcbiAgICAgICAgICAgICQoJyNtYXAtaW5mby1ib3gnKS5zaG93KCk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBjb25zdCB1cGRhdGVNYXAgPSAoKSA9PiB7XG5cbiAgICAgICAgY29uc29sZS5sb2coJ3JlbG9hZGluZyBmbGlnaHRzIGZyb20gYWNhcnMuLi4nKTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQUpBWCBVUERBVEVcbiAgICAgICAgICovXG4gICAgICAgIGNvbnN0IHBpcmVwX3VyaSA9IG9wdHMucGlyZXBfdXJpLnJlcGxhY2UoJ3tpZH0nLCAnJyk7XG4gICAgICAgIGxldCBwaXJlcHMgPSAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBwaXJlcF91cmksXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgZXJyb3I6IGNvbnNvbGUubG9nXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGxldCBmbGlnaHRzID0gJC5hamF4KHtcbiAgICAgICAgICAgIHVybDogb3B0cy51cGRhdGVfdXJpLFxuICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgIGVycm9yOiBjb25zb2xlLmxvZ1xuICAgICAgICB9KTtcblxuICAgICAgICAkLndoZW4oZmxpZ2h0cykuZG9uZShmbGlnaHRHZW9Kc29uID0+IHtcblxuICAgICAgICAgICAgaWYgKGxheWVyRmxpZ2h0cyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGxheWVyRmxpZ2h0cy5jbGVhckxheWVycygpXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxheWVyRmxpZ2h0cyA9IGxlYWZsZXQuZ2VvSlNPTihmbGlnaHRHZW9Kc29uLCB7XG4gICAgICAgICAgICAgICAgb25FYWNoRmVhdHVyZTogKGZlYXR1cmUsIGxheWVyKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGxheWVyLm9uKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsaWNrOiAoZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhbm5lZFRvQ2VudGVyID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25GbGlnaHRDbGljayhmZWF0dXJlLCBsYXllcilcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgbGV0IHBvcHVwX2h0bWwgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZlYXR1cmUucHJvcGVydGllcyAmJiAoZmVhdHVyZS5wcm9wZXJ0aWVzLnBvcHVwICE9PSAnJyAmJiBmZWF0dXJlLnByb3BlcnRpZXMucG9wdXAgIT09IHVuZGVmaW5lZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvcHVwX2h0bWwgKz0gZmVhdHVyZS5wcm9wZXJ0aWVzLnBvcHVwO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGF5ZXIuYmluZFBvcHVwKHBvcHVwX2h0bWwpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gYWRkIHRvIHRoZSBsaXN0XG4gICAgICAgICAgICAgICAgICAgIG1hcmtlcnNfbGlzdFtmZWF0dXJlLnByb3BlcnRpZXMucGlyZXBfaWRdID0gW2ZlYXR1cmUsIGxheWVyXTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHBvaW50VG9MYXllcjogZnVuY3Rpb24gKGZlYXR1cmUsIGxhdGxvbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbGVhZmxldC5tYXJrZXIobGF0bG9uLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uOiBhaXJjcmFmdEljb24sXG4gICAgICAgICAgICAgICAgICAgICAgICByb3RhdGlvbkFuZ2xlOiBmZWF0dXJlLnByb3BlcnRpZXMuaGVhZGluZ1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBsYXllckZsaWdodHMuYWRkVG8obWFwKTtcblxuICAgICAgICAgICAgLy8gUmVsb2FkIHRoZSBjbGlja2VkLWZsaWdodCBpbmZvcm1hdGlvblxuICAgICAgICAgICAgaWYgKGxheWVyU2VsRmxpZ2h0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgb25GbGlnaHRDbGljayhsYXllclNlbEZsaWdodEZlYXR1cmUsIGxheWVyU2VsRmxpZ2h0TGF5ZXIpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgICQud2hlbihwaXJlcHMpLmRvbmUocGlyZXBzID0+IHtcbiAgICAgICAgICAgIHJfdGFibGVfdmlldy51cGRhdGUoe1xuICAgICAgICAgICAgICAgIHBpcmVwczogcGlyZXBzLmRhdGEsXG4gICAgICAgICAgICAgICAgaGFzX2RhdGE6IChwaXJlcHMuZGF0YS5sZW5ndGggPiAwKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgdXBkYXRlTWFwKCk7XG4gICAgc2V0SW50ZXJ2YWwodXBkYXRlTWFwLCAxMDAwMClcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9yZXNvdXJjZXMvanMvbWFwcy9saXZlX21hcC5qcyJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./resources/js/maps/live_map.js\n");
/***/ }),
/***/ "./resources/js/maps/route_map.js":
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
eval("/* unused harmony export onFeaturePointClick */\n/* unused harmony export pointToLayer */\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__base_map__ = __webpack_require__(\"./resources/js/maps/base_map.js\");\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__helpers__ = __webpack_require__(\"./resources/js/maps/helpers.js\");\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__config__ = __webpack_require__(\"./resources/js/maps/config.js\");\nvar leaflet = __webpack_require__(\"./node_modules/leaflet/dist/leaflet-src.js\");\n\n\n\n\n\n\n/**\n * Show some popup text when a feature is clicked on\n * @param feature\n * @param layer\n */\nvar onFeaturePointClick = function onFeaturePointClick(feature, layer) {\n var popup_html = '';\n if (feature.properties && feature.properties.popup) {\n popup_html += feature.properties.popup;\n }\n\n layer.bindPopup(popup_html);\n};\n\n/**\n * Show each point as a marker\n * @param feature\n * @param latlng\n * @returns {*}\n */\nvar pointToLayer = function pointToLayer(feature, latlng) {\n return leaflet.circleMarker(latlng, {\n radius: 5,\n fillColor: __WEBPACK_IMPORTED_MODULE_2__config__[\"b\" /* CIRCLE_COLOR */],\n color: '#000',\n weight: 1,\n opacity: 1,\n fillOpacity: 0.8\n });\n};\n\n/**\n *\n * @param opts\n * @private\n */\n/* harmony default export */ __webpack_exports__[\"a\"] = (function (opts) {\n\n opts = Object.assign({\n\n route_points: null,\n planned_route_line: null,\n actual_route_points: null,\n actual_route_line: null,\n render_elem: 'map',\n live_map: false,\n aircraft_icon: '/assets/img/acars/aircraft.png',\n metar_wms: {\n url: '',\n params: {}\n }\n }, opts);\n\n var aircraftIcon = leaflet.icon({\n iconUrl: opts.aircraft_icon,\n iconSize: [42, 42],\n iconAnchor: [21, 21]\n });\n\n var map = Object(__WEBPACK_IMPORTED_MODULE_0__base_map__[\"a\" /* default */])(opts);\n var layerLiveFlight = void 0;\n\n if (opts.metar_wms.url !== '') {\n Object(__WEBPACK_IMPORTED_MODULE_1__helpers__[\"a\" /* addWMSLayer */])(map, opts.metar_wms);\n }\n\n var geodesicLayer = leaflet.geodesic([], {\n weight: 4,\n opacity: 0.9,\n color: __WEBPACK_IMPORTED_MODULE_2__config__[\"c\" /* PLAN_ROUTE_COLOR */],\n steps: 50,\n wrap: false\n }).addTo(map);\n\n geodesicLayer.geoJson(opts.planned_route_line);\n\n try {\n map.fitBounds(geodesicLayer.getBounds());\n } catch (e) {\n console.log(e);\n }\n\n // Draw the route points after\n if (opts.route_points !== null) {\n var route_points = leaflet.geoJSON(opts.route_points, {\n onEachFeature: onFeaturePointClick,\n pointToLayer: pointToLayer,\n style: {\n 'color': __WEBPACK_IMPORTED_MODULE_2__config__[\"c\" /* PLAN_ROUTE_COLOR */],\n 'weight': 3,\n 'opacity': 0.65\n }\n });\n\n route_points.addTo(map);\n }\n\n /**\n * draw the actual route\n */\n\n if (opts.actual_route_line !== null && opts.actual_route_line.features.length > 0) {\n var _geodesicLayer = leaflet.geodesic([], {\n weight: 3,\n opacity: 0.9,\n color: __WEBPACK_IMPORTED_MODULE_2__config__[\"a\" /* ACTUAL_ROUTE_COLOR */],\n steps: 50,\n wrap: false\n }).addTo(map);\n\n _geodesicLayer.geoJson(opts.actual_route_line);\n\n try {\n map.fitBounds(_geodesicLayer.getBounds());\n } catch (e) {\n console.log(e);\n }\n }\n\n if (opts.actual_route_points !== null && opts.actual_route_points.features.length > 0) {\n var _route_points = leaflet.geoJSON(opts.actual_route_points, {\n onEachFeature: onFeaturePointClick,\n pointToLayer: pointToLayer,\n style: {\n 'color': __WEBPACK_IMPORTED_MODULE_2__config__[\"a\" /* ACTUAL_ROUTE_COLOR */],\n 'weight': 3,\n 'opacity': 0.65\n }\n });\n\n _route_points.addTo(map);\n }\n\n /**\n *\n */\n var liveFlight = function liveFlight() {\n var uri = opts.pirep_uri;\n var live_route = $.ajax({\n url: uri,\n dataType: 'json',\n error: console.log\n });\n\n $.when(live_route).done(function (routeJson) {\n layerLiveFlight = leaflet.geoJSON(routeJson, {\n pointToLayer: function pointToLayer(feature, latlon) {\n return leaflet.marker(latlon, {\n icon: aircraftIcon,\n rotationAngle: feature.properties.heading\n });\n }\n });\n\n layerLiveFlight.addTo(map);\n });\n };\n\n setInterval(liveFlight, 10000);\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9yb3V0ZV9tYXAuanM/YTc0NSJdLCJuYW1lcyI6WyJsZWFmbGV0IiwicmVxdWlyZSIsIm9uRmVhdHVyZVBvaW50Q2xpY2siLCJmZWF0dXJlIiwibGF5ZXIiLCJwb3B1cF9odG1sIiwicHJvcGVydGllcyIsInBvcHVwIiwiYmluZFBvcHVwIiwicG9pbnRUb0xheWVyIiwibGF0bG5nIiwiY2lyY2xlTWFya2VyIiwicmFkaXVzIiwiZmlsbENvbG9yIiwiQ0lSQ0xFX0NPTE9SIiwiY29sb3IiLCJ3ZWlnaHQiLCJvcGFjaXR5IiwiZmlsbE9wYWNpdHkiLCJvcHRzIiwiT2JqZWN0IiwiYXNzaWduIiwicm91dGVfcG9pbnRzIiwicGxhbm5lZF9yb3V0ZV9saW5lIiwiYWN0dWFsX3JvdXRlX3BvaW50cyIsImFjdHVhbF9yb3V0ZV9saW5lIiwicmVuZGVyX2VsZW0iLCJsaXZlX21hcCIsImFpcmNyYWZ0X2ljb24iLCJtZXRhcl93bXMiLCJ1cmwiLCJwYXJhbXMiLCJhaXJjcmFmdEljb24iLCJpY29uIiwiaWNvblVybCIsImljb25TaXplIiwiaWNvbkFuY2hvciIsIm1hcCIsImRyYXdfYmFzZV9tYXAiLCJsYXllckxpdmVGbGlnaHQiLCJhZGRXTVNMYXllciIsImdlb2Rlc2ljTGF5ZXIiLCJnZW9kZXNpYyIsIlBMQU5fUk9VVEVfQ09MT1IiLCJzdGVwcyIsIndyYXAiLCJhZGRUbyIsImdlb0pzb24iLCJmaXRCb3VuZHMiLCJnZXRCb3VuZHMiLCJlIiwiY29uc29sZSIsImxvZyIsImdlb0pTT04iLCJvbkVhY2hGZWF0dXJlIiwic3R5bGUiLCJmZWF0dXJlcyIsImxlbmd0aCIsIkFDVFVBTF9ST1VURV9DT0xPUiIsImxpdmVGbGlnaHQiLCJ1cmkiLCJwaXJlcF91cmkiLCJsaXZlX3JvdXRlIiwiJCIsImFqYXgiLCJkYXRhVHlwZSIsImVycm9yIiwid2hlbiIsImRvbmUiLCJyb3V0ZUpzb24iLCJsYXRsb24iLCJtYXJrZXIiLCJyb3RhdGlvbkFuZ2xlIiwiaGVhZGluZyIsInNldEludGVydmFsIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsSUFBTUEsVUFBVUMsbUJBQU9BLENBQUMsNENBQVIsQ0FBaEI7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7Ozs7QUFLTyxJQUFNQyxzQkFBc0IsU0FBdEJBLG1CQUFzQixDQUFDQyxPQUFELEVBQVVDLEtBQVYsRUFBb0I7QUFDbkQsUUFBSUMsYUFBYSxFQUFqQjtBQUNBLFFBQUlGLFFBQVFHLFVBQVIsSUFBc0JILFFBQVFHLFVBQVIsQ0FBbUJDLEtBQTdDLEVBQW9EO0FBQ2hERixzQkFBY0YsUUFBUUcsVUFBUixDQUFtQkMsS0FBakM7QUFDSDs7QUFFREgsVUFBTUksU0FBTixDQUFnQkgsVUFBaEI7QUFDSCxDQVBNOztBQVNQOzs7Ozs7QUFNTyxJQUFNSSxlQUFlLFNBQWZBLFlBQWUsQ0FBQ04sT0FBRCxFQUFVTyxNQUFWLEVBQXFCO0FBQzdDLFdBQU9WLFFBQVFXLFlBQVIsQ0FBcUJELE1BQXJCLEVBQTZCO0FBQ2hDRSxnQkFBUSxDQUR3QjtBQUVoQ0MsbUJBQVdDLDZEQUZxQjtBQUdoQ0MsZUFBTyxNQUh5QjtBQUloQ0MsZ0JBQVEsQ0FKd0I7QUFLaENDLGlCQUFTLENBTHVCO0FBTWhDQyxxQkFBYTtBQU5tQixLQUE3QixDQUFQO0FBUUgsQ0FUTTs7QUFXUDs7Ozs7QUFLZSxtRUFBQ0MsSUFBRCxFQUFVOztBQUVyQkEsV0FBT0MsT0FBT0MsTUFBUCxDQUFjOztBQUVqQkMsc0JBQWMsSUFGRztBQUdqQkMsNEJBQW9CLElBSEg7QUFJakJDLDZCQUFxQixJQUpKO0FBS2pCQywyQkFBbUIsSUFMRjtBQU1qQkMscUJBQWEsS0FOSTtBQU9qQkMsa0JBQVUsS0FQTztBQVFqQkMsdUJBQWUsZ0NBUkU7QUFTakJDLG1CQUFXO0FBQ1BDLGlCQUFLLEVBREU7QUFFUEMsb0JBQVE7QUFGRDtBQVRNLEtBQWQsRUFhSlosSUFiSSxDQUFQOztBQWVBLFFBQU1hLGVBQWVoQyxRQUFRaUMsSUFBUixDQUFhO0FBQzlCQyxpQkFBU2YsS0FBS1MsYUFEZ0I7QUFFOUJPLGtCQUFVLENBQUMsRUFBRCxFQUFLLEVBQUwsQ0FGb0I7QUFHOUJDLG9CQUFZLENBQUMsRUFBRCxFQUFLLEVBQUw7QUFIa0IsS0FBYixDQUFyQjs7QUFNQSxRQUFJQyxNQUFNQyxrRUFBYUEsQ0FBQ25CLElBQWQsQ0FBVjtBQUNBLFFBQUlvQix3QkFBSjs7QUFFQSxRQUFJcEIsS0FBS1UsU0FBTCxDQUFlQyxHQUFmLEtBQXVCLEVBQTNCLEVBQStCO0FBQzNCVSw2RUFBV0EsQ0FBQ0gsR0FBWixFQUFpQmxCLEtBQUtVLFNBQXRCO0FBQ0g7O0FBRUQsUUFBSVksZ0JBQWdCekMsUUFBUTBDLFFBQVIsQ0FBaUIsRUFBakIsRUFBcUI7QUFDckMxQixnQkFBUSxDQUQ2QjtBQUVyQ0MsaUJBQVMsR0FGNEI7QUFHckNGLGVBQU80QixpRUFIOEI7QUFJckNDLGVBQU8sRUFKOEI7QUFLckNDLGNBQU07QUFMK0IsS0FBckIsRUFNakJDLEtBTmlCLENBTVhULEdBTlcsQ0FBcEI7O0FBUUFJLGtCQUFjTSxPQUFkLENBQXNCNUIsS0FBS0ksa0JBQTNCOztBQUVBLFFBQUk7QUFDQWMsWUFBSVcsU0FBSixDQUFjUCxjQUFjUSxTQUFkLEVBQWQ7QUFDSCxLQUZELENBRUUsT0FBT0MsQ0FBUCxFQUFVO0FBQ1JDLGdCQUFRQyxHQUFSLENBQVlGLENBQVo7QUFDSDs7QUFFRDtBQUNBLFFBQUkvQixLQUFLRyxZQUFMLEtBQXNCLElBQTFCLEVBQWdDO0FBQzVCLFlBQUlBLGVBQWV0QixRQUFRcUQsT0FBUixDQUFnQmxDLEtBQUtHLFlBQXJCLEVBQW1DO0FBQ2xEZ0MsMkJBQWVwRCxtQkFEbUM7QUFFbERPLDBCQUFjQSxZQUZvQztBQUdsRDhDLG1CQUFPO0FBQ0gseUJBQVNaLGlFQUROO0FBRUgsMEJBQVUsQ0FGUDtBQUdILDJCQUFXO0FBSFI7QUFIMkMsU0FBbkMsQ0FBbkI7O0FBVUFyQixxQkFBYXdCLEtBQWIsQ0FBbUJULEdBQW5CO0FBQ0g7O0FBRUQ7Ozs7QUFJQSxRQUFJbEIsS0FBS00saUJBQUwsS0FBMkIsSUFBM0IsSUFBbUNOLEtBQUtNLGlCQUFMLENBQXVCK0IsUUFBdkIsQ0FBZ0NDLE1BQWhDLEdBQXlDLENBQWhGLEVBQW1GO0FBQy9FLFlBQUloQixpQkFBZ0J6QyxRQUFRMEMsUUFBUixDQUFpQixFQUFqQixFQUFxQjtBQUNyQzFCLG9CQUFRLENBRDZCO0FBRXJDQyxxQkFBUyxHQUY0QjtBQUdyQ0YsbUJBQU8yQyxtRUFIOEI7QUFJckNkLG1CQUFPLEVBSjhCO0FBS3JDQyxrQkFBTTtBQUwrQixTQUFyQixFQU1qQkMsS0FOaUIsQ0FNWFQsR0FOVyxDQUFwQjs7QUFRQUksdUJBQWNNLE9BQWQsQ0FBc0I1QixLQUFLTSxpQkFBM0I7O0FBRUEsWUFBSTtBQUNBWSxnQkFBSVcsU0FBSixDQUFjUCxlQUFjUSxTQUFkLEVBQWQ7QUFDSCxTQUZELENBRUUsT0FBT0MsQ0FBUCxFQUFVO0FBQ1JDLG9CQUFRQyxHQUFSLENBQVlGLENBQVo7QUFDSDtBQUNKOztBQUVELFFBQUkvQixLQUFLSyxtQkFBTCxLQUE2QixJQUE3QixJQUFxQ0wsS0FBS0ssbUJBQUwsQ0FBeUJnQyxRQUF6QixDQUFrQ0MsTUFBbEMsR0FBMkMsQ0FBcEYsRUFBdUY7QUFDbkYsWUFBSW5DLGdCQUFldEIsUUFBUXFELE9BQVIsQ0FBZ0JsQyxLQUFLSyxtQkFBckIsRUFBMEM7QUFDekQ4QiwyQkFBZXBELG1CQUQwQztBQUV6RE8sMEJBQWNBLFlBRjJDO0FBR3pEOEMsbUJBQU87QUFDSCx5QkFBU0csbUVBRE47QUFFSCwwQkFBVSxDQUZQO0FBR0gsMkJBQVc7QUFIUjtBQUhrRCxTQUExQyxDQUFuQjs7QUFVQXBDLHNCQUFhd0IsS0FBYixDQUFtQlQsR0FBbkI7QUFDSDs7QUFFRDs7O0FBR0EsUUFBTXNCLGFBQWEsU0FBYkEsVUFBYSxHQUFNO0FBQ3JCLFlBQU1DLE1BQU16QyxLQUFLMEMsU0FBakI7QUFDQSxZQUFNQyxhQUFhQyxFQUFFQyxJQUFGLENBQU87QUFDdEJsQyxpQkFBSzhCLEdBRGlCO0FBRXRCSyxzQkFBVSxNQUZZO0FBR3RCQyxtQkFBT2YsUUFBUUM7QUFITyxTQUFQLENBQW5COztBQU1BVyxVQUFFSSxJQUFGLENBQU9MLFVBQVAsRUFBbUJNLElBQW5CLENBQXdCLFVBQUNDLFNBQUQsRUFBZTtBQUNuQzlCLDhCQUFrQnZDLFFBQVFxRCxPQUFSLENBQWdCZ0IsU0FBaEIsRUFBMkI7QUFDekM1RCw4QkFBYyxzQkFBVU4sT0FBVixFQUFtQm1FLE1BQW5CLEVBQTJCO0FBQ3JDLDJCQUFPdEUsUUFBUXVFLE1BQVIsQ0FBZUQsTUFBZixFQUF1QjtBQUMxQnJDLDhCQUFNRCxZQURvQjtBQUUxQndDLHVDQUFlckUsUUFBUUcsVUFBUixDQUFtQm1FO0FBRlIscUJBQXZCLENBQVA7QUFJSDtBQU53QyxhQUEzQixDQUFsQjs7QUFTQWxDLDRCQUFnQk8sS0FBaEIsQ0FBc0JULEdBQXRCO0FBQ0gsU0FYRDtBQVlILEtBcEJEOztBQXNCQXFDLGdCQUFZZixVQUFaLEVBQXdCLEtBQXhCO0FBQ0gsQ0EzSEQiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvbWFwcy9yb3V0ZV9tYXAuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBsZWFmbGV0ID0gcmVxdWlyZSgnbGVhZmxldCcpO1xuXG5pbXBvcnQgZHJhd19iYXNlX21hcCBmcm9tICcuL2Jhc2VfbWFwJ1xuaW1wb3J0IHthZGRXTVNMYXllcn0gZnJvbSAnLi9oZWxwZXJzJztcblxuaW1wb3J0IHtBQ1RVQUxfUk9VVEVfQ09MT1IsIENJUkNMRV9DT0xPUiwgUExBTl9ST1VURV9DT0xPUn0gZnJvbSAnLi9jb25maWcnXG5cbi8qKlxuICogU2hvdyBzb21lIHBvcHVwIHRleHQgd2hlbiBhIGZlYXR1cmUgaXMgY2xpY2tlZCBvblxuICogQHBhcmFtIGZlYXR1cmVcbiAqIEBwYXJhbSBsYXllclxuICovXG5leHBvcnQgY29uc3Qgb25GZWF0dXJlUG9pbnRDbGljayA9IChmZWF0dXJlLCBsYXllcikgPT4ge1xuICAgIGxldCBwb3B1cF9odG1sID0gJyc7XG4gICAgaWYgKGZlYXR1cmUucHJvcGVydGllcyAmJiBmZWF0dXJlLnByb3BlcnRpZXMucG9wdXApIHtcbiAgICAgICAgcG9wdXBfaHRtbCArPSBmZWF0dXJlLnByb3BlcnRpZXMucG9wdXBcbiAgICB9XG5cbiAgICBsYXllci5iaW5kUG9wdXAocG9wdXBfaHRtbClcbn07XG5cbi8qKlxuICogU2hvdyBlYWNoIHBvaW50IGFzIGEgbWFya2VyXG4gKiBAcGFyYW0gZmVhdHVyZVxuICogQHBhcmFtIGxhdGxuZ1xuICogQHJldHVybnMgeyp9XG4gKi9cbmV4cG9ydCBjb25zdCBwb2ludFRvTGF5ZXIgPSAoZmVhdHVyZSwgbGF0bG5nKSA9PiB7XG4gICAgcmV0dXJuIGxlYWZsZXQuY2lyY2xlTWFya2VyKGxhdGxuZywge1xuICAgICAgICByYWRpdXM6IDUsXG4gICAgICAgIGZpbGxDb2xvcjogQ0lSQ0xFX0NPTE9SLFxuICAgICAgICBjb2xvcjogJyMwMDAnLFxuICAgICAgICB3ZWlnaHQ6IDEsXG4gICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgIGZpbGxPcGFjaXR5OiAwLjhcbiAgICB9KVxufVxuXG4vKipcbiAqXG4gKiBAcGFyYW0gb3B0c1xuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGRlZmF1bHQgKG9wdHMpID0+IHtcblxuICAgIG9wdHMgPSBPYmplY3QuYXNzaWduKHtcblxuICAgICAgICByb3V0ZV9wb2ludHM6IG51bGwsXG4gICAgICAgIHBsYW5uZWRfcm91dGVfbGluZTogbnVsbCxcbiAgICAgICAgYWN0dWFsX3JvdXRlX3BvaW50czogbnVsbCxcbiAgICAgICAgYWN0dWFsX3JvdXRlX2xpbmU6IG51bGwsXG4gICAgICAgIHJlbmRlcl9lbGVtOiAnbWFwJyxcbiAgICAgICAgbGl2ZV9tYXA6IGZhbHNlLFxuICAgICAgICBhaXJjcmFmdF9pY29uOiAnL2Fzc2V0cy9pbWcvYWNhcnMvYWlyY3JhZnQucG5nJyxcbiAgICAgICAgbWV0YXJfd21zOiB7XG4gICAgICAgICAgICB1cmw6ICcnLFxuICAgICAgICAgICAgcGFyYW1zOiB7fVxuICAgICAgICB9LFxuICAgIH0sIG9wdHMpO1xuXG4gICAgY29uc3QgYWlyY3JhZnRJY29uID0gbGVhZmxldC5pY29uKHtcbiAgICAgICAgaWNvblVybDogb3B0cy5haXJjcmFmdF9pY29uLFxuICAgICAgICBpY29uU2l6ZTogWzQyLCA0Ml0sXG4gICAgICAgIGljb25BbmNob3I6IFsyMSwgMjFdLFxuICAgIH0pO1xuXG4gICAgbGV0IG1hcCA9IGRyYXdfYmFzZV9tYXAob3B0cyk7XG4gICAgbGV0IGxheWVyTGl2ZUZsaWdodDtcblxuICAgIGlmIChvcHRzLm1ldGFyX3dtcy51cmwgIT09ICcnKSB7XG4gICAgICAgIGFkZFdNU0xheWVyKG1hcCwgb3B0cy5tZXRhcl93bXMpO1xuICAgIH1cblxuICAgIGxldCBnZW9kZXNpY0xheWVyID0gbGVhZmxldC5nZW9kZXNpYyhbXSwge1xuICAgICAgICB3ZWlnaHQ6IDQsXG4gICAgICAgIG9wYWNpdHk6IDAuOSxcbiAgICAgICAgY29sb3I6IFBMQU5fUk9VVEVfQ09MT1IsXG4gICAgICAgIHN0ZXBzOiA1MCxcbiAgICAgICAgd3JhcDogZmFsc2UsXG4gICAgfSkuYWRkVG8obWFwKTtcblxuICAgIGdlb2Rlc2ljTGF5ZXIuZ2VvSnNvbihvcHRzLnBsYW5uZWRfcm91dGVfbGluZSk7XG5cbiAgICB0cnkge1xuICAgICAgICBtYXAuZml0Qm91bmRzKGdlb2Rlc2ljTGF5ZXIuZ2V0Qm91bmRzKCkpXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhlKVxuICAgIH1cblxuICAgIC8vIERyYXcgdGhlIHJvdXRlIHBvaW50cyBhZnRlclxuICAgIGlmIChvcHRzLnJvdXRlX3BvaW50cyAhPT0gbnVsbCkge1xuICAgICAgICBsZXQgcm91dGVfcG9pbnRzID0gbGVhZmxldC5nZW9KU09OKG9wdHMucm91dGVfcG9pbnRzLCB7XG4gICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBvbkZlYXR1cmVQb2ludENsaWNrLFxuICAgICAgICAgICAgcG9pbnRUb0xheWVyOiBwb2ludFRvTGF5ZXIsXG4gICAgICAgICAgICBzdHlsZToge1xuICAgICAgICAgICAgICAgICdjb2xvcic6IFBMQU5fUk9VVEVfQ09MT1IsXG4gICAgICAgICAgICAgICAgJ3dlaWdodCc6IDMsXG4gICAgICAgICAgICAgICAgJ29wYWNpdHknOiAwLjY1LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcm91dGVfcG9pbnRzLmFkZFRvKG1hcCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogZHJhdyB0aGUgYWN0dWFsIHJvdXRlXG4gICAgICovXG5cbiAgICBpZiAob3B0cy5hY3R1YWxfcm91dGVfbGluZSAhPT0gbnVsbCAmJiBvcHRzLmFjdHVhbF9yb3V0ZV9saW5lLmZlYXR1cmVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbGV0IGdlb2Rlc2ljTGF5ZXIgPSBsZWFmbGV0Lmdlb2Rlc2ljKFtdLCB7XG4gICAgICAgICAgICB3ZWlnaHQ6IDMsXG4gICAgICAgICAgICBvcGFjaXR5OiAwLjksXG4gICAgICAgICAgICBjb2xvcjogQUNUVUFMX1JPVVRFX0NPTE9SLFxuICAgICAgICAgICAgc3RlcHM6IDUwLFxuICAgICAgICAgICAgd3JhcDogZmFsc2UsXG4gICAgICAgIH0pLmFkZFRvKG1hcCk7XG5cbiAgICAgICAgZ2VvZGVzaWNMYXllci5nZW9Kc29uKG9wdHMuYWN0dWFsX3JvdXRlX2xpbmUpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBtYXAuZml0Qm91bmRzKGdlb2Rlc2ljTGF5ZXIuZ2V0Qm91bmRzKCkpXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGUpXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAob3B0cy5hY3R1YWxfcm91dGVfcG9pbnRzICE9PSBudWxsICYmIG9wdHMuYWN0dWFsX3JvdXRlX3BvaW50cy5mZWF0dXJlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGxldCByb3V0ZV9wb2ludHMgPSBsZWFmbGV0Lmdlb0pTT04ob3B0cy5hY3R1YWxfcm91dGVfcG9pbnRzLCB7XG4gICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiBvbkZlYXR1cmVQb2ludENsaWNrLFxuICAgICAgICAgICAgcG9pbnRUb0xheWVyOiBwb2ludFRvTGF5ZXIsXG4gICAgICAgICAgICBzdHlsZToge1xuICAgICAgICAgICAgICAgICdjb2xvcic6IEFDVFVBTF9ST1VURV9DT0xPUixcbiAgICAgICAgICAgICAgICAnd2VpZ2h0JzogMyxcbiAgICAgICAgICAgICAgICAnb3BhY2l0eSc6IDAuNjUsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICByb3V0ZV9wb2ludHMuYWRkVG8obWFwKVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqXG4gICAgICovXG4gICAgY29uc3QgbGl2ZUZsaWdodCA9ICgpID0+IHtcbiAgICAgICAgY29uc3QgdXJpID0gb3B0cy5waXJlcF91cmk7XG4gICAgICAgIGNvbnN0IGxpdmVfcm91dGUgPSAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiB1cmksXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgZXJyb3I6IGNvbnNvbGUubG9nXG4gICAgICAgIH0pO1xuXG4gICAgICAgICQud2hlbihsaXZlX3JvdXRlKS5kb25lKChyb3V0ZUpzb24pID0+IHtcbiAgICAgICAgICAgIGxheWVyTGl2ZUZsaWdodCA9IGxlYWZsZXQuZ2VvSlNPTihyb3V0ZUpzb24sIHtcbiAgICAgICAgICAgICAgICBwb2ludFRvTGF5ZXI6IGZ1bmN0aW9uIChmZWF0dXJlLCBsYXRsb24pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxlYWZsZXQubWFya2VyKGxhdGxvbiwge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWNvbjogYWlyY3JhZnRJY29uLFxuICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb25BbmdsZTogZmVhdHVyZS5wcm9wZXJ0aWVzLmhlYWRpbmdcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgbGF5ZXJMaXZlRmxpZ2h0LmFkZFRvKG1hcClcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHNldEludGVydmFsKGxpdmVGbGlnaHQsIDEwMDAwKTtcbn07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9yZXNvdXJjZXMvanMvbWFwcy9yb3V0ZV9tYXAuanMiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./resources/js/maps/route_map.js\n");
/***/ }),
/***/ "./resources/sass/admin/paper-dashboard.scss":
/***/ (function(module, exports) {
eval("// removed by extract-text-webpack-plugin//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvc2Fzcy9hZG1pbi9wYXBlci1kYXNoYm9hcmQuc2Nzcz9lNGZhIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIiwiZmlsZSI6Ii4vcmVzb3VyY2VzL3Nhc3MvYWRtaW4vcGFwZXItZGFzaGJvYXJkLnNjc3MuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyByZW1vdmVkIGJ5IGV4dHJhY3QtdGV4dC13ZWJwYWNrLXBsdWdpblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vcmVzb3VyY2VzL3Nhc3MvYWRtaW4vcGFwZXItZGFzaGJvYXJkLnNjc3Ncbi8vIG1vZHVsZSBpZCA9IC4vcmVzb3VyY2VzL3Nhc3MvYWRtaW4vcGFwZXItZGFzaGJvYXJkLnNjc3Ncbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./resources/sass/admin/paper-dashboard.scss\n");
/***/ }),
/***/ "./resources/sass/now-ui/now-ui-kit.scss":
/***/ (function(module, exports) {
eval("// removed by extract-text-webpack-plugin//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvc2Fzcy9ub3ctdWkvbm93LXVpLWtpdC5zY3NzPzMzODkiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEiLCJmaWxlIjoiLi9yZXNvdXJjZXMvc2Fzcy9ub3ctdWkvbm93LXVpLWtpdC5zY3NzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gcmVtb3ZlZCBieSBleHRyYWN0LXRleHQtd2VicGFjay1wbHVnaW5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3Jlc291cmNlcy9zYXNzL25vdy11aS9ub3ctdWkta2l0LnNjc3Ncbi8vIG1vZHVsZSBpZCA9IC4vcmVzb3VyY2VzL3Nhc3Mvbm93LXVpL25vdy11aS1raXQuc2Nzc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./resources/sass/now-ui/now-ui-kit.scss\n");
/***/ }),
/***/ 0:
/***/ (function(module, exports, __webpack_require__) {
__webpack_require__("./resources/js/frontend/app.js");
__webpack_require__("./resources/sass/now-ui/now-ui-kit.scss");
module.exports = __webpack_require__("./resources/sass/admin/paper-dashboard.scss");
/***/ })
/******/ });