phpvms/public/assets/frontend/js/app.js
2018-05-04 13:59:47 -05:00

432 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvTGVhZmxldC5HZW9kZXNpYy9MZWFmbGV0Lkdlb2Rlc2ljLmpzPzU3NGMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0QkFBNEI7O0FBRTVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxzQkFBc0I7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUCxrQkFBa0IsNkJBQTZCO0FBQy9DO0FBQ0Esc0JBQXNCLDJDQUEyQztBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLDRCQUE0QjtBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLHNCQUFzQjtBQUN0QjtBQUNBO0FBQ0E7O0FBRUEsc0JBQXNCLHVCQUF1QjtBQUM3QztBQUNBO0FBQ0EsMEJBQTBCLHFDQUFxQztBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHlCQUF5QjtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEIsc0JBQXNCO0FBQ3RCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDREQUE0RDtBQUM1RCxLQUFLO0FBQ0wsb0JBQW9CO0FBQ3BCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCLGVBQWUsT0FBTztBQUN0QixjQUFjLE1BQU07QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQztBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBEQUEwRDtBQUMxRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSw2REFBNkQ7QUFDN0QsNkRBQTZEOztBQUU3RCw0REFBNEQ7QUFDNUQscURBQXFEOztBQUVyRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0RBQXNEOztBQUV0RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9MZWFmbGV0Lkdlb2Rlc2ljL0xlYWZsZXQuR2VvZGVzaWMuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJcInVzZSBzdHJpY3RcIjtcblxuLy8gVGhpcyBmaWxlIGlzIHBhcnQgb2YgTGVhZmxldC5HZW9kZXNpYy5cbi8vIENvcHlyaWdodCAoQykgMjAxNyAgSGVucnkgVGhhc2xlclxuLy8gYmFzZWQgb24gY29kZSBieSBDaHJpcyBWZW5lc3MgQ29weXJpZ2h0IChDKSAyMDE0IGh0dHBzOi8vZ2l0aHViLmNvbS9jaHJpc3ZlbmVzcy9nZW9kZXN5XG4vL1xuLy8gTGVhZmxldC5HZW9kZXNpYyBpcyBmcmVlIHNvZnR3YXJlOiB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3IgbW9kaWZ5XG4vLyBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieVxuLy8gdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3Jcbi8vIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vL1xuLy8gTGVhZmxldC5HZW9kZXNpYyBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbi8vIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vL1xuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2Vcbi8vIGFsb25nIHdpdGggTGVhZmxldC5HZW9kZXNpYy4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cblxuXG4vKiogRXh0ZW5kIE51bWJlciBvYmplY3Qgd2l0aCBtZXRob2QgdG8gY29udmVydCBudW1lcmljIGRlZ3JlZXMgdG8gcmFkaWFucyAqL1xuaWYgKHR5cGVvZiBOdW1iZXIucHJvdG90eXBlLnRvUmFkaWFucyA9PT0gXCJ1bmRlZmluZWRcIikge1xuICBOdW1iZXIucHJvdG90eXBlLnRvUmFkaWFucyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzICogTWF0aC5QSSAvIDE4MDtcbiAgfTtcbn1cblxuLyoqIEV4dGVuZCBOdW1iZXIgb2JqZWN0IHdpdGggbWV0aG9kIHRvIGNvbnZlcnQgcmFkaWFucyB0byBudW1lcmljIChzaWduZWQpIGRlZ3JlZXMgKi9cbmlmICh0eXBlb2YgTnVtYmVyLnByb3RvdHlwZS50b0RlZ3JlZXMgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgTnVtYmVyLnByb3RvdHlwZS50b0RlZ3JlZXMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcyAqIDE4MCAvIE1hdGguUEk7XG4gIH07XG59XG5cbnZhciBJTlRFUlNFQ1RfTE5HID0gMTc5Ljk5OTsgLy8gTG5nIHVzZWQgZm9yIGludGVyc2VjdGlvbiBhbmQgd3JhcCBhcm91bmQgb24gbWFwIGVkZ2VzXG5cbkwuR2VvZGVzaWMgPSBMLlBvbHlsaW5lLmV4dGVuZCh7XG4gIG9wdGlvbnM6IHtcbiAgICBjb2xvcjogXCJibHVlXCIsXG4gICAgc3RlcHM6IDEwLFxuICAgIGRhc2g6IDEsXG4gICAgd3JhcDogdHJ1ZVxuICB9LFxuXG4gIGluaXRpYWxpemU6IGZ1bmN0aW9uKGxhdGxuZ3MsIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSB0aGlzLl9tZXJnZV9vcHRpb25zKHRoaXMub3B0aW9ucywgb3B0aW9ucyk7XG4gICAgdGhpcy5vcHRpb25zLmRhc2ggPSBNYXRoLm1heCgxZS0zLCBNYXRoLm1pbigxLCBwYXJzZUZsb2F0KHRoaXMub3B0aW9ucy5kYXNoKSB8fCAxKSk7XG4gICAgdGhpcy5kYXR1bSA9IHt9O1xuICAgIHRoaXMuZGF0dW0uZWxsaXBzb2lkID0ge1xuICAgICAgICBhOiA2Mzc4MTM3LFxuICAgICAgICBiOiA2MzU2NzUyLjMxNDIsXG4gICAgICAgIGY6IDEgLyAyOTguMjU3MjIzNTYzXG4gICAgICB9OyAvLyBXR1MtODRcbiAgICB0aGlzLl9sYXRsbmdzID0gdGhpcy5fZ2VuZXJhdGVfR2VvZGVzaWMobGF0bG5ncyk7XG4gICAgTC5Qb2x5bGluZS5wcm90b3R5cGUuaW5pdGlhbGl6ZS5jYWxsKHRoaXMsIHRoaXMuX2xhdGxuZ3MsIHRoaXMub3B0aW9ucyk7XG4gIH0sXG5cbiAgc2V0TGF0TG5nczogZnVuY3Rpb24obGF0bG5ncykge1xuICAgIHRoaXMuX2xhdGxuZ3MgPSB0aGlzLl9nZW5lcmF0ZV9HZW9kZXNpYyhsYXRsbmdzKTtcbiAgICBMLlBvbHlsaW5lLnByb3RvdHlwZS5zZXRMYXRMbmdzLmNhbGwodGhpcywgdGhpcy5fbGF0bG5ncyk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgc29tZSBzdGF0aXN0aWMgdmFsdWVzIG9mIGN1cnJlbnQgZ2VvZGVzaWMgbXVsdGlwb2x5bGluZVxuICAgKiBAcmV0dXJucyAoT2JqZWN0fSBPYmplY3Qgd2l0aCBzZXZlcmFsIHByb3BlcnRpZXMgKGUuZy4gb3ZlcmFsbCBkaXN0YW5jZSlcbiAgICovXG4gIGdldFN0YXRzOiBmdW5jdGlvbigpIHtcbiAgICBsZXQgb2JqID0ge1xuICAgICAgICBkaXN0YW5jZTogMCxcbiAgICAgICAgcG9pbnRzOiAwLFxuICAgICAgICBwb2x5Z29uczogdGhpcy5fbGF0bG5ncy5sZW5ndGhcbiAgICAgIH0sIHBvbHksIHBvaW50cztcblxuICAgIGZvciAocG9seSA9IDA7IHBvbHkgPCB0aGlzLl9sYXRsbmdzLmxlbmd0aDsgcG9seSsrKSB7XG4gICAgICBvYmoucG9pbnRzICs9IHRoaXMuX2xhdGxuZ3NbcG9seV0ubGVuZ3RoO1xuICAgICAgZm9yIChwb2ludHMgPSAwOyBwb2ludHMgPCAodGhpcy5fbGF0bG5nc1twb2x5XS5sZW5ndGggLSAxKTsgcG9pbnRzKyspIHtcbiAgICAgICAgb2JqLmRpc3RhbmNlICs9IHRoaXMuX3ZpbmNlbnR5X2ludmVyc2UodGhpcy5fbGF0bG5nc1twb2x5XVtwb2ludHNdLFxuICAgICAgICAgIHRoaXMuX2xhdGxuZ3NbcG9seV1bcG9pbnRzICsgMV0pLmRpc3RhbmNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gb2JqO1xuICB9LFxuXG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgZ2VvZGVzaWMgbGluZXMgZnJvbSBnZW9Kc29uLiBSZXBsYWNlcyBhbGwgY3VycmVudCBmZWF0dXJlcyBvZiB0aGlzIGluc3RhbmNlLlxuICAgKiBTdXBwb3J0cyBMaW5lU3RyaW5nLCBNdWx0aUxpbmVTdHJpbmcgYW5kIFBvbHlnb25cbiAgICogQHBhcmFtIHtPYmplY3R9IGdlb2pzb24gLSBnZW9zam9uIGFzIG9iamVjdC5cbiAgICovXG4gIGdlb0pzb246IGZ1bmN0aW9uKGdlb2pzb24pIHtcblxuICAgIGxldCBub3JtYWxpemVkID0gTC5HZW9KU09OLmFzRmVhdHVyZShnZW9qc29uKTtcbiAgICBsZXQgZmVhdHVyZXMgPSBub3JtYWxpemVkLnR5cGUgPT09IFwiRmVhdHVyZUNvbGxlY3Rpb25cIiA/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/OWFkNSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9pbmRleC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9saWIvYXhpb3MnKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9pbmRleC5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvaW5kZXguanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\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\");\nvar btoa = (typeof window !== 'undefined' && window.btoa && window.btoa.bind(window)) || __webpack_require__(\"./node_modules/axios/lib/helpers/btoa.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 var loadEvent = 'onreadystatechange';\n var xDomain = false;\n\n // For IE 8/9 CORS support\n // Only supports POST and GET calls and doesn't returns the response headers.\n // DON'T do this for testing b/c XMLHttpRequest is mocked, not XDomainRequest.\n if (\"development\" !== 'test' &&\n typeof window !== 'undefined' &&\n window.XDomainRequest && !('withCredentials' in request) &&\n !isURLSameOrigin(config.url)) {\n request = new window.XDomainRequest();\n loadEvent = 'onload';\n xDomain = true;\n request.onprogress = function handleProgress() {};\n request.ontimeout = function handleTimeout() {};\n }\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[loadEvent] = function handleLoad() {\n if (!request || (request.readyState !== 4 && !xDomain)) {\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 // IE sends 1223 instead of 204 (https://github.com/axios/axios/issues/201)\n status: request.status === 1223 ? 204 : request.status,\n statusText: request.status === 1223 ? 'No Content' : 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2FkYXB0ZXJzL3hoci5qcz9lYzZjIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNENBQTRDO0FBQzVDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0giLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2FkYXB0ZXJzL3hoci5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzID0gcmVxdWlyZSgnLi8uLi91dGlscycpO1xudmFyIHNldHRsZSA9IHJlcXVpcmUoJy4vLi4vY29yZS9zZXR0bGUnKTtcbnZhciBidWlsZFVSTCA9IHJlcXVpcmUoJy4vLi4vaGVscGVycy9idWlsZFVSTCcpO1xudmFyIHBhcnNlSGVhZGVycyA9IHJlcXVpcmUoJy4vLi4vaGVscGVycy9wYXJzZUhlYWRlcnMnKTtcbnZhciBpc1VSTFNhbWVPcmlnaW4gPSByZXF1aXJlKCcuLy4uL2hlbHBlcnMvaXNVUkxTYW1lT3JpZ2luJyk7XG52YXIgY3JlYXRlRXJyb3IgPSByZXF1aXJlKCcuLi9jb3JlL2NyZWF0ZUVycm9yJyk7XG52YXIgYnRvYSA9ICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB3aW5kb3cuYnRvYSAmJiB3aW5kb3cuYnRvYS5iaW5kKHdpbmRvdykpIHx8IHJlcXVpcmUoJy4vLi4vaGVscGVycy9idG9hJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24geGhyQWRhcHRlcihjb25maWcpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIGRpc3BhdGNoWGhyUmVxdWVzdChyZXNvbHZlLCByZWplY3QpIHtcbiAgICB2YXIgcmVxdWVzdERhdGEgPSBjb25maWcuZGF0YTtcbiAgICB2YXIgcmVxdWVzdEhlYWRlcnMgPSBjb25maWcuaGVhZGVycztcblxuICAgIGlmICh1dGlscy5pc0Zvcm1EYXRhKHJlcXVlc3REYXRhKSkge1xuICAgICAgZGVsZXRlIHJlcXVlc3RIZWFkZXJzWydDb250ZW50LVR5cGUnXTsgLy8gTGV0IHRoZSBicm93c2VyIHNldCBpdFxuICAgIH1cblxuICAgIHZhciByZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgdmFyIGxvYWRFdmVudCA9ICdvbnJlYWR5c3RhdGVjaGFuZ2UnO1xuICAgIHZhciB4RG9tYWluID0gZmFsc2U7XG5cbiAgICAvLyBGb3IgSUUgOC85IENPUlMgc3VwcG9ydFxuICAgIC8vIE9ubHkgc3VwcG9ydHMgUE9TVCBhbmQgR0VUIGNhbGxzIGFuZCBkb2Vzbid0IHJldHVybnMgdGhlIHJlc3BvbnNlIGhlYWRlcnMuXG4gICAgLy8gRE9OJ1QgZG8gdGhpcyBmb3IgdGVzdGluZyBiL2MgWE1MSHR0cFJlcXVlc3QgaXMgbW9ja2VkLCBub3QgWERvbWFpblJlcXVlc3QuXG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAndGVzdCcgJiZcbiAgICAgICAgdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgd2luZG93LlhEb21haW5SZXF1ZXN0ICYmICEoJ3dpdGhDcmVkZW50aWFscycgaW4gcmVxdWVzdCkgJiZcbiAgICAgICAgIWlzVVJMU2FtZU9yaWdpbihjb25maWcudXJsKSkge1xuICAgICAgcmVxdWVzdCA9IG5ldyB3aW5kb3cuWERvbWFpblJlcXVlc3QoKTtcbiAgICAgIGxvYWRFdmVudCA9ICdvbmxvYWQnO1xuICAgICAgeERvbWFpbiA9IHRydWU7XG4gICAgICByZXF1ZXN0Lm9ucHJvZ3Jlc3MgPSBmdW5jdGlvbiBoYW5kbGVQcm9ncmVzcygpIHt9O1xuICAgICAgcmVxdWVzdC5vbnRpbWVvdXQgPSBmdW5jdGlvbiBoYW5kbGVUaW1lb3V0KCkge307XG4gICAgfVxuXG4gICAgLy8gSFRUUCBiYXNpYyBhdXRoZW50aWNhdGlvblxuICAgIGlmIChjb25maWcuYXV0aCkge1xuICAgICAgdmFyIHVzZXJuYW1lID0gY29uZmlnLmF1dGgudXNlcm5hbWUgfHwgJyc7XG4gICAgICB2YXIgcGFzc3dvcmQgPSBjb25maWcuYXV0aC5wYXNzd29yZCB8fCAnJztcbiAgICAgIHJlcXVlc3RIZWFkZXJzLkF1dGhvcml6YXRpb24gPSAnQmFzaWMgJyArIGJ0b2EodXNlcm5hbWUgKyAnOicgKyBwYXNzd29yZCk7XG4gICAgfVxuXG4gICAgcmVxdWVzdC5vcGVuKGNvbmZpZy5tZXRob2QudG9VcHBlckNhc2UoKSwgYnVpbGRVUkwoY29uZmlnLnVybCwgY29uZmlnLnBhcmFtcywgY29uZmlnLnBhcmFtc1NlcmlhbGl6ZXIpLCB0cnVlKTtcblxuICAgIC8vIFNldCB0aGUgcmVxdWVzdCB0aW1lb3V0IGluIE1TXG4gICAgcmVxdWVzdC50aW1lb3V0ID0gY29uZmlnLnRpbWVvdXQ7XG5cbiAgICAvLyBMaXN0ZW4gZm9yIHJlYWR5IHN0YXRlXG4gICAgcmVxdWVzdFtsb2FkRXZlbnRdID0gZnVuY3Rpb24gaGFuZGxlTG9hZCgpIHtcbiAgICAgIGlmICghcmVxdWVzdCB8fCAocmVxdWVzdC5yZWFkeVN0YXRlICE9PSA0ICYmICF4RG9tYWluKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIFRoZSByZXF1ZXN0IGVycm9yZWQgb3V0IGFuZCB3ZSBkaWRuJ3QgZ2V0IGEgcmVzcG9uc2UsIHRoaXMgd2lsbCBiZVxuICAgICAgLy8gaGFuZGxlZCBieSBvbmVycm9yIGluc3RlYWRcbiAgICAgIC8vIFdpdGggb25lIGV4Y2VwdGlvbjogcmVxdWVzdCB0aGF0IHVzaW5nIGZpbGU6IHByb3RvY29sLCBtb3N0IGJyb3dzZXJzXG4gICAgICAvLyB3aWxsIHJldHVybiBzdGF0dXMgYXMgMCBldmVuIHRob3VnaCBpdCdzIGEgc3VjY2Vzc2Z1bCByZXF1ZXN0XG4gICAgICBpZiAocmVxdWVzdC5zdGF0dXMgPT09IDAgJiYgIShyZXF1ZXN0LnJlc3BvbnNlVVJMICYmIHJlcXVlc3QucmVzcG9uc2VVUkwuaW5kZXhPZignZmlsZTonKSA9PT0gMCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBQcmVwYXJlIHRoZSByZXNwb25zZVxuICAgICAgdmFyIHJlc3BvbnNlSGVhZGVycyA9ICdnZXRBbGxSZXNwb25zZUhlYWRlcnMnIGluIHJlcXVlc3QgPyBwYXJzZUhlYWRlcnMocmVxdWVzdC5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKSkgOiBudWxsO1xuICAgICAgdmFyIHJlc3BvbnNlRGF0YSA9ICFjb25maWcucmVzcG9uc2VUeXBlIHx8IGNvbmZpZy5yZXNwb25zZVR5cGUgPT09ICd0ZXh0JyA/IHJlcXVlc3QucmVzcG9uc2VUZXh0IDogcmVxdWVzdC5yZXNwb25zZTtcbiAgICAgIHZhciByZXNwb25zZSA9IHtcbiAgICAgICAgZGF0YTogcmVzcG9uc2VEYXRhLFxuICAgICAgICAvLyBJRSBzZW5kcyAxMjIzIGluc3RlYWQgb2YgMjA0IChodHRwczovL2dpdGh1Yi5jb20vYXhpb3MvYXhpb3MvaXNzdWVzLzIwMSlcbiAgICAgICAgc3RhdHVzOiByZXF1ZXN0LnN0YXR1cyA9PT0gMTIyMyA/IDIwNCA6IHJlcXVlc3Quc3RhdHVzLFxuICAgICAgICBzdGF0dXNUZXh0OiByZXF1ZXN0LnN0YXR1cyA9PT0gMTIyMyA/ICdObyBDb250ZW50JyA6IHJlcXVlc3Quc3RhdHVzVGV4dCxcbiAgICAgICAgaGVhZGVyczogcmVzcG9uc2VIZWFkZXJzLFxuICAgICAgICBjb25maWc6IGNvbmZpZyxcbiAgICAgICAgcmVxdWVzdDogcmVxdWVzdFxuICAgICAgfTtcblxuICAgICAgc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgcmVzcG9uc2UpO1xuXG4gICAgICAvLyBDbGVhbiB1cCByZXF1ZXN0XG4gICAgICByZXF1ZXN0ID0gbnVsbDtcbiAgICB9O1xuXG4gICAgLy8gSGFuZGxlIGxvdyBsZXZlbCBuZXR3b3JrIGVycm9yc1xuICAgIHJlcXVlc3Qub25lcnJvciA9IGZ1bmN0aW9uIGhhbmRsZUVycm9yKCkge1xuICAgICAgLy8gUmVhbCBlcnJvcnMgYXJlIGhpZGRlbiBmcm9tIHVzIGJ5IHRoZSBicm93c2VyXG4gICAgICAvLyBvbmVycm9yIHNob3VsZCBvbmx5IGZpcmUgaWYgaXQncyBhIG5ldHdvcmsgZXJyb3JcbiAgICAgIHJlamVjdChjcmVhdGVFcnJvcignTmV0d29yayBFcnJvcicsIGNvbmZpZywgbnVsbCwgcmVxdWVzdCkpO1xuXG4gICAgICAvLyBDbGVhbiB1cCByZXF1ZXN0XG4gICAgICByZXF1ZXN0ID0gbnVsbDtcbiAgICB9O1xuXG4gICAgLy8gSGFuZGxlIHRpbWVvdXRcbiAgICByZXF1ZXN0Lm9udGltZW91dCA9IGZ1bmN0aW9uIGhhbmRsZVRpbWVvdXQoKSB7XG4gICAgICByZWplY3QoY3JlYXRlRXJyb3IoJ3RpbWVvdXQgb2YgJyArIGNvbmZpZy50aW1lb3V0ICsgJ21zIGV4Y2VlZGVkJywgY29uZmlnLCAnRUNPTk5BQk9SVEVEJyxcbiAgICAgICAgcmVxdWVzdCkpO1xuXG4gICAgICAvLyBDbGVhbiB1cCByZXF1ZXN0XG4gICAgICByZXF1ZXN0ID0gbnVsbDtcbiAgICB9O1xuXG4gICAgLy8gQWRkIHhzcmYgaGVhZGVyXG4gICAgLy8gVGhpcyBpcyBvbmx5IGRvbmUgaWYgcnVubmluZyBpbiBhIHN0YW5kYXJkIGJyb3dzZXIgZW52aXJvbm1lbnQuXG4gICAgLy8gU3BlY2lmaWNhbGx5IG5vdCBpZiB3ZSdyZSBpbiBhIHdlYiB3b3JrZXIsIG9yIHJlYWN0LW5hdGl2ZS5cbiAgICBpZiAodXRpbHMuaXNTdGFuZGFyZEJyb3dzZXJFbnYoKSkge1xuICAgICAgdmFyIGNvb2tpZXMgPSByZXF1aXJlKCcuLy4uL2hlbHBlcnMvY29va2llcycpO1xuXG4gICAgICAvLyBBZGQgeHNyZiBoZWFkZXJcbiAgICAgIHZhciB4c3JmVmFsdWUgPSAoY29uZmlnLndpdGhDcmVkZW50aWFscyB8fCBpc1VSTFNhbWVPcmlnaW4oY29uZmlnLnVybCkpICYmIGNvbmZpZy54c3JmQ29va2llTmFtZSA/XG4gICAgICAgICAgY29va2llcy5yZWFkKGNvbmZpZy54c3JmQ29va2llTmFtZSkgOlxuICAgICAgICAgIHVuZGVmaW5lZDtcblxuICAgICAgaWYgKHhzcmZWYWx1ZSkge1xuICAgICAgICByZXF1ZXN0SGVhZGVyc1tjb25maWcueHNyZkhlYWRlck5hbWVdID0geHNyZlZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFkZCBoZWFkZXJzIHRvIHRoZSByZXF1ZXN0XG4gICAgaWYgKCdzZXRSZXF1ZXN0SGVhZGVyJyBpbiByZXF1ZXN0KSB7XG4gICAgICB1dGlscy5mb3JFYWNoKHJlcXVlc3RIZWFkZXJzLCBmdW5jdGlvbiBzZXRSZXF1ZXN0SGVhZGVyKHZhbCwga2V5KSB7XG4gICAgICAgIGlmICh0eXBlb2YgcmVxdWVzdERhdGEgPT09ICd1bmRlZmluZWQnICYmIGtleS50b0xvd2VyQ2FzZSgpID09PSAnY29udGVudC10eXBlJykge1xuICAgICAgICAgIC8vIFJlbW92ZSBDb250ZW50LVR5cGUgaWYgZGF0YSBpcyB1bmRlZmluZWRcbiAgICAgICAgICBkZWxldGUgcmVxdWVzdEhlYWRlcnNba2V5XTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBPdGhlcndpc2UgYWRkIGhlYWRlciB0byB0aGUgcmVxdWVzdFxuICAgICAgICAgIHJlcXVlc3Quc2V0UmVxdWVzdEhlYWRlcihrZXksIHZhbCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEFkZCB3aXRoQ3JlZGVudGlhbHMgdG8gcmVxdWVzdCBpZiBuZWVkZWRcbiAgICBpZiAoY29uZmlnLndpdGhDcmVkZW50aWFscykge1xuICAgICAgcmVxdWVzdC53aXRoQ3JlZGVudGlhbHMgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIEFkZCByZXNwb25zZVR5cGUgdG8gcmVxdWVzdCBpZiBuZWVkZWRcbiAgICBpZiAoY29uZmlnLnJlc3BvbnNlVHlwZSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmVxdWVzdC5yZXNwb25zZVR5cGUgPSBjb25maWcucmVzcG9uc2VUeXBlO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBFeHBlY3RlZCBET01FeGNlcHRpb24gdGhyb3duIGJ5IGJyb3dzZXJzIG5vdCBjb21wYXRpYmxlIFhNTEh0dHBSZXF1ZXN0IExldmVsIDIuXG4gICAgICAgIC8vIEJ1dCwgdGhpcyBjYW4gYmUgc3VwcHJlc3NlZCBmb3IgJ2pzb24nIHR5cGUgYXMgaXQgY2FuIGJlIHBhcnNlZCBieSBkZWZhdWx0ICd0cmFuc2Zvcm1SZXNwb25zZScgZnVuY3Rpb24uXG4gICAgICAgIGlmIChjb25maWcucmVzcG9uc2VUeXBlICE9PSAnanNvbicpIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIHByb2dyZXNzIGlmIG5lZWRlZFxuICAgIGlmICh0eXBlb2YgY29uZmlnLm9uRG93bmxvYWRQcm9ncmVzcyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmVxdWVzdC5hZGRFdmVudExpc3RlbmVyKCdwcm9ncmVzcycsIGNvbmZpZy5vbkRvd25sb2FkUHJvZ3Jlc3MpO1xuICAgIH1cblxuICAgIC8vIE5vdCBhbGwgYnJvd3NlcnMgc3VwcG9ydCB1cGxvYWQgZXZlbnRzXG4gICAgaWYgKHR5cGVvZiBjb25maWcub25VcGxvYWRQcm9ncmVzcyA9PT0gJ2Z1bmN0aW9uJyAmJiByZXF1ZXN0LnVwbG9hZCkge1xuICAgICAgcmVxdWVzdC51cGxvYWQuYWRkRXZlbnRMaXN0ZW5lcigncHJvZ3Jlc3MnLCBjb25maWcub25VcGxvYWRQcm9ncmVzcyk7XG4gICAgfVxuXG4gICAgaWYgKGNvbmZpZy5jYW5jZWxUb2tlbikge1xuICAgICAgLy8gSGFuZGxlIGNhbmNlbGxhdGlvblxuICAgICAgY29uZmlnLmNhbmNlbFRva2VuLnByb21pc2UudGhlbihmdW5jdGlvbiBvbkNhbmNlbGVkKGNhbmNlbCkge1xuICAgICAgICBpZiAoIXJlcXVlc3QpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICByZXF1ZXN0LmFib3J0KCk7XG4gICAgICAgIHJlamVjdChjYW5jZWwpO1xuICAgICAgICAvLyBDbGVhbiB1cCByZXF1ZXN0XG4gICAgICAgIHJlcXVlc3QgPSBudWxsO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKHJlcXVlc3REYXRhID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJlcXVlc3REYXRhID0gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBTZW5kIHRoZSByZXF1ZXN0XG4gICAgcmVxdWVzdC5zZW5kKHJlcXVlc3REYXRhKTtcbiAgfSk7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2FkYXB0ZXJzL3hoci5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2FkYXB0ZXJzL3hoci5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2F4aW9zLmpzP2I0ODEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLFlBQVksTUFBTTtBQUNsQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9heGlvcy5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzID0gcmVxdWlyZSgnLi91dGlscycpO1xudmFyIGJpbmQgPSByZXF1aXJlKCcuL2hlbHBlcnMvYmluZCcpO1xudmFyIEF4aW9zID0gcmVxdWlyZSgnLi9jb3JlL0F4aW9zJyk7XG52YXIgZGVmYXVsdHMgPSByZXF1aXJlKCcuL2RlZmF1bHRzJyk7XG5cbi8qKlxuICogQ3JlYXRlIGFuIGluc3RhbmNlIG9mIEF4aW9zXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGRlZmF1bHRDb25maWcgVGhlIGRlZmF1bHQgY29uZmlnIGZvciB0aGUgaW5zdGFuY2VcbiAqIEByZXR1cm4ge0F4aW9zfSBBIG5ldyBpbnN0YW5jZSBvZiBBeGlvc1xuICovXG5mdW5jdGlvbiBjcmVhdGVJbnN0YW5jZShkZWZhdWx0Q29uZmlnKSB7XG4gIHZhciBjb250ZXh0ID0gbmV3IEF4aW9zKGRlZmF1bHRDb25maWcpO1xuICB2YXIgaW5zdGFuY2UgPSBiaW5kKEF4aW9zLnByb3RvdHlwZS5yZXF1ZXN0LCBjb250ZXh0KTtcblxuICAvLyBDb3B5IGF4aW9zLnByb3RvdHlwZSB0byBpbnN0YW5jZVxuICB1dGlscy5leHRlbmQoaW5zdGFuY2UsIEF4aW9zLnByb3RvdHlwZSwgY29udGV4dCk7XG5cbiAgLy8gQ29weSBjb250ZXh0IHRvIGluc3RhbmNlXG4gIHV0aWxzLmV4dGVuZChpbnN0YW5jZSwgY29udGV4dCk7XG5cbiAgcmV0dXJuIGluc3RhbmNlO1xufVxuXG4vLyBDcmVhdGUgdGhlIGRlZmF1bHQgaW5zdGFuY2UgdG8gYmUgZXhwb3J0ZWRcbnZhciBheGlvcyA9IGNyZWF0ZUluc3RhbmNlKGRlZmF1bHRzKTtcblxuLy8gRXhwb3NlIEF4aW9zIGNsYXNzIHRvIGFsbG93IGNsYXNzIGluaGVyaXRhbmNlXG5heGlvcy5BeGlvcyA9IEF4aW9zO1xuXG4vLyBGYWN0b3J5IGZvciBjcmVhdGluZyBuZXcgaW5zdGFuY2VzXG5heGlvcy5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoaW5zdGFuY2VDb25maWcpIHtcbiAgcmV0dXJuIGNyZWF0ZUluc3RhbmNlKHV0aWxzLm1lcmdlKGRlZmF1bHRzLCBpbnN0YW5jZUNvbmZpZykpO1xufTtcblxuLy8gRXhwb3NlIENhbmNlbCAmIENhbmNlbFRva2VuXG5heGlvcy5DYW5jZWwgPSByZXF1aXJlKCcuL2NhbmNlbC9DYW5jZWwnKTtcbmF4aW9zLkNhbmNlbFRva2VuID0gcmVxdWlyZSgnLi9jYW5jZWwvQ2FuY2VsVG9rZW4nKTtcbmF4aW9zLmlzQ2FuY2VsID0gcmVxdWlyZSgnLi9jYW5jZWwvaXNDYW5jZWwnKTtcblxuLy8gRXhwb3NlIGFsbC9zcHJlYWRcbmF4aW9zLmFsbCA9IGZ1bmN0aW9uIGFsbChwcm9taXNlcykge1xuICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xufTtcbmF4aW9zLnNwcmVhZCA9IHJlcXVpcmUoJy4vaGVscGVycy9zcHJlYWQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBheGlvcztcblxuLy8gQWxsb3cgdXNlIG9mIGRlZmF1bHQgaW1wb3J0IHN5bnRheCBpbiBUeXBlU2NyaXB0XG5tb2R1bGUuZXhwb3J0cy5kZWZhdWx0ID0gYXhpb3M7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvYXhpb3MuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9heGlvcy5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\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/NzU1MyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NhbmNlbC9DYW5jZWwuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQSBgQ2FuY2VsYCBpcyBhbiBvYmplY3QgdGhhdCBpcyB0aHJvd24gd2hlbiBhbiBvcGVyYXRpb24gaXMgY2FuY2VsZWQuXG4gKlxuICogQGNsYXNzXG4gKiBAcGFyYW0ge3N0cmluZz19IG1lc3NhZ2UgVGhlIG1lc3NhZ2UuXG4gKi9cbmZ1bmN0aW9uIENhbmNlbChtZXNzYWdlKSB7XG4gIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG59XG5cbkNhbmNlbC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgcmV0dXJuICdDYW5jZWwnICsgKHRoaXMubWVzc2FnZSA/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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NhbmNlbC9DYW5jZWxUb2tlbi5qcz83MTZjIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY2FuY2VsL0NhbmNlbFRva2VuLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgQ2FuY2VsID0gcmVxdWlyZSgnLi9DYW5jZWwnKTtcblxuLyoqXG4gKiBBIGBDYW5jZWxUb2tlbmAgaXMgYW4gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gcmVxdWVzdCBjYW5jZWxsYXRpb24gb2YgYW4gb3BlcmF0aW9uLlxuICpcbiAqIEBjbGFzc1xuICogQHBhcmFtIHtGdW5jdGlvbn0gZXhlY3V0b3IgVGhlIGV4ZWN1dG9yIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBDYW5jZWxUb2tlbihleGVjdXRvcikge1xuICBpZiAodHlwZW9mIGV4ZWN1dG9yICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZXhlY3V0b3IgbXVzdCBiZSBhIGZ1bmN0aW9uLicpO1xuICB9XG5cbiAgdmFyIHJlc29sdmVQcm9taXNlO1xuICB0aGlzLnByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbiBwcm9taXNlRXhlY3V0b3IocmVzb2x2ZSkge1xuICAgIHJlc29sdmVQcm9taXNlID0gcmVzb2x2ZTtcbiAgfSk7XG5cbiAgdmFyIHRva2VuID0gdGhpcztcbiAgZXhlY3V0b3IoZnVuY3Rpb24gY2FuY2VsKG1lc3NhZ2UpIHtcbiAgICBpZiAodG9rZW4ucmVhc29uKSB7XG4gICAgICAvLyBDYW5jZWxsYXRpb24gaGFzIGFscmVhZHkgYmVlbiByZXF1ZXN0ZWRcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0b2tlbi5yZWFzb24gPSBuZXcgQ2FuY2VsKG1lc3NhZ2UpO1xuICAgIHJlc29sdmVQcm9taXNlKHRva2VuLnJlYXNvbik7XG4gIH0pO1xufVxuXG4vKipcbiAqIFRocm93cyBhIGBDYW5jZWxgIGlmIGNhbmNlbGxhdGlvbiBoYXMgYmVlbiByZXF1ZXN0ZWQuXG4gKi9cbkNhbmNlbFRva2VuLnByb3RvdHlwZS50aHJvd0lmUmVxdWVzdGVkID0gZnVuY3Rpb24gdGhyb3dJZlJlcXVlc3RlZCgpIHtcbiAgaWYgKHRoaXMucmVhc29uKSB7XG4gICAgdGhyb3cgdGhpcy5yZWFzb247XG4gIH1cbn07XG5cbi8qKlxuICogUmV0dXJucyBhbiBvYmplY3QgdGhhdCBjb250YWlucyBhIG5ldyBgQ2FuY2VsVG9rZW5gIGFuZCBhIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLFxuICogY2FuY2VscyB0aGUgYENhbmNlbFRva2VuYC5cbiAqL1xuQ2FuY2VsVG9rZW4uc291cmNlID0gZnVuY3Rpb24gc291cmNlKCkge1xuICB2YXIgY2FuY2VsO1xuICB2YXIgdG9rZW4gPSBuZXcgQ2FuY2VsVG9rZW4oZnVuY3Rpb24gZXhlY3V0b3IoYykge1xuICAgIGNhbmNlbCA9IGM7XG4gIH0pO1xuICByZXR1cm4ge1xuICAgIHRva2VuOiB0b2tlbixcbiAgICBjYW5jZWw6IGNhbmNlbFxuICB9O1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBDYW5jZWxUb2tlbjtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jYW5jZWwvQ2FuY2VsVG9rZW4uanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jYW5jZWwvQ2FuY2VsVG9rZW4uanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NhbmNlbC9pc0NhbmNlbC5qcz9hNDFiIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBO0FBQ0E7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY2FuY2VsL2lzQ2FuY2VsLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzQ2FuY2VsKHZhbHVlKSB7XG4gIHJldHVybiAhISh2YWx1ZSAmJiB2YWx1ZS5fX0NBTkNFTF9fKTtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY2FuY2VsL2lzQ2FuY2VsLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY2FuY2VsL2lzQ2FuY2VsLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\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, this.defaults, { method: 'get' }, 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/NWU2NSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUEsaURBQWlELGdCQUFnQjtBQUNqRTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0Q7QUFDaEQ7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdEO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLENBQUM7O0FBRUQiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvQXhpb3MuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciBkZWZhdWx0cyA9IHJlcXVpcmUoJy4vLi4vZGVmYXVsdHMnKTtcbnZhciB1dGlscyA9IHJlcXVpcmUoJy4vLi4vdXRpbHMnKTtcbnZhciBJbnRlcmNlcHRvck1hbmFnZXIgPSByZXF1aXJlKCcuL0ludGVyY2VwdG9yTWFuYWdlcicpO1xudmFyIGRpc3BhdGNoUmVxdWVzdCA9IHJlcXVpcmUoJy4vZGlzcGF0Y2hSZXF1ZXN0Jyk7XG5cbi8qKlxuICogQ3JlYXRlIGEgbmV3IGluc3RhbmNlIG9mIEF4aW9zXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGluc3RhbmNlQ29uZmlnIFRoZSBkZWZhdWx0IGNvbmZpZyBmb3IgdGhlIGluc3RhbmNlXG4gKi9cbmZ1bmN0aW9uIEF4aW9zKGluc3RhbmNlQ29uZmlnKSB7XG4gIHRoaXMuZGVmYXVsdHMgPSBpbnN0YW5jZUNvbmZpZztcbiAgdGhpcy5pbnRlcmNlcHRvcnMgPSB7XG4gICAgcmVxdWVzdDogbmV3IEludGVyY2VwdG9yTWFuYWdlcigpLFxuICAgIHJlc3BvbnNlOiBuZXcgSW50ZXJjZXB0b3JNYW5hZ2VyKClcbiAgfTtcbn1cblxuLyoqXG4gKiBEaXNwYXRjaCBhIHJlcXVlc3RcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIFRoZSBjb25maWcgc3BlY2lmaWMgZm9yIHRoaXMgcmVxdWVzdCAobWVyZ2VkIHdpdGggdGhpcy5kZWZhdWx0cylcbiAqL1xuQXhpb3MucHJvdG90eXBlLnJlcXVlc3QgPSBmdW5jdGlvbiByZXF1ZXN0KGNvbmZpZykge1xuICAvKmVzbGludCBuby1wYXJhbS1yZWFzc2lnbjowKi9cbiAgLy8gQWxsb3cgZm9yIGF4aW9zKCdleGFtcGxlL3VybCdbLCBjb25maWddKSBhIGxhIGZldGNoIEFQSVxuICBpZiAodHlwZW9mIGNvbmZpZyA9PT0gJ3N0cmluZycpIHtcbiAgICBjb25maWcgPSB1dGlscy5tZXJnZSh7XG4gICAgICB1cmw6IGFyZ3VtZW50c1swXVxuICAgIH0sIGFyZ3VtZW50c1sxXSk7XG4gIH1cblxuICBjb25maWcgPSB1dGlscy5tZXJnZShkZWZhdWx0cywgdGhpcy5kZWZhdWx0cywgeyBtZXRob2Q6ICdnZXQnIH0sIGNvbmZpZyk7XG4gIGNvbmZpZy5tZXRob2QgPSBjb25maWcubWV0aG9kLnRvTG93ZXJDYXNlKCk7XG5cbiAgLy8gSG9vayB1cCBpbnRlcmNlcHRvcnMgbWlkZGxld2FyZVxuICB2YXIgY2hhaW4gPSBbZGlzcGF0Y2hSZXF1ZXN0LCB1bmRlZmluZWRdO1xuICB2YXIgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShjb25maWcpO1xuXG4gIHRoaXMuaW50ZXJjZXB0b3JzLnJlcXVlc3QuZm9yRWFjaChmdW5jdGlvbiB1bnNoaWZ0UmVxdWVzdEludGVyY2VwdG9ycyhpbnRlcmNlcHRvcikge1xuICAgIGNoYWluLnVuc2hpZnQoaW50ZXJjZXB0b3IuZnVsZmlsbGVkLCBpbnRlcmNlcHRvci5yZWplY3RlZCk7XG4gIH0pO1xuXG4gIHRoaXMuaW50ZXJjZXB0b3JzLnJlc3BvbnNlLmZvckVhY2goZnVuY3Rpb24gcHVzaFJlc3BvbnNlSW50ZXJjZXB0b3JzKGludGVyY2VwdG9yKSB7XG4gICAgY2hhaW4ucHVzaChpbnRlcmNlcHRvci5mdWxmaWxsZWQsIGludGVyY2VwdG9yLnJlamVjdGVkKTtcbiAgfSk7XG5cbiAgd2hpbGUgKGNoYWluLmxlbmd0aCkge1xuICAgIHByb21pc2UgPSBwcm9taXNlLnRoZW4oY2hhaW4uc2hpZnQoKSwgY2hhaW4uc2hpZnQoKSk7XG4gIH1cblxuICByZXR1cm4gcHJvbWlzZTtcbn07XG5cbi8vIFByb3ZpZGUgYWxpYXNlcyBmb3Igc3VwcG9ydGVkIHJlcXVlc3QgbWV0aG9kc1xudXRpbHMuZm9yRWFjaChbJ2RlbGV0ZScsICdnZXQnLCAnaGVhZCcsICdvcHRpb25zJ10sIGZ1bmN0aW9uIGZvckVhY2hNZXRob2ROb0RhdGEobWV0aG9kKSB7XG4gIC8qZXNsaW50IGZ1bmMtbmFtZXM6MCovXG4gIEF4aW9zLnByb3RvdHlwZVttZXRob2RdID0gZnVuY3Rpb24odXJsLCBjb25maWcpIHtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0KHV0aWxzLm1lcmdlKGNvbmZpZyB8fCB7fSwge1xuICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICB1cmw6IHVybFxuICAgIH0pKTtcbiAgfTtcbn0pO1xuXG51dGlscy5mb3JFYWNoKFsncG9zdCcsICdwdXQnLCAncGF0Y2gnXSwgZnVuY3Rpb24gZm9yRWFjaE1ldGhvZFdpdGhEYXRhKG1ldGhvZCkge1xuICAvKmVzbGludCBmdW5jLW5hbWVzOjAqL1xuICBBeGlvcy5wcm90b3R5cGVbbWV0aG9kXSA9IGZ1bmN0aW9uKHVybCwgZGF0YSwgY29uZmlnKSB7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdCh1dGlscy5tZXJnZShjb25maWcgfHwge30sIHtcbiAgICAgIG1ldGhvZDogbWV0aG9kLFxuICAgICAgdXJsOiB1cmwsXG4gICAgICBkYXRhOiBkYXRhXG4gICAgfSkpO1xuICB9O1xufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gQXhpb3M7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9BeGlvcy5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvQXhpb3MuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvSW50ZXJjZXB0b3JNYW5hZ2VyLmpzPzdlZTEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQixXQUFXLFNBQVM7QUFDcEI7QUFDQSxZQUFZLE9BQU87QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9JbnRlcmNlcHRvck1hbmFnZXIuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlscyA9IHJlcXVpcmUoJy4vLi4vdXRpbHMnKTtcblxuZnVuY3Rpb24gSW50ZXJjZXB0b3JNYW5hZ2VyKCkge1xuICB0aGlzLmhhbmRsZXJzID0gW107XG59XG5cbi8qKlxuICogQWRkIGEgbmV3IGludGVyY2VwdG9yIHRvIHRoZSBzdGFja1xuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bGZpbGxlZCBUaGUgZnVuY3Rpb24gdG8gaGFuZGxlIGB0aGVuYCBmb3IgYSBgUHJvbWlzZWBcbiAqIEBwYXJhbSB7RnVuY3Rpb259IHJlamVjdGVkIFRoZSBmdW5jdGlvbiB0byBoYW5kbGUgYHJlamVjdGAgZm9yIGEgYFByb21pc2VgXG4gKlxuICogQHJldHVybiB7TnVtYmVyfSBBbiBJRCB1c2VkIHRvIHJlbW92ZSBpbnRlcmNlcHRvciBsYXRlclxuICovXG5JbnRlcmNlcHRvck1hbmFnZXIucHJvdG90eXBlLnVzZSA9IGZ1bmN0aW9uIHVzZShmdWxmaWxsZWQsIHJlamVjdGVkKSB7XG4gIHRoaXMuaGFuZGxlcnMucHVzaCh7XG4gICAgZnVsZmlsbGVkOiBmdWxmaWxsZWQsXG4gICAgcmVqZWN0ZWQ6IHJlamVjdGVkXG4gIH0pO1xuICByZXR1cm4gdGhpcy5oYW5kbGVycy5sZW5ndGggLSAxO1xufTtcblxuLyoqXG4gKiBSZW1vdmUgYW4gaW50ZXJjZXB0b3IgZnJvbSB0aGUgc3RhY2tcbiAqXG4gKiBAcGFyYW0ge051bWJlcn0gaWQgVGhlIElEIHRoYXQgd2FzIHJldHVybmVkIGJ5IGB1c2VgXG4gKi9cbkludGVyY2VwdG9yTWFuYWdlci5wcm90b3R5cGUuZWplY3QgPSBmdW5jdGlvbiBlamVjdChpZCkge1xuICBpZiAodGhpcy5oYW5kbGVyc1tpZF0pIHtcbiAgICB0aGlzLmhhbmRsZXJzW2lkXSA9IG51bGw7XG4gIH1cbn07XG5cbi8qKlxuICogSXRlcmF0ZSBvdmVyIGFsbCB0aGUgcmVnaXN0ZXJlZCBpbnRlcmNlcHRvcnNcbiAqXG4gKiBUaGlzIG1ldGhvZCBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciBza2lwcGluZyBvdmVyIGFueVxuICogaW50ZXJjZXB0b3JzIHRoYXQgbWF5IGhhdmUgYmVjb21lIGBudWxsYCBjYWxsaW5nIGBlamVjdGAuXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm4gVGhlIGZ1bmN0aW9uIHRvIGNhbGwgZm9yIGVhY2ggaW50ZXJjZXB0b3JcbiAqL1xuSW50ZXJjZXB0b3JNYW5hZ2VyLnByb3RvdHlwZS5mb3JFYWNoID0gZnVuY3Rpb24gZm9yRWFjaChmbikge1xuICB1dGlscy5mb3JFYWNoKHRoaXMuaGFuZGxlcnMsIGZ1bmN0aW9uIGZvckVhY2hIYW5kbGVyKGgpIHtcbiAgICBpZiAoaCAhPT0gbnVsbCkge1xuICAgICAgZm4oaCk7XG4gICAgfVxuICB9KTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gSW50ZXJjZXB0b3JNYW5hZ2VyO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvSW50ZXJjZXB0b3JNYW5hZ2VyLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9JbnRlcmNlcHRvck1hbmFnZXIuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\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/MTZkMCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsTUFBTTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL2NyZWF0ZUVycm9yLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZW5oYW5jZUVycm9yID0gcmVxdWlyZSgnLi9lbmhhbmNlRXJyb3InKTtcblxuLyoqXG4gKiBDcmVhdGUgYW4gRXJyb3Igd2l0aCB0aGUgc3BlY2lmaWVkIG1lc3NhZ2UsIGNvbmZpZywgZXJyb3IgY29kZSwgcmVxdWVzdCBhbmQgcmVzcG9uc2UuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgVGhlIGVycm9yIG1lc3NhZ2UuXG4gKiBAcGFyYW0ge09iamVjdH0gY29uZmlnIFRoZSBjb25maWcuXG4gKiBAcGFyYW0ge3N0cmluZ30gW2NvZGVdIFRoZSBlcnJvciBjb2RlIChmb3IgZXhhbXBsZSwgJ0VDT05OQUJPUlRFRCcpLlxuICogQHBhcmFtIHtPYmplY3R9IFtyZXF1ZXN0XSBUaGUgcmVxdWVzdC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbcmVzcG9uc2VdIFRoZSByZXNwb25zZS5cbiAqIEByZXR1cm5zIHtFcnJvcn0gVGhlIGNyZWF0ZWQgZXJyb3IuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY3JlYXRlRXJyb3IobWVzc2FnZSwgY29uZmlnLCBjb2RlLCByZXF1ZXN0LCByZXNwb25zZSkge1xuICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IobWVzc2FnZSk7XG4gIHJldHVybiBlbmhhbmNlRXJyb3IoZXJyb3IsIGNvbmZpZywgY29kZSwgcmVxdWVzdCwgcmVzcG9uc2UpO1xufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL2NyZWF0ZUVycm9yLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9jcmVhdGVFcnJvci5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvZGlzcGF0Y2hSZXF1ZXN0LmpzP2M0YmIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLCtCQUErQjtBQUMvQix1Q0FBdUM7QUFDdkM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0giLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvZGlzcGF0Y2hSZXF1ZXN0LmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLy4uL3V0aWxzJyk7XG52YXIgdHJhbnNmb3JtRGF0YSA9IHJlcXVpcmUoJy4vdHJhbnNmb3JtRGF0YScpO1xudmFyIGlzQ2FuY2VsID0gcmVxdWlyZSgnLi4vY2FuY2VsL2lzQ2FuY2VsJyk7XG52YXIgZGVmYXVsdHMgPSByZXF1aXJlKCcuLi9kZWZhdWx0cycpO1xudmFyIGlzQWJzb2x1dGVVUkwgPSByZXF1aXJlKCcuLy4uL2hlbHBlcnMvaXNBYnNvbHV0ZVVSTCcpO1xudmFyIGNvbWJpbmVVUkxzID0gcmVxdWlyZSgnLi8uLi9oZWxwZXJzL2NvbWJpbmVVUkxzJyk7XG5cbi8qKlxuICogVGhyb3dzIGEgYENhbmNlbGAgaWYgY2FuY2VsbGF0aW9uIGhhcyBiZWVuIHJlcXVlc3RlZC5cbiAqL1xuZnVuY3Rpb24gdGhyb3dJZkNhbmNlbGxhdGlvblJlcXVlc3RlZChjb25maWcpIHtcbiAgaWYgKGNvbmZpZy5jYW5jZWxUb2tlbikge1xuICAgIGNvbmZpZy5jYW5jZWxUb2tlbi50aHJvd0lmUmVxdWVzdGVkKCk7XG4gIH1cbn1cblxuLyoqXG4gKiBEaXNwYXRjaCBhIHJlcXVlc3QgdG8gdGhlIHNlcnZlciB1c2luZyB0aGUgY29uZmlndXJlZCBhZGFwdGVyLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb25maWcgVGhlIGNvbmZpZyB0aGF0IGlzIHRvIGJlIHVzZWQgZm9yIHRoZSByZXF1ZXN0XG4gKiBAcmV0dXJucyB7UHJvbWlzZX0gVGhlIFByb21pc2UgdG8gYmUgZnVsZmlsbGVkXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZGlzcGF0Y2hSZXF1ZXN0KGNvbmZpZykge1xuICB0aHJvd0lmQ2FuY2VsbGF0aW9uUmVxdWVzdGVkKGNvbmZpZyk7XG5cbiAgLy8gU3VwcG9ydCBiYXNlVVJMIGNvbmZpZ1xuICBpZiAoY29uZmlnLmJhc2VVUkwgJiYgIWlzQWJzb2x1dGVVUkwoY29uZmlnLnVybCkpIHtcbiAgICBjb25maWcudXJsID0gY29tYmluZVVSTHMoY29uZmlnLmJhc2VVUkwsIGNvbmZpZy51cmwpO1xuICB9XG5cbiAgLy8gRW5zdXJlIGhlYWRlcnMgZXhpc3RcbiAgY29uZmlnLmhlYWRlcnMgPSBjb25maWcuaGVhZGVycyB8fCB7fTtcblxuICAvLyBUcmFuc2Zvcm0gcmVxdWVzdCBkYXRhXG4gIGNvbmZpZy5kYXRhID0gdHJhbnNmb3JtRGF0YShcbiAgICBjb25maWcuZGF0YSxcbiAgICBjb25maWcuaGVhZGVycyxcbiAgICBjb25maWcudHJhbnNmb3JtUmVxdWVzdFxuICApO1xuXG4gIC8vIEZsYXR0ZW4gaGVhZGVyc1xuICBjb25maWcuaGVhZGVycyA9IHV0aWxzLm1lcmdlKFxuICAgIGNvbmZpZy5oZWFkZXJzLmNvbW1vbiB8fCB7fSxcbiAgICBjb25maWcuaGVhZGVyc1tjb25maWcubWV0aG9kXSB8fCB7fSxcbiAgICBjb25maWcuaGVhZGVycyB8fCB7fVxuICApO1xuXG4gIHV0aWxzLmZvckVhY2goXG4gICAgWydkZWxldGUnLCAnZ2V0JywgJ2hlYWQnLCAncG9zdCcsICdwdXQnLCAncGF0Y2gnLCAnY29tbW9uJ10sXG4gICAgZnVuY3Rpb24gY2xlYW5IZWFkZXJDb25maWcobWV0aG9kKSB7XG4gICAgICBkZWxldGUgY29uZmlnLmhlYWRlcnNbbWV0aG9kXTtcbiAgICB9XG4gICk7XG5cbiAgdmFyIGFkYXB0ZXIgPSBjb25maWcuYWRhcHRlciB8fCBkZWZhdWx0cy5hZGFwdGVyO1xuXG4gIHJldHVybiBhZGFwdGVyKGNvbmZpZykudGhlbihmdW5jdGlvbiBvbkFkYXB0ZXJSZXNvbHV0aW9uKHJlc3BvbnNlKSB7XG4gICAgdGhyb3dJZkNhbmNlbGxhdGlvblJlcXVlc3RlZChjb25maWcpO1xuXG4gICAgLy8gVHJhbnNmb3JtIHJlc3BvbnNlIGRhdGFcbiAgICByZXNwb25zZS5kYXRhID0gdHJhbnNmb3JtRGF0YShcbiAgICAgIHJlc3BvbnNlLmRhdGEsXG4gICAgICByZXNwb25zZS5oZWFkZXJzLFxuICAgICAgY29uZmlnLnRyYW5zZm9ybVJlc3BvbnNlXG4gICAgKTtcblxuICAgIHJldHVybiByZXNwb25zZTtcbiAgfSwgZnVuY3Rpb24gb25BZGFwdGVyUmVqZWN0aW9uKHJlYXNvbikge1xuICAgIGlmICghaXNDYW5jZWwocmVhc29uKSkge1xuICAgICAgdGhyb3dJZkNhbmNlbGxhdGlvblJlcXVlc3RlZChjb25maWcpO1xuXG4gICAgICAvLyBUcmFuc2Zvcm0gcmVzcG9uc2UgZGF0YVxuICAgICAgaWYgKHJlYXNvbiAmJiByZWFzb24ucmVzcG9uc2UpIHtcbiAgICAgICAgcmVhc29uLnJlc3BvbnNlLmRhdGEgPSB0cmFuc2Zvcm1EYXRhKFxuICAgICAgICAgIHJlYXNvbi5yZXNwb25zZS5kYXRhLFxuICAgICAgICAgIHJlYXNvbi5yZXNwb25zZS5oZWFkZXJzLFxuICAgICAgICAgIGNvbmZpZy50cmFuc2Zvcm1SZXNwb25zZVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChyZWFzb24pO1xuICB9KTtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9kaXNwYXRjaFJlcXVlc3QuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL2Rpc3BhdGNoUmVxdWVzdC5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvZW5oYW5jZUVycm9yLmpzP2I3Y2EiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxNQUFNO0FBQ2pCLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixhQUFhLE1BQU07QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvZW5oYW5jZUVycm9yLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIFVwZGF0ZSBhbiBFcnJvciB3aXRoIHRoZSBzcGVjaWZpZWQgY29uZmlnLCBlcnJvciBjb2RlLCBhbmQgcmVzcG9uc2UuXG4gKlxuICogQHBhcmFtIHtFcnJvcn0gZXJyb3IgVGhlIGVycm9yIHRvIHVwZGF0ZS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBjb25maWcgVGhlIGNvbmZpZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbY29kZV0gVGhlIGVycm9yIGNvZGUgKGZvciBleGFtcGxlLCAnRUNPTk5BQk9SVEVEJykuXG4gKiBAcGFyYW0ge09iamVjdH0gW3JlcXVlc3RdIFRoZSByZXF1ZXN0LlxuICogQHBhcmFtIHtPYmplY3R9IFtyZXNwb25zZV0gVGhlIHJlc3BvbnNlLlxuICogQHJldHVybnMge0Vycm9yfSBUaGUgZXJyb3IuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZW5oYW5jZUVycm9yKGVycm9yLCBjb25maWcsIGNvZGUsIHJlcXVlc3QsIHJlc3BvbnNlKSB7XG4gIGVycm9yLmNvbmZpZyA9IGNvbmZpZztcbiAgaWYgKGNvZGUpIHtcbiAgICBlcnJvci5jb2RlID0gY29kZTtcbiAgfVxuICBlcnJvci5yZXF1ZXN0ID0gcmVxdWVzdDtcbiAgZXJyb3IucmVzcG9uc2UgPSByZXNwb25zZTtcbiAgcmV0dXJuIGVycm9yO1xufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL2VuaGFuY2VFcnJvci5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvZW5oYW5jZUVycm9yLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvc2V0dGxlLmpzP2RiNTIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCLFdBQVcsU0FBUztBQUNwQixXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9zZXR0bGUuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciBjcmVhdGVFcnJvciA9IHJlcXVpcmUoJy4vY3JlYXRlRXJyb3InKTtcblxuLyoqXG4gKiBSZXNvbHZlIG9yIHJlamVjdCBhIFByb21pc2UgYmFzZWQgb24gcmVzcG9uc2Ugc3RhdHVzLlxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IHJlc29sdmUgQSBmdW5jdGlvbiB0aGF0IHJlc29sdmVzIHRoZSBwcm9taXNlLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gcmVqZWN0IEEgZnVuY3Rpb24gdGhhdCByZWplY3RzIHRoZSBwcm9taXNlLlxuICogQHBhcmFtIHtvYmplY3R9IHJlc3BvbnNlIFRoZSByZXNwb25zZS5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCByZXNwb25zZSkge1xuICB2YXIgdmFsaWRhdGVTdGF0dXMgPSByZXNwb25zZS5jb25maWcudmFsaWRhdGVTdGF0dXM7XG4gIC8vIE5vdGU6IHN0YXR1cyBpcyBub3QgZXhwb3NlZCBieSBYRG9tYWluUmVxdWVzdFxuICBpZiAoIXJlc3BvbnNlLnN0YXR1cyB8fCAhdmFsaWRhdGVTdGF0dXMgfHwgdmFsaWRhdGVTdGF0dXMocmVzcG9uc2Uuc3RhdHVzKSkge1xuICAgIHJlc29sdmUocmVzcG9uc2UpO1xuICB9IGVsc2Uge1xuICAgIHJlamVjdChjcmVhdGVFcnJvcihcbiAgICAgICdSZXF1ZXN0IGZhaWxlZCB3aXRoIHN0YXR1cyBjb2RlICcgKyByZXNwb25zZS5zdGF0dXMsXG4gICAgICByZXNwb25zZS5jb25maWcsXG4gICAgICBudWxsLFxuICAgICAgcmVzcG9uc2UucmVxdWVzdCxcbiAgICAgIHJlc3BvbnNlXG4gICAgKSk7XG4gIH1cbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9zZXR0bGUuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL3NldHRsZS5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvdHJhbnNmb3JtRGF0YS5qcz80Y2Q1Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsY0FBYztBQUN6QixXQUFXLE1BQU07QUFDakIsV0FBVyxlQUFlO0FBQzFCLGFBQWEsRUFBRTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2NvcmUvdHJhbnNmb3JtRGF0YS5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzID0gcmVxdWlyZSgnLi8uLi91dGlscycpO1xuXG4vKipcbiAqIFRyYW5zZm9ybSB0aGUgZGF0YSBmb3IgYSByZXF1ZXN0IG9yIGEgcmVzcG9uc2VcbiAqXG4gKiBAcGFyYW0ge09iamVjdHxTdHJpbmd9IGRhdGEgVGhlIGRhdGEgdG8gYmUgdHJhbnNmb3JtZWRcbiAqIEBwYXJhbSB7QXJyYXl9IGhlYWRlcnMgVGhlIGhlYWRlcnMgZm9yIHRoZSByZXF1ZXN0IG9yIHJlc3BvbnNlXG4gKiBAcGFyYW0ge0FycmF5fEZ1bmN0aW9ufSBmbnMgQSBzaW5nbGUgZnVuY3Rpb24gb3IgQXJyYXkgb2YgZnVuY3Rpb25zXG4gKiBAcmV0dXJucyB7Kn0gVGhlIHJlc3VsdGluZyB0cmFuc2Zvcm1lZCBkYXRhXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gdHJhbnNmb3JtRGF0YShkYXRhLCBoZWFkZXJzLCBmbnMpIHtcbiAgLyplc2xpbnQgbm8tcGFyYW0tcmVhc3NpZ246MCovXG4gIHV0aWxzLmZvckVhY2goZm5zLCBmdW5jdGlvbiB0cmFuc2Zvcm0oZm4pIHtcbiAgICBkYXRhID0gZm4oZGF0YSwgaGVhZGVycyk7XG4gIH0pO1xuXG4gIHJldHVybiBkYXRhO1xufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL3RyYW5zZm9ybURhdGEuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL3RyYW5zZm9ybURhdGEuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\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 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2RlZmF1bHRzLmpzPzI4MjIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IitDQUFBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0VBQXdFO0FBQ3hFO0FBQ0E7QUFDQTtBQUNBLHVEQUF1RDtBQUN2RDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLFlBQVk7QUFDbkI7QUFDQTtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQSxDQUFDOztBQUVEIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9kZWZhdWx0cy5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzID0gcmVxdWlyZSgnLi91dGlscycpO1xudmFyIG5vcm1hbGl6ZUhlYWRlck5hbWUgPSByZXF1aXJlKCcuL2hlbHBlcnMvbm9ybWFsaXplSGVhZGVyTmFtZScpO1xuXG52YXIgREVGQVVMVF9DT05URU5UX1RZUEUgPSB7XG4gICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJ1xufTtcblxuZnVuY3Rpb24gc2V0Q29udGVudFR5cGVJZlVuc2V0KGhlYWRlcnMsIHZhbHVlKSB7XG4gIGlmICghdXRpbHMuaXNVbmRlZmluZWQoaGVhZGVycykgJiYgdXRpbHMuaXNVbmRlZmluZWQoaGVhZGVyc1snQ29udGVudC1UeXBlJ10pKSB7XG4gICAgaGVhZGVyc1snQ29udGVudC1UeXBlJ10gPSB2YWx1ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXREZWZhdWx0QWRhcHRlcigpIHtcbiAgdmFyIGFkYXB0ZXI7XG4gIGlmICh0eXBlb2YgWE1MSHR0cFJlcXVlc3QgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgLy8gRm9yIGJyb3dzZXJzIHVzZSBYSFIgYWRhcHRlclxuICAgIGFkYXB0ZXIgPSByZXF1aXJlKCcuL2FkYXB0ZXJzL3hocicpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBwcm9jZXNzICE9PSAndW5kZWZpbmVkJykge1xuICAgIC8vIEZvciBub2RlIHVzZSBIVFRQIGFkYXB0ZXJcbiAgICBhZGFwdGVyID0gcmVxdWlyZSgnLi9hZGFwdGVycy9odHRwJyk7XG4gIH1cbiAgcmV0dXJuIGFkYXB0ZXI7XG59XG5cbnZhciBkZWZhdWx0cyA9IHtcbiAgYWRhcHRlcjogZ2V0RGVmYXVsdEFkYXB0ZXIoKSxcblxuICB0cmFuc2Zvcm1SZXF1ZXN0OiBbZnVuY3Rpb24gdHJhbnNmb3JtUmVxdWVzdChkYXRhLCBoZWFkZXJzKSB7XG4gICAgbm9ybWFsaXplSGVhZGVyTmFtZShoZWFkZXJzLCAnQ29udGVudC1UeXBlJyk7XG4gICAgaWYgKHV0aWxzLmlzRm9ybURhdGEoZGF0YSkgfHxcbiAgICAgIHV0aWxzLmlzQXJyYXlCdWZmZXIoZGF0YSkgfHxcbiAgICAgIHV0aWxzLmlzQnVmZmVyKGRhdGEpIHx8XG4gICAgICB1dGlscy5pc1N0cmVhbShkYXRhKSB8fFxuICAgICAgdXRpbHMuaXNGaWxlKGRhdGEpIHx8XG4gICAgICB1dGlscy5pc0Jsb2IoZGF0YSlcbiAgICApIHtcbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgICBpZiAodXRpbHMuaXNBcnJheUJ1ZmZlclZpZXcoZGF0YSkpIHtcbiAgICAgIHJldHVybiBkYXRhLmJ1ZmZlcjtcbiAgICB9XG4gICAgaWYgKHV0aWxzLmlzVVJMU2VhcmNoUGFyYW1zKGRhdGEpKSB7XG4gICAgICBzZXRDb250ZW50VHlwZUlmVW5zZXQoaGVhZGVycywgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZDtjaGFyc2V0PXV0Zi04Jyk7XG4gICAgICByZXR1cm4gZGF0YS50b1N0cmluZygpO1xuICAgIH1cbiAgICBpZiAodXRpbHMuaXNPYmplY3QoZGF0YSkpIHtcbiAgICAgIHNldENvbnRlbnRUeXBlSWZVbnNldChoZWFkZXJzLCAnYXBwbGljYXRpb24vanNvbjtjaGFyc2V0PXV0Zi04Jyk7XG4gICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoZGF0YSk7XG4gICAgfVxuICAgIHJldHVybiBkYXRhO1xuICB9XSxcblxuICB0cmFuc2Zvcm1SZXNwb25zZTogW2Z1bmN0aW9uIHRyYW5zZm9ybVJlc3BvbnNlKGRhdGEpIHtcbiAgICAvKmVzbGludCBuby1wYXJhbS1yZWFzc2lnbjowKi9cbiAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0cnkge1xuICAgICAgICBkYXRhID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHsgLyogSWdub3JlICovIH1cbiAgICB9XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1dLFxuXG4gIHRpbWVvdXQ6IDAsXG5cbiAgeHNyZkNvb2tpZU5hbWU6ICdYU1JGLVRPS0VOJyxcbiAgeHNyZkhlYWRlck5hbWU6ICdYLVhTUkYtVE9LRU4nLFxuXG4gIG1heENvbnRlbnRMZW5ndGg6IC0xLFxuXG4gIHZhbGlkYXRlU3RhdHVzOiBmdW5jdGlvbiB2YWxpZGF0ZVN0YXR1cyhzdGF0dXMpIHtcbiAgICByZXR1cm4gc3RhdHVzID49IDIwMCAmJiBzdGF0dXMgPCAzMDA7XG4gIH1cbn07XG5cbmRlZmF1bHRzLmhlYWRlcnMgPSB7XG4gIGNvbW1vbjoge1xuICAgICdBY2NlcHQnOiAnYXBwbGljYXRpb24vanNvbiwgdGV4dC9wbGFpbiwgKi8qJ1xuICB9XG59O1xuXG51dGlscy5mb3JFYWNoKFsnZGVsZXRlJywgJ2dldCcsICdoZWFkJ10sIGZ1bmN0aW9uIGZvckVhY2hNZXRob2ROb0RhdGEobWV0aG9kKSB7XG4gIGRlZmF1bHRzLmhlYWRlcnNbbWV0aG9kXSA9IHt9O1xufSk7XG5cbnV0aWxzLmZvckVhY2goWydwb3N0JywgJ3B1dCcsICdwYXRjaCddLCBmdW5jdGlvbiBmb3JFYWNoTWV0aG9kV2l0aERhdGEobWV0aG9kKSB7XG4gIGRlZmF1bHRzLmhlYWRlcnNbbWV0aG9kXSA9IHV0aWxzLm1lcmdlKERFRkFVTFRfQ09OVEVOVF9UWVBFKTtcbn0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRlZmF1bHRzO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2RlZmF1bHRzLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvZGVmYXVsdHMuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYmluZC5qcz8yNGZmIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixpQkFBaUI7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9iaW5kLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGJpbmQoZm4sIHRoaXNBcmcpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHdyYXAoKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhcmdzW2ldID0gYXJndW1lbnRzW2ldO1xuICAgIH1cbiAgICByZXR1cm4gZm4uYXBwbHkodGhpc0FyZywgYXJncyk7XG4gIH07XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYmluZC5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYmluZC5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/bind.js\n");
/***/ }),
/***/ "./node_modules/axios/lib/helpers/btoa.js":
/***/ (function(module, exports, __webpack_require__) {
"use strict";
eval("\n\n// btoa polyfill for IE<10 courtesy https://github.com/davidchambers/Base64.js\n\nvar chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n\nfunction E() {\n this.message = 'String contains an invalid character';\n}\nE.prototype = new Error;\nE.prototype.code = 5;\nE.prototype.name = 'InvalidCharacterError';\n\nfunction btoa(input) {\n var str = String(input);\n var output = '';\n for (\n // initialize result and counter\n var block, charCode, idx = 0, map = chars;\n // if the next str index does not exist:\n // change the mapping table to \"=\"\n // check if d has no fractional digits\n str.charAt(idx | 0) || (map = '=', idx % 1);\n // \"8 - idx % 1 * 8\" generates the sequence 2, 4, 6, 8\n output += map.charAt(63 & block >> 8 - idx % 1 * 8)\n ) {\n charCode = str.charCodeAt(idx += 3 / 4);\n if (charCode > 0xFF) {\n throw new E();\n }\n block = block << 8 | charCode;\n }\n return output;\n}\n\nmodule.exports = btoa;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYnRvYS5qcz9iNjEyIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYnRvYS5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuLy8gYnRvYSBwb2x5ZmlsbCBmb3IgSUU8MTAgY291cnRlc3kgaHR0cHM6Ly9naXRodWIuY29tL2RhdmlkY2hhbWJlcnMvQmFzZTY0LmpzXG5cbnZhciBjaGFycyA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvPSc7XG5cbmZ1bmN0aW9uIEUoKSB7XG4gIHRoaXMubWVzc2FnZSA9ICdTdHJpbmcgY29udGFpbnMgYW4gaW52YWxpZCBjaGFyYWN0ZXInO1xufVxuRS5wcm90b3R5cGUgPSBuZXcgRXJyb3I7XG5FLnByb3RvdHlwZS5jb2RlID0gNTtcbkUucHJvdG90eXBlLm5hbWUgPSAnSW52YWxpZENoYXJhY3RlckVycm9yJztcblxuZnVuY3Rpb24gYnRvYShpbnB1dCkge1xuICB2YXIgc3RyID0gU3RyaW5nKGlucHV0KTtcbiAgdmFyIG91dHB1dCA9ICcnO1xuICBmb3IgKFxuICAgIC8vIGluaXRpYWxpemUgcmVzdWx0IGFuZCBjb3VudGVyXG4gICAgdmFyIGJsb2NrLCBjaGFyQ29kZSwgaWR4ID0gMCwgbWFwID0gY2hhcnM7XG4gICAgLy8gaWYgdGhlIG5leHQgc3RyIGluZGV4IGRvZXMgbm90IGV4aXN0OlxuICAgIC8vICAgY2hhbmdlIHRoZSBtYXBwaW5nIHRhYmxlIHRvIFwiPVwiXG4gICAgLy8gICBjaGVjayBpZiBkIGhhcyBubyBmcmFjdGlvbmFsIGRpZ2l0c1xuICAgIHN0ci5jaGFyQXQoaWR4IHwgMCkgfHwgKG1hcCA9ICc9JywgaWR4ICUgMSk7XG4gICAgLy8gXCI4IC0gaWR4ICUgMSAqIDhcIiBnZW5lcmF0ZXMgdGhlIHNlcXVlbmNlIDIsIDQsIDYsIDhcbiAgICBvdXRwdXQgKz0gbWFwLmNoYXJBdCg2MyAmIGJsb2NrID4+IDggLSBpZHggJSAxICogOClcbiAgKSB7XG4gICAgY2hhckNvZGUgPSBzdHIuY2hhckNvZGVBdChpZHggKz0gMyAvIDQpO1xuICAgIGlmIChjaGFyQ29kZSA+IDB4RkYpIHtcbiAgICAgIHRocm93IG5ldyBFKCk7XG4gICAgfVxuICAgIGJsb2NrID0gYmxvY2sgPDwgOCB8IGNoYXJDb2RlO1xuICB9XG4gIHJldHVybiBvdXRwdXQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnRvYTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9oZWxwZXJzL2J0b2EuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9oZWxwZXJzL2J0b2EuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/helpers/btoa.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 }\n\n if (!utils.isArray(val)) {\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/MGQwMCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYnVpbGRVUkwuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlscyA9IHJlcXVpcmUoJy4vLi4vdXRpbHMnKTtcblxuZnVuY3Rpb24gZW5jb2RlKHZhbCkge1xuICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KHZhbCkuXG4gICAgcmVwbGFjZSgvJTQwL2dpLCAnQCcpLlxuICAgIHJlcGxhY2UoLyUzQS9naSwgJzonKS5cbiAgICByZXBsYWNlKC8lMjQvZywgJyQnKS5cbiAgICByZXBsYWNlKC8lMkMvZ2ksICcsJykuXG4gICAgcmVwbGFjZSgvJTIwL2csICcrJykuXG4gICAgcmVwbGFjZSgvJTVCL2dpLCAnWycpLlxuICAgIHJlcGxhY2UoLyU1RC9naSwgJ10nKTtcbn1cblxuLyoqXG4gKiBCdWlsZCBhIFVSTCBieSBhcHBlbmRpbmcgcGFyYW1zIHRvIHRoZSBlbmRcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIFRoZSBiYXNlIG9mIHRoZSB1cmwgKGUuZy4sIGh0dHA6Ly93d3cuZ29vZ2xlLmNvbSlcbiAqIEBwYXJhbSB7b2JqZWN0fSBbcGFyYW1zXSBUaGUgcGFyYW1zIHRvIGJlIGFwcGVuZGVkXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHVybFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGJ1aWxkVVJMKHVybCwgcGFyYW1zLCBwYXJhbXNTZXJpYWxpemVyKSB7XG4gIC8qZXNsaW50IG5vLXBhcmFtLXJlYXNzaWduOjAqL1xuICBpZiAoIXBhcmFtcykge1xuICAgIHJldHVybiB1cmw7XG4gIH1cblxuICB2YXIgc2VyaWFsaXplZFBhcmFtcztcbiAgaWYgKHBhcmFtc1NlcmlhbGl6ZXIpIHtcbiAgICBzZXJpYWxpemVkUGFyYW1zID0gcGFyYW1zU2VyaWFsaXplcihwYXJhbXMpO1xuICB9IGVsc2UgaWYgKHV0aWxzLmlzVVJMU2VhcmNoUGFyYW1zKHBhcmFtcykpIHtcbiAgICBzZXJpYWxpemVkUGFyYW1zID0gcGFyYW1zLnRvU3RyaW5nKCk7XG4gIH0gZWxzZSB7XG4gICAgdmFyIHBhcnRzID0gW107XG5cbiAgICB1dGlscy5mb3JFYWNoKHBhcmFtcywgZnVuY3Rpb24gc2VyaWFsaXplKHZhbCwga2V5KSB7XG4gICAgICBpZiAodmFsID09PSBudWxsIHx8IHR5cGVvZiB2YWwgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHV0aWxzLmlzQXJyYXkodmFsKSkge1xuICAgICAgICBrZXkgPSBrZXkgKyAnW10nO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXV0aWxzLmlzQXJyYXkodmFsKSkge1xuICAgICAgICB2YWwgPSBbdmFsXTtcbiAgICAgIH1cblxuICAgICAgdXRpbHMuZm9yRWFjaCh2YWwsIGZ1bmN0aW9uIHBhcnNlVmFsdWUodikge1xuICAgICAgICBpZiAodXRpbHMuaXNEYXRlKHYpKSB7XG4gICAgICAgICAgdiA9IHYudG9JU09TdHJpbmcoKTtcbiAgICAgICAgfSBlbHNlIGlmICh1dGlscy5pc09iamVjdCh2KSkge1xuICAgICAgICAgIHYgPSBKU09OLnN0cmluZ2lmeSh2KTtcbiAgICAgICAgfVxuICAgICAgICBwYXJ0cy5wdXNoKGVuY29kZShrZXkpICsgJz0nICsgZW5jb2RlKHYpKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgc2VyaWFsaXplZFBhcmFtcyA9IHBhcnRzLmpvaW4oJyYnKTtcbiAgfVxuXG4gIGlmIChzZXJpYWxpemVkUGFyYW1zKSB7XG4gICAgdXJsICs9ICh1cmwuaW5kZXhPZignPycpID09PSAtMSA/ICc/JyA6ICcmJykgKyBzZXJpYWxpemVkUGFyYW1zO1xuICB9XG5cbiAgcmV0dXJuIHVybDtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9idWlsZFVSTC5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvYnVpbGRVUkwuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\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/YTkxNyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvY29tYmluZVVSTHMuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBVUkwgYnkgY29tYmluaW5nIHRoZSBzcGVjaWZpZWQgVVJMc1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlVVJMIFRoZSBiYXNlIFVSTFxuICogQHBhcmFtIHtzdHJpbmd9IHJlbGF0aXZlVVJMIFRoZSByZWxhdGl2ZSBVUkxcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjb21iaW5lZCBVUkxcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjb21iaW5lVVJMcyhiYXNlVVJMLCByZWxhdGl2ZVVSTCkge1xuICByZXR1cm4gcmVsYXRpdmVVUkxcbiAgICA/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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvY29va2llcy5qcz9hNzU2Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSx3Q0FBd0M7QUFDeEMsT0FBTzs7QUFFUDtBQUNBLDBEQUEwRCx3QkFBd0I7QUFDbEY7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEMsNkJBQTZCLGFBQWEsRUFBRTtBQUM1QztBQUNBO0FBQ0EsR0FBRztBQUNIIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9oZWxwZXJzL2Nvb2tpZXMuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciB1dGlscyA9IHJlcXVpcmUoJy4vLi4vdXRpbHMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSAoXG4gIHV0aWxzLmlzU3RhbmRhcmRCcm93c2VyRW52KCkgP1xuXG4gIC8vIFN0YW5kYXJkIGJyb3dzZXIgZW52cyBzdXBwb3J0IGRvY3VtZW50LmNvb2tpZVxuICAoZnVuY3Rpb24gc3RhbmRhcmRCcm93c2VyRW52KCkge1xuICAgIHJldHVybiB7XG4gICAgICB3cml0ZTogZnVuY3Rpb24gd3JpdGUobmFtZSwgdmFsdWUsIGV4cGlyZXMsIHBhdGgsIGRvbWFpbiwgc2VjdXJlKSB7XG4gICAgICAgIHZhciBjb29raWUgPSBbXTtcbiAgICAgICAgY29va2llLnB1c2gobmFtZSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudCh2YWx1ZSkpO1xuXG4gICAgICAgIGlmICh1dGlscy5pc051bWJlcihleHBpcmVzKSkge1xuICAgICAgICAgIGNvb2tpZS5wdXNoKCdleHBpcmVzPScgKyBuZXcgRGF0ZShleHBpcmVzKS50b0dNVFN0cmluZygpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh1dGlscy5pc1N0cmluZyhwYXRoKSkge1xuICAgICAgICAgIGNvb2tpZS5wdXNoKCdwYXRoPScgKyBwYXRoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh1dGlscy5pc1N0cmluZyhkb21haW4pKSB7XG4gICAgICAgICAgY29va2llLnB1c2goJ2RvbWFpbj0nICsgZG9tYWluKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzZWN1cmUgPT09IHRydWUpIHtcbiAgICAgICAgICBjb29raWUucHVzaCgnc2VjdXJlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBkb2N1bWVudC5jb29raWUgPSBjb29raWUuam9pbignOyAnKTtcbiAgICAgIH0sXG5cbiAgICAgIHJlYWQ6IGZ1bmN0aW9uIHJlYWQobmFtZSkge1xuICAgICAgICB2YXIgbWF0Y2ggPSBkb2N1bWVudC5jb29raWUubWF0Y2gobmV3IFJlZ0V4cCgnKF58O1xcXFxzKikoJyArIG5hbWUgKyAnKT0oW147XSopJykpO1xuICAgICAgICByZXR1cm4gKG1hdGNoID8gZGVjb2RlVVJJQ29tcG9uZW50KG1hdGNoWzNdKSA6IG51bGwpO1xuICAgICAgfSxcblxuICAgICAgcmVtb3ZlOiBmdW5jdGlvbiByZW1vdmUobmFtZSkge1xuICAgICAgICB0aGlzLndyaXRlKG5hbWUsICcnLCBEYXRlLm5vdygpIC0gODY0MDAwMDApO1xuICAgICAgfVxuICAgIH07XG4gIH0pKCkgOlxuXG4gIC8vIE5vbiBzdGFuZGFyZCBicm93c2VyIGVudiAod2ViIHdvcmtlcnMsIHJlYWN0LW5hdGl2ZSkgbGFjayBuZWVkZWQgc3VwcG9ydC5cbiAgKGZ1bmN0aW9uIG5vblN0YW5kYXJkQnJvd3NlckVudigpIHtcbiAgICByZXR1cm4ge1xuICAgICAgd3JpdGU6IGZ1bmN0aW9uIHdyaXRlKCkge30sXG4gICAgICByZWFkOiBmdW5jdGlvbiByZWFkKCkgeyByZXR1cm4gbnVsbDsgfSxcbiAgICAgIHJlbW92ZTogZnVuY3Rpb24gcmVtb3ZlKCkge31cbiAgICB9O1xuICB9KSgpXG4pO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvY29va2llcy5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvY29va2llcy5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNBYnNvbHV0ZVVSTC5qcz83NDhjIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNBYnNvbHV0ZVVSTC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuLyoqXG4gKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlIHNwZWNpZmllZCBVUkwgaXMgYWJzb2x1dGVcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIFRoZSBVUkwgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHNwZWNpZmllZCBVUkwgaXMgYWJzb2x1dGUsIG90aGVyd2lzZSBmYWxzZVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzQWJzb2x1dGVVUkwodXJsKSB7XG4gIC8vIEEgVVJMIGlzIGNvbnNpZGVyZWQgYWJzb2x1dGUgaWYgaXQgYmVnaW5zIHdpdGggXCI8c2NoZW1lPjovL1wiIG9yIFwiLy9cIiAocHJvdG9jb2wtcmVsYXRpdmUgVVJMKS5cbiAgLy8gUkZDIDM5ODYgZGVmaW5lcyBzY2hlbWUgbmFtZSBhcyBhIHNlcXVlbmNlIG9mIGNoYXJhY3RlcnMgYmVnaW5uaW5nIHdpdGggYSBsZXR0ZXIgYW5kIGZvbGxvd2VkXG4gIC8vIGJ5IGFueSBjb21iaW5hdGlvbiBvZiBsZXR0ZXJzLCBkaWdpdHMsIHBsdXMsIHBlcmlvZCwgb3IgaHlwaGVuLlxuICByZXR1cm4gL14oW2Etel1bYS16XFxkXFwrXFwtXFwuXSo6KT9cXC9cXC8vaS50ZXN0KHVybCk7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNBYnNvbHV0ZVVSTC5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNBYnNvbHV0ZVVSTC5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNVUkxTYW1lT3JpZ2luLmpzPzE4NzAiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixnQkFBZ0IsUUFBUTtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0giLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNVUkxTYW1lT3JpZ2luLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLy4uL3V0aWxzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gKFxuICB1dGlscy5pc1N0YW5kYXJkQnJvd3NlckVudigpID9cblxuICAvLyBTdGFuZGFyZCBicm93c2VyIGVudnMgaGF2ZSBmdWxsIHN1cHBvcnQgb2YgdGhlIEFQSXMgbmVlZGVkIHRvIHRlc3RcbiAgLy8gd2hldGhlciB0aGUgcmVxdWVzdCBVUkwgaXMgb2YgdGhlIHNhbWUgb3JpZ2luIGFzIGN1cnJlbnQgbG9jYXRpb24uXG4gIChmdW5jdGlvbiBzdGFuZGFyZEJyb3dzZXJFbnYoKSB7XG4gICAgdmFyIG1zaWUgPSAvKG1zaWV8dHJpZGVudCkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgIHZhciB1cmxQYXJzaW5nTm9kZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICB2YXIgb3JpZ2luVVJMO1xuXG4gICAgLyoqXG4gICAgKiBQYXJzZSBhIFVSTCB0byBkaXNjb3ZlciBpdCdzIGNvbXBvbmVudHNcbiAgICAqXG4gICAgKiBAcGFyYW0ge1N0cmluZ30gdXJsIFRoZSBVUkwgdG8gYmUgcGFyc2VkXG4gICAgKiBAcmV0dXJucyB7T2JqZWN0fVxuICAgICovXG4gICAgZnVuY3Rpb24gcmVzb2x2ZVVSTCh1cmwpIHtcbiAgICAgIHZhciBocmVmID0gdXJsO1xuXG4gICAgICBpZiAobXNpZSkge1xuICAgICAgICAvLyBJRSBuZWVkcyBhdHRyaWJ1dGUgc2V0IHR3aWNlIHRvIG5vcm1hbGl6ZSBwcm9wZXJ0aWVzXG4gICAgICAgIHVybFBhcnNpbmdOb2RlLnNldEF0dHJpYnV0ZSgnaHJlZicsIGhyZWYpO1xuICAgICAgICBocmVmID0gdXJsUGFyc2luZ05vZGUuaHJlZjtcbiAgICAgIH1cblxuICAgICAgdXJsUGFyc2luZ05vZGUuc2V0QXR0cmlidXRlKCdocmVmJywgaHJlZik7XG5cbiAgICAgIC8vIHVybFBhcnNpbmdOb2RlIHByb3ZpZGVzIHRoZSBVcmxVdGlscyBpbnRlcmZhY2UgLSBodHRwOi8vdXJsLnNwZWMud2hhdHdnLm9yZy8jdXJsdXRpbHNcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGhyZWY6IHVybFBhcnNpbmdOb2RlLmhyZWYsXG4gICAgICAgIHByb3RvY29sOiB1cmxQYXJzaW5nTm9kZS5wcm90b2NvbCA/IHVybFBhcnNpbmdOb2RlLnByb3RvY29sLnJlcGxhY2UoLzokLywgJycpIDogJycsXG4gICAgICAgIGhvc3Q6IHVybFBhcnNpbmdOb2RlLmhvc3QsXG4gICAgICAgIHNlYXJjaDogdXJsUGFyc2luZ05vZGUuc2VhcmNoID8gdXJsUGFyc2luZ05vZGUuc2VhcmNoLnJlcGxhY2UoL15cXD8vLCAnJykgOiAnJyxcbiAgICAgICAgaGFzaDogdXJsUGFyc2luZ05vZGUuaGFzaCA/IHVybFBhcnNpbmdOb2RlLmhhc2gucmVwbGFjZSgvXiMvLCAnJykgOiAnJyxcbiAgICAgICAgaG9zdG5hbWU6IHVybFBhcnNpbmdOb2RlLmhvc3RuYW1lLFxuICAgICAgICBwb3J0OiB1cmxQYXJzaW5nTm9kZS5wb3J0LFxuICAgICAgICBwYXRobmFtZTogKHVybFBhcnNpbmdOb2RlLnBhdGhuYW1lLmNoYXJBdCgwKSA9PT0gJy8nKSA/XG4gICAgICAgICAgICAgICAgICB1cmxQYXJzaW5nTm9kZS5wYXRobmFtZSA6XG4gICAgICAgICAgICAgICAgICAnLycgKyB1cmxQYXJzaW5nTm9kZS5wYXRobmFtZVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBvcmlnaW5VUkwgPSByZXNvbHZlVVJMKHdpbmRvdy5sb2NhdGlvbi5ocmVmKTtcblxuICAgIC8qKlxuICAgICogRGV0ZXJtaW5lIGlmIGEgVVJMIHNoYXJlcyB0aGUgc2FtZSBvcmlnaW4gYXMgdGhlIGN1cnJlbnQgbG9jYXRpb25cbiAgICAqXG4gICAgKiBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdFVSTCBUaGUgVVJMIHRvIHRlc3RcbiAgICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIFVSTCBzaGFyZXMgdGhlIHNhbWUgb3JpZ2luLCBvdGhlcndpc2UgZmFsc2VcbiAgICAqL1xuICAgIHJldHVybiBmdW5jdGlvbiBpc1VSTFNhbWVPcmlnaW4ocmVxdWVzdFVSTCkge1xuICAgICAgdmFyIHBhcnNlZCA9ICh1dGlscy5pc1N0cmluZyhyZXF1ZXN0VVJMKSkgPyByZXNvbHZlVVJMKHJlcXVlc3RVUkwpIDogcmVxdWVzdFVSTDtcbiAgICAgIHJldHVybiAocGFyc2VkLnByb3RvY29sID09PSBvcmlnaW5VUkwucHJvdG9jb2wgJiZcbiAgICAgICAgICAgIHBhcnNlZC5ob3N0ID09PSBvcmlnaW5VUkwuaG9zdCk7XG4gICAgfTtcbiAgfSkoKSA6XG5cbiAgLy8gTm9uIHN0YW5kYXJkIGJyb3dzZXIgZW52cyAod2ViIHdvcmtlcnMsIHJlYWN0LW5hdGl2ZSkgbGFjayBuZWVkZWQgc3VwcG9ydC5cbiAgKGZ1bmN0aW9uIG5vblN0YW5kYXJkQnJvd3NlckVudigpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gaXNVUkxTYW1lT3JpZ2luKCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcbiAgfSkoKVxuKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9oZWxwZXJzL2lzVVJMU2FtZU9yaWdpbi5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvaXNVUkxTYW1lT3JpZ2luLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvbm9ybWFsaXplSGVhZGVyTmFtZS5qcz9lNTU0Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9ub3JtYWxpemVIZWFkZXJOYW1lLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLi91dGlscycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG5vcm1hbGl6ZUhlYWRlck5hbWUoaGVhZGVycywgbm9ybWFsaXplZE5hbWUpIHtcbiAgdXRpbHMuZm9yRWFjaChoZWFkZXJzLCBmdW5jdGlvbiBwcm9jZXNzSGVhZGVyKHZhbHVlLCBuYW1lKSB7XG4gICAgaWYgKG5hbWUgIT09IG5vcm1hbGl6ZWROYW1lICYmIG5hbWUudG9VcHBlckNhc2UoKSA9PT0gbm9ybWFsaXplZE5hbWUudG9VcHBlckNhc2UoKSkge1xuICAgICAgaGVhZGVyc1tub3JtYWxpemVkTmFtZV0gPSB2YWx1ZTtcbiAgICAgIGRlbGV0ZSBoZWFkZXJzW25hbWVdO1xuICAgIH1cbiAgfSk7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvbm9ybWFsaXplSGVhZGVyTmFtZS5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvbm9ybWFsaXplSGVhZGVyTmFtZS5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvcGFyc2VIZWFkZXJzLmpzP2EwOTkiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlCQUFpQixlQUFlOztBQUVoQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9oZWxwZXJzL3BhcnNlSGVhZGVycy5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxudmFyIHV0aWxzID0gcmVxdWlyZSgnLi8uLi91dGlscycpO1xuXG4vLyBIZWFkZXJzIHdob3NlIGR1cGxpY2F0ZXMgYXJlIGlnbm9yZWQgYnkgbm9kZVxuLy8gYy5mLiBodHRwczovL25vZGVqcy5vcmcvYXBpL2h0dHAuaHRtbCNodHRwX21lc3NhZ2VfaGVhZGVyc1xudmFyIGlnbm9yZUR1cGxpY2F0ZU9mID0gW1xuICAnYWdlJywgJ2F1dGhvcml6YXRpb24nLCAnY29udGVudC1sZW5ndGgnLCAnY29udGVudC10eXBlJywgJ2V0YWcnLFxuICAnZXhwaXJlcycsICdmcm9tJywgJ2hvc3QnLCAnaWYtbW9kaWZpZWQtc2luY2UnLCAnaWYtdW5tb2RpZmllZC1zaW5jZScsXG4gICdsYXN0LW1vZGlmaWVkJywgJ2xvY2F0aW9uJywgJ21heC1mb3J3YXJkcycsICdwcm94eS1hdXRob3JpemF0aW9uJyxcbiAgJ3JlZmVyZXInLCAncmV0cnktYWZ0ZXInLCAndXNlci1hZ2VudCdcbl07XG5cbi8qKlxuICogUGFyc2UgaGVhZGVycyBpbnRvIGFuIG9iamVjdFxuICpcbiAqIGBgYFxuICogRGF0ZTogV2VkLCAyNyBBdWcgMjAxNCAwODo1ODo0OSBHTVRcbiAqIENvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvblxuICogQ29ubmVjdGlvbjoga2VlcC1hbGl2ZVxuICogVHJhbnNmZXItRW5jb2Rpbmc6IGNodW5rZWRcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBoZWFkZXJzIEhlYWRlcnMgbmVlZGluZyB0byBiZSBwYXJzZWRcbiAqIEByZXR1cm5zIHtPYmplY3R9IEhlYWRlcnMgcGFyc2VkIGludG8gYW4gb2JqZWN0XG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFyc2VIZWFkZXJzKGhlYWRlcnMpIHtcbiAgdmFyIHBhcnNlZCA9IHt9O1xuICB2YXIga2V5O1xuICB2YXIgdmFsO1xuICB2YXIgaTtcblxuICBpZiAoIWhlYWRlcnMpIHsgcmV0dXJuIHBhcnNlZDsgfVxuXG4gIHV0aWxzLmZvckVhY2goaGVhZGVycy5zcGxpdCgnXFxuJyksIGZ1bmN0aW9uIHBhcnNlcihsaW5lKSB7XG4gICAgaSA9IGxpbmUuaW5kZXhPZignOicpO1xuICAgIGtleSA9IHV0aWxzLnRyaW0obGluZS5zdWJzdHIoMCwgaSkpLnRvTG93ZXJDYXNlKCk7XG4gICAgdmFsID0gdXRpbHMudHJpbShsaW5lLnN1YnN0cihpICsgMSkpO1xuXG4gICAgaWYgKGtleSkge1xuICAgICAgaWYgKHBhcnNlZFtrZXldICYmIGlnbm9yZUR1cGxpY2F0ZU9mLmluZGV4T2Yoa2V5KSA+PSAwKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChrZXkgPT09ICdzZXQtY29va2llJykge1xuICAgICAgICBwYXJzZWRba2V5XSA9IChwYXJzZWRba2V5XSA/IHBhcnNlZFtrZXldIDogW10pLmNvbmNhdChbdmFsXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYXJzZWRba2V5XSA9IHBhcnNlZFtrZXldID8gcGFyc2VkW2tleV0gKyAnLCAnICsgdmFsIDogdmFsO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIHBhcnNlZDtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9wYXJzZUhlYWRlcnMuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9oZWxwZXJzL3BhcnNlSGVhZGVycy5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSAyIl0sInNvdXJjZVJvb3QiOiIifQ==\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvc3ByZWFkLmpzP2E3MTEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvc3ByZWFkLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG4vKipcbiAqIFN5bnRhY3RpYyBzdWdhciBmb3IgaW52b2tpbmcgYSBmdW5jdGlvbiBhbmQgZXhwYW5kaW5nIGFuIGFycmF5IGZvciBhcmd1bWVudHMuXG4gKlxuICogQ29tbW9uIHVzZSBjYXNlIHdvdWxkIGJlIHRvIHVzZSBgRnVuY3Rpb24ucHJvdG90eXBlLmFwcGx5YC5cbiAqXG4gKiAgYGBganNcbiAqICBmdW5jdGlvbiBmKHgsIHksIHopIHt9XG4gKiAgdmFyIGFyZ3MgPSBbMSwgMiwgM107XG4gKiAgZi5hcHBseShudWxsLCBhcmdzKTtcbiAqICBgYGBcbiAqXG4gKiBXaXRoIGBzcHJlYWRgIHRoaXMgZXhhbXBsZSBjYW4gYmUgcmUtd3JpdHRlbi5cbiAqXG4gKiAgYGBganNcbiAqICBzcHJlYWQoZnVuY3Rpb24oeCwgeSwgeikge30pKFsxLCAyLCAzXSk7XG4gKiAgYGBgXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn1cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzcHJlYWQoY2FsbGJhY2spIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHdyYXAoYXJyKSB7XG4gICAgcmV0dXJuIGNhbGxiYWNrLmFwcGx5KG51bGwsIGFycik7XG4gIH07XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvc3ByZWFkLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9zcHJlYWQuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\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/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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL3V0aWxzLmpzPzcwNjEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsYUFBYTtBQUN4QixXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1DQUFtQyxPQUFPO0FBQzFDO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixTQUFTLEdBQUcsU0FBUztBQUM1QywyQkFBMkI7QUFDM0I7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSx1Q0FBdUMsT0FBTztBQUM5QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQixZQUFZLE9BQU87QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL3V0aWxzLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYmluZCA9IHJlcXVpcmUoJy4vaGVscGVycy9iaW5kJyk7XG52YXIgaXNCdWZmZXIgPSByZXF1aXJlKCdpcy1idWZmZXInKTtcblxuLypnbG9iYWwgdG9TdHJpbmc6dHJ1ZSovXG5cbi8vIHV0aWxzIGlzIGEgbGlicmFyeSBvZiBnZW5lcmljIGhlbHBlciBmdW5jdGlvbnMgbm9uLXNwZWNpZmljIHRvIGF4aW9zXG5cbnZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYW4gQXJyYXlcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhbiBBcnJheSwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzQXJyYXkodmFsKSB7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKHZhbCkgPT09ICdbb2JqZWN0IEFycmF5XSc7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYW4gQXJyYXlCdWZmZXJcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhbiBBcnJheUJ1ZmZlciwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzQXJyYXlCdWZmZXIodmFsKSB7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKHZhbCkgPT09ICdbb2JqZWN0IEFycmF5QnVmZmVyXSc7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBGb3JtRGF0YVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGFuIEZvcm1EYXRhLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNGb3JtRGF0YSh2YWwpIHtcbiAgcmV0dXJuICh0eXBlb2YgRm9ybURhdGEgIT09ICd1bmRlZmluZWQnKSAmJiAodmFsIGluc3RhbmNlb2YgRm9ybURhdGEpO1xufVxuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGEgdmlldyBvbiBhbiBBcnJheUJ1ZmZlclxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGEgdmlldyBvbiBhbiBBcnJheUJ1ZmZlciwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzQXJyYXlCdWZmZXJWaWV3KHZhbCkge1xuICB2YXIgcmVzdWx0O1xuICBpZiAoKHR5cGVvZiBBcnJheUJ1ZmZlciAhPT0gJ3VuZGVmaW5lZCcpICYmIChBcnJheUJ1ZmZlci5pc1ZpZXcpKSB7XG4gICAgcmVzdWx0ID0gQXJyYXlCdWZmZXIuaXNWaWV3KHZhbCk7XG4gIH0gZWxzZSB7XG4gICAgcmVzdWx0ID0gKHZhbCkgJiYgKHZhbC5idWZmZXIpICYmICh2YWwuYnVmZmVyIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBTdHJpbmdcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIFN0cmluZywgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzU3RyaW5nKHZhbCkge1xuICByZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ3N0cmluZyc7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBOdW1iZXJcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gdmFsIFRoZSB2YWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZSBpcyBhIE51bWJlciwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzTnVtYmVyKHZhbCkge1xuICByZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ251bWJlcic7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgdW5kZWZpbmVkXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIHVuZGVmaW5lZCwgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKHZhbCkge1xuICByZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ3VuZGVmaW5lZCc7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYW4gT2JqZWN0XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYW4gT2JqZWN0LCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNPYmplY3QodmFsKSB7XG4gIHJldHVybiB2YWwgIT09IG51bGwgJiYgdHlwZW9mIHZhbCA9PT0gJ29iamVjdCc7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBEYXRlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBEYXRlLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNEYXRlKHZhbCkge1xuICByZXR1cm4gdG9TdHJpbmcuY2FsbCh2YWwpID09PSAnW29iamVjdCBEYXRlXSc7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBGaWxlXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBGaWxlLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNGaWxlKHZhbCkge1xuICByZXR1cm4gdG9TdHJpbmcuY2FsbCh2YWwpID09PSAnW29iamVjdCBGaWxlXSc7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBCbG9iXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBCbG9iLCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNCbG9iKHZhbCkge1xuICByZXR1cm4gdG9TdHJpbmcuY2FsbCh2YWwpID09PSAnW29iamVjdCBCbG9iXSc7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBGdW5jdGlvblxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB2YWwgVGhlIHZhbHVlIHRvIHRlc3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIGEgRnVuY3Rpb24sIG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKHZhbCkge1xuICByZXR1cm4gdG9TdHJpbmcuY2FsbCh2YWwpID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG4vKipcbiAqIERldGVybWluZSBpZiBhIHZhbHVlIGlzIGEgU3RyZWFtXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBTdHJlYW0sIG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiBpc1N0cmVhbSh2YWwpIHtcbiAgcmV0dXJuIGlzT2JqZWN0KHZhbCkgJiYgaXNGdW5jdGlvbih2YWwucGlwZSk7XG59XG5cbi8qKlxuICogRGV0ZXJtaW5lIGlmIGEgdmFsdWUgaXMgYSBVUkxTZWFyY2hQYXJhbXMgb2JqZWN0XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHZhbCBUaGUgdmFsdWUgdG8gdGVzdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgYSBVUkxTZWFyY2hQYXJhbXMgb2JqZWN0LCBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNVUkxTZWFyY2hQYXJhbXModmFsKSB7XG4gIHJldHVybiB0eXBlb2YgVVJMU2VhcmNoUGFyYW1zICE9PSAndW5kZWZpbmVkJyAmJiB2YWwgaW5zdGFuY2VvZiBVUkxTZWFyY2hQYXJhbXM7XG59XG5cbi8qKlxuICogVHJpbSBleGNlc3Mgd2hpdGVzcGFjZSBvZmYgdGhlIGJlZ2lubmluZyBhbmQgZW5kIG9mIGEgc3RyaW5nXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHN0ciBUaGUgU3RyaW5nIHRvIHRyaW1cbiAqIEByZXR1cm5zIHtTdHJpbmd9IFRoZSBTdHJpbmcgZnJlZWQgb2YgZXhjZXNzIHdoaXRlc3BhY2VcbiAqL1xuZnVuY3Rpb24gdHJpbShzdHIpIHtcbiAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eXFxzKi8sICcnKS5yZXBsYWNlKC9cXHMqJC8sICcnKTtcbn1cblxuLyoqXG4gKiBEZXRlcm1pbmUgaWYgd2UncmUgcnVubmluZyBpbiBhIHN0YW5kYXJkIGJyb3dzZXIgZW52aXJvbm1lbnRcbiAqXG4gKiBUaGlzIGFsbG93cyBheGlvcyB0byBydW4gaW4gYSB3ZWIgd29ya2VyLCBhbmQgcmVhY3QtbmF0aXZlLlxuICogQm90aCBlbnZpcm9ubWVudHMgc3VwcG9ydCBYTUxIdHRwUmVxdWVzdCwgYnV0IG5vdCBmdWxseSBzdGFuZGFyZCBnbG9iYWxzLlxuICpcbiAqIHdlYiB3b3JrZXJzOlxuICogIHR5cGVvZiB3aW5kb3cgLT4gdW5kZWZpbmVkXG4gKiAgdHlwZW9mIGRvY3VtZW50IC0+IHVuZGVmaW5lZFxuICpcbiAqIHJlYWN0LW5hdGl2ZTpcbiAqICBuYXZpZ2F0b3IucHJvZHVjdCAtPiAnUmVhY3ROYXRpdmUnXG4gKi9cbmZ1bmN0aW9uIGlzU3RhbmRhcmRCcm93c2VyRW52KCkge1xuICBpZiAodHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcgJiYgbmF2aWdhdG9yLnByb2R1Y3QgPT09ICdSZWFjdE5hdGl2ZScpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIChcbiAgICB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJlxuICAgIHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCdcbiAgKTtcbn1cblxuLyoqXG4gKiBJdGVyYXRlIG92ZXIgYW4gQXJyYXkgb3IgYW4gT2JqZWN0IGludm9raW5nIGEgZnVuY3Rpb24gZm9yIGVhY2ggaXRlbS5cbiAqXG4gKiBJZiBgb2JqYCBpcyBhbiBBcnJheSBjYWxsYmFjayB3aWxsIGJlIGNhbGxlZCBwYXNzaW5nXG4gKiB0aGUgdmFsdWUsIGluZGV4LCBhbmQgY29tcGxldGUgYXJyYXkgZm9yIGVhY2ggaXRlbS5cbiAqXG4gKiBJZiAnb2JqJyBpcyBhbiBPYmplY3QgY2FsbGJhY2sgd2lsbCBiZSBjYWxsZWQgcGFzc2luZ1xuICogdGhlIHZhbHVlLCBrZXksIGFuZCBjb21wbGV0ZSBvYmplY3QgZm9yIGVhY2ggcHJvcGVydHkuXG4gKlxuICogQHBhcmFtIHtPYmplY3R8QXJyYXl9IG9iaiBUaGUgb2JqZWN0IHRvIGl0ZXJhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBjYWxsYmFjayB0byBpbnZva2UgZm9yIGVhY2ggaXRlbVxuICovXG5mdW5jdGlvbiBmb3JFYWNoKG9iaiwgZm4pIHtcbiAgLy8gRG9uJ3QgYm90aGVyIGlmIG5vIHZhbHVlIHByb3ZpZGVkXG4gIGlmIChvYmogPT09IG51bGwgfHwgdHlwZW9mIG9iaiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBGb3JjZSBhbiBhcnJheSBpZiBub3QgYWxyZWFkeSBzb21ldGhpbmcgaXRlcmFibGVcbiAgaWYgKHR5cGVvZiBvYmogIT09ICdvYmplY3QnKSB7XG4gICAgLyplc2xpbnQgbm8tcGFyYW0tcmVhc3NpZ246MCovXG4gICAgb2JqID0gW29ial07XG4gIH1cblxuICBpZiAoaXNBcnJheShvYmopKSB7XG4gICAgLy8gSXRlcmF0ZSBvdmVyIGFycmF5IHZhbHVlc1xuICAgIGZvciAodmFyIGkgPSAwLCBsID0gb2JqLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgZm4uY2FsbChudWxsLCBvYmpbaV0sIGksIG9iaik7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIEl0ZXJhdGUgb3ZlciBvYmplY3Qga2V5c1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpKSB7XG4gICAgICAgIGZuLmNhbGwobnVsbCwgb2JqW2tleV0sIGtleSwgb2JqKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBBY2NlcHRzIHZhcmFyZ3MgZXhwZWN0aW5nIGVhY2ggYXJndW1lbnQgdG8gYmUgYW4gb2JqZWN0LCB0aGVuXG4gKiBpbW11dGFibHkgbWVyZ2VzIHRoZSBwcm9wZXJ0aWVzIG9mIGVhY2ggb2JqZWN0IGFuZCByZXR1cm5zIHJlc3VsdC5cbiAqXG4gKiBXaGVuIG11bHRpcGxlIG9iamVjdHMgY29udGFpbiB0aGUgc2FtZSBrZXkgdGhlIGxhdGVyIG9iamVjdCBpblxuICogdGhlIGFyZ3VtZW50cyBsaXN0IHdpbGwgdGFrZSBwcmVjZWRlbmNlLlxuICpcbiAqIEV4YW1wbGU6XG4gKlxuICogYGBganNcbiAqIHZhciByZXN1bHQgPSBtZXJnZSh7Zm9vOiAxMjN9LCB7Zm9vOiA0NTZ9KTtcbiAqIGNvbnNvbGUubG9nKHJlc3VsdC5mb28pOyAvLyBvdXRwdXRzIDQ1NlxuICogYGBgXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iajEgT2JqZWN0IHRvIG1lcmdlXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXN1bHQgb2YgYWxsIG1lcmdlIHByb3BlcnRpZXNcbiAqL1xuZnVuY3Rpb24gbWVyZ2UoLyogb2JqMSwgb2JqMiwgb2JqMywgLi4uICovKSB7XG4gIHZhciByZXN1bHQgPSB7fTtcbiAgZnVuY3Rpb24gYXNzaWduVmFsdWUodmFsLCBrZXkpIHtcbiAgICBpZiAodHlwZW9mIHJlc3VsdFtrZXldID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgdmFsID09PSAnb2JqZWN0Jykge1xuICAgICAgcmVzdWx0W2tleV0gPSBtZXJnZShyZXN1bHRba2V5XSwgdmFsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0W2tleV0gPSB2YWw7XG4gICAgfVxuICB9XG5cbiAgZm9yICh2YXIgaSA9IDAsIGwgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgZm9yRWFjaChhcmd1bWVudHNbaV0sIGFzc2lnblZhbHVlKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vKipcbiAqIEV4dGVuZHMgb2JqZWN0IGEgYnkgbXV0YWJseSBhZGRpbmcgdG8gaXQgdGhlIHByb3BlcnRpZXMgb2Ygb2JqZWN0IGIuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGEgVGhlIG9iamVjdCB0byBiZSBleHRlbmRlZFxuICogQHBhcmFtIHtPYmplY3R9IGIgVGhlIG9iamVjdCB0byBjb3B5IHByb3BlcnRpZXMgZnJvbVxuICogQHBhcmFtIHtPYmplY3R9IHRoaXNBcmcgVGhlIG9iamVjdCB0byBiaW5kIGZ1bmN0aW9uIHRvXG4gKiBAcmV0dXJuIHtPYmplY3R9IFRoZSByZXN1bHRpbmcgdmFsdWUgb2Ygb2JqZWN0IGFcbiAqL1xuZnVuY3Rpb24gZXh0ZW5kKGEsIGIsIHRoaXNBcmcpIHtcbiAgZm9yRWFjaChiLCBmdW5jdGlvbiBhc3NpZ25WYWx1ZSh2YWwsIGtleSkge1xuICAgIGlmICh0aGlzQXJnICYmIHR5cGVvZiB2YWwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGFba2V5XSA9IGJpbmQodmFsLCB0aGlzQXJnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYVtrZXldID0gdmFsO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBhO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgaXNBcnJheTogaXNBcnJheSxcbiAgaXNBcnJheUJ1ZmZlcjogaXNBcnJheUJ1ZmZlcixcbiAgaXNCdWZmZXI6IGlzQnVmZmVyLFxuICBpc0Zvcm1EYXRhOiBpc0Zvcm1EYXRhLFxuICBpc0FycmF5QnVmZmVyVmlldzogaXNBcnJheUJ1ZmZlclZpZXcsXG4gIGlzU3RyaW5nOiBpc1N0cmluZyxcbiAgaXNOdW1iZXI6IGlzTnVtYmVyLFxuICBpc09iamVjdDogaXNPYmplY3QsXG4gIGlzVW5kZWZpbmVkOiBpc1VuZGVmaW5lZCxcbiAgaXNEYXRlOiBpc0RhdGUsXG4gIGlzRmlsZTogaXNGaWxlLFxuICBpc0Jsb2I6IGlzQmxvYixcbiAgaXNGdW5jdGlvbjogaXNGdW5jdGlvbixcbiAgaXNTdHJlYW06IGlzU3RyZWFtLFxuICBpc1VSTFNlYXJjaFBhcmFtczogaXNVUkxTZWFyY2hQYXJhbXMsXG4gIGlzU3RhbmRhcmRCcm93c2VyRW52OiBpc1N0YW5kYXJkQnJvd3NlckVudixcbiAgZm9yRWFjaDogZm9yRWFjaCxcbiAgbWVyZ2U6IG1lcmdlLFxuICBleHRlbmQ6IGV4dGVuZCxcbiAgdHJpbTogdHJpbVxufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi91dGlscy5qc1xuLy8gbW9kdWxlIGlkID0gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL3V0aWxzLmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./node_modules/axios/lib/utils.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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvZ2VvbGliL2Rpc3QvZ2VvbGliLmpzPzcwNmYiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLDRCQUE0QixJQUFJLFlBQVksSUFBSSxjQUFjLElBQUksZ0JBQWdCLElBQUksVUFBVSxJQUFJO0FBQ3BHLFNBQVM7QUFDVDtBQUNBO0FBQ0EsdUJBQXVCLFNBQVM7QUFDaEMsdUJBQXVCLGFBQWE7QUFDcEMsdUJBQXVCLFdBQVc7QUFDbEMsdUJBQXVCLFlBQVk7QUFDbkMsdUJBQXVCLHNCQUFzQjtBQUM3Qyx1QkFBdUIsc0JBQXNCO0FBQzdDLHVCQUF1QixxQkFBcUI7QUFDNUMsdUJBQXVCLG9CQUFvQjtBQUMzQyx1QkFBdUI7QUFDdkIsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG1CQUFtQjs7QUFFbkIsdUJBQXVCOztBQUV2Qjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9FQUFvRSxXQUFXLGNBQWMsRUFBRTtBQUMvRixpQkFBaUI7O0FBRWpCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7O0FBR1Q7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDO0FBQzlDLDRDQUE0QztBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxzRUFBc0U7QUFDdEU7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQztBQUMvQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUNBQW1DO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsYUFBYTs7QUFFYjtBQUNBLDJCQUEyQjtBQUMzQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1EQUFtRDs7QUFFbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQkFBb0I7QUFDcEI7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEM7QUFDOUMsNENBQTRDO0FBQzVDO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0EsMkRBQTJELG9DQUFvQyxHQUFHLHlDQUF5QztBQUMzSSxxQ0FBcUM7QUFDckM7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQSw2REFBNkQscUNBQXFDLEdBQUcsOEJBQThCO0FBQ25JLGlDQUFpQztBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhDQUE4QyxPQUFPOztBQUVyRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQsb0NBQW9DLEdBQUcseUNBQXlDO0FBQzNJLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhEQUE4RDtBQUM5RCw2REFBNkQscUNBQXFDLEdBQUcsOEJBQThCO0FBQ25JO0FBQ0E7QUFDQTs7QUFFQSxvRUFBb0UsU0FBUzs7QUFFN0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZEQUE2RCxxQ0FBcUMsR0FBRyw4QkFBOEI7QUFDbkk7QUFDQTs7QUFFQSwrQ0FBK0MsbUJBQW1COztBQUVsRTs7QUFFQTtBQUNBOztBQUVBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUEsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMERBQTBEO0FBQzFELHlEQUF5RCxxQ0FBcUMsR0FBRyw4QkFBOEI7QUFDL0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwrQ0FBK0MsbUJBQW1COztBQUVsRTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQSwrREFBK0QscUNBQXFDO0FBQ3BHLDZFQUE2RSxxQ0FBcUM7QUFDbEg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2REFBNkQscUNBQXFDO0FBQ2xHO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBLDZEQUE2RCxxQ0FBcUM7QUFDbEc7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0EsNkRBQTZELHFDQUFxQztBQUNsRztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDOztBQUVBO0FBQ0E7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBLCtEQUErRDtBQUMvRCxrRUFBa0UscUNBQXFDLEdBQUcsOEJBQThCO0FBQ3hJO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQSxhQUFhOztBQUViLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsK0NBQStDO0FBQy9DLDZDQUE2QztBQUM3QywyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0M7QUFDL0MsNkNBQTZDO0FBQzdDLDJDQUEyQztBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZDQUE2QztBQUM3QywyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsK0RBQStEO0FBQy9ELGtFQUFrRSxxQ0FBcUMsR0FBRyw4QkFBOEI7QUFDeEk7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0Esa0VBQWtFLHFDQUFxQyxHQUFHLDhCQUE4QjtBQUN4STtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSw4Q0FBOEMsT0FBTztBQUNyRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0Esc0VBQXNFO0FBQ3RFLHNFQUFzRTtBQUN0RTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTOzs7QUFHVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQscUNBQXFDO0FBQ2pHO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSw4Q0FBOEM7QUFDOUM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdEQUF3RDs7QUFFeEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLGFBQWE7O0FBRWI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEscUJBQXFCOztBQUVyQjs7QUFFQTs7QUFFQSx5QkFBeUI7O0FBRXpCO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQSxxQkFBcUI7O0FBRXJCOztBQUVBLHFCQUFxQjs7QUFFckI7O0FBRUE7O0FBRUEsaUJBQWlCOztBQUVqQjs7QUFFQSxhQUFhOztBQUViOztBQUVBLGFBQWE7O0FBRWI7QUFDQTtBQUNBOztBQUVBOztBQUVBOzs7QUFHQTs7QUFFQTs7QUFFQSxhQUFhOztBQUViOztBQUVBOztBQUVBOztBQUVBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUEsU0FBUzs7O0FBR1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVM7OztBQUdUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSzs7QUFFTDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsU0FBUztBQUFBOztBQUVUO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTs7QUFFQSxDQUFDIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2dlb2xpYi9kaXN0L2dlb2xpYi5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qISBnZW9saWIgMi4wLjIzIGJ5IE1hbnVlbCBCaWVoXHJcbiogTGlicmFyeSB0byBwcm92aWRlIGdlbyBmdW5jdGlvbnMgbGlrZSBkaXN0YW5jZSBjYWxjdWxhdGlvbixcclxuKiBjb252ZXJzaW9uIG9mIGRlY2ltYWwgY29vcmRpbmF0ZXMgdG8gc2V4YWdlc2ltYWwgYW5kIHZpY2UgdmVyc2EsIGV0Yy5cclxuKiBXR1MgODQgKFdvcmxkIEdlb2RldGljIFN5c3RlbSAxOTg0KVxyXG4qIFxyXG4qIEBhdXRob3IgTWFudWVsIEJpZWhcclxuKiBAdXJsIGh0dHA6Ly93d3cubWFudWVsYmllaC5jb20vXHJcbiogQHZlcnNpb24gMi4wLjIzXHJcbiogQGxpY2Vuc2UgTUlUIFxyXG4qKi87KGZ1bmN0aW9uKGdsb2JhbCwgdW5kZWZpbmVkKSB7XG5cbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIGZ1bmN0aW9uIEdlb2xpYigpIHt9XG5cbiAgICAvLyBDb25zdGFudHNcbiAgICBHZW9saWIuVE9fUkFEID0gTWF0aC5QSSAvIDE4MDtcbiAgICBHZW9saWIuVE9fREVHID0gMTgwIC8gTWF0aC5QSTtcbiAgICBHZW9saWIuUElfWDIgPSBNYXRoLlBJICogMjtcbiAgICBHZW9saWIuUElfRElWNCA9IE1hdGguUEkgLyA0O1xuXG4gICAgLy8gU2V0dGluZyByZWFkb25seSBkZWZhdWx0c1xuICAgIHZhciBnZW9saWIgPSBPYmplY3QuY3JlYXRlKEdlb2xpYi5wcm90b3R5cGUsIHtcbiAgICAgICAgdmVyc2lvbjoge1xuICAgICAgICAgICAgdmFsdWU6IFwiMi4wLjIzXCJcbiAgICAgICAgfSxcbiAgICAgICAgcmFkaXVzOiB7XG4gICAgICAgICAgICB2YWx1ZTogNjM3ODEzN1xuICAgICAgICB9LFxuICAgICAgICBtaW5MYXQ6IHtcbiAgICAgICAgICAgIHZhbHVlOiAtOTBcbiAgICAgICAgfSxcbiAgICAgICAgbWF4TGF0OiB7XG4gICAgICAgICAgICB2YWx1ZTogOTBcbiAgICAgICAgfSxcbiAgICAgICAgbWluTG9uOiB7XG4gICAgICAgICAgICB2YWx1ZTogLTE4MFxuICAgICAgICB9LFxuICAgICAgICBtYXhMb246IHtcbiAgICAgICAgICAgIHZhbHVlOiAxODBcbiAgICAgICAgfSxcbiAgICAgICAgc2V4YWdlc2ltYWxQYXR0ZXJuOiB7XG4gICAgICAgICAgICB2YWx1ZTogL14oWzAtOV17MSwzfSnCsFxccyooWzAtOV17MSwzfSg/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/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\n// The _isBuffer check is for Safari 5-7 support, because it's missing\n// Object.prototype.constructor. Remove this eventually\nmodule.exports = function (obj) {\n return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)\n}\n\nfunction isBuffer (obj) {\n return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)\n}\n\n// For Node v0.10 support. Remove this eventually.\nfunction isSlowBuffer (obj) {\n return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvaXMtYnVmZmVyL2luZGV4LmpzPzQ1ZWQiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2lzLWJ1ZmZlci9pbmRleC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIVxuICogRGV0ZXJtaW5lIGlmIGFuIG9iamVjdCBpcyBhIEJ1ZmZlclxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cblxuLy8gVGhlIF9pc0J1ZmZlciBjaGVjayBpcyBmb3IgU2FmYXJpIDUtNyBzdXBwb3J0LCBiZWNhdXNlIGl0J3MgbWlzc2luZ1xuLy8gT2JqZWN0LnByb3RvdHlwZS5jb25zdHJ1Y3Rvci4gUmVtb3ZlIHRoaXMgZXZlbnR1YWxseVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gIHJldHVybiBvYmogIT0gbnVsbCAmJiAoaXNCdWZmZXIob2JqKSB8fCBpc1Nsb3dCdWZmZXIob2JqKSB8fCAhIW9iai5faXNCdWZmZXIpXG59XG5cbmZ1bmN0aW9uIGlzQnVmZmVyIChvYmopIHtcbiAgcmV0dXJuICEhb2JqLmNvbnN0cnVjdG9yICYmIHR5cGVvZiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIgPT09ICdmdW5jdGlvbicgJiYgb2JqLmNvbnN0cnVjdG9yLmlzQnVmZmVyKG9iailcbn1cblxuLy8gRm9yIE5vZGUgdjAuMTAgc3VwcG9ydC4gUmVtb3ZlIHRoaXMgZXZlbnR1YWxseS5cbmZ1bmN0aW9uIGlzU2xvd0J1ZmZlciAob2JqKSB7XG4gIHJldHVybiB0eXBlb2Ygb2JqLnJlYWRGbG9hdExFID09PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBvYmouc2xpY2UgPT09ICdmdW5jdGlvbicgJiYgaXNCdWZmZXIob2JqLnNsaWNlKDAsIDApKVxufVxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvaXMtYnVmZmVyL2luZGV4LmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9pcy1idWZmZXIvaW5kZXguanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./node_modules/is-buffer/index.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.3.1, a JS library for interactive maps. http://leafletjs.com\n * (c) 2010-2017 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.3.1\";\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\tvar pow = Math.pow(10, (digits === undefined ? 6 : digits));\r\n\treturn Math.round(num * pow) / pow;\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.\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 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 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 SphericalMercator = {\r\n\r\n\tR: 6378137,\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 = 6378137 * 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.\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\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 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` 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 rect = container.getBoundingClientRect();\r\n\r\n\tvar scaleX = rect.width / container.offsetWidth || 1;\r\n\tvar scaleY = rect.height / container.offsetHeight || 1;\r\n\treturn new Point(\r\n\t\te.clientX / scaleX - rect.left - container.clientLeft,\r\n\t\te.clientY / scaleY - rect.top - container.clientTop);\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/*\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.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.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\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\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});\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\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._handlers = [];\r\n\t\tthis._layers = {};\r\n\t\tthis._zoomBoundLayers = {};\r\n\t\tthis._sizeChanged = true;\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 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),\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\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): 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 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', 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') {\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') {\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 on every frame of a zoom animation\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\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 = 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._form.style.height = null;\r\n\t\tvar acceptableHeight = this._map.getSize().y - (this._container.offsetTop + 50);\r\n\t\tif (acceptableHeight < this._form.clientHeight) {\r\n\t\t\taddClass(this._form, 'leaflet-control-layers-scrollbar');\r\n\t\t\tthis._form.style.height = acceptableHeight + 'px';\r\n\t\t} else {\r\n\t\t\tremoveClass(this._form, '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 form = this._form = create$1('form', 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', form);\r\n\t\tthis._separator = create$1('div', className + '-separator', form);\r\n\t\tthis._overlaysList = create$1('div', className + '-overlays', form);\r\n\r\n\t\tcontainer.appendChild(form);\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', 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\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=\"http://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\r\n\t\tthis._startPoint = new Point(first.clientX, first.clientY);\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 newPoint = new Point(first.clientX, first.clientY),\r\n\t\t offset = newPoint.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\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. Takes into account that Earth is a geoid, not a perfect sphere. 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, describes the layer data, e.g. \"© Mapbox\".\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 = L.DomUtil.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\tL.DomUtil.setPosition(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\ticonPos = 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 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// Set it to `true` if you want the map to do panning animation when marker hits the edges.\r\n\t\tautoPan: false,\r\n\r\n\t\t// @option autoPanPadding: Point = Point(50, 50)\r\n\t\t// Equivalent of setting both top left and bottom right autopan padding to the same value.\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 move by.\r\n\t\tautoPanSpeed: 10,\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 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\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 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('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\tsetOpacity(this._icon, opacity);\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}\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: 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\tvar w = this._clickTolerance(),\n\t\t p = new Point(w, w);\n\n\t\tif (this._bounds.isValid() && pxBounds.isValid()) {\n\t\t\tpxBounds.min._subtract(p);\n\t\t\tpxBounds.max._add(p);\n\t\t\tthis._pxBounds = pxBounds;\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.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 (typeof style === 'function') {\r\n\t\t\tstyle = style(layer.feature);\r\n\t\t}\r\n\t\tif (layer.setStyle) {\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(): Object\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(): Object\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(): Object\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(): Object\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(): Object\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](http://geojson.org/geojson-spec.html) 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 = false\r\n\t\t// If true, the image will have its crossOrigin attribute set to ''. This is needed if you want to access image pixel data.\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 tile 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) {\r\n\t\t\timg.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 has loaded 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\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\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/*\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_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 || (this._map._panAnim && this._map._panAnim._inProgress)) { return; }\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 (!(layer instanceof Layer)) {\r\n\t\t\tlatlng = layer;\r\n\t\t\tlayer = this;\r\n\t\t}\r\n\r\n\t\tif (layer instanceof FeatureGroup) {\r\n\t\t\tfor (var id in this._layers) {\r\n\t\t\t\tlayer = this._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\tlatlng = layer.getCenter ? layer.getCenter() : layer.getLatLng();\r\n\t\t}\r\n\r\n\t\tif (this._popup && this._map) {\r\n\t\t\t// set popup source to this layer\r\n\t\t\tthis._popup._source = layer;\r\n\r\n\t\t\t// update the popup (content, layout, ect...)\r\n\t\t\tthis._popup.update();\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 (!(layer instanceof Layer)) {\n\t\t\tlatlng = layer;\n\t\t\tlayer = this;\n\t\t}\n\n\t\tif (layer instanceof FeatureGroup) {\n\t\t\tfor (var id in this._layers) {\n\t\t\t\tlayer = this._layers[id];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (!latlng) {\n\t\t\tlatlng = layer.getCenter ? layer.getCenter() : layer.getLatLng();\n\t\t}\n\n\t\tif (this._tooltip && this._map) {\n\n\t\t\t// set tooltip source to this layer\n\t\t\tthis._tooltip._source = layer;\n\n\t\t\t// update the tooltip (content, layout, ect...)\n\t\t\tthis._tooltip.update();\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 = ''\n\t\t// Custom HTML code to put inside the div element, empty by default.\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\tdiv.innerHTML = options.html !== false ? options.html : '';\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\t// Cancels any pending http requests associated with the tile\n\t\t// unless we're on Android's stock browser,\n\t\t// see https://github.com/Leaflet/Leaflet/issues/137\n\t\tif (!androidStock) {\n\t\t\ttile.el.setAttribute('src', emptyImageUrl);\n\t\t}\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 (!this._map) { return; }\n\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. Extends `GridLayer`.\r\n *\r\n * @example\r\n *\r\n * ```js\r\n * L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{foo}', {foo: 'bar'}).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 = false\r\n\t\t// If true, all tiles will have their crossOrigin attribute set to ''. This is needed if you want to access tile pixel data.\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\tsetUrl: function (url, noRedraw) {\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) {\r\n\t\t\ttile.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\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\turl = L.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\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\tthis._drawnLayers = {};\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[L.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 (layer.options.dashArray) {\n\t\t\tvar parts = layer.options.dashArray.split(','),\n\t\t\t dashArray = [],\n\t\t\t i;\n\t\t\tfor (i = 0; i < parts.length; i++) {\n\t\t\t\tdashArray.push(Number(parts[i]));\n\t\t\t}\n\t\t\tlayer.options._dashArray = 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\tthis._drawnLayers[layer._leaflet_id] = layer;\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\tthis._drawnLayers[layer._leaflet_id] = layer;\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\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\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 * Although SVG is not available on IE7 and IE8, these browsers support [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language), and the SVG renderer will fall back to VML in this case.\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\t// @namespace Map; @option preferCanvas: Boolean = false\n\t\t\t// Whether `Path`s should be rendered on a `Canvas` renderer.\n\t\t\t// By default, all `Path`s are rendered in a `SVG` renderer.\n\t\t\trenderer = this._renderer = (this.options.preferCanvas && canvas$1()) || svg$1();\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 = (SVG && svg$1({pane: name})) || (Canvas && canvas$1({pane: name}));\n\t\t\tthis._paneRenderers[name] = renderer;\n\t\t}\n\t\treturn renderer;\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\n\t\t\tif (map._panAnim && map._panAnim._inProgress) { return; }\n\n\t\t\toffset = this._panKeys[key];\n\t\t\tif (e.shiftKey) {\n\t\t\t\toffset = toPoint(offset).multiplyBy(3);\n\t\t\t}\n\n\t\t\tmap.panBy(offset);\n\n\t\t\tif (map.options.maxBounds) {\n\t\t\t\tmap.panInsideBounds(map.options.maxBounds);\n\t\t\t}\n\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\n// misc\r\n\r\nvar oldL = window.L;\r\nfunction noConflict() {\r\n\twindow.L = oldL;\r\n\treturn this;\r\n}\r\n\r\n// Always export us to window global (see #2364)\r\nwindow.L = exports;\r\n\r\nObject.freeze = freeze;\n\nexports.version = version;\nexports.noConflict = noConflict;\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.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\n})));\n//# sourceMappingURL=leaflet-src.js.map\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbGVhZmxldC9kaXN0L2xlYWZsZXQtc3JjLmpzPzllYjciXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCLENBQUMsNEJBQTRCOztBQUU3Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZ0NBQWdDLFlBQVk7O0FBRTVDO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQyxTQUFTO0FBQzdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0JBQW9CLGNBQWM7O0FBRWxDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDBEQUEwRCxtQkFBbUI7QUFDN0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0JBQW9CLGVBQWU7O0FBRW5DO0FBQ0EsOEVBQThFLEVBQUUsR0FBRyxFQUFFO0FBQ3JGLDRCQUE0QixtQkFBbUI7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0Isa0JBQWtCO0FBQ2xDLHdCQUF3QixVQUFVO0FBQ2xDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQzs7QUFFcEM7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsK0RBQStELHlCQUF5Qjs7QUFFeEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsOEJBQThCLFFBQVE7O0FBRXRDO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxnREFBZ0QsU0FBUztBQUN6RDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUNBQW1DO0FBQ25DOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtEQUFrRCxRQUFROztBQUUxRDs7QUFFQSxnQkFBZ0IscUJBQXFCO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOENBQThDLHVDQUF1QztBQUNyRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBOztBQUVBLHNDQUFzQyxTQUFTO0FBQy9DO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDs7QUFFQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUIscUJBQXFCO0FBQzFDOztBQUVBO0FBQ0EseUNBQXlDLFNBQVM7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNCQUFzQixRQUFROztBQUU5Qjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHNDQUFzQyxTQUFTO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBLDRCQUE0QixVQUFVO0FBQ3RDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxhQUFhOztBQUVwRCx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQSwyQ0FBMkMsU0FBUztBQUNwRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQyxhQUFhOztBQUVuRDtBQUNBO0FBQ0E7QUFDQSwwREFBMEQsYUFBYTtBQUN2RTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQSxXQUFXOztBQUVYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx3Q0FBd0MscUJBQXFCO0FBQzdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVLFFBQVE7O0FBRWxCOztBQUVBLHFDQUFxQyxTQUFTO0FBQzlDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEIsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEIsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHlDQUF5QztBQUN6QyxnQkFBZ0IsUUFBUTs7QUFFeEI7O0FBRUEsc0NBQXNDLFNBQVM7QUFDL0M7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBOztBQUVBLHNCQUFzQixhQUFhOztBQUVuQyxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixjQUFjOztBQUU5Qjs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxpQkFBaUI7QUFDL0IsY0FBYyxpQkFBaUI7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLGNBQWM7O0FBRTNCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7OztBQUlBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx5Q0FBeUMseUJBQXlCLE9BQU8sc0NBQXNDOztBQUUvRztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGFBQWE7O0FBRW5DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUJBQXFCO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDO0FBQ3hDO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0JBQXdCO0FBQ3hCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGLENBQUM7O0FBRUQsMEJBQTBCO0FBQzFCO0FBQ0EsQ0FBQzs7QUFFRCxrQkFBa0I7QUFDbEI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdDQUFnQyxTQUFTO0FBQ3pDOztBQUVBLG1DQUFtQyxVQUFVO0FBQzdDO0FBQ0E7QUFDQTs7QUFFQSxrQ0FBa0M7QUFDbEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSx5QkFBeUI7QUFDekI7O0FBRUEsNEJBQTRCO0FBQzVCOztBQUVBLDJCQUEyQjtBQUMzQjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGdDQUFnQztBQUNoQzs7QUFFQTtBQUNBLGdGQUFnRjtBQUNoRixtQ0FBbUM7QUFDbkM7O0FBRUEsNEJBQTRCO0FBQzVCOztBQUVBLDZCQUE2QjtBQUM3Qjs7QUFFQSw0QkFBNEI7QUFDNUI7O0FBRUEsNkJBQTZCO0FBQzdCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwwQkFBMEI7QUFDMUI7O0FBRUEsMkJBQTJCO0FBQzNCOztBQUVBLCtCQUErQjtBQUMvQjs7QUFFQSw4QkFBOEI7QUFDOUI7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDZCQUE2QjtBQUM3Qjs7QUFFQSxtQ0FBbUM7QUFDbkM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDO0FBQ2xDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsRUFBRTtBQUNGO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEVBQUU7QUFDRjs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7O0FBRUEsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1HQUFtRyxRQUFROztBQUUzRztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLDhDQUE4QyxRQUFRO0FBQ3REO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUEsa0JBQWtCLFFBQVE7O0FBRTFCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLFFBQVE7QUFDdkQ7QUFDQSxxQkFBcUI7QUFDckI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDZDQUE2Qyx1Q0FBdUM7QUFDcEY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUEscUNBQXFDLFNBQVM7QUFDOUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdEQUFnRCx1Q0FBdUM7QUFDdkY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUEscUNBQXFDLFNBQVM7QUFDOUM7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSw0Q0FBNEMsYUFBYTs7QUFFekQ7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsRUFBRTs7QUFFRjtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsZ0JBQWdCLGFBQWE7O0FBRTdCO0FBQ0E7O0FBRUEsRUFBRTtBQUNGO0FBQ0E7O0FBRUEsRUFBRTs7QUFFRjtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRSw0QkFBNEI7QUFDOUI7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxnQkFBZ0IsYUFBYTs7QUFFN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsU0FBUztBQUNoRDtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLG9CQUFvQixRQUFRO0FBQzVCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdCQUFnQixrQkFBa0I7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsUUFBUTtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLFFBQVE7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsUUFBUTs7QUFFbEM7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkRBQTZEO0FBQzdEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRixxQ0FBcUM7QUFDckM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx5REFBeUQsWUFBWTtBQUNyRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7O0FBR0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0EsMkJBQTJCLHlCQUF5QjtBQUNwRCwwQkFBMEIscURBQXFEO0FBQy9FOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQyxjQUFjO0FBQzdELEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSx3Q0FBd0MsY0FBYztBQUN0RCxFQUFFOztBQUVGOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLG9DQUFvQztBQUNwQywyQ0FBMkMsYUFBYTtBQUN4RCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG9CQUFvQix5Q0FBeUM7QUFDN0Qsb0JBQW9CLHlDQUF5QztBQUM3RCxvQkFBb0IsMEJBQTBCOztBQUU5Qzs7QUFFQSxpQkFBaUIsNkNBQTZDO0FBQzlELGlCQUFpQiwrREFBK0Q7O0FBRWhGLHVCQUF1QixpQ0FBaUM7O0FBRXhEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNLFlBQVk7O0FBRWxCLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsYUFBYTs7QUFFbkM7QUFDQTtBQUNBO0FBQ0EsR0FBRyxzQkFBc0IsY0FBYzs7QUFFdkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtCQUErQixhQUFhOztBQUU1QztBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxpRUFBaUUsWUFBWTtBQUM3RTtBQUNBLE1BQU0sY0FBYztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGFBQWE7O0FBRW5DOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9EQUFvRDtBQUNwRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSx5REFBeUQ7QUFDekQ7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7O0FBR0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsK0NBQStDO0FBQy9DO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0M7QUFDL0M7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DO0FBQ25DO0FBQ0EsRUFBRTs7O0FBR0Y7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QztBQUM1QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixzQkFBc0Isc0JBQXNCLEVBQUUsRUFBRTtBQUN2RSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLE9BQU87QUFDdEQ7QUFDQSxrQkFBa0IsT0FBTztBQUN6QjtBQUNBLGlDQUFpQyxPQUFPO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxvQ0FBb0MsUUFBUTs7QUFFNUM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7O0FBRUEsbUJBQW1CLFFBQVE7O0FBRTNCO0FBQ0E7O0FBRUEsd0JBQXdCLFFBQVE7O0FBRWhDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxpQkFBaUIsb0JBQW9CO0FBQ3JDO0FBQ0E7QUFDQSxvR0FBb0csUUFBUTtBQUM1RztBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLDhDQUE4QyxTQUFTO0FBQ3ZEO0FBQ0E7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1DQUFtQyxhQUFhO0FBQ2hELEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQSxnQkFBZ0IsZUFBZTs7QUFFL0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsZ0JBQWdCLGVBQWU7O0FBRS9CO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0Esa0ZBQWtGLGNBQWM7O0FBRWhHOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQSw0QkFBNEIsYUFBYTs7QUFFekM7O0FBRUE7QUFDQTtBQUNBLDhFQUE4RSxjQUFjOztBQUU1RjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxxRUFBcUUsY0FBYzs7QUFFbkY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLHVCQUF1QixRQUFROztBQUUvQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSw2QkFBNkIsUUFBUTs7QUFFckM7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLHlDQUF5QztBQUN6QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxpQkFBaUIseUJBQXlCO0FBQzFDO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBLGlCQUFpQix5QkFBeUI7QUFDMUM7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLGlCQUFpQix5QkFBeUI7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLHlCQUF5QixhQUFhOztBQUV0QztBQUNBOztBQUVBO0FBQ0E7O0FBRUEsYUFBYSx5QkFBeUI7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGlDQUFpQyxRQUFRO0FBQ3pDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxhQUFhLDBCQUEwQjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsd0JBQXdCO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlDQUFpQyxRQUFRO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDRDQUE0QztBQUM1QztBQUNBLHdCQUF3Qjs7QUFFeEI7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSx1REFBdUQ7QUFDdkQ7QUFDQSxjQUFjLGFBQWE7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxjQUFjLGFBQWE7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLG1CQUFtQixRQUFROztBQUUzQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGFBQWE7O0FBRW5DO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLGFBQWE7O0FBRXBDO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsUUFBUTs7QUFFOUI7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QixRQUFROztBQUUvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxzQkFBc0I7QUFDdEI7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQSx1Q0FBdUMsUUFBUTs7QUFFL0M7O0FBRUEscURBQXFELFFBQVE7O0FBRTdELGlHQUFpRyxRQUFRO0FBQ3pHLDZCQUE2Qjs7QUFFN0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEscUJBQXFCLFFBQVE7O0FBRTdCO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0Esc0JBQXNCO0FBQ3RCO0FBQ0EsdUNBQXVDO0FBQ3ZDO0FBQ0EsdUNBQXVDLFFBQVE7O0FBRS9DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwrQkFBK0IsUUFBUTtBQUN2Qyw4RUFBOEUsUUFBUTs7QUFFdEY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxzQkFBc0I7QUFDdEI7QUFDQSx1Q0FBdUM7QUFDdkM7QUFDQSx1Q0FBdUMsUUFBUTtBQUMvQztBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLFlBQVksU0FBUztBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUEsb0JBQW9CLGVBQWU7QUFDbkM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwrQ0FBK0MsU0FBUztBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCO0FBQ2hCO0FBQ0E7O0FBRUEsRUFBRSxxQkFBcUI7QUFDdkI7QUFDQTs7QUFFQSxFQUFFLHFCQUFxQjtBQUN2QjtBQUNBOztBQUVBLEVBQUUscUJBQXFCO0FBQ3ZCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsMEJBQTBCO0FBQzFCO0FBQ0EsRUFBRSwrQkFBK0I7QUFDakM7QUFDQTs7QUFFQSwwQkFBMEI7QUFDMUI7QUFDQSxFQUFFLCtCQUErQjtBQUNqQztBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlDQUFpQyxTQUFTO0FBQzFDO0FBQ0E7O0FBRUE7QUFDQSxZQUFZLE9BQU87QUFDbkI7QUFDQTs7QUFFQSwrQ0FBK0MsU0FBUztBQUN4RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDLGlDQUFpQztBQUNuRTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQkFBc0I7QUFDdEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0EsNEJBQTRCLFFBQVE7O0FBRXBDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx3QkFBd0IsWUFBWTtBQUNwQztBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdURBQXVELHlCQUF5QjtBQUNoRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EseUJBQXlCLGFBQWE7QUFDdEM7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwwQkFBMEIsYUFBYTs7QUFFdkM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLDZCQUE2QixhQUFhO0FBQzFDO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBLHNDQUFzQyxTQUFTO0FBQy9DO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBLG1DQUFtQyxTQUFTO0FBQzVDO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCLDRDQUE0QyxFQUFFO0FBQzNFO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsZ0NBQWdDLGFBQWE7QUFDN0MsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsbUNBQW1DLGFBQWE7QUFDaEQsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSw4QkFBOEIsYUFBYTtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkM7O0FBRTdDOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSx3QkFBd0IsZUFBZTs7QUFFdkM7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsNEJBQTRCLDJDQUEyQztBQUN2RSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBLGtDQUFrQyxRQUFROztBQUUxQzs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLHFCQUFxQjtBQUNqRCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLFlBQVk7QUFDdkM7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0Isa0JBQWtCLGdCQUFnQjtBQUN4RDtBQUNBO0FBQ0E7O0FBRUEsbUNBQW1DLGdEQUFnRDs7QUFFbkY7QUFDQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZ0RBQWdEO0FBQ2hEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsYUFBYTtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNENBQTRDLFVBQVU7QUFDdEQ7O0FBRUEsdUNBQXVDLFNBQVM7QUFDaEQ7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGFBQWEsYUFBYTs7QUFFMUIsaUNBQWlDOztBQUVqQywyQkFBMkIsYUFBYTtBQUN4QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHVCQUF1QixhQUFhO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRixtRUFBbUU7QUFDbkU7QUFDQTtBQUNBOztBQUVBLHVDQUF1QyxTQUFTO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsY0FBYyxTQUFTO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILGNBQWMsU0FBUztBQUN2QjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLDhDQUE4QyxTQUFTO0FBQ3ZEOztBQUVBLG9DQUFvQyxjQUFjO0FBQ2xEOztBQUVBLG1CQUFtQixVQUFVOztBQUU3QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLG1CQUFtQixRQUFROztBQUUzQjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHVEQUF1RCxjQUFjOztBQUVyRTtBQUNBLHVDQUF1QyxTQUFTO0FBQ2hEOztBQUVBLGdEQUFnRCxVQUFVO0FBQzFELCtCQUErQixVQUFVOztBQUV6QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDLGFBQWE7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsYUFBYSxhQUFhOztBQUUxQixnQ0FBZ0M7O0FBRWhDOztBQUVBLDBCQUEwQixTQUFTO0FBQ25DO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvREFBb0QsU0FBUztBQUM3RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQ0FBb0MsY0FBYzs7QUFFbEQ7QUFDQSx1Q0FBdUMsU0FBUztBQUNoRDs7QUFFQSxnREFBZ0QsVUFBVTtBQUMxRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1EQUFtRCxhQUFhOztBQUVoRTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQ0FBa0MsU0FBUztBQUMzQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLCtDQUErQyxTQUFTO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNkNBQTZDLFNBQVM7QUFDdEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0NBQXNDLFNBQVM7QUFDL0M7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsa0JBQWtCLHNCQUFzQjtBQUNuRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUYsOENBQThDO0FBQzlDO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkIsd0NBQXdDO0FBQ25FLCtCQUErQix1Q0FBdUM7O0FBRXRFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJCQUEyQix3Q0FBd0M7O0FBRW5FO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQiwyQkFBMkI7QUFDN0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsNEJBQTRCLHlCQUF5Qjs7QUFFckQ7QUFDQTtBQUNBLGlCQUFpQixzQkFBc0I7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsUUFBUTs7QUFFM0I7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLHVCQUF1QixRQUFROztBQUUvQjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLG1CQUFtQixRQUFROztBQUUzQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUEsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLFlBQVk7O0FBRXJDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBbUMsWUFBWTtBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsWUFBWTs7QUFFdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQyxZQUFZO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDOztBQUVsQztBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLHdGQUF3RixRQUFROztBQUVoRztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtEQUErRDtBQUMvRDtBQUNBO0FBQ0EsOENBQThDO0FBQzlDO0FBQ0E7QUFDQSxnRUFBZ0U7QUFDaEU7QUFDQTtBQUNBLDhDQUE4QztBQUM5QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsY0FBYzs7QUFFekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxjQUFjO0FBQ25EO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNEJBQTRCLGNBQWM7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0MsY0FBYztBQUNwRDtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGLDhCQUE4Qjs7QUFFOUIsMkJBQTJCOztBQUUzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLGlEQUFpRCxRQUFRO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQix5QkFBeUI7QUFDcEQ7QUFDQTtBQUNBLDhCQUE4QixhQUFhO0FBQzNDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0EsaURBQWlEOztBQUVqRCw4Q0FBOEMsU0FBUzs7QUFFdkQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0EsbUJBQW1CLFFBQVE7O0FBRTNCO0FBQ0EsY0FBYyxRQUFROztBQUV0Qjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHVDQUF1QyxVQUFVOztBQUVqRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQyxvQkFBb0I7O0FBRXhEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBLHdCQUF3QixRQUFROztBQUVoQztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTs7QUFFQSwyQkFBMkIsa0JBQWtCOztBQUU3QztBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUEscUJBQXFCLGVBQWU7QUFDcEMsc0JBQXNCLGVBQWU7O0FBRXJDO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0EsK0NBQStDLFFBQVE7O0FBRXZEO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLGFBQWEsUUFBUTtBQUNyQjs7QUFFQSw2QkFBNkIsMEJBQTBCO0FBQ3ZELHFDQUFxQyxRQUFRLEVBQUU7O0FBRS9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDLGtFQUFrRTs7QUFFdkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw0Q0FBNEMsNkJBQTZCLFFBQVE7O0FBRWpGO0FBQ0EsK0JBQStCLHNCQUFzQjtBQUNyRCxnQ0FBZ0Msc0JBQXNCO0FBQ3REO0FBQ0E7O0FBRUEscUNBQXFDLFVBQVU7O0FBRS9DO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxjQUFjLGtCQUFrQjtBQUNoQztBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnRkFBZ0YsY0FBYztBQUM5Rjs7QUFFQSw2QkFBNkIsYUFBYTs7QUFFMUM7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLGNBQWMsUUFBUTs7QUFFdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0Esd0RBQXdEO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBLG1CQUFtQixRQUFROztBQUUzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTs7QUFFQTtBQUNBLGNBQWMsUUFBUTs7QUFFdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxrQ0FBa0MsY0FBYztBQUNoRDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLEVBQUUseUJBQXlCLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxNQUFNLElBQUksSUFBSSxXQUFXO0FBQ3RGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLEVBQUUsd0JBQXdCLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFO0FBQ25EO0FBQ0E7QUFDQSxLQUFLLEVBQUUsd0hBQXdILDJDQUEyQyxnREFBZ0QsRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsd0JBQXdCLEVBQUUsOEJBQThCO0FBQ2xUO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLEVBQUUsaUJBQWlCLElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsUUFBUSxXQUFXO0FBQzlFO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTs7QUFFQSwyQkFBMkI7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EseUJBQXlCOztBQUV6QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixlQUFlO0FBQzdDLHdDQUF3Qyx1QkFBdUI7QUFDL0QsbUNBQW1DLHVCQUF1QjtBQUMxRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLGtDQUFrQyxRQUFROztBQUUxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxpREFBaUQsUUFBUTs7QUFFekQ7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsd0NBQXdDO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLDZCQUE2QjtBQUNwRDtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxrQkFBa0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0EsbUJBQW1CLFFBQVE7O0FBRTNCO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdCQUFnQjtBQUNoQixlQUFlOztBQUVmO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxtQ0FBbUMsT0FBTztBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLHNCQUFzQjtBQUN0QixFQUFFOztBQUVGO0FBQ0EsdUJBQXVCLFFBQVE7O0FBRS9CO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGFBQWEsUUFBUTs7QUFFckI7O0FBRUE7O0FBRUEsYUFBYSxTQUFTO0FBQ3RCLHNDQUFzQyxVQUFVO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQSx5Q0FBeUMsUUFBUTs7QUFFakQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsbUNBQW1DLE9BQU87QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLDhFQUE4RSxRQUFROztBQUV0RjtBQUNBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQSxtQ0FBbUMsT0FBTztBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxxREFBcUQ7QUFDckQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxpQ0FBaUMsUUFBUTtBQUN6QztBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixlQUFlO0FBQzFDLHdDQUF3Qyx1QkFBdUI7QUFDL0QsbUNBQW1DLHVCQUF1QjtBQUMxRDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBLGlEQUFpRDtBQUNqRDs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0EsaURBQWlELFFBQVE7O0FBRXpEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSx5QkFBeUIsdUJBQXVCO0FBQ2hEO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQSxjQUFjLFFBQVE7O0FBRXRCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG1CQUFtQjtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw2QkFBNkIsV0FBVywyQkFBMkIsV0FBVztBQUM5RTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsNEJBQTRCO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLDZEQUE2RCxjQUFjOztBQUUzRTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBLDRDQUE0QyxRQUFROztBQUVwRDs7QUFFQSxxQkFBcUIsUUFBUTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHdCQUF3QixzQkFBc0I7QUFDOUMsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSwrQ0FBK0MsUUFBUTs7QUFFdkQ7O0FBRUE7QUFDQSwrQkFBK0Isc0RBQXNEO0FBQ3JGLCtCQUErQixzREFBc0Q7QUFDckYsK0JBQStCLHNEQUFzRDtBQUNyRiwrQkFBK0Isc0RBQXNEOztBQUVyRjtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0Esc0JBQXNCLFFBQVE7O0FBRTlCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTs7QUFFQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBO0FBQ0EsdUNBQXVDLFNBQVM7QUFDaEQ7QUFDQTtBQUNBLHNDQUFzQyxTQUFTO0FBQy9DO0FBQ0E7QUFDQSxvQ0FBb0MsU0FBUztBQUM3QztBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLGdDQUFnQztBQUNoQztBQUNBOztBQUVBLHdDQUF3QyxTQUFTO0FBQ2pEO0FBQ0E7QUFDQSx5Q0FBeUMsU0FBUztBQUNsRDtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLDJDQUEyQyxRQUFROztBQUVuRDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsa0RBQWtELFFBQVE7O0FBRTFEO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7O0FBRUEsR0FBRztBQUNIOztBQUVBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGNBQWM7O0FBRWQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGVBQWUsUUFBUTs7QUFFdkI7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0EsbUJBQW1CLFFBQVE7O0FBRTNCOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxvRkFBb0YsUUFBUTs7QUFFNUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBLCtEQUErRCxRQUFROztBQUV2RTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxxQkFBcUIsUUFBUTtBQUM3QixHQUFHO0FBQ0g7QUFDQTtBQUNBLHVEQUF1RCxRQUFRO0FBQy9EO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsK0RBQStELDBCQUEwQjtBQUN6Rjs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNEIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL2xlYWZsZXQvZGlzdC9sZWFmbGV0LXNyYy5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIEBwcmVzZXJ2ZVxuICogTGVhZmxldCAxLjMuMSwgYSBKUyBsaWJyYXJ5IGZvciBpbnRlcmFjdGl2ZSBtYXBzLiBodHRwOi8vbGVhZmxldGpzLmNvbVxuICogKGMpIDIwMTAtMjAxNyBWbGFkaW1pciBBZ2Fmb25raW4sIChjKSAyMDEwLTIwMTEgQ2xvdWRNYWRlXG4gKi9cblxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLkwgPSB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIHZlcnNpb24gPSBcIjEuMy4xXCI7XG5cbi8qXHJcbiAqIEBuYW1lc3BhY2UgVXRpbFxyXG4gKlxyXG4gKiBWYXJpb3VzIHV0aWxpdHkgZnVuY3Rpb25zLCB1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseS5cclxuICovXHJcblxyXG52YXIgZnJlZXplID0gT2JqZWN0LmZyZWV6ZTtcclxuT2JqZWN0LmZyZWV6ZSA9IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIG9iajsgfTtcclxuXHJcbi8vIEBmdW5jdGlvbiBleHRlbmQoZGVzdDogT2JqZWN0LCBzcmM/OiBPYmplY3QpOiBPYmplY3RcclxuLy8gTWVyZ2VzIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBgc3JjYCBvYmplY3QgKG9yIG11bHRpcGxlIG9iamVjdHMpIGludG8gYGRlc3RgIG9iamVjdCBhbmQgcmV0dXJucyB0aGUgbGF0dGVyLiBIYXMgYW4gYEwuZXh0ZW5kYCBzaG9ydGN1dC5cclxuZnVuY3Rpb24gZXh0ZW5kKGRlc3QpIHtcclxuXHR2YXIgaSwgaiwgbGVuLCBzcmM7XHJcblxyXG5cdGZvciAoaiA9IDEsIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGogPCBsZW47IGorKykge1xyXG5cdFx0c3JjID0gYXJndW1lbnRzW2pdO1xyXG5cdFx0Zm9yIChpIGluIHNyYykge1xyXG5cdFx0XHRkZXN0W2ldID0gc3JjW2ldO1xyXG5cdFx0fVxyXG5cdH1cclxuXHRyZXR1cm4gZGVzdDtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGNyZWF0ZShwcm90bzogT2JqZWN0LCBwcm9wZXJ0aWVzPzogT2JqZWN0KTogT2JqZWN0XHJcbi8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtPYmplY3QuY3JlYXRlXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9PYmplY3QvY3JlYXRlKVxyXG52YXIgY3JlYXRlID0gT2JqZWN0LmNyZWF0ZSB8fCAoZnVuY3Rpb24gKCkge1xyXG5cdGZ1bmN0aW9uIEYoKSB7fVxyXG5cdHJldHVybiBmdW5jdGlvbiAocHJvdG8pIHtcclxuXHRcdEYucHJvdG90eXBlID0gcHJvdG87XHJcblx0XHRyZXR1cm4gbmV3IEYoKTtcclxuXHR9O1xyXG59KSgpO1xyXG5cclxuLy8gQGZ1bmN0aW9uIGJpbmQoZm46IEZ1bmN0aW9uLCDigKYpOiBGdW5jdGlvblxyXG4vLyBSZXR1cm5zIGEgbmV3IGZ1bmN0aW9uIGJvdW5kIHRvIHRoZSBhcmd1bWVudHMgcGFzc2VkLCBsaWtlIFtGdW5jdGlvbi5wcm90b3R5cGUuYmluZF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRnVuY3Rpb24vYmluZCkuXHJcbi8vIEhhcyBhIGBMLmJpbmQoKWAgc2hvcnRjdXQuXHJcbmZ1bmN0aW9uIGJpbmQoZm4sIG9iaikge1xyXG5cdHZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcclxuXHJcblx0aWYgKGZuLmJpbmQpIHtcclxuXHRcdHJldHVybiBmbi5iaW5kLmFwcGx5KGZuLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xyXG5cdH1cclxuXHJcblx0dmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XHJcblxyXG5cdHJldHVybiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gZm4uYXBwbHkob2JqLCBhcmdzLmxlbmd0aCA/IGFyZ3MuY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzKSkgOiBhcmd1bWVudHMpO1xyXG5cdH07XHJcbn1cclxuXHJcbi8vIEBwcm9wZXJ0eSBsYXN0SWQ6IE51bWJlclxyXG4vLyBMYXN0IHVuaXF1ZSBJRCB1c2VkIGJ5IFtgc3RhbXAoKWBdKCN1dGlsLXN0YW1wKVxyXG52YXIgbGFzdElkID0gMDtcclxuXHJcbi8vIEBmdW5jdGlvbiBzdGFtcChvYmo6IE9iamVjdCk6IE51bWJlclxyXG4vLyBSZXR1cm5zIHRoZSB1bmlxdWUgSUQgb2YgYW4gb2JqZWN0LCBhc3NpZ25pbmcgaXQgb25lIGlmIGl0IGRvZXNuJ3QgaGF2ZSBpdC5cclxuZnVuY3Rpb24gc3RhbXAob2JqKSB7XHJcblx0Lyplc2xpbnQtZGlzYWJsZSAqL1xyXG5cdG9iai5fbGVhZmxldF9pZCA9IG9iai5fbGVhZmxldF9pZCB8fCArK2xhc3RJZDtcclxuXHRyZXR1cm4gb2JqLl9sZWFmbGV0X2lkO1xyXG5cdC8qIGVzbGludC1lbmFibGUgKi9cclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHRocm90dGxlKGZuOiBGdW5jdGlvbiwgdGltZTogTnVtYmVyLCBjb250ZXh0OiBPYmplY3QpOiBGdW5jdGlvblxyXG4vLyBSZXR1cm5zIGEgZnVuY3Rpb24gd2hpY2ggZXhlY3V0ZXMgZnVuY3Rpb24gYGZuYCB3aXRoIHRoZSBnaXZlbiBzY29wZSBgY29udGV4dGBcclxuLy8gKHNvIHRoYXQgdGhlIGB0aGlzYCBrZXl3b3JkIHJlZmVycyB0byBgY29udGV4dGAgaW5zaWRlIGBmbmAncyBjb2RlKS4gVGhlIGZ1bmN0aW9uXHJcbi8vIGBmbmAgd2lsbCBiZSBjYWxsZWQgbm8gbW9yZSB0aGFuIG9uZSB0aW1lIHBlciBnaXZlbiBhbW91bnQgb2YgYHRpbWVgLiBUaGUgYXJndW1lbnRzXHJcbi8vIHJlY2VpdmVkIGJ5IHRoZSBib3VuZCBmdW5jdGlvbiB3aWxsIGJlIGFueSBhcmd1bWVudHMgcGFzc2VkIHdoZW4gYmluZGluZyB0aGVcclxuLy8gZnVuY3Rpb24sIGZvbGxvd2VkIGJ5IGFueSBhcmd1bWVudHMgcGFzc2VkIHdoZW4gaW52b2tpbmcgdGhlIGJvdW5kIGZ1bmN0aW9uLlxyXG4vLyBIYXMgYW4gYEwudGhyb3R0bGVgIHNob3J0Y3V0LlxyXG5mdW5jdGlvbiB0aHJvdHRsZShmbiwgdGltZSwgY29udGV4dCkge1xyXG5cdHZhciBsb2NrLCBhcmdzLCB3cmFwcGVyRm4sIGxhdGVyO1xyXG5cclxuXHRsYXRlciA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdC8vIHJlc2V0IGxvY2sgYW5kIGNhbGwgaWYgcXVldWVkXHJcblx0XHRsb2NrID0gZmFsc2U7XHJcblx0XHRpZiAoYXJncykge1xyXG5cdFx0XHR3cmFwcGVyRm4uYXBwbHkoY29udGV4dCwgYXJncyk7XHJcblx0XHRcdGFyZ3MgPSBmYWxzZTtcclxuXHRcdH1cclxuXHR9O1xyXG5cclxuXHR3cmFwcGVyRm4gPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAobG9jaykge1xyXG5cdFx0XHQvLyBjYWxsZWQgdG9vIHNvb24sIHF1ZXVlIHRvIGNhbGwgbGF0ZXJcclxuXHRcdFx0YXJncyA9IGFyZ3VtZW50cztcclxuXHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHQvLyBjYWxsIGFuZCBsb2NrIHVudGlsIGxhdGVyXHJcblx0XHRcdGZuLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XHJcblx0XHRcdHNldFRpbWVvdXQobGF0ZXIsIHRpbWUpO1xyXG5cdFx0XHRsb2NrID0gdHJ1ZTtcclxuXHRcdH1cclxuXHR9O1xyXG5cclxuXHRyZXR1cm4gd3JhcHBlckZuO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gd3JhcE51bShudW06IE51bWJlciwgcmFuZ2U6IE51bWJlcltdLCBpbmNsdWRlTWF4PzogQm9vbGVhbik6IE51bWJlclxyXG4vLyBSZXR1cm5zIHRoZSBudW1iZXIgYG51bWAgbW9kdWxvIGByYW5nZWAgaW4gc3VjaCBhIHdheSBzbyBpdCBsaWVzIHdpdGhpblxyXG4vLyBgcmFuZ2VbMF1gIGFuZCBgcmFuZ2VbMV1gLiBUaGUgcmV0dXJuZWQgdmFsdWUgd2lsbCBiZSBhbHdheXMgc21hbGxlciB0aGFuXHJcbi8vIGByYW5nZVsxXWAgdW5sZXNzIGBpbmNsdWRlTWF4YCBpcyBzZXQgdG8gYHRydWVgLlxyXG5mdW5jdGlvbiB3cmFwTnVtKHgsIHJhbmdlLCBpbmNsdWRlTWF4KSB7XHJcblx0dmFyIG1heCA9IHJhbmdlWzFdLFxyXG5cdCAgICBtaW4gPSByYW5nZVswXSxcclxuXHQgICAgZCA9IG1heCAtIG1pbjtcclxuXHRyZXR1cm4geCA9PT0gbWF4ICYmIGluY2x1ZGVNYXggPyB4IDogKCh4IC0gbWluKSAlIGQgKyBkKSAlIGQgKyBtaW47XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBmYWxzZUZuKCk6IEZ1bmN0aW9uXHJcbi8vIFJldHVybnMgYSBmdW5jdGlvbiB3aGljaCBhbHdheXMgcmV0dXJucyBgZmFsc2VgLlxyXG5mdW5jdGlvbiBmYWxzZUZuKCkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcbi8vIEBmdW5jdGlvbiBmb3JtYXROdW0obnVtOiBOdW1iZXIsIGRpZ2l0cz86IE51bWJlcik6IE51bWJlclxyXG4vLyBSZXR1cm5zIHRoZSBudW1iZXIgYG51bWAgcm91bmRlZCB0byBgZGlnaXRzYCBkZWNpbWFscywgb3IgdG8gNiBkZWNpbWFscyBieSBkZWZhdWx0LlxyXG5mdW5jdGlvbiBmb3JtYXROdW0obnVtLCBkaWdpdHMpIHtcclxuXHR2YXIgcG93ID0gTWF0aC5wb3coMTAsIChkaWdpdHMgPT09IHVuZGVmaW5lZCA/IDYgOiBkaWdpdHMpKTtcclxuXHRyZXR1cm4gTWF0aC5yb3VuZChudW0gKiBwb3cpIC8gcG93O1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gdHJpbShzdHI6IFN0cmluZyk6IFN0cmluZ1xyXG4vLyBDb21wYXRpYmlsaXR5IHBvbHlmaWxsIGZvciBbU3RyaW5nLnByb3RvdHlwZS50cmltXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9TdHJpbmcvVHJpbSlcclxuZnVuY3Rpb24gdHJpbShzdHIpIHtcclxuXHRyZXR1cm4gc3RyLnRyaW0gPyBzdHIudHJpbSgpIDogc3RyLnJlcGxhY2UoL15cXHMrfFxccyskL2csICcnKTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHNwbGl0V29yZHMoc3RyOiBTdHJpbmcpOiBTdHJpbmdbXVxyXG4vLyBUcmltcyBhbmQgc3BsaXRzIHRoZSBzdHJpbmcgb24gd2hpdGVzcGFjZSBhbmQgcmV0dXJucyB0aGUgYXJyYXkgb2YgcGFydHMuXHJcbmZ1bmN0aW9uIHNwbGl0V29yZHMoc3RyKSB7XHJcblx0cmV0dXJuIHRyaW0oc3RyKS5zcGxpdCgvXFxzKy8pO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gc2V0T3B0aW9ucyhvYmo6IE9iamVjdCwgb3B0aW9uczogT2JqZWN0KTogT2JqZWN0XHJcbi8vIE1lcmdlcyB0aGUgZ2l2ZW4gcHJvcGVydGllcyB0byB0aGUgYG9wdGlvbnNgIG9mIHRoZSBgb2JqYCBvYmplY3QsIHJldHVybmluZyB0aGUgcmVzdWx0aW5nIG9wdGlvbnMuIFNlZSBgQ2xhc3Mgb3B0aW9uc2AuIEhhcyBhbiBgTC5zZXRPcHRpb25zYCBzaG9ydGN1dC5cclxuZnVuY3Rpb24gc2V0T3B0aW9ucyhvYmosIG9wdGlvbnMpIHtcclxuXHRpZiAoIW9iai5oYXNPd25Qcm9wZXJ0eSgnb3B0aW9ucycpKSB7XHJcblx0XHRvYmoub3B0aW9ucyA9IG9iai5vcHRpb25zID8gY3JlYXRlKG9iai5vcHRpb25zKSA6IHt9O1xyXG5cdH1cclxuXHRmb3IgKHZhciBpIGluIG9wdGlvbnMpIHtcclxuXHRcdG9iai5vcHRpb25zW2ldID0gb3B0aW9uc1tpXTtcclxuXHR9XHJcblx0cmV0dXJuIG9iai5vcHRpb25zO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gZ2V0UGFyYW1TdHJpbmcob2JqOiBPYmplY3QsIGV4aXN0aW5nVXJsPzogU3RyaW5nLCB1cHBlcmNhc2U/OiBCb29sZWFuKTogU3RyaW5nXHJcbi8vIENvbnZlcnRzIGFuIG9iamVjdCBpbnRvIGEgcGFyYW1ldGVyIFVSTCBzdHJpbmcsIGUuZy4gYHthOiBcImZvb1wiLCBiOiBcImJhclwifWBcclxuLy8gdHJhbnNsYXRlcyB0byBgJz9hPWZvbyZiPWJhcidgLiBJZiBgZXhpc3RpbmdVcmxgIGlzIHNldCwgdGhlIHBhcmFtZXRlcnMgd2lsbFxyXG4vLyBiZSBhcHBlbmRlZCBhdCB0aGUgZW5kLiBJZiBgdXBwZXJjYXNlYCBpcyBgdHJ1ZWAsIHRoZSBwYXJhbWV0ZXIgbmFtZXMgd2lsbFxyXG4vLyBiZSB1cHBlcmNhc2VkIChlLmcuIGAnP0E9Zm9vJkI9YmFyJ2ApXHJcbmZ1bmN0aW9uIGdldFBhcmFtU3RyaW5nKG9iaiwgZXhpc3RpbmdVcmwsIHVwcGVyY2FzZSkge1xyXG5cdHZhciBwYXJhbXMgPSBbXTtcclxuXHRmb3IgKHZhciBpIGluIG9iaikge1xyXG5cdFx0cGFyYW1zLnB1c2goZW5jb2RlVVJJQ29tcG9uZW50KHVwcGVyY2FzZSA/IGkudG9VcHBlckNhc2UoKSA6IGkpICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KG9ialtpXSkpO1xyXG5cdH1cclxuXHRyZXR1cm4gKCghZXhpc3RpbmdVcmwgfHwgZXhpc3RpbmdVcmwuaW5kZXhPZignPycpID09PSAtMSkgPyAnPycgOiAnJicpICsgcGFyYW1zLmpvaW4oJyYnKTtcclxufVxyXG5cclxudmFyIHRlbXBsYXRlUmUgPSAvXFx7ICooW1xcd18tXSspICpcXH0vZztcclxuXHJcbi8vIEBmdW5jdGlvbiB0ZW1wbGF0ZShzdHI6IFN0cmluZywgZGF0YTogT2JqZWN0KTogU3RyaW5nXHJcbi8vIFNpbXBsZSB0ZW1wbGF0aW5nIGZhY2lsaXR5LCBhY2NlcHRzIGEgdGVtcGxhdGUgc3RyaW5nIG9mIHRoZSBmb3JtIGAnSGVsbG8ge2F9LCB7Yn0nYFxyXG4vLyBhbmQgYSBkYXRhIG9iamVjdCBsaWtlIGB7YTogJ2ZvbycsIGI6ICdiYXInfWAsIHJldHVybnMgZXZhbHVhdGVkIHN0cmluZ1xyXG4vLyBgKCdIZWxsbyBmb28sIGJhcicpYC4gWW91IGNhbiBhbHNvIHNwZWNpZnkgZnVuY3Rpb25zIGluc3RlYWQgb2Ygc3RyaW5ncyBmb3JcclxuLy8gZGF0YSB2YWx1ZXMg4oCUIHRoZXkgd2lsbCBiZSBldmFsdWF0ZWQgcGFzc2luZyBgZGF0YWAgYXMgYW4gYXJndW1lbnQuXHJcbmZ1bmN0aW9uIHRlbXBsYXRlKHN0ciwgZGF0YSkge1xyXG5cdHJldHVybiBzdHIucmVwbGFjZSh0ZW1wbGF0ZVJlLCBmdW5jdGlvbiAoc3RyLCBrZXkpIHtcclxuXHRcdHZhciB2YWx1ZSA9IGRhdGFba2V5XTtcclxuXHJcblx0XHRpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xyXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ05vIHZhbHVlIHByb3ZpZGVkIGZvciB2YXJpYWJsZSAnICsgc3RyKTtcclxuXHJcblx0XHR9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG5cdFx0XHR2YWx1ZSA9IHZhbHVlKGRhdGEpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHZhbHVlO1xyXG5cdH0pO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gaXNBcnJheShvYmopOiBCb29sZWFuXHJcbi8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtBcnJheS5pc0FycmF5XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9pc0FycmF5KVxyXG52YXIgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24gKG9iaikge1xyXG5cdHJldHVybiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IEFycmF5XScpO1xyXG59O1xyXG5cclxuLy8gQGZ1bmN0aW9uIGluZGV4T2YoYXJyYXk6IEFycmF5LCBlbDogT2JqZWN0KTogTnVtYmVyXHJcbi8vIENvbXBhdGliaWxpdHkgcG9seWZpbGwgZm9yIFtBcnJheS5wcm90b3R5cGUuaW5kZXhPZl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvaW5kZXhPZilcclxuZnVuY3Rpb24gaW5kZXhPZihhcnJheSwgZWwpIHtcclxuXHRmb3IgKHZhciBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XHJcblx0XHRpZiAoYXJyYXlbaV0gPT09IGVsKSB7IHJldHVybiBpOyB9XHJcblx0fVxyXG5cdHJldHVybiAtMTtcclxufVxyXG5cclxuLy8gQHByb3BlcnR5IGVtcHR5SW1hZ2VVcmw6IFN0cmluZ1xyXG4vLyBEYXRhIFVSSSBzdHJpbmcgY29udGFpbmluZyBhIGJhc2U2NC1lbmNvZGVkIGVtcHR5IEdJRiBpbWFnZS5cclxuLy8gVXNlZCBhcyBhIGhhY2sgdG8gZnJlZSBtZW1vcnkgZnJvbSB1bnVzZWQgaW1hZ2VzIG9uIFdlYktpdC1wb3dlcmVkXHJcbi8vIG1vYmlsZSBkZXZpY2VzIChieSBzZXR0aW5nIGltYWdlIGBzcmNgIHRvIHRoaXMgc3RyaW5nKS5cclxudmFyIGVtcHR5SW1hZ2VVcmwgPSAnZGF0YTppbWFnZS9naWY7YmFzZTY0LFIwbEdPRGxoQVFBQkFBRC9BQ3dBQUFBQUFRQUJBQUFDQURzPSc7XHJcblxyXG4vLyBpbnNwaXJlZCBieSBodHRwOi8vcGF1bGlyaXNoLmNvbS8yMDExL3JlcXVlc3RhbmltYXRpb25mcmFtZS1mb3Itc21hcnQtYW5pbWF0aW5nL1xyXG5cclxuZnVuY3Rpb24gZ2V0UHJlZml4ZWQobmFtZSkge1xyXG5cdHJldHVybiB3aW5kb3dbJ3dlYmtpdCcgKyBuYW1lXSB8fCB3aW5kb3dbJ21veicgKyBuYW1lXSB8fCB3aW5kb3dbJ21zJyArIG5hbWVdO1xyXG59XHJcblxyXG52YXIgbGFzdFRpbWUgPSAwO1xyXG5cclxuLy8gZmFsbGJhY2sgZm9yIElFIDctOFxyXG5mdW5jdGlvbiB0aW1lb3V0RGVmZXIoZm4pIHtcclxuXHR2YXIgdGltZSA9ICtuZXcgRGF0ZSgpLFxyXG5cdCAgICB0aW1lVG9DYWxsID0gTWF0aC5tYXgoMCwgMTYgLSAodGltZSAtIGxhc3RUaW1lKSk7XHJcblxyXG5cdGxhc3RUaW1lID0gdGltZSArIHRpbWVUb0NhbGw7XHJcblx0cmV0dXJuIHdpbmRvdy5zZXRUaW1lb3V0KGZuLCB0aW1lVG9DYWxsKTtcclxufVxyXG5cclxudmFyIHJlcXVlc3RGbiA9IHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHwgZ2V0UHJlZml4ZWQoJ1JlcXVlc3RBbmltYXRpb25GcmFtZScpIHx8IHRpbWVvdXREZWZlcjtcclxudmFyIGNhbmNlbEZuID0gd2luZG93LmNhbmNlbEFuaW1hdGlvbkZyYW1lIHx8IGdldFByZWZpeGVkKCdDYW5jZWxBbmltYXRpb25GcmFtZScpIHx8XHJcblx0XHRnZXRQcmVmaXhlZCgnQ2FuY2VsUmVxdWVzdEFuaW1hdGlvbkZyYW1lJykgfHwgZnVuY3Rpb24gKGlkKSB7IHdpbmRvdy5jbGVhclRpbWVvdXQoaWQpOyB9O1xyXG5cclxuLy8gQGZ1bmN0aW9uIHJlcXVlc3RBbmltRnJhbWUoZm46IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0LCBpbW1lZGlhdGU/OiBCb29sZWFuKTogTnVtYmVyXHJcbi8vIFNjaGVkdWxlcyBgZm5gIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGJyb3dzZXIgcmVwYWludHMuIGBmbmAgaXMgYm91bmQgdG9cclxuLy8gYGNvbnRleHRgIGlmIGdpdmVuLiBXaGVuIGBpbW1lZGlhdGVgIGlzIHNldCwgYGZuYCBpcyBjYWxsZWQgaW1tZWRpYXRlbHkgaWZcclxuLy8gdGhlIGJyb3dzZXIgZG9lc24ndCBoYXZlIG5hdGl2ZSBzdXBwb3J0IGZvclxyXG4vLyBbYHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWVgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvd2luZG93L3JlcXVlc3RBbmltYXRpb25GcmFtZSksXHJcbi8vIG90aGVyd2lzZSBpdCdzIGRlbGF5ZWQuIFJldHVybnMgYSByZXF1ZXN0IElEIHRoYXQgY2FuIGJlIHVzZWQgdG8gY2FuY2VsIHRoZSByZXF1ZXN0LlxyXG5mdW5jdGlvbiByZXF1ZXN0QW5pbUZyYW1lKGZuLCBjb250ZXh0LCBpbW1lZGlhdGUpIHtcclxuXHRpZiAoaW1tZWRpYXRlICYmIHJlcXVlc3RGbiA9PT0gdGltZW91dERlZmVyKSB7XHJcblx0XHRmbi5jYWxsKGNvbnRleHQpO1xyXG5cdH0gZWxzZSB7XHJcblx0XHRyZXR1cm4gcmVxdWVzdEZuLmNhbGwod2luZG93LCBiaW5kKGZuLCBjb250ZXh0KSk7XHJcblx0fVxyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gY2FuY2VsQW5pbUZyYW1lKGlkOiBOdW1iZXIpOiB1bmRlZmluZWRcclxuLy8gQ2FuY2VscyBhIHByZXZpb3VzIGByZXF1ZXN0QW5pbUZyYW1lYC4gU2VlIGFsc28gW3dpbmRvdy5jYW5jZWxBbmltYXRpb25GcmFtZV0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL3dpbmRvdy9jYW5jZWxBbmltYXRpb25GcmFtZSkuXHJcbmZ1bmN0aW9uIGNhbmNlbEFuaW1GcmFtZShpZCkge1xyXG5cdGlmIChpZCkge1xyXG5cdFx0Y2FuY2VsRm4uY2FsbCh3aW5kb3csIGlkKTtcclxuXHR9XHJcbn1cclxuXG5cbnZhciBVdGlsID0gKE9iamVjdC5mcmVlemUgfHwgT2JqZWN0KSh7XG5cdGZyZWV6ZTogZnJlZXplLFxuXHRleHRlbmQ6IGV4dGVuZCxcblx0Y3JlYXRlOiBjcmVhdGUsXG5cdGJpbmQ6IGJpbmQsXG5cdGxhc3RJZDogbGFzdElkLFxuXHRzdGFtcDogc3RhbXAsXG5cdHRocm90dGxlOiB0aHJvdHRsZSxcblx0d3JhcE51bTogd3JhcE51bSxcblx0ZmFsc2VGbjogZmFsc2VGbixcblx0Zm9ybWF0TnVtOiBmb3JtYXROdW0sXG5cdHRyaW06IHRyaW0sXG5cdHNwbGl0V29yZHM6IHNwbGl0V29yZHMsXG5cdHNldE9wdGlvbnM6IHNldE9wdGlvbnMsXG5cdGdldFBhcmFtU3RyaW5nOiBnZXRQYXJhbVN0cmluZyxcblx0dGVtcGxhdGU6IHRlbXBsYXRlLFxuXHRpc0FycmF5OiBpc0FycmF5LFxuXHRpbmRleE9mOiBpbmRleE9mLFxuXHRlbXB0eUltYWdlVXJsOiBlbXB0eUltYWdlVXJsLFxuXHRyZXF1ZXN0Rm46IHJlcXVlc3RGbixcblx0Y2FuY2VsRm46IGNhbmNlbEZuLFxuXHRyZXF1ZXN0QW5pbUZyYW1lOiByZXF1ZXN0QW5pbUZyYW1lLFxuXHRjYW5jZWxBbmltRnJhbWU6IGNhbmNlbEFuaW1GcmFtZVxufSk7XG5cbi8vIEBjbGFzcyBDbGFzc1xyXG4vLyBAYWthIEwuQ2xhc3NcclxuXHJcbi8vIEBzZWN0aW9uXHJcbi8vIEB1bmluaGVyaXRhYmxlXHJcblxyXG4vLyBUaGFua3MgdG8gSm9obiBSZXNpZyBhbmQgRGVhbiBFZHdhcmRzIGZvciBpbnNwaXJhdGlvbiFcclxuXHJcbmZ1bmN0aW9uIENsYXNzKCkge31cclxuXHJcbkNsYXNzLmV4dGVuZCA9IGZ1bmN0aW9uIChwcm9wcykge1xyXG5cclxuXHQvLyBAZnVuY3Rpb24gZXh0ZW5kKHByb3BzOiBPYmplY3QpOiBGdW5jdGlvblxyXG5cdC8vIFtFeHRlbmRzIHRoZSBjdXJyZW50IGNsYXNzXSgjY2xhc3MtaW5oZXJpdGFuY2UpIGdpdmVuIHRoZSBwcm9wZXJ0aWVzIHRvIGJlIGluY2x1ZGVkLlxyXG5cdC8vIFJldHVybnMgYSBKYXZhc2NyaXB0IGZ1bmN0aW9uIHRoYXQgaXMgYSBjbGFzcyBjb25zdHJ1Y3RvciAodG8gYmUgY2FsbGVkIHdpdGggYG5ld2ApLlxyXG5cdHZhciBOZXdDbGFzcyA9IGZ1bmN0aW9uICgpIHtcclxuXHJcblx0XHQvLyBjYWxsIHRoZSBjb25zdHJ1Y3RvclxyXG5cdFx0aWYgKHRoaXMuaW5pdGlhbGl6ZSkge1xyXG5cdFx0XHR0aGlzLmluaXRpYWxpemUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBjYWxsIGFsbCBjb25zdHJ1Y3RvciBob29rc1xyXG5cdFx0dGhpcy5jYWxsSW5pdEhvb2tzKCk7XHJcblx0fTtcclxuXHJcblx0dmFyIHBhcmVudFByb3RvID0gTmV3Q2xhc3MuX19zdXBlcl9fID0gdGhpcy5wcm90b3R5cGU7XHJcblxyXG5cdHZhciBwcm90byA9IGNyZWF0ZShwYXJlbnRQcm90byk7XHJcblx0cHJvdG8uY29uc3RydWN0b3IgPSBOZXdDbGFzcztcclxuXHJcblx0TmV3Q2xhc3MucHJvdG90eXBlID0gcHJvdG87XHJcblxyXG5cdC8vIGluaGVyaXQgcGFyZW50J3Mgc3RhdGljc1xyXG5cdGZvciAodmFyIGkgaW4gdGhpcykge1xyXG5cdFx0aWYgKHRoaXMuaGFzT3duUHJvcGVydHkoaSkgJiYgaSAhPT0gJ3Byb3RvdHlwZScgJiYgaSAhPT0gJ19fc3VwZXJfXycpIHtcclxuXHRcdFx0TmV3Q2xhc3NbaV0gPSB0aGlzW2ldO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0Ly8gbWl4IHN0YXRpYyBwcm9wZXJ0aWVzIGludG8gdGhlIGNsYXNzXHJcblx0aWYgKHByb3BzLnN0YXRpY3MpIHtcclxuXHRcdGV4dGVuZChOZXdDbGFzcywgcHJvcHMuc3RhdGljcyk7XHJcblx0XHRkZWxldGUgcHJvcHMuc3RhdGljcztcclxuXHR9XHJcblxyXG5cdC8vIG1peCBpbmNsdWRlcyBpbnRvIHRoZSBwcm90b3R5cGVcclxuXHRpZiAocHJvcHMuaW5jbHVkZXMpIHtcclxuXHRcdGNoZWNrRGVwcmVjYXRlZE1peGluRXZlbnRzKHByb3BzLmluY2x1ZGVzKTtcclxuXHRcdGV4dGVuZC5hcHBseShudWxsLCBbcHJvdG9dLmNvbmNhdChwcm9wcy5pbmNsdWRlcykpO1xyXG5cdFx0ZGVsZXRlIHByb3BzLmluY2x1ZGVzO1xyXG5cdH1cclxuXHJcblx0Ly8gbWVyZ2Ugb3B0aW9uc1xyXG5cdGlmIChwcm90by5vcHRpb25zKSB7XHJcblx0XHRwcm9wcy5vcHRpb25zID0gZXh0ZW5kKGNyZWF0ZShwcm90by5vcHRpb25zKSwgcHJvcHMub3B0aW9ucyk7XHJcblx0fVxyXG5cclxuXHQvLyBtaXggZ2l2ZW4gcHJvcGVydGllcyBpbnRvIHRoZSBwcm90b3R5cGVcclxuXHRleHRlbmQocHJvdG8sIHByb3BzKTtcclxuXHJcblx0cHJvdG8uX2luaXRIb29rcyA9IFtdO1xyXG5cclxuXHQvLyBhZGQgbWV0aG9kIGZvciBjYWxsaW5nIGFsbCBob29rc1xyXG5cdHByb3RvLmNhbGxJbml0SG9va3MgPSBmdW5jdGlvbiAoKSB7XHJcblxyXG5cdFx0aWYgKHRoaXMuX2luaXRIb29rc0NhbGxlZCkgeyByZXR1cm47IH1cclxuXHJcblx0XHRpZiAocGFyZW50UHJvdG8uY2FsbEluaXRIb29rcykge1xyXG5cdFx0XHRwYXJlbnRQcm90by5jYWxsSW5pdEhvb2tzLmNhbGwodGhpcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5faW5pdEhvb2tzQ2FsbGVkID0gdHJ1ZTtcclxuXHJcblx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gcHJvdG8uX2luaXRIb29rcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0XHRwcm90by5faW5pdEhvb2tzW2ldLmNhbGwodGhpcyk7XHJcblx0XHR9XHJcblx0fTtcclxuXHJcblx0cmV0dXJuIE5ld0NsYXNzO1xyXG59O1xyXG5cclxuXHJcbi8vIEBmdW5jdGlvbiBpbmNsdWRlKHByb3BlcnRpZXM6IE9iamVjdCk6IHRoaXNcclxuLy8gW0luY2x1ZGVzIGEgbWl4aW5dKCNjbGFzcy1pbmNsdWRlcykgaW50byB0aGUgY3VycmVudCBjbGFzcy5cclxuQ2xhc3MuaW5jbHVkZSA9IGZ1bmN0aW9uIChwcm9wcykge1xyXG5cdGV4dGVuZCh0aGlzLnByb3RvdHlwZSwgcHJvcHMpO1xyXG5cdHJldHVybiB0aGlzO1xyXG59O1xyXG5cclxuLy8gQGZ1bmN0aW9uIG1lcmdlT3B0aW9ucyhvcHRpb25zOiBPYmplY3QpOiB0aGlzXHJcbi8vIFtNZXJnZXMgYG9wdGlvbnNgXSgjY2xhc3Mtb3B0aW9ucykgaW50byB0aGUgZGVmYXVsdHMgb2YgdGhlIGNsYXNzLlxyXG5DbGFzcy5tZXJnZU9wdGlvbnMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xyXG5cdGV4dGVuZCh0aGlzLnByb3RvdHlwZS5vcHRpb25zLCBvcHRpb25zKTtcclxuXHRyZXR1cm4gdGhpcztcclxufTtcclxuXHJcbi8vIEBmdW5jdGlvbiBhZGRJbml0SG9vayhmbjogRnVuY3Rpb24pOiB0aGlzXHJcbi8vIEFkZHMgYSBbY29uc3RydWN0b3IgaG9va10oI2NsYXNzLWNvbnN0cnVjdG9yLWhvb2tzKSB0byB0aGUgY2xhc3MuXHJcbkNsYXNzLmFkZEluaXRIb29rID0gZnVuY3Rpb24gKGZuKSB7IC8vIChGdW5jdGlvbikgfHwgKFN0cmluZywgYXJncy4uLilcclxuXHR2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XHJcblxyXG5cdHZhciBpbml0ID0gdHlwZW9mIGZuID09PSAnZnVuY3Rpb24nID8gZm4gOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR0aGlzW2ZuXS5hcHBseSh0aGlzLCBhcmdzKTtcclxuXHR9O1xyXG5cclxuXHR0aGlzLnByb3RvdHlwZS5faW5pdEhvb2tzID0gdGhpcy5wcm90b3R5cGUuX2luaXRIb29rcyB8fCBbXTtcclxuXHR0aGlzLnByb3RvdHlwZS5faW5pdEhvb2tzLnB1c2goaW5pdCk7XHJcblx0cmV0dXJuIHRoaXM7XHJcbn07XHJcblxyXG5mdW5jdGlvbiBjaGVja0RlcHJlY2F0ZWRNaXhpbkV2ZW50cyhpbmNsdWRlcykge1xyXG5cdGlmICh0eXBlb2YgTCA9PT0gJ3VuZGVmaW5lZCcgfHwgIUwgfHwgIUwuTWl4aW4pIHsgcmV0dXJuOyB9XHJcblxyXG5cdGluY2x1ZGVzID0gaXNBcnJheShpbmNsdWRlcykgPyBpbmNsdWRlcyA6IFtpbmNsdWRlc107XHJcblxyXG5cdGZvciAodmFyIGkgPSAwOyBpIDwgaW5jbHVkZXMubGVuZ3RoOyBpKyspIHtcclxuXHRcdGlmIChpbmNsdWRlc1tpXSA9PT0gTC5NaXhpbi5FdmVudHMpIHtcclxuXHRcdFx0Y29uc29sZS53YXJuKCdEZXByZWNhdGVkIGluY2x1ZGUgb2YgTC5NaXhpbi5FdmVudHM6ICcgK1xyXG5cdFx0XHRcdCd0aGlzIHByb3BlcnR5IHdpbGwgYmUgcmVtb3ZlZCBpbiBmdXR1cmUgcmVsZWFzZXMsICcgK1xyXG5cdFx0XHRcdCdwbGVhc2UgaW5oZXJpdCBmcm9tIEwuRXZlbnRlZCBpbnN0ZWFkLicsIG5ldyBFcnJvcigpLnN0YWNrKTtcclxuXHRcdH1cclxuXHR9XHJcbn1cblxuLypcclxuICogQGNsYXNzIEV2ZW50ZWRcclxuICogQGFrYSBMLkV2ZW50ZWRcclxuICogQGluaGVyaXRzIENsYXNzXHJcbiAqXHJcbiAqIEEgc2V0IG9mIG1ldGhvZHMgc2hhcmVkIGJldHdlZW4gZXZlbnQtcG93ZXJlZCBjbGFzc2VzIChsaWtlIGBNYXBgIGFuZCBgTWFya2VyYCkuIEdlbmVyYWxseSwgZXZlbnRzIGFsbG93IHlvdSB0byBleGVjdXRlIHNvbWUgZnVuY3Rpb24gd2hlbiBzb21ldGhpbmcgaGFwcGVucyB3aXRoIGFuIG9iamVjdCAoZS5nLiB0aGUgdXNlciBjbGlja3Mgb24gdGhlIG1hcCwgY2F1c2luZyB0aGUgbWFwIHRvIGZpcmUgYCdjbGljaydgIGV2ZW50KS5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogbWFwLm9uKCdjbGljaycsIGZ1bmN0aW9uKGUpIHtcclxuICogXHRhbGVydChlLmxhdGxuZyk7XHJcbiAqIH0gKTtcclxuICogYGBgXHJcbiAqXHJcbiAqIExlYWZsZXQgZGVhbHMgd2l0aCBldmVudCBsaXN0ZW5lcnMgYnkgcmVmZXJlbmNlLCBzbyBpZiB5b3Ugd2FudCB0byBhZGQgYSBsaXN0ZW5lciBhbmQgdGhlbiByZW1vdmUgaXQsIGRlZmluZSBpdCBhcyBhIGZ1bmN0aW9uOlxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiBmdW5jdGlvbiBvbkNsaWNrKGUpIHsgLi4uIH1cclxuICpcclxuICogbWFwLm9uKCdjbGljaycsIG9uQ2xpY2spO1xyXG4gKiBtYXAub2ZmKCdjbGljaycsIG9uQ2xpY2spO1xyXG4gKiBgYGBcclxuICovXHJcblxyXG52YXIgRXZlbnRzID0ge1xyXG5cdC8qIEBtZXRob2Qgb24odHlwZTogU3RyaW5nLCBmbjogRnVuY3Rpb24sIGNvbnRleHQ/OiBPYmplY3QpOiB0aGlzXHJcblx0ICogQWRkcyBhIGxpc3RlbmVyIGZ1bmN0aW9uIChgZm5gKSB0byBhIHBhcnRpY3VsYXIgZXZlbnQgdHlwZSBvZiB0aGUgb2JqZWN0LiBZb3UgY2FuIG9wdGlvbmFsbHkgc3BlY2lmeSB0aGUgY29udGV4dCBvZiB0aGUgbGlzdGVuZXIgKG9iamVjdCB0aGUgdGhpcyBrZXl3b3JkIHdpbGwgcG9pbnQgdG8pLiBZb3UgY2FuIGFsc28gcGFzcyBzZXZlcmFsIHNwYWNlLXNlcGFyYXRlZCB0eXBlcyAoZS5nLiBgJ2NsaWNrIGRibGNsaWNrJ2ApLlxyXG5cdCAqXHJcblx0ICogQGFsdGVybmF0aXZlXHJcblx0ICogQG1ldGhvZCBvbihldmVudE1hcDogT2JqZWN0KTogdGhpc1xyXG5cdCAqIEFkZHMgYSBzZXQgb2YgdHlwZS9saXN0ZW5lciBwYWlycywgZS5nLiBge2NsaWNrOiBvbkNsaWNrLCBtb3VzZW1vdmU6IG9uTW91c2VNb3ZlfWBcclxuXHQgKi9cclxuXHRvbjogZnVuY3Rpb24gKHR5cGVzLCBmbiwgY29udGV4dCkge1xyXG5cclxuXHRcdC8vIHR5cGVzIGNhbiBiZSBhIG1hcCBvZiB0eXBlcy9oYW5kbGVyc1xyXG5cdFx0aWYgKHR5cGVvZiB0eXBlcyA9PT0gJ29iamVjdCcpIHtcclxuXHRcdFx0Zm9yICh2YXIgdHlwZSBpbiB0eXBlcykge1xyXG5cdFx0XHRcdC8vIHdlIGRvbid0IHByb2Nlc3Mgc3BhY2Utc2VwYXJhdGVkIGV2ZW50cyBoZXJlIGZvciBwZXJmb3JtYW5jZTtcclxuXHRcdFx0XHQvLyBpdCdzIGEgaG90IHBhdGggc2luY2UgTGF5ZXIgdXNlcyB0aGUgb24ob2JqKSBzeW50YXhcclxuXHRcdFx0XHR0aGlzLl9vbih0eXBlLCB0eXBlc1t0eXBlXSwgZm4pO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0Ly8gdHlwZXMgY2FuIGJlIGEgc3RyaW5nIG9mIHNwYWNlLXNlcGFyYXRlZCB3b3Jkc1xyXG5cdFx0XHR0eXBlcyA9IHNwbGl0V29yZHModHlwZXMpO1xyXG5cclxuXHRcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHR5cGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0dGhpcy5fb24odHlwZXNbaV0sIGZuLCBjb250ZXh0KTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8qIEBtZXRob2Qgb2ZmKHR5cGU6IFN0cmluZywgZm4/OiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuXHQgKiBSZW1vdmVzIGEgcHJldmlvdXNseSBhZGRlZCBsaXN0ZW5lciBmdW5jdGlvbi4gSWYgbm8gZnVuY3Rpb24gaXMgc3BlY2lmaWVkLCBpdCB3aWxsIHJlbW92ZSBhbGwgdGhlIGxpc3RlbmVycyBvZiB0aGF0IHBhcnRpY3VsYXIgZXZlbnQgZnJvbSB0aGUgb2JqZWN0LiBOb3RlIHRoYXQgaWYgeW91IHBhc3NlZCBhIGN1c3RvbSBjb250ZXh0IHRvIGBvbmAsIHlvdSBtdXN0IHBhc3MgdGhlIHNhbWUgY29udGV4dCB0byBgb2ZmYCBpbiBvcmRlciB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxyXG5cdCAqXHJcblx0ICogQGFsdGVybmF0aXZlXHJcblx0ICogQG1ldGhvZCBvZmYoZXZlbnRNYXA6IE9iamVjdCk6IHRoaXNcclxuXHQgKiBSZW1vdmVzIGEgc2V0IG9mIHR5cGUvbGlzdGVuZXIgcGFpcnMuXHJcblx0ICpcclxuXHQgKiBAYWx0ZXJuYXRpdmVcclxuXHQgKiBAbWV0aG9kIG9mZjogdGhpc1xyXG5cdCAqIFJlbW92ZXMgYWxsIGxpc3RlbmVycyB0byBhbGwgZXZlbnRzIG9uIHRoZSBvYmplY3QuXHJcblx0ICovXHJcblx0b2ZmOiBmdW5jdGlvbiAodHlwZXMsIGZuLCBjb250ZXh0KSB7XHJcblxyXG5cdFx0aWYgKCF0eXBlcykge1xyXG5cdFx0XHQvLyBjbGVhciBhbGwgbGlzdGVuZXJzIGlmIGNhbGxlZCB3aXRob3V0IGFyZ3VtZW50c1xyXG5cdFx0XHRkZWxldGUgdGhpcy5fZXZlbnRzO1xyXG5cclxuXHRcdH0gZWxzZSBpZiAodHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG5cdFx0XHRmb3IgKHZhciB0eXBlIGluIHR5cGVzKSB7XHJcblx0XHRcdFx0dGhpcy5fb2ZmKHR5cGUsIHR5cGVzW3R5cGVdLCBmbik7XHJcblx0XHRcdH1cclxuXHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHR0eXBlcyA9IHNwbGl0V29yZHModHlwZXMpO1xyXG5cclxuXHRcdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHR5cGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0dGhpcy5fb2ZmKHR5cGVzW2ldLCBmbiwgY29udGV4dCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBhdHRhY2ggbGlzdGVuZXIgKHdpdGhvdXQgc3ludGFjdGljIHN1Z2FyIG5vdylcclxuXHRfb246IGZ1bmN0aW9uICh0eXBlLCBmbiwgY29udGV4dCkge1xyXG5cdFx0dGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xyXG5cclxuXHRcdC8qIGdldC9pbml0IGxpc3RlbmVycyBmb3IgdHlwZSAqL1xyXG5cdFx0dmFyIHR5cGVMaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV07XHJcblx0XHRpZiAoIXR5cGVMaXN0ZW5lcnMpIHtcclxuXHRcdFx0dHlwZUxpc3RlbmVycyA9IFtdO1xyXG5cdFx0XHR0aGlzLl9ldmVudHNbdHlwZV0gPSB0eXBlTGlzdGVuZXJzO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChjb250ZXh0ID09PSB0aGlzKSB7XHJcblx0XHRcdC8vIExlc3MgbWVtb3J5IGZvb3RwcmludC5cclxuXHRcdFx0Y29udGV4dCA9IHVuZGVmaW5lZDtcclxuXHRcdH1cclxuXHRcdHZhciBuZXdMaXN0ZW5lciA9IHtmbjogZm4sIGN0eDogY29udGV4dH0sXHJcblx0XHQgICAgbGlzdGVuZXJzID0gdHlwZUxpc3RlbmVycztcclxuXHJcblx0XHQvLyBjaGVjayBpZiBmbiBhbHJlYWR5IHRoZXJlXHJcblx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdGlmIChsaXN0ZW5lcnNbaV0uZm4gPT09IGZuICYmIGxpc3RlbmVyc1tpXS5jdHggPT09IGNvbnRleHQpIHtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRsaXN0ZW5lcnMucHVzaChuZXdMaXN0ZW5lcik7XHJcblx0fSxcclxuXHJcblx0X29mZjogZnVuY3Rpb24gKHR5cGUsIGZuLCBjb250ZXh0KSB7XHJcblx0XHR2YXIgbGlzdGVuZXJzLFxyXG5cdFx0ICAgIGksXHJcblx0XHQgICAgbGVuO1xyXG5cclxuXHRcdGlmICghdGhpcy5fZXZlbnRzKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcclxuXHJcblx0XHRpZiAoIWxpc3RlbmVycykge1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCFmbikge1xyXG5cdFx0XHQvLyBTZXQgYWxsIHJlbW92ZWQgbGlzdGVuZXJzIHRvIG5vb3Agc28gdGhleSBhcmUgbm90IGNhbGxlZCBpZiByZW1vdmUgaGFwcGVucyBpbiBmaXJlXHJcblx0XHRcdGZvciAoaSA9IDAsIGxlbiA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0XHRcdGxpc3RlbmVyc1tpXS5mbiA9IGZhbHNlRm47XHJcblx0XHRcdH1cclxuXHRcdFx0Ly8gY2xlYXIgYWxsIGxpc3RlbmVycyBmb3IgYSB0eXBlIGlmIGZ1bmN0aW9uIGlzbid0IHNwZWNpZmllZFxyXG5cdFx0XHRkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKGNvbnRleHQgPT09IHRoaXMpIHtcclxuXHRcdFx0Y29udGV4dCA9IHVuZGVmaW5lZDtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAobGlzdGVuZXJzKSB7XHJcblxyXG5cdFx0XHQvLyBmaW5kIGZuIGFuZCByZW1vdmUgaXRcclxuXHRcdFx0Zm9yIChpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0dmFyIGwgPSBsaXN0ZW5lcnNbaV07XHJcblx0XHRcdFx0aWYgKGwuY3R4ICE9PSBjb250ZXh0KSB7IGNvbnRpbnVlOyB9XHJcblx0XHRcdFx0aWYgKGwuZm4gPT09IGZuKSB7XHJcblxyXG5cdFx0XHRcdFx0Ly8gc2V0IHRoZSByZW1vdmVkIGxpc3RlbmVyIHRvIG5vb3Agc28gdGhhdCdzIG5vdCBjYWxsZWQgaWYgcmVtb3ZlIGhhcHBlbnMgaW4gZmlyZVxyXG5cdFx0XHRcdFx0bC5mbiA9IGZhbHNlRm47XHJcblxyXG5cdFx0XHRcdFx0aWYgKHRoaXMuX2ZpcmluZ0NvdW50KSB7XHJcblx0XHRcdFx0XHRcdC8qIGNvcHkgYXJyYXkgaW4gY2FzZSBldmVudHMgYXJlIGJlaW5nIGZpcmVkICovXHJcblx0XHRcdFx0XHRcdHRoaXMuX2V2ZW50c1t0eXBlXSA9IGxpc3RlbmVycyA9IGxpc3RlbmVycy5zbGljZSgpO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0bGlzdGVuZXJzLnNwbGljZShpLCAxKTtcclxuXHJcblx0XHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBmaXJlKHR5cGU6IFN0cmluZywgZGF0YT86IE9iamVjdCwgcHJvcGFnYXRlPzogQm9vbGVhbik6IHRoaXNcclxuXHQvLyBGaXJlcyBhbiBldmVudCBvZiB0aGUgc3BlY2lmaWVkIHR5cGUuIFlvdSBjYW4gb3B0aW9uYWxseSBwcm92aWRlIGFuIGRhdGFcclxuXHQvLyBvYmplY3Qg4oCUIHRoZSBmaXJzdCBhcmd1bWVudCBvZiB0aGUgbGlzdGVuZXIgZnVuY3Rpb24gd2lsbCBjb250YWluIGl0c1xyXG5cdC8vIHByb3BlcnRpZXMuIFRoZSBldmVudCBjYW4gb3B0aW9uYWxseSBiZSBwcm9wYWdhdGVkIHRvIGV2ZW50IHBhcmVudHMuXHJcblx0ZmlyZTogZnVuY3Rpb24gKHR5cGUsIGRhdGEsIHByb3BhZ2F0ZSkge1xyXG5cdFx0aWYgKCF0aGlzLmxpc3RlbnModHlwZSwgcHJvcGFnYXRlKSkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdHZhciBldmVudCA9IGV4dGVuZCh7fSwgZGF0YSwge1xyXG5cdFx0XHR0eXBlOiB0eXBlLFxyXG5cdFx0XHR0YXJnZXQ6IHRoaXMsXHJcblx0XHRcdHNvdXJjZVRhcmdldDogZGF0YSAmJiBkYXRhLnNvdXJjZVRhcmdldCB8fCB0aGlzXHJcblx0XHR9KTtcclxuXHJcblx0XHRpZiAodGhpcy5fZXZlbnRzKSB7XHJcblx0XHRcdHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHNbdHlwZV07XHJcblxyXG5cdFx0XHRpZiAobGlzdGVuZXJzKSB7XHJcblx0XHRcdFx0dGhpcy5fZmlyaW5nQ291bnQgPSAodGhpcy5fZmlyaW5nQ291bnQgKyAxKSB8fCAxO1xyXG5cdFx0XHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0XHRcdHZhciBsID0gbGlzdGVuZXJzW2ldO1xyXG5cdFx0XHRcdFx0bC5mbi5jYWxsKGwuY3R4IHx8IHRoaXMsIGV2ZW50KTtcclxuXHRcdFx0XHR9XHJcblxyXG5cdFx0XHRcdHRoaXMuX2ZpcmluZ0NvdW50LS07XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRpZiAocHJvcGFnYXRlKSB7XHJcblx0XHRcdC8vIHByb3BhZ2F0ZSB0aGUgZXZlbnQgdG8gcGFyZW50cyAoc2V0IHdpdGggYWRkRXZlbnRQYXJlbnQpXHJcblx0XHRcdHRoaXMuX3Byb3BhZ2F0ZUV2ZW50KGV2ZW50KTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGxpc3RlbnModHlwZTogU3RyaW5nKTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIGEgcGFydGljdWxhciBldmVudCB0eXBlIGhhcyBhbnkgbGlzdGVuZXJzIGF0dGFjaGVkIHRvIGl0LlxyXG5cdGxpc3RlbnM6IGZ1bmN0aW9uICh0eXBlLCBwcm9wYWdhdGUpIHtcclxuXHRcdHZhciBsaXN0ZW5lcnMgPSB0aGlzLl9ldmVudHMgJiYgdGhpcy5fZXZlbnRzW3R5cGVdO1xyXG5cdFx0aWYgKGxpc3RlbmVycyAmJiBsaXN0ZW5lcnMubGVuZ3RoKSB7IHJldHVybiB0cnVlOyB9XHJcblxyXG5cdFx0aWYgKHByb3BhZ2F0ZSkge1xyXG5cdFx0XHQvLyBhbHNvIGNoZWNrIHBhcmVudHMgZm9yIGxpc3RlbmVycyBpZiBldmVudCBwcm9wYWdhdGVzXHJcblx0XHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2V2ZW50UGFyZW50cykge1xyXG5cdFx0XHRcdGlmICh0aGlzLl9ldmVudFBhcmVudHNbaWRdLmxpc3RlbnModHlwZSwgcHJvcGFnYXRlKSkgeyByZXR1cm4gdHJ1ZTsgfVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gZmFsc2U7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBvbmNlKOKApik6IHRoaXNcclxuXHQvLyBCZWhhdmVzIGFzIFtgb24o4oCmKWBdKCNldmVudGVkLW9uKSwgZXhjZXB0IHRoZSBsaXN0ZW5lciB3aWxsIG9ubHkgZ2V0IGZpcmVkIG9uY2UgYW5kIHRoZW4gcmVtb3ZlZC5cclxuXHRvbmNlOiBmdW5jdGlvbiAodHlwZXMsIGZuLCBjb250ZXh0KSB7XHJcblxyXG5cdFx0aWYgKHR5cGVvZiB0eXBlcyA9PT0gJ29iamVjdCcpIHtcclxuXHRcdFx0Zm9yICh2YXIgdHlwZSBpbiB0eXBlcykge1xyXG5cdFx0XHRcdHRoaXMub25jZSh0eXBlLCB0eXBlc1t0eXBlXSwgZm4pO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBoYW5kbGVyID0gYmluZChmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHRoaXNcclxuXHRcdFx0ICAgIC5vZmYodHlwZXMsIGZuLCBjb250ZXh0KVxyXG5cdFx0XHQgICAgLm9mZih0eXBlcywgaGFuZGxlciwgY29udGV4dCk7XHJcblx0XHR9LCB0aGlzKTtcclxuXHJcblx0XHQvLyBhZGQgYSBsaXN0ZW5lciB0aGF0J3MgZXhlY3V0ZWQgb25jZSBhbmQgcmVtb3ZlZCBhZnRlciB0aGF0XHJcblx0XHRyZXR1cm4gdGhpc1xyXG5cdFx0ICAgIC5vbih0eXBlcywgZm4sIGNvbnRleHQpXHJcblx0XHQgICAgLm9uKHR5cGVzLCBoYW5kbGVyLCBjb250ZXh0KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGFkZEV2ZW50UGFyZW50KG9iajogRXZlbnRlZCk6IHRoaXNcclxuXHQvLyBBZGRzIGFuIGV2ZW50IHBhcmVudCAtIGFuIGBFdmVudGVkYCB0aGF0IHdpbGwgcmVjZWl2ZSBwcm9wYWdhdGVkIGV2ZW50c1xyXG5cdGFkZEV2ZW50UGFyZW50OiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHR0aGlzLl9ldmVudFBhcmVudHMgPSB0aGlzLl9ldmVudFBhcmVudHMgfHwge307XHJcblx0XHR0aGlzLl9ldmVudFBhcmVudHNbc3RhbXAob2JqKV0gPSBvYmo7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHJlbW92ZUV2ZW50UGFyZW50KG9iajogRXZlbnRlZCk6IHRoaXNcclxuXHQvLyBSZW1vdmVzIGFuIGV2ZW50IHBhcmVudCwgc28gaXQgd2lsbCBzdG9wIHJlY2VpdmluZyBwcm9wYWdhdGVkIGV2ZW50c1xyXG5cdHJlbW92ZUV2ZW50UGFyZW50OiBmdW5jdGlvbiAob2JqKSB7XHJcblx0XHRpZiAodGhpcy5fZXZlbnRQYXJlbnRzKSB7XHJcblx0XHRcdGRlbGV0ZSB0aGlzLl9ldmVudFBhcmVudHNbc3RhbXAob2JqKV07XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRfcHJvcGFnYXRlRXZlbnQ6IGZ1bmN0aW9uIChlKSB7XHJcblx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9ldmVudFBhcmVudHMpIHtcclxuXHRcdFx0dGhpcy5fZXZlbnRQYXJlbnRzW2lkXS5maXJlKGUudHlwZSwgZXh0ZW5kKHtcclxuXHRcdFx0XHRsYXllcjogZS50YXJnZXQsXHJcblx0XHRcdFx0cHJvcGFnYXRlZEZyb206IGUudGFyZ2V0XHJcblx0XHRcdH0sIGUpLCB0cnVlKTtcclxuXHRcdH1cclxuXHR9XHJcbn07XHJcblxyXG4vLyBhbGlhc2VzOyB3ZSBzaG91bGQgZGl0Y2ggdGhvc2UgZXZlbnR1YWxseVxyXG5cclxuLy8gQG1ldGhvZCBhZGRFdmVudExpc3RlbmVyKOKApik6IHRoaXNcclxuLy8gQWxpYXMgdG8gW2BvbijigKYpYF0oI2V2ZW50ZWQtb24pXHJcbkV2ZW50cy5hZGRFdmVudExpc3RlbmVyID0gRXZlbnRzLm9uO1xyXG5cclxuLy8gQG1ldGhvZCByZW1vdmVFdmVudExpc3RlbmVyKOKApik6IHRoaXNcclxuLy8gQWxpYXMgdG8gW2BvZmYo4oCmKWBdKCNldmVudGVkLW9mZilcclxuXHJcbi8vIEBtZXRob2QgY2xlYXJBbGxFdmVudExpc3RlbmVycyjigKYpOiB0aGlzXHJcbi8vIEFsaWFzIHRvIFtgb2ZmKClgXSgjZXZlbnRlZC1vZmYpXHJcbkV2ZW50cy5yZW1vdmVFdmVudExpc3RlbmVyID0gRXZlbnRzLmNsZWFyQWxsRXZlbnRMaXN0ZW5lcnMgPSBFdmVudHMub2ZmO1xyXG5cclxuLy8gQG1ldGhvZCBhZGRPbmVUaW1lRXZlbnRMaXN0ZW5lcijigKYpOiB0aGlzXHJcbi8vIEFsaWFzIHRvIFtgb25jZSjigKYpYF0oI2V2ZW50ZWQtb25jZSlcclxuRXZlbnRzLmFkZE9uZVRpbWVFdmVudExpc3RlbmVyID0gRXZlbnRzLm9uY2U7XHJcblxyXG4vLyBAbWV0aG9kIGZpcmVFdmVudCjigKYpOiB0aGlzXHJcbi8vIEFsaWFzIHRvIFtgZmlyZSjigKYpYF0oI2V2ZW50ZWQtZmlyZSlcclxuRXZlbnRzLmZpcmVFdmVudCA9IEV2ZW50cy5maXJlO1xyXG5cclxuLy8gQG1ldGhvZCBoYXNFdmVudExpc3RlbmVycyjigKYpOiBCb29sZWFuXHJcbi8vIEFsaWFzIHRvIFtgbGlzdGVucyjigKYpYF0oI2V2ZW50ZWQtbGlzdGVucylcclxuRXZlbnRzLmhhc0V2ZW50TGlzdGVuZXJzID0gRXZlbnRzLmxpc3RlbnM7XHJcblxyXG52YXIgRXZlbnRlZCA9IENsYXNzLmV4dGVuZChFdmVudHMpO1xuXG4vKlxyXG4gKiBAY2xhc3MgUG9pbnRcclxuICogQGFrYSBMLlBvaW50XHJcbiAqXHJcbiAqIFJlcHJlc2VudHMgYSBwb2ludCB3aXRoIGB4YCBhbmQgYHlgIGNvb3JkaW5hdGVzIGluIHBpeGVscy5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogdmFyIHBvaW50ID0gTC5wb2ludCgyMDAsIDMwMCk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBBbGwgTGVhZmxldCBtZXRob2RzIGFuZCBvcHRpb25zIHRoYXQgYWNjZXB0IGBQb2ludGAgb2JqZWN0cyBhbHNvIGFjY2VwdCB0aGVtIGluIGEgc2ltcGxlIEFycmF5IGZvcm0gKHVubGVzcyBub3RlZCBvdGhlcndpc2UpLCBzbyB0aGVzZSBsaW5lcyBhcmUgZXF1aXZhbGVudDpcclxuICpcclxuICogYGBganNcclxuICogbWFwLnBhbkJ5KFsyMDAsIDMwMF0pO1xyXG4gKiBtYXAucGFuQnkoTC5wb2ludCgyMDAsIDMwMCkpO1xyXG4gKiBgYGBcclxuICpcclxuICogTm90ZSB0aGF0IGBQb2ludGAgZG9lcyBub3QgaW5oZXJpdCBmcm9tIExlYWZldCdzIGBDbGFzc2Agb2JqZWN0LFxyXG4gKiB3aGljaCBtZWFucyBuZXcgY2xhc3NlcyBjYW4ndCBpbmhlcml0IGZyb20gaXQsIGFuZCBuZXcgbWV0aG9kc1xyXG4gKiBjYW4ndCBiZSBhZGRlZCB0byBpdCB3aXRoIHRoZSBgaW5jbHVkZWAgZnVuY3Rpb24uXHJcbiAqL1xyXG5cclxuZnVuY3Rpb24gUG9pbnQoeCwgeSwgcm91bmQpIHtcclxuXHQvLyBAcHJvcGVydHkgeDogTnVtYmVyOyBUaGUgYHhgIGNvb3JkaW5hdGUgb2YgdGhlIHBvaW50XHJcblx0dGhpcy54ID0gKHJvdW5kID8gTWF0aC5yb3VuZCh4KSA6IHgpO1xyXG5cdC8vIEBwcm9wZXJ0eSB5OiBOdW1iZXI7IFRoZSBgeWAgY29vcmRpbmF0ZSBvZiB0aGUgcG9pbnRcclxuXHR0aGlzLnkgPSAocm91bmQgPyBNYXRoLnJvdW5kKHkpIDogeSk7XHJcbn1cclxuXHJcbnZhciB0cnVuYyA9IE1hdGgudHJ1bmMgfHwgZnVuY3Rpb24gKHYpIHtcclxuXHRyZXR1cm4gdiA+IDAgPyBNYXRoLmZsb29yKHYpIDogTWF0aC5jZWlsKHYpO1xyXG59O1xyXG5cclxuUG9pbnQucHJvdG90eXBlID0ge1xyXG5cclxuXHQvLyBAbWV0aG9kIGNsb25lKCk6IFBvaW50XHJcblx0Ly8gUmV0dXJucyBhIGNvcHkgb2YgdGhlIGN1cnJlbnQgcG9pbnQuXHJcblx0Y2xvbmU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiBuZXcgUG9pbnQodGhpcy54LCB0aGlzLnkpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgYWRkKG90aGVyUG9pbnQ6IFBvaW50KTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2YgYWRkaXRpb24gb2YgdGhlIGN1cnJlbnQgYW5kIHRoZSBnaXZlbiBwb2ludHMuXHJcblx0YWRkOiBmdW5jdGlvbiAocG9pbnQpIHtcclxuXHRcdC8vIG5vbi1kZXN0cnVjdGl2ZSwgcmV0dXJucyBhIG5ldyBwb2ludFxyXG5cdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fYWRkKHRvUG9pbnQocG9pbnQpKTtcclxuXHR9LFxyXG5cclxuXHRfYWRkOiBmdW5jdGlvbiAocG9pbnQpIHtcclxuXHRcdC8vIGRlc3RydWN0aXZlLCB1c2VkIGRpcmVjdGx5IGZvciBwZXJmb3JtYW5jZSBpbiBzaXR1YXRpb25zIHdoZXJlIGl0J3Mgc2FmZSB0byBtb2RpZnkgZXhpc3RpbmcgcG9pbnRcclxuXHRcdHRoaXMueCArPSBwb2ludC54O1xyXG5cdFx0dGhpcy55ICs9IHBvaW50Lnk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHN1YnRyYWN0KG90aGVyUG9pbnQ6IFBvaW50KTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIHRoZSByZXN1bHQgb2Ygc3VidHJhY3Rpb24gb2YgdGhlIGdpdmVuIHBvaW50IGZyb20gdGhlIGN1cnJlbnQuXHJcblx0c3VidHJhY3Q6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fc3VidHJhY3QodG9Qb2ludChwb2ludCkpO1xyXG5cdH0sXHJcblxyXG5cdF9zdWJ0cmFjdDogZnVuY3Rpb24gKHBvaW50KSB7XHJcblx0XHR0aGlzLnggLT0gcG9pbnQueDtcclxuXHRcdHRoaXMueSAtPSBwb2ludC55O1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBkaXZpZGVCeShudW06IE51bWJlcik6IFBvaW50XHJcblx0Ly8gUmV0dXJucyB0aGUgcmVzdWx0IG9mIGRpdmlzaW9uIG9mIHRoZSBjdXJyZW50IHBvaW50IGJ5IHRoZSBnaXZlbiBudW1iZXIuXHJcblx0ZGl2aWRlQnk6IGZ1bmN0aW9uIChudW0pIHtcclxuXHRcdHJldHVybiB0aGlzLmNsb25lKCkuX2RpdmlkZUJ5KG51bSk7XHJcblx0fSxcclxuXHJcblx0X2RpdmlkZUJ5OiBmdW5jdGlvbiAobnVtKSB7XHJcblx0XHR0aGlzLnggLz0gbnVtO1xyXG5cdFx0dGhpcy55IC89IG51bTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgbXVsdGlwbHlCeShudW06IE51bWJlcik6IFBvaW50XHJcblx0Ly8gUmV0dXJucyB0aGUgcmVzdWx0IG9mIG11bHRpcGxpY2F0aW9uIG9mIHRoZSBjdXJyZW50IHBvaW50IGJ5IHRoZSBnaXZlbiBudW1iZXIuXHJcblx0bXVsdGlwbHlCeTogZnVuY3Rpb24gKG51bSkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fbXVsdGlwbHlCeShudW0pO1xyXG5cdH0sXHJcblxyXG5cdF9tdWx0aXBseUJ5OiBmdW5jdGlvbiAobnVtKSB7XHJcblx0XHR0aGlzLnggKj0gbnVtO1xyXG5cdFx0dGhpcy55ICo9IG51bTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2NhbGVCeShzY2FsZTogUG9pbnQpOiBQb2ludFxyXG5cdC8vIE11bHRpcGx5IGVhY2ggY29vcmRpbmF0ZSBvZiB0aGUgY3VycmVudCBwb2ludCBieSBlYWNoIGNvb3JkaW5hdGUgb2ZcclxuXHQvLyBgc2NhbGVgLiBJbiBsaW5lYXIgYWxnZWJyYSB0ZXJtcywgbXVsdGlwbHkgdGhlIHBvaW50IGJ5IHRoZVxyXG5cdC8vIFtzY2FsaW5nIG1hdHJpeF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2NhbGluZ18lMjhnZW9tZXRyeSUyOSNNYXRyaXhfcmVwcmVzZW50YXRpb24pXHJcblx0Ly8gZGVmaW5lZCBieSBgc2NhbGVgLlxyXG5cdHNjYWxlQnk6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0cmV0dXJuIG5ldyBQb2ludCh0aGlzLnggKiBwb2ludC54LCB0aGlzLnkgKiBwb2ludC55KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHVuc2NhbGVCeShzY2FsZTogUG9pbnQpOiBQb2ludFxyXG5cdC8vIEludmVyc2Ugb2YgYHNjYWxlQnlgLiBEaXZpZGUgZWFjaCBjb29yZGluYXRlIG9mIHRoZSBjdXJyZW50IHBvaW50IGJ5XHJcblx0Ly8gZWFjaCBjb29yZGluYXRlIG9mIGBzY2FsZWAuXHJcblx0dW5zY2FsZUJ5OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuXHRcdHJldHVybiBuZXcgUG9pbnQodGhpcy54IC8gcG9pbnQueCwgdGhpcy55IC8gcG9pbnQueSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCByb3VuZCgpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgYSBjb3B5IG9mIHRoZSBjdXJyZW50IHBvaW50IHdpdGggcm91bmRlZCBjb29yZGluYXRlcy5cclxuXHRyb3VuZDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fcm91bmQoKTtcclxuXHR9LFxyXG5cclxuXHRfcm91bmQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMueCA9IE1hdGgucm91bmQodGhpcy54KTtcclxuXHRcdHRoaXMueSA9IE1hdGgucm91bmQodGhpcy55KTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZmxvb3IoKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludCB3aXRoIGZsb29yZWQgY29vcmRpbmF0ZXMgKHJvdW5kZWQgZG93bikuXHJcblx0Zmxvb3I6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLmNsb25lKCkuX2Zsb29yKCk7XHJcblx0fSxcclxuXHJcblx0X2Zsb29yOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR0aGlzLnggPSBNYXRoLmZsb29yKHRoaXMueCk7XHJcblx0XHR0aGlzLnkgPSBNYXRoLmZsb29yKHRoaXMueSk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGNlaWwoKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIGEgY29weSBvZiB0aGUgY3VycmVudCBwb2ludCB3aXRoIGNlaWxlZCBjb29yZGluYXRlcyAocm91bmRlZCB1cCkuXHJcblx0Y2VpbDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY2xvbmUoKS5fY2VpbCgpO1xyXG5cdH0sXHJcblxyXG5cdF9jZWlsOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR0aGlzLnggPSBNYXRoLmNlaWwodGhpcy54KTtcclxuXHRcdHRoaXMueSA9IE1hdGguY2VpbCh0aGlzLnkpO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB0cnVuYygpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgYSBjb3B5IG9mIHRoZSBjdXJyZW50IHBvaW50IHdpdGggdHJ1bmNhdGVkIGNvb3JkaW5hdGVzIChyb3VuZGVkIHRvd2FyZHMgemVybykuXHJcblx0dHJ1bmM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLmNsb25lKCkuX3RydW5jKCk7XHJcblx0fSxcclxuXHJcblx0X3RydW5jOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR0aGlzLnggPSB0cnVuYyh0aGlzLngpO1xyXG5cdFx0dGhpcy55ID0gdHJ1bmModGhpcy55KTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZGlzdGFuY2VUbyhvdGhlclBvaW50OiBQb2ludCk6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIGNhcnRlc2lhbiBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBjdXJyZW50IGFuZCB0aGUgZ2l2ZW4gcG9pbnRzLlxyXG5cdGRpc3RhbmNlVG86IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0cG9pbnQgPSB0b1BvaW50KHBvaW50KTtcclxuXHJcblx0XHR2YXIgeCA9IHBvaW50LnggLSB0aGlzLngsXHJcblx0XHQgICAgeSA9IHBvaW50LnkgLSB0aGlzLnk7XHJcblxyXG5cdFx0cmV0dXJuIE1hdGguc3FydCh4ICogeCArIHkgKiB5KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGVxdWFscyhvdGhlclBvaW50OiBQb2ludCk6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gcG9pbnQgaGFzIHRoZSBzYW1lIGNvb3JkaW5hdGVzLlxyXG5cdGVxdWFsczogZnVuY3Rpb24gKHBvaW50KSB7XHJcblx0XHRwb2ludCA9IHRvUG9pbnQocG9pbnQpO1xyXG5cclxuXHRcdHJldHVybiBwb2ludC54ID09PSB0aGlzLnggJiZcclxuXHRcdCAgICAgICBwb2ludC55ID09PSB0aGlzLnk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBjb250YWlucyhvdGhlclBvaW50OiBQb2ludCk6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiBib3RoIGNvb3JkaW5hdGVzIG9mIHRoZSBnaXZlbiBwb2ludCBhcmUgbGVzcyB0aGFuIHRoZSBjb3JyZXNwb25kaW5nIGN1cnJlbnQgcG9pbnQgY29vcmRpbmF0ZXMgKGluIGFic29sdXRlIHZhbHVlcykuXHJcblx0Y29udGFpbnM6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0cG9pbnQgPSB0b1BvaW50KHBvaW50KTtcclxuXHJcblx0XHRyZXR1cm4gTWF0aC5hYnMocG9pbnQueCkgPD0gTWF0aC5hYnModGhpcy54KSAmJlxyXG5cdFx0ICAgICAgIE1hdGguYWJzKHBvaW50LnkpIDw9IE1hdGguYWJzKHRoaXMueSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB0b1N0cmluZygpOiBTdHJpbmdcclxuXHQvLyBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwb2ludCBmb3IgZGVidWdnaW5nIHB1cnBvc2VzLlxyXG5cdHRvU3RyaW5nOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gJ1BvaW50KCcgK1xyXG5cdFx0ICAgICAgICBmb3JtYXROdW0odGhpcy54KSArICcsICcgK1xyXG5cdFx0ICAgICAgICBmb3JtYXROdW0odGhpcy55KSArICcpJztcclxuXHR9XHJcbn07XHJcblxyXG4vLyBAZmFjdG9yeSBMLnBvaW50KHg6IE51bWJlciwgeTogTnVtYmVyLCByb3VuZD86IEJvb2xlYW4pXHJcbi8vIENyZWF0ZXMgYSBQb2ludCBvYmplY3Qgd2l0aCB0aGUgZ2l2ZW4gYHhgIGFuZCBgeWAgY29vcmRpbmF0ZXMuIElmIG9wdGlvbmFsIGByb3VuZGAgaXMgc2V0IHRvIHRydWUsIHJvdW5kcyB0aGUgYHhgIGFuZCBgeWAgdmFsdWVzLlxyXG5cclxuLy8gQGFsdGVybmF0aXZlXHJcbi8vIEBmYWN0b3J5IEwucG9pbnQoY29vcmRzOiBOdW1iZXJbXSlcclxuLy8gRXhwZWN0cyBhbiBhcnJheSBvZiB0aGUgZm9ybSBgW3gsIHldYCBpbnN0ZWFkLlxyXG5cclxuLy8gQGFsdGVybmF0aXZlXHJcbi8vIEBmYWN0b3J5IEwucG9pbnQoY29vcmRzOiBPYmplY3QpXHJcbi8vIEV4cGVjdHMgYSBwbGFpbiBvYmplY3Qgb2YgdGhlIGZvcm0gYHt4OiBOdW1iZXIsIHk6IE51bWJlcn1gIGluc3RlYWQuXHJcbmZ1bmN0aW9uIHRvUG9pbnQoeCwgeSwgcm91bmQpIHtcclxuXHRpZiAoeCBpbnN0YW5jZW9mIFBvaW50KSB7XHJcblx0XHRyZXR1cm4geDtcclxuXHR9XHJcblx0aWYgKGlzQXJyYXkoeCkpIHtcclxuXHRcdHJldHVybiBuZXcgUG9pbnQoeFswXSwgeFsxXSk7XHJcblx0fVxyXG5cdGlmICh4ID09PSB1bmRlZmluZWQgfHwgeCA9PT0gbnVsbCkge1xyXG5cdFx0cmV0dXJuIHg7XHJcblx0fVxyXG5cdGlmICh0eXBlb2YgeCA9PT0gJ29iamVjdCcgJiYgJ3gnIGluIHggJiYgJ3knIGluIHgpIHtcclxuXHRcdHJldHVybiBuZXcgUG9pbnQoeC54LCB4LnkpO1xyXG5cdH1cclxuXHRyZXR1cm4gbmV3IFBvaW50KHgsIHksIHJvdW5kKTtcclxufVxuXG4vKlxyXG4gKiBAY2xhc3MgQm91bmRzXHJcbiAqIEBha2EgTC5Cb3VuZHNcclxuICpcclxuICogUmVwcmVzZW50cyBhIHJlY3Rhbmd1bGFyIGFyZWEgaW4gcGl4ZWwgY29vcmRpbmF0ZXMuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBwMSA9IEwucG9pbnQoMTAsIDEwKSxcclxuICogcDIgPSBMLnBvaW50KDQwLCA2MCksXHJcbiAqIGJvdW5kcyA9IEwuYm91bmRzKHAxLCBwMik7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBBbGwgTGVhZmxldCBtZXRob2RzIHRoYXQgYWNjZXB0IGBCb3VuZHNgIG9iamVjdHMgYWxzbyBhY2NlcHQgdGhlbSBpbiBhIHNpbXBsZSBBcnJheSBmb3JtICh1bmxlc3Mgbm90ZWQgb3RoZXJ3aXNlKSwgc28gdGhlIGJvdW5kcyBleGFtcGxlIGFib3ZlIGNhbiBiZSBwYXNzZWQgbGlrZSB0aGlzOlxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiBvdGhlckJvdW5kcy5pbnRlcnNlY3RzKFtbMTAsIDEwXSwgWzQwLCA2MF1dKTtcclxuICogYGBgXHJcbiAqXHJcbiAqIE5vdGUgdGhhdCBgQm91bmRzYCBkb2VzIG5vdCBpbmhlcml0IGZyb20gTGVhZmV0J3MgYENsYXNzYCBvYmplY3QsXHJcbiAqIHdoaWNoIG1lYW5zIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSBpdCwgYW5kIG5ldyBtZXRob2RzXHJcbiAqIGNhbid0IGJlIGFkZGVkIHRvIGl0IHdpdGggdGhlIGBpbmNsdWRlYCBmdW5jdGlvbi5cclxuICovXHJcblxyXG5mdW5jdGlvbiBCb3VuZHMoYSwgYikge1xyXG5cdGlmICghYSkgeyByZXR1cm47IH1cclxuXHJcblx0dmFyIHBvaW50cyA9IGIgPyBbYSwgYl0gOiBhO1xyXG5cclxuXHRmb3IgKHZhciBpID0gMCwgbGVuID0gcG9pbnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHR0aGlzLmV4dGVuZChwb2ludHNbaV0pO1xyXG5cdH1cclxufVxyXG5cclxuQm91bmRzLnByb3RvdHlwZSA9IHtcclxuXHQvLyBAbWV0aG9kIGV4dGVuZChwb2ludDogUG9pbnQpOiB0aGlzXHJcblx0Ly8gRXh0ZW5kcyB0aGUgYm91bmRzIHRvIGNvbnRhaW4gdGhlIGdpdmVuIHBvaW50LlxyXG5cdGV4dGVuZDogZnVuY3Rpb24gKHBvaW50KSB7IC8vIChQb2ludClcclxuXHRcdHBvaW50ID0gdG9Qb2ludChwb2ludCk7XHJcblxyXG5cdFx0Ly8gQHByb3BlcnR5IG1pbjogUG9pbnRcclxuXHRcdC8vIFRoZSB0b3AgbGVmdCBjb3JuZXIgb2YgdGhlIHJlY3RhbmdsZS5cclxuXHRcdC8vIEBwcm9wZXJ0eSBtYXg6IFBvaW50XHJcblx0XHQvLyBUaGUgYm90dG9tIHJpZ2h0IGNvcm5lciBvZiB0aGUgcmVjdGFuZ2xlLlxyXG5cdFx0aWYgKCF0aGlzLm1pbiAmJiAhdGhpcy5tYXgpIHtcclxuXHRcdFx0dGhpcy5taW4gPSBwb2ludC5jbG9uZSgpO1xyXG5cdFx0XHR0aGlzLm1heCA9IHBvaW50LmNsb25lKCk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHR0aGlzLm1pbi54ID0gTWF0aC5taW4ocG9pbnQueCwgdGhpcy5taW4ueCk7XHJcblx0XHRcdHRoaXMubWF4LnggPSBNYXRoLm1heChwb2ludC54LCB0aGlzLm1heC54KTtcclxuXHRcdFx0dGhpcy5taW4ueSA9IE1hdGgubWluKHBvaW50LnksIHRoaXMubWluLnkpO1xyXG5cdFx0XHR0aGlzLm1heC55ID0gTWF0aC5tYXgocG9pbnQueSwgdGhpcy5tYXgueSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldENlbnRlcihyb3VuZD86IEJvb2xlYW4pOiBQb2ludFxyXG5cdC8vIFJldHVybnMgdGhlIGNlbnRlciBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG5cdGdldENlbnRlcjogZnVuY3Rpb24gKHJvdW5kKSB7XHJcblx0XHRyZXR1cm4gbmV3IFBvaW50KFxyXG5cdFx0ICAgICAgICAodGhpcy5taW4ueCArIHRoaXMubWF4LngpIC8gMixcclxuXHRcdCAgICAgICAgKHRoaXMubWluLnkgKyB0aGlzLm1heC55KSAvIDIsIHJvdW5kKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldEJvdHRvbUxlZnQoKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIHRoZSBib3R0b20tbGVmdCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG5cdGdldEJvdHRvbUxlZnQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiBuZXcgUG9pbnQodGhpcy5taW4ueCwgdGhpcy5tYXgueSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRUb3BSaWdodCgpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgdGhlIHRvcC1yaWdodCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG5cdGdldFRvcFJpZ2h0OiBmdW5jdGlvbiAoKSB7IC8vIC0+IFBvaW50XHJcblx0XHRyZXR1cm4gbmV3IFBvaW50KHRoaXMubWF4LngsIHRoaXMubWluLnkpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0VG9wTGVmdCgpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgdGhlIHRvcC1sZWZ0IHBvaW50IG9mIHRoZSBib3VuZHMgKGkuZS4gW2B0aGlzLm1pbmBdKCNib3VuZHMtbWluKSkuXHJcblx0Z2V0VG9wTGVmdDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMubWluOyAvLyBsZWZ0LCB0b3BcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldEJvdHRvbVJpZ2h0KCk6IFBvaW50XHJcblx0Ly8gUmV0dXJucyB0aGUgYm90dG9tLXJpZ2h0IHBvaW50IG9mIHRoZSBib3VuZHMgKGkuZS4gW2B0aGlzLm1heGBdKCNib3VuZHMtbWF4KSkuXHJcblx0Z2V0Qm90dG9tUmlnaHQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLm1heDsgLy8gcmlnaHQsIGJvdHRvbVxyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0U2l6ZSgpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgdGhlIHNpemUgb2YgdGhlIGdpdmVuIGJvdW5kc1xyXG5cdGdldFNpemU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLm1heC5zdWJ0cmFjdCh0aGlzLm1pbik7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBjb250YWlucyhvdGhlckJvdW5kczogQm91bmRzKTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgY29udGFpbnMgdGhlIGdpdmVuIG9uZS5cclxuXHQvLyBAYWx0ZXJuYXRpdmVcclxuXHQvLyBAbWV0aG9kIGNvbnRhaW5zKHBvaW50OiBQb2ludCk6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIGNvbnRhaW5zIHRoZSBnaXZlbiBwb2ludC5cclxuXHRjb250YWluczogZnVuY3Rpb24gKG9iaikge1xyXG5cdFx0dmFyIG1pbiwgbWF4O1xyXG5cclxuXHRcdGlmICh0eXBlb2Ygb2JqWzBdID09PSAnbnVtYmVyJyB8fCBvYmogaW5zdGFuY2VvZiBQb2ludCkge1xyXG5cdFx0XHRvYmogPSB0b1BvaW50KG9iaik7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRvYmogPSB0b0JvdW5kcyhvYmopO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChvYmogaW5zdGFuY2VvZiBCb3VuZHMpIHtcclxuXHRcdFx0bWluID0gb2JqLm1pbjtcclxuXHRcdFx0bWF4ID0gb2JqLm1heDtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdG1pbiA9IG1heCA9IG9iajtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gKG1pbi54ID49IHRoaXMubWluLngpICYmXHJcblx0XHQgICAgICAgKG1heC54IDw9IHRoaXMubWF4LngpICYmXHJcblx0XHQgICAgICAgKG1pbi55ID49IHRoaXMubWluLnkpICYmXHJcblx0XHQgICAgICAgKG1heC55IDw9IHRoaXMubWF4LnkpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgaW50ZXJzZWN0cyhvdGhlckJvdW5kczogQm91bmRzKTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgaW50ZXJzZWN0cyB0aGUgZ2l2ZW4gYm91bmRzLiBUd28gYm91bmRzXHJcblx0Ly8gaW50ZXJzZWN0IGlmIHRoZXkgaGF2ZSBhdCBsZWFzdCBvbmUgcG9pbnQgaW4gY29tbW9uLlxyXG5cdGludGVyc2VjdHM6IGZ1bmN0aW9uIChib3VuZHMpIHsgLy8gKEJvdW5kcykgLT4gQm9vbGVhblxyXG5cdFx0Ym91bmRzID0gdG9Cb3VuZHMoYm91bmRzKTtcclxuXHJcblx0XHR2YXIgbWluID0gdGhpcy5taW4sXHJcblx0XHQgICAgbWF4ID0gdGhpcy5tYXgsXHJcblx0XHQgICAgbWluMiA9IGJvdW5kcy5taW4sXHJcblx0XHQgICAgbWF4MiA9IGJvdW5kcy5tYXgsXHJcblx0XHQgICAgeEludGVyc2VjdHMgPSAobWF4Mi54ID49IG1pbi54KSAmJiAobWluMi54IDw9IG1heC54KSxcclxuXHRcdCAgICB5SW50ZXJzZWN0cyA9IChtYXgyLnkgPj0gbWluLnkpICYmIChtaW4yLnkgPD0gbWF4LnkpO1xyXG5cclxuXHRcdHJldHVybiB4SW50ZXJzZWN0cyAmJiB5SW50ZXJzZWN0cztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIG92ZXJsYXBzKG90aGVyQm91bmRzOiBCb3VuZHMpOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBvdmVybGFwcyB0aGUgZ2l2ZW4gYm91bmRzLiBUd28gYm91bmRzXHJcblx0Ly8gb3ZlcmxhcCBpZiB0aGVpciBpbnRlcnNlY3Rpb24gaXMgYW4gYXJlYS5cclxuXHRvdmVybGFwczogZnVuY3Rpb24gKGJvdW5kcykgeyAvLyAoQm91bmRzKSAtPiBCb29sZWFuXHJcblx0XHRib3VuZHMgPSB0b0JvdW5kcyhib3VuZHMpO1xyXG5cclxuXHRcdHZhciBtaW4gPSB0aGlzLm1pbixcclxuXHRcdCAgICBtYXggPSB0aGlzLm1heCxcclxuXHRcdCAgICBtaW4yID0gYm91bmRzLm1pbixcclxuXHRcdCAgICBtYXgyID0gYm91bmRzLm1heCxcclxuXHRcdCAgICB4T3ZlcmxhcHMgPSAobWF4Mi54ID4gbWluLngpICYmIChtaW4yLnggPCBtYXgueCksXHJcblx0XHQgICAgeU92ZXJsYXBzID0gKG1heDIueSA+IG1pbi55KSAmJiAobWluMi55IDwgbWF4LnkpO1xyXG5cclxuXHRcdHJldHVybiB4T3ZlcmxhcHMgJiYgeU92ZXJsYXBzO1xyXG5cdH0sXHJcblxyXG5cdGlzVmFsaWQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiAhISh0aGlzLm1pbiAmJiB0aGlzLm1heCk7XHJcblx0fVxyXG59O1xyXG5cclxuXHJcbi8vIEBmYWN0b3J5IEwuYm91bmRzKGNvcm5lcjE6IFBvaW50LCBjb3JuZXIyOiBQb2ludClcclxuLy8gQ3JlYXRlcyBhIEJvdW5kcyBvYmplY3QgZnJvbSB0d28gY29ybmVycyBjb29yZGluYXRlIHBhaXJzLlxyXG4vLyBAYWx0ZXJuYXRpdmVcclxuLy8gQGZhY3RvcnkgTC5ib3VuZHMocG9pbnRzOiBQb2ludFtdKVxyXG4vLyBDcmVhdGVzIGEgQm91bmRzIG9iamVjdCBmcm9tIHRoZSBnaXZlbiBhcnJheSBvZiBwb2ludHMuXHJcbmZ1bmN0aW9uIHRvQm91bmRzKGEsIGIpIHtcclxuXHRpZiAoIWEgfHwgYSBpbnN0YW5jZW9mIEJvdW5kcykge1xyXG5cdFx0cmV0dXJuIGE7XHJcblx0fVxyXG5cdHJldHVybiBuZXcgQm91bmRzKGEsIGIpO1xyXG59XG5cbi8qXHJcbiAqIEBjbGFzcyBMYXRMbmdCb3VuZHNcclxuICogQGFrYSBMLkxhdExuZ0JvdW5kc1xyXG4gKlxyXG4gKiBSZXByZXNlbnRzIGEgcmVjdGFuZ3VsYXIgZ2VvZ3JhcGhpY2FsIGFyZWEgb24gYSBtYXAuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBjb3JuZXIxID0gTC5sYXRMbmcoNDAuNzEyLCAtNzQuMjI3KSxcclxuICogY29ybmVyMiA9IEwubGF0TG5nKDQwLjc3NCwgLTc0LjEyNSksXHJcbiAqIGJvdW5kcyA9IEwubGF0TG5nQm91bmRzKGNvcm5lcjEsIGNvcm5lcjIpO1xyXG4gKiBgYGBcclxuICpcclxuICogQWxsIExlYWZsZXQgbWV0aG9kcyB0aGF0IGFjY2VwdCBMYXRMbmdCb3VuZHMgb2JqZWN0cyBhbHNvIGFjY2VwdCB0aGVtIGluIGEgc2ltcGxlIEFycmF5IGZvcm0gKHVubGVzcyBub3RlZCBvdGhlcndpc2UpLCBzbyB0aGUgYm91bmRzIGV4YW1wbGUgYWJvdmUgY2FuIGJlIHBhc3NlZCBsaWtlIHRoaXM6XHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIG1hcC5maXRCb3VuZHMoW1xyXG4gKiBcdFs0MC43MTIsIC03NC4yMjddLFxyXG4gKiBcdFs0MC43NzQsIC03NC4xMjVdXHJcbiAqIF0pO1xyXG4gKiBgYGBcclxuICpcclxuICogQ2F1dGlvbjogaWYgdGhlIGFyZWEgY3Jvc3NlcyB0aGUgYW50aW1lcmlkaWFuIChvZnRlbiBjb25mdXNlZCB3aXRoIHRoZSBJbnRlcm5hdGlvbmFsIERhdGUgTGluZSksIHlvdSBtdXN0IHNwZWNpZnkgY29ybmVycyBfb3V0c2lkZV8gdGhlIFstMTgwLCAxODBdIGRlZ3JlZXMgbG9uZ2l0dWRlIHJhbmdlLlxyXG4gKlxyXG4gKiBOb3RlIHRoYXQgYExhdExuZ0JvdW5kc2AgZG9lcyBub3QgaW5oZXJpdCBmcm9tIExlYWZldCdzIGBDbGFzc2Agb2JqZWN0LFxyXG4gKiB3aGljaCBtZWFucyBuZXcgY2xhc3NlcyBjYW4ndCBpbmhlcml0IGZyb20gaXQsIGFuZCBuZXcgbWV0aG9kc1xyXG4gKiBjYW4ndCBiZSBhZGRlZCB0byBpdCB3aXRoIHRoZSBgaW5jbHVkZWAgZnVuY3Rpb24uXHJcbiAqL1xyXG5cclxuZnVuY3Rpb24gTGF0TG5nQm91bmRzKGNvcm5lcjEsIGNvcm5lcjIpIHsgLy8gKExhdExuZywgTGF0TG5nKSBvciAoTGF0TG5nW10pXHJcblx0aWYgKCFjb3JuZXIxKSB7IHJldHVybjsgfVxyXG5cclxuXHR2YXIgbGF0bG5ncyA9IGNvcm5lcjIgPyBbY29ybmVyMSwgY29ybmVyMl0gOiBjb3JuZXIxO1xyXG5cclxuXHRmb3IgKHZhciBpID0gMCwgbGVuID0gbGF0bG5ncy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0dGhpcy5leHRlbmQobGF0bG5nc1tpXSk7XHJcblx0fVxyXG59XHJcblxyXG5MYXRMbmdCb3VuZHMucHJvdG90eXBlID0ge1xyXG5cclxuXHQvLyBAbWV0aG9kIGV4dGVuZChsYXRsbmc6IExhdExuZyk6IHRoaXNcclxuXHQvLyBFeHRlbmQgdGhlIGJvdW5kcyB0byBjb250YWluIHRoZSBnaXZlbiBwb2ludFxyXG5cclxuXHQvLyBAYWx0ZXJuYXRpdmVcclxuXHQvLyBAbWV0aG9kIGV4dGVuZChvdGhlckJvdW5kczogTGF0TG5nQm91bmRzKTogdGhpc1xyXG5cdC8vIEV4dGVuZCB0aGUgYm91bmRzIHRvIGNvbnRhaW4gdGhlIGdpdmVuIGJvdW5kc1xyXG5cdGV4dGVuZDogZnVuY3Rpb24gKG9iaikge1xyXG5cdFx0dmFyIHN3ID0gdGhpcy5fc291dGhXZXN0LFxyXG5cdFx0ICAgIG5lID0gdGhpcy5fbm9ydGhFYXN0LFxyXG5cdFx0ICAgIHN3MiwgbmUyO1xyXG5cclxuXHRcdGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmcpIHtcclxuXHRcdFx0c3cyID0gb2JqO1xyXG5cdFx0XHRuZTIgPSBvYmo7XHJcblxyXG5cdFx0fSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBMYXRMbmdCb3VuZHMpIHtcclxuXHRcdFx0c3cyID0gb2JqLl9zb3V0aFdlc3Q7XHJcblx0XHRcdG5lMiA9IG9iai5fbm9ydGhFYXN0O1xyXG5cclxuXHRcdFx0aWYgKCFzdzIgfHwgIW5lMikgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHJldHVybiBvYmogPyB0aGlzLmV4dGVuZCh0b0xhdExuZyhvYmopIHx8IHRvTGF0TG5nQm91bmRzKG9iaikpIDogdGhpcztcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIXN3ICYmICFuZSkge1xyXG5cdFx0XHR0aGlzLl9zb3V0aFdlc3QgPSBuZXcgTGF0TG5nKHN3Mi5sYXQsIHN3Mi5sbmcpO1xyXG5cdFx0XHR0aGlzLl9ub3J0aEVhc3QgPSBuZXcgTGF0TG5nKG5lMi5sYXQsIG5lMi5sbmcpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0c3cubGF0ID0gTWF0aC5taW4oc3cyLmxhdCwgc3cubGF0KTtcclxuXHRcdFx0c3cubG5nID0gTWF0aC5taW4oc3cyLmxuZywgc3cubG5nKTtcclxuXHRcdFx0bmUubGF0ID0gTWF0aC5tYXgobmUyLmxhdCwgbmUubGF0KTtcclxuXHRcdFx0bmUubG5nID0gTWF0aC5tYXgobmUyLmxuZywgbmUubG5nKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHBhZChidWZmZXJSYXRpbzogTnVtYmVyKTogTGF0TG5nQm91bmRzXHJcblx0Ly8gUmV0dXJucyBib3VuZHMgY3JlYXRlZCBieSBleHRlbmRpbmcgb3IgcmV0cmFjdGluZyB0aGUgY3VycmVudCBib3VuZHMgYnkgYSBnaXZlbiByYXRpbyBpbiBlYWNoIGRpcmVjdGlvbi5cclxuXHQvLyBGb3IgZXhhbXBsZSwgYSByYXRpbyBvZiAwLjUgZXh0ZW5kcyB0aGUgYm91bmRzIGJ5IDUwJSBpbiBlYWNoIGRpcmVjdGlvbi5cclxuXHQvLyBOZWdhdGl2ZSB2YWx1ZXMgd2lsbCByZXRyYWN0IHRoZSBib3VuZHMuXHJcblx0cGFkOiBmdW5jdGlvbiAoYnVmZmVyUmF0aW8pIHtcclxuXHRcdHZhciBzdyA9IHRoaXMuX3NvdXRoV2VzdCxcclxuXHRcdCAgICBuZSA9IHRoaXMuX25vcnRoRWFzdCxcclxuXHRcdCAgICBoZWlnaHRCdWZmZXIgPSBNYXRoLmFicyhzdy5sYXQgLSBuZS5sYXQpICogYnVmZmVyUmF0aW8sXHJcblx0XHQgICAgd2lkdGhCdWZmZXIgPSBNYXRoLmFicyhzdy5sbmcgLSBuZS5sbmcpICogYnVmZmVyUmF0aW87XHJcblxyXG5cdFx0cmV0dXJuIG5ldyBMYXRMbmdCb3VuZHMoXHJcblx0XHQgICAgICAgIG5ldyBMYXRMbmcoc3cubGF0IC0gaGVpZ2h0QnVmZmVyLCBzdy5sbmcgLSB3aWR0aEJ1ZmZlciksXHJcblx0XHQgICAgICAgIG5ldyBMYXRMbmcobmUubGF0ICsgaGVpZ2h0QnVmZmVyLCBuZS5sbmcgKyB3aWR0aEJ1ZmZlcikpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0Q2VudGVyKCk6IExhdExuZ1xyXG5cdC8vIFJldHVybnMgdGhlIGNlbnRlciBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG5cdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIG5ldyBMYXRMbmcoXHJcblx0XHQgICAgICAgICh0aGlzLl9zb3V0aFdlc3QubGF0ICsgdGhpcy5fbm9ydGhFYXN0LmxhdCkgLyAyLFxyXG5cdFx0ICAgICAgICAodGhpcy5fc291dGhXZXN0LmxuZyArIHRoaXMuX25vcnRoRWFzdC5sbmcpIC8gMik7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRTb3V0aFdlc3QoKTogTGF0TG5nXHJcblx0Ly8gUmV0dXJucyB0aGUgc291dGgtd2VzdCBwb2ludCBvZiB0aGUgYm91bmRzLlxyXG5cdGdldFNvdXRoV2VzdDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuX3NvdXRoV2VzdDtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldE5vcnRoRWFzdCgpOiBMYXRMbmdcclxuXHQvLyBSZXR1cm5zIHRoZSBub3J0aC1lYXN0IHBvaW50IG9mIHRoZSBib3VuZHMuXHJcblx0Z2V0Tm9ydGhFYXN0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fbm9ydGhFYXN0O1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0Tm9ydGhXZXN0KCk6IExhdExuZ1xyXG5cdC8vIFJldHVybnMgdGhlIG5vcnRoLXdlc3QgcG9pbnQgb2YgdGhlIGJvdW5kcy5cclxuXHRnZXROb3J0aFdlc3Q6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiBuZXcgTGF0TG5nKHRoaXMuZ2V0Tm9ydGgoKSwgdGhpcy5nZXRXZXN0KCkpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0U291dGhFYXN0KCk6IExhdExuZ1xyXG5cdC8vIFJldHVybnMgdGhlIHNvdXRoLWVhc3QgcG9pbnQgb2YgdGhlIGJvdW5kcy5cclxuXHRnZXRTb3V0aEVhc3Q6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiBuZXcgTGF0TG5nKHRoaXMuZ2V0U291dGgoKSwgdGhpcy5nZXRFYXN0KCkpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0V2VzdCgpOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSB3ZXN0IGxvbmdpdHVkZSBvZiB0aGUgYm91bmRzXHJcblx0Z2V0V2VzdDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuX3NvdXRoV2VzdC5sbmc7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRTb3V0aCgpOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBzb3V0aCBsYXRpdHVkZSBvZiB0aGUgYm91bmRzXHJcblx0Z2V0U291dGg6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9zb3V0aFdlc3QubGF0O1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0RWFzdCgpOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBlYXN0IGxvbmdpdHVkZSBvZiB0aGUgYm91bmRzXHJcblx0Z2V0RWFzdDogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuX25vcnRoRWFzdC5sbmc7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXROb3J0aCgpOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBub3J0aCBsYXRpdHVkZSBvZiB0aGUgYm91bmRzXHJcblx0Z2V0Tm9ydGg6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9ub3J0aEVhc3QubGF0O1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY29udGFpbnMob3RoZXJCb3VuZHM6IExhdExuZ0JvdW5kcyk6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIGNvbnRhaW5zIHRoZSBnaXZlbiBvbmUuXHJcblxyXG5cdC8vIEBhbHRlcm5hdGl2ZVxyXG5cdC8vIEBtZXRob2QgY29udGFpbnMgKGxhdGxuZzogTGF0TG5nKTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSByZWN0YW5nbGUgY29udGFpbnMgdGhlIGdpdmVuIHBvaW50LlxyXG5cdGNvbnRhaW5zOiBmdW5jdGlvbiAob2JqKSB7IC8vIChMYXRMbmdCb3VuZHMpIG9yIChMYXRMbmcpIC0+IEJvb2xlYW5cclxuXHRcdGlmICh0eXBlb2Ygb2JqWzBdID09PSAnbnVtYmVyJyB8fCBvYmogaW5zdGFuY2VvZiBMYXRMbmcgfHwgJ2xhdCcgaW4gb2JqKSB7XHJcblx0XHRcdG9iaiA9IHRvTGF0TG5nKG9iaik7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRvYmogPSB0b0xhdExuZ0JvdW5kcyhvYmopO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBzdyA9IHRoaXMuX3NvdXRoV2VzdCxcclxuXHRcdCAgICBuZSA9IHRoaXMuX25vcnRoRWFzdCxcclxuXHRcdCAgICBzdzIsIG5lMjtcclxuXHJcblx0XHRpZiAob2JqIGluc3RhbmNlb2YgTGF0TG5nQm91bmRzKSB7XHJcblx0XHRcdHN3MiA9IG9iai5nZXRTb3V0aFdlc3QoKTtcclxuXHRcdFx0bmUyID0gb2JqLmdldE5vcnRoRWFzdCgpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0c3cyID0gbmUyID0gb2JqO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiAoc3cyLmxhdCA+PSBzdy5sYXQpICYmIChuZTIubGF0IDw9IG5lLmxhdCkgJiZcclxuXHRcdCAgICAgICAoc3cyLmxuZyA+PSBzdy5sbmcpICYmIChuZTIubG5nIDw9IG5lLmxuZyk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBpbnRlcnNlY3RzKG90aGVyQm91bmRzOiBMYXRMbmdCb3VuZHMpOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBpbnRlcnNlY3RzIHRoZSBnaXZlbiBib3VuZHMuIFR3byBib3VuZHMgaW50ZXJzZWN0IGlmIHRoZXkgaGF2ZSBhdCBsZWFzdCBvbmUgcG9pbnQgaW4gY29tbW9uLlxyXG5cdGludGVyc2VjdHM6IGZ1bmN0aW9uIChib3VuZHMpIHtcclxuXHRcdGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG5cdFx0dmFyIHN3ID0gdGhpcy5fc291dGhXZXN0LFxyXG5cdFx0ICAgIG5lID0gdGhpcy5fbm9ydGhFYXN0LFxyXG5cdFx0ICAgIHN3MiA9IGJvdW5kcy5nZXRTb3V0aFdlc3QoKSxcclxuXHRcdCAgICBuZTIgPSBib3VuZHMuZ2V0Tm9ydGhFYXN0KCksXHJcblxyXG5cdFx0ICAgIGxhdEludGVyc2VjdHMgPSAobmUyLmxhdCA+PSBzdy5sYXQpICYmIChzdzIubGF0IDw9IG5lLmxhdCksXHJcblx0XHQgICAgbG5nSW50ZXJzZWN0cyA9IChuZTIubG5nID49IHN3LmxuZykgJiYgKHN3Mi5sbmcgPD0gbmUubG5nKTtcclxuXHJcblx0XHRyZXR1cm4gbGF0SW50ZXJzZWN0cyAmJiBsbmdJbnRlcnNlY3RzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgb3ZlcmxhcHMob3RoZXJCb3VuZHM6IEJvdW5kcyk6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmVjdGFuZ2xlIG92ZXJsYXBzIHRoZSBnaXZlbiBib3VuZHMuIFR3byBib3VuZHMgb3ZlcmxhcCBpZiB0aGVpciBpbnRlcnNlY3Rpb24gaXMgYW4gYXJlYS5cclxuXHRvdmVybGFwczogZnVuY3Rpb24gKGJvdW5kcykge1xyXG5cdFx0Ym91bmRzID0gdG9MYXRMbmdCb3VuZHMoYm91bmRzKTtcclxuXHJcblx0XHR2YXIgc3cgPSB0aGlzLl9zb3V0aFdlc3QsXHJcblx0XHQgICAgbmUgPSB0aGlzLl9ub3J0aEVhc3QsXHJcblx0XHQgICAgc3cyID0gYm91bmRzLmdldFNvdXRoV2VzdCgpLFxyXG5cdFx0ICAgIG5lMiA9IGJvdW5kcy5nZXROb3J0aEVhc3QoKSxcclxuXHJcblx0XHQgICAgbGF0T3ZlcmxhcHMgPSAobmUyLmxhdCA+IHN3LmxhdCkgJiYgKHN3Mi5sYXQgPCBuZS5sYXQpLFxyXG5cdFx0ICAgIGxuZ092ZXJsYXBzID0gKG5lMi5sbmcgPiBzdy5sbmcpICYmIChzdzIubG5nIDwgbmUubG5nKTtcclxuXHJcblx0XHRyZXR1cm4gbGF0T3ZlcmxhcHMgJiYgbG5nT3ZlcmxhcHM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB0b0JCb3hTdHJpbmcoKTogU3RyaW5nXHJcblx0Ly8gUmV0dXJucyBhIHN0cmluZyB3aXRoIGJvdW5kaW5nIGJveCBjb29yZGluYXRlcyBpbiBhICdzb3V0aHdlc3RfbG5nLHNvdXRod2VzdF9sYXQsbm9ydGhlYXN0X2xuZyxub3J0aGVhc3RfbGF0JyBmb3JtYXQuIFVzZWZ1bCBmb3Igc2VuZGluZyByZXF1ZXN0cyB0byB3ZWIgc2VydmljZXMgdGhhdCByZXR1cm4gZ2VvIGRhdGEuXHJcblx0dG9CQm94U3RyaW5nOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gW3RoaXMuZ2V0V2VzdCgpLCB0aGlzLmdldFNvdXRoKCksIHRoaXMuZ2V0RWFzdCgpLCB0aGlzLmdldE5vcnRoKCldLmpvaW4oJywnKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGVxdWFscyhvdGhlckJvdW5kczogTGF0TG5nQm91bmRzLCBtYXhNYXJnaW4/OiBOdW1iZXIpOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJlY3RhbmdsZSBpcyBlcXVpdmFsZW50ICh3aXRoaW4gYSBzbWFsbCBtYXJnaW4gb2YgZXJyb3IpIHRvIHRoZSBnaXZlbiBib3VuZHMuIFRoZSBtYXJnaW4gb2YgZXJyb3IgY2FuIGJlIG92ZXJyaWRkZW4gYnkgc2V0dGluZyBgbWF4TWFyZ2luYCB0byBhIHNtYWxsIG51bWJlci5cclxuXHRlcXVhbHM6IGZ1bmN0aW9uIChib3VuZHMsIG1heE1hcmdpbikge1xyXG5cdFx0aWYgKCFib3VuZHMpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG5cdFx0Ym91bmRzID0gdG9MYXRMbmdCb3VuZHMoYm91bmRzKTtcclxuXHJcblx0XHRyZXR1cm4gdGhpcy5fc291dGhXZXN0LmVxdWFscyhib3VuZHMuZ2V0U291dGhXZXN0KCksIG1heE1hcmdpbikgJiZcclxuXHRcdCAgICAgICB0aGlzLl9ub3J0aEVhc3QuZXF1YWxzKGJvdW5kcy5nZXROb3J0aEVhc3QoKSwgbWF4TWFyZ2luKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGlzVmFsaWQoKTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBib3VuZHMgYXJlIHByb3Blcmx5IGluaXRpYWxpemVkLlxyXG5cdGlzVmFsaWQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiAhISh0aGlzLl9zb3V0aFdlc3QgJiYgdGhpcy5fbm9ydGhFYXN0KTtcclxuXHR9XHJcbn07XHJcblxyXG4vLyBUT0RPIEludGVybmF0aW9uYWwgZGF0ZSBsaW5lP1xyXG5cclxuLy8gQGZhY3RvcnkgTC5sYXRMbmdCb3VuZHMoY29ybmVyMTogTGF0TG5nLCBjb3JuZXIyOiBMYXRMbmcpXHJcbi8vIENyZWF0ZXMgYSBgTGF0TG5nQm91bmRzYCBvYmplY3QgYnkgZGVmaW5pbmcgdHdvIGRpYWdvbmFsbHkgb3Bwb3NpdGUgY29ybmVycyBvZiB0aGUgcmVjdGFuZ2xlLlxyXG5cclxuLy8gQGFsdGVybmF0aXZlXHJcbi8vIEBmYWN0b3J5IEwubGF0TG5nQm91bmRzKGxhdGxuZ3M6IExhdExuZ1tdKVxyXG4vLyBDcmVhdGVzIGEgYExhdExuZ0JvdW5kc2Agb2JqZWN0IGRlZmluZWQgYnkgdGhlIGdlb2dyYXBoaWNhbCBwb2ludHMgaXQgY29udGFpbnMuIFZlcnkgdXNlZnVsIGZvciB6b29taW5nIHRoZSBtYXAgdG8gZml0IGEgcGFydGljdWxhciBzZXQgb2YgbG9jYXRpb25zIHdpdGggW2BmaXRCb3VuZHNgXSgjbWFwLWZpdGJvdW5kcykuXHJcbmZ1bmN0aW9uIHRvTGF0TG5nQm91bmRzKGEsIGIpIHtcclxuXHRpZiAoYSBpbnN0YW5jZW9mIExhdExuZ0JvdW5kcykge1xyXG5cdFx0cmV0dXJuIGE7XHJcblx0fVxyXG5cdHJldHVybiBuZXcgTGF0TG5nQm91bmRzKGEsIGIpO1xyXG59XG5cbi8qIEBjbGFzcyBMYXRMbmdcclxuICogQGFrYSBMLkxhdExuZ1xyXG4gKlxyXG4gKiBSZXByZXNlbnRzIGEgZ2VvZ3JhcGhpY2FsIHBvaW50IHdpdGggYSBjZXJ0YWluIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYFxyXG4gKiB2YXIgbGF0bG5nID0gTC5sYXRMbmcoNTAuNSwgMzAuNSk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBBbGwgTGVhZmxldCBtZXRob2RzIHRoYXQgYWNjZXB0IExhdExuZyBvYmplY3RzIGFsc28gYWNjZXB0IHRoZW0gaW4gYSBzaW1wbGUgQXJyYXkgZm9ybSBhbmQgc2ltcGxlIG9iamVjdCBmb3JtICh1bmxlc3Mgbm90ZWQgb3RoZXJ3aXNlKSwgc28gdGhlc2UgbGluZXMgYXJlIGVxdWl2YWxlbnQ6XHJcbiAqXHJcbiAqIGBgYFxyXG4gKiBtYXAucGFuVG8oWzUwLCAzMF0pO1xyXG4gKiBtYXAucGFuVG8oe2xvbjogMzAsIGxhdDogNTB9KTtcclxuICogbWFwLnBhblRvKHtsYXQ6IDUwLCBsbmc6IDMwfSk7XHJcbiAqIG1hcC5wYW5UbyhMLmxhdExuZyg1MCwgMzApKTtcclxuICogYGBgXHJcbiAqXHJcbiAqIE5vdGUgdGhhdCBgTGF0TG5nYCBkb2VzIG5vdCBpbmhlcml0IGZyb20gTGVhZmV0J3MgYENsYXNzYCBvYmplY3QsXHJcbiAqIHdoaWNoIG1lYW5zIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSBpdCwgYW5kIG5ldyBtZXRob2RzXHJcbiAqIGNhbid0IGJlIGFkZGVkIHRvIGl0IHdpdGggdGhlIGBpbmNsdWRlYCBmdW5jdGlvbi5cclxuICovXHJcblxyXG5mdW5jdGlvbiBMYXRMbmcobGF0LCBsbmcsIGFsdCkge1xyXG5cdGlmIChpc05hTihsYXQpIHx8IGlzTmFOKGxuZykpIHtcclxuXHRcdHRocm93IG5ldyBFcnJvcignSW52YWxpZCBMYXRMbmcgb2JqZWN0OiAoJyArIGxhdCArICcsICcgKyBsbmcgKyAnKScpO1xyXG5cdH1cclxuXHJcblx0Ly8gQHByb3BlcnR5IGxhdDogTnVtYmVyXHJcblx0Ly8gTGF0aXR1ZGUgaW4gZGVncmVlc1xyXG5cdHRoaXMubGF0ID0gK2xhdDtcclxuXHJcblx0Ly8gQHByb3BlcnR5IGxuZzogTnVtYmVyXHJcblx0Ly8gTG9uZ2l0dWRlIGluIGRlZ3JlZXNcclxuXHR0aGlzLmxuZyA9ICtsbmc7XHJcblxyXG5cdC8vIEBwcm9wZXJ0eSBhbHQ6IE51bWJlclxyXG5cdC8vIEFsdGl0dWRlIGluIG1ldGVycyAob3B0aW9uYWwpXHJcblx0aWYgKGFsdCAhPT0gdW5kZWZpbmVkKSB7XHJcblx0XHR0aGlzLmFsdCA9ICthbHQ7XHJcblx0fVxyXG59XHJcblxyXG5MYXRMbmcucHJvdG90eXBlID0ge1xyXG5cdC8vIEBtZXRob2QgZXF1YWxzKG90aGVyTGF0TG5nOiBMYXRMbmcsIG1heE1hcmdpbj86IE51bWJlcik6IEJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gYExhdExuZ2AgcG9pbnQgaXMgYXQgdGhlIHNhbWUgcG9zaXRpb24gKHdpdGhpbiBhIHNtYWxsIG1hcmdpbiBvZiBlcnJvcikuIFRoZSBtYXJnaW4gb2YgZXJyb3IgY2FuIGJlIG92ZXJyaWRkZW4gYnkgc2V0dGluZyBgbWF4TWFyZ2luYCB0byBhIHNtYWxsIG51bWJlci5cclxuXHRlcXVhbHM6IGZ1bmN0aW9uIChvYmosIG1heE1hcmdpbikge1xyXG5cdFx0aWYgKCFvYmopIHsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG5cdFx0b2JqID0gdG9MYXRMbmcob2JqKTtcclxuXHJcblx0XHR2YXIgbWFyZ2luID0gTWF0aC5tYXgoXHJcblx0XHQgICAgICAgIE1hdGguYWJzKHRoaXMubGF0IC0gb2JqLmxhdCksXHJcblx0XHQgICAgICAgIE1hdGguYWJzKHRoaXMubG5nIC0gb2JqLmxuZykpO1xyXG5cclxuXHRcdHJldHVybiBtYXJnaW4gPD0gKG1heE1hcmdpbiA9PT0gdW5kZWZpbmVkID8gMS4wRS05IDogbWF4TWFyZ2luKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHRvU3RyaW5nKCk6IFN0cmluZ1xyXG5cdC8vIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvaW50IChmb3IgZGVidWdnaW5nIHB1cnBvc2VzKS5cclxuXHR0b1N0cmluZzogZnVuY3Rpb24gKHByZWNpc2lvbikge1xyXG5cdFx0cmV0dXJuICdMYXRMbmcoJyArXHJcblx0XHQgICAgICAgIGZvcm1hdE51bSh0aGlzLmxhdCwgcHJlY2lzaW9uKSArICcsICcgK1xyXG5cdFx0ICAgICAgICBmb3JtYXROdW0odGhpcy5sbmcsIHByZWNpc2lvbikgKyAnKSc7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBkaXN0YW5jZVRvKG90aGVyTGF0TG5nOiBMYXRMbmcpOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBkaXN0YW5jZSAoaW4gbWV0ZXJzKSB0byB0aGUgZ2l2ZW4gYExhdExuZ2AgY2FsY3VsYXRlZCB1c2luZyB0aGUgW1NwaGVyaWNhbCBMYXcgb2YgQ29zaW5lc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU3BoZXJpY2FsX2xhd19vZl9jb3NpbmVzKS5cclxuXHRkaXN0YW5jZVRvOiBmdW5jdGlvbiAob3RoZXIpIHtcclxuXHRcdHJldHVybiBFYXJ0aC5kaXN0YW5jZSh0aGlzLCB0b0xhdExuZyhvdGhlcikpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgd3JhcCgpOiBMYXRMbmdcclxuXHQvLyBSZXR1cm5zIGEgbmV3IGBMYXRMbmdgIG9iamVjdCB3aXRoIHRoZSBsb25naXR1ZGUgd3JhcHBlZCBzbyBpdCdzIGFsd2F5cyBiZXR3ZWVuIC0xODAgYW5kICsxODAgZGVncmVlcy5cclxuXHR3cmFwOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gRWFydGgud3JhcExhdExuZyh0aGlzKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHRvQm91bmRzKHNpemVJbk1ldGVyczogTnVtYmVyKTogTGF0TG5nQm91bmRzXHJcblx0Ly8gUmV0dXJucyBhIG5ldyBgTGF0TG5nQm91bmRzYCBvYmplY3QgaW4gd2hpY2ggZWFjaCBib3VuZGFyeSBpcyBgc2l6ZUluTWV0ZXJzLzJgIG1ldGVycyBhcGFydCBmcm9tIHRoZSBgTGF0TG5nYC5cclxuXHR0b0JvdW5kczogZnVuY3Rpb24gKHNpemVJbk1ldGVycykge1xyXG5cdFx0dmFyIGxhdEFjY3VyYWN5ID0gMTgwICogc2l6ZUluTWV0ZXJzIC8gNDAwNzUwMTcsXHJcblx0XHQgICAgbG5nQWNjdXJhY3kgPSBsYXRBY2N1cmFjeSAvIE1hdGguY29zKChNYXRoLlBJIC8gMTgwKSAqIHRoaXMubGF0KTtcclxuXHJcblx0XHRyZXR1cm4gdG9MYXRMbmdCb3VuZHMoXHJcblx0XHQgICAgICAgIFt0aGlzLmxhdCAtIGxhdEFjY3VyYWN5LCB0aGlzLmxuZyAtIGxuZ0FjY3VyYWN5XSxcclxuXHRcdCAgICAgICAgW3RoaXMubGF0ICsgbGF0QWNjdXJhY3ksIHRoaXMubG5nICsgbG5nQWNjdXJhY3ldKTtcclxuXHR9LFxyXG5cclxuXHRjbG9uZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIG5ldyBMYXRMbmcodGhpcy5sYXQsIHRoaXMubG5nLCB0aGlzLmFsdCk7XHJcblx0fVxyXG59O1xyXG5cclxuXHJcblxyXG4vLyBAZmFjdG9yeSBMLmxhdExuZyhsYXRpdHVkZTogTnVtYmVyLCBsb25naXR1ZGU6IE51bWJlciwgYWx0aXR1ZGU/OiBOdW1iZXIpOiBMYXRMbmdcclxuLy8gQ3JlYXRlcyBhbiBvYmplY3QgcmVwcmVzZW50aW5nIGEgZ2VvZ3JhcGhpY2FsIHBvaW50IHdpdGggdGhlIGdpdmVuIGxhdGl0dWRlIGFuZCBsb25naXR1ZGUgKGFuZCBvcHRpb25hbGx5IGFsdGl0dWRlKS5cclxuXHJcbi8vIEBhbHRlcm5hdGl2ZVxyXG4vLyBAZmFjdG9yeSBMLmxhdExuZyhjb29yZHM6IEFycmF5KTogTGF0TG5nXHJcbi8vIEV4cGVjdHMgYW4gYXJyYXkgb2YgdGhlIGZvcm0gYFtOdW1iZXIsIE51bWJlcl1gIG9yIGBbTnVtYmVyLCBOdW1iZXIsIE51bWJlcl1gIGluc3RlYWQuXHJcblxyXG4vLyBAYWx0ZXJuYXRpdmVcclxuLy8gQGZhY3RvcnkgTC5sYXRMbmcoY29vcmRzOiBPYmplY3QpOiBMYXRMbmdcclxuLy8gRXhwZWN0cyBhbiBwbGFpbiBvYmplY3Qgb2YgdGhlIGZvcm0gYHtsYXQ6IE51bWJlciwgbG5nOiBOdW1iZXJ9YCBvciBge2xhdDogTnVtYmVyLCBsbmc6IE51bWJlciwgYWx0OiBOdW1iZXJ9YCBpbnN0ZWFkLlxyXG5cclxuZnVuY3Rpb24gdG9MYXRMbmcoYSwgYiwgYykge1xyXG5cdGlmIChhIGluc3RhbmNlb2YgTGF0TG5nKSB7XHJcblx0XHRyZXR1cm4gYTtcclxuXHR9XHJcblx0aWYgKGlzQXJyYXkoYSkgJiYgdHlwZW9mIGFbMF0gIT09ICdvYmplY3QnKSB7XHJcblx0XHRpZiAoYS5sZW5ndGggPT09IDMpIHtcclxuXHRcdFx0cmV0dXJuIG5ldyBMYXRMbmcoYVswXSwgYVsxXSwgYVsyXSk7XHJcblx0XHR9XHJcblx0XHRpZiAoYS5sZW5ndGggPT09IDIpIHtcclxuXHRcdFx0cmV0dXJuIG5ldyBMYXRMbmcoYVswXSwgYVsxXSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gbnVsbDtcclxuXHR9XHJcblx0aWYgKGEgPT09IHVuZGVmaW5lZCB8fCBhID09PSBudWxsKSB7XHJcblx0XHRyZXR1cm4gYTtcclxuXHR9XHJcblx0aWYgKHR5cGVvZiBhID09PSAnb2JqZWN0JyAmJiAnbGF0JyBpbiBhKSB7XHJcblx0XHRyZXR1cm4gbmV3IExhdExuZyhhLmxhdCwgJ2xuZycgaW4gYSA/IGEubG5nIDogYS5sb24sIGEuYWx0KTtcclxuXHR9XHJcblx0aWYgKGIgPT09IHVuZGVmaW5lZCkge1xyXG5cdFx0cmV0dXJuIG51bGw7XHJcblx0fVxyXG5cdHJldHVybiBuZXcgTGF0TG5nKGEsIGIsIGMpO1xyXG59XG5cbi8qXHJcbiAqIEBuYW1lc3BhY2UgQ1JTXHJcbiAqIEBjcnMgTC5DUlMuQmFzZVxyXG4gKiBPYmplY3QgdGhhdCBkZWZpbmVzIGNvb3JkaW5hdGUgcmVmZXJlbmNlIHN5c3RlbXMgZm9yIHByb2plY3RpbmdcclxuICogZ2VvZ3JhcGhpY2FsIHBvaW50cyBpbnRvIHBpeGVsIChzY3JlZW4pIGNvb3JkaW5hdGVzIGFuZCBiYWNrIChhbmQgdG9cclxuICogY29vcmRpbmF0ZXMgaW4gb3RoZXIgdW5pdHMgZm9yIFtXTVNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dlYl9NYXBfU2VydmljZSkgc2VydmljZXMpLiBTZWVcclxuICogW3NwYXRpYWwgcmVmZXJlbmNlIHN5c3RlbV0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db29yZGluYXRlX3JlZmVyZW5jZV9zeXN0ZW0pLlxyXG4gKlxyXG4gKiBMZWFmbGV0IGRlZmluZXMgdGhlIG1vc3QgdXN1YWwgQ1JTcyBieSBkZWZhdWx0LiBJZiB5b3Ugd2FudCB0byB1c2UgYVxyXG4gKiBDUlMgbm90IGRlZmluZWQgYnkgZGVmYXVsdCwgdGFrZSBhIGxvb2sgYXQgdGhlXHJcbiAqIFtQcm9qNExlYWZsZXRdKGh0dHBzOi8vZ2l0aHViLmNvbS9rYXJ0ZW5hL1Byb2o0TGVhZmxldCkgcGx1Z2luLlxyXG4gKlxyXG4gKiBOb3RlIHRoYXQgdGhlIENSUyBpbnN0YW5jZXMgZG8gbm90IGluaGVyaXQgZnJvbSBMZWFmZXQncyBgQ2xhc3NgIG9iamVjdCxcclxuICogYW5kIGNhbid0IGJlIGluc3RhbnRpYXRlZC4gQWxzbywgbmV3IGNsYXNzZXMgY2FuJ3QgaW5oZXJpdCBmcm9tIHRoZW0sXHJcbiAqIGFuZCBtZXRob2RzIGNhbid0IGJlIGFkZGVkIHRvIHRoZW0gd2l0aCB0aGUgYGluY2x1ZGVgIGZ1bmN0aW9uLlxyXG4gKi9cclxuXHJcbnZhciBDUlMgPSB7XHJcblx0Ly8gQG1ldGhvZCBsYXRMbmdUb1BvaW50KGxhdGxuZzogTGF0TG5nLCB6b29tOiBOdW1iZXIpOiBQb2ludFxyXG5cdC8vIFByb2plY3RzIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlcyBpbnRvIHBpeGVsIGNvb3JkaW5hdGVzIGZvciBhIGdpdmVuIHpvb20uXHJcblx0bGF0TG5nVG9Qb2ludDogZnVuY3Rpb24gKGxhdGxuZywgem9vbSkge1xyXG5cdFx0dmFyIHByb2plY3RlZFBvaW50ID0gdGhpcy5wcm9qZWN0aW9uLnByb2plY3QobGF0bG5nKSxcclxuXHRcdCAgICBzY2FsZSA9IHRoaXMuc2NhbGUoem9vbSk7XHJcblxyXG5cdFx0cmV0dXJuIHRoaXMudHJhbnNmb3JtYXRpb24uX3RyYW5zZm9ybShwcm9qZWN0ZWRQb2ludCwgc2NhbGUpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgcG9pbnRUb0xhdExuZyhwb2ludDogUG9pbnQsIHpvb206IE51bWJlcik6IExhdExuZ1xyXG5cdC8vIFRoZSBpbnZlcnNlIG9mIGBsYXRMbmdUb1BvaW50YC4gUHJvamVjdHMgcGl4ZWwgY29vcmRpbmF0ZXMgb24gYSBnaXZlblxyXG5cdC8vIHpvb20gaW50byBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMuXHJcblx0cG9pbnRUb0xhdExuZzogZnVuY3Rpb24gKHBvaW50LCB6b29tKSB7XHJcblx0XHR2YXIgc2NhbGUgPSB0aGlzLnNjYWxlKHpvb20pLFxyXG5cdFx0ICAgIHVudHJhbnNmb3JtZWRQb2ludCA9IHRoaXMudHJhbnNmb3JtYXRpb24udW50cmFuc2Zvcm0ocG9pbnQsIHNjYWxlKTtcclxuXHJcblx0XHRyZXR1cm4gdGhpcy5wcm9qZWN0aW9uLnVucHJvamVjdCh1bnRyYW5zZm9ybWVkUG9pbnQpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgcHJvamVjdChsYXRsbmc6IExhdExuZyk6IFBvaW50XHJcblx0Ly8gUHJvamVjdHMgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGludG8gY29vcmRpbmF0ZXMgaW4gdW5pdHMgYWNjZXB0ZWQgZm9yXHJcblx0Ly8gdGhpcyBDUlMgKGUuZy4gbWV0ZXJzIGZvciBFUFNHOjM4NTcsIGZvciBwYXNzaW5nIGl0IHRvIFdNUyBzZXJ2aWNlcykuXHJcblx0cHJvamVjdDogZnVuY3Rpb24gKGxhdGxuZykge1xyXG5cdFx0cmV0dXJuIHRoaXMucHJvamVjdGlvbi5wcm9qZWN0KGxhdGxuZyk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB1bnByb2plY3QocG9pbnQ6IFBvaW50KTogTGF0TG5nXHJcblx0Ly8gR2l2ZW4gYSBwcm9qZWN0ZWQgY29vcmRpbmF0ZSByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIExhdExuZy5cclxuXHQvLyBUaGUgaW52ZXJzZSBvZiBgcHJvamVjdGAuXHJcblx0dW5wcm9qZWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuXHRcdHJldHVybiB0aGlzLnByb2plY3Rpb24udW5wcm9qZWN0KHBvaW50KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNjYWxlKHpvb206IE51bWJlcik6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIHNjYWxlIHVzZWQgd2hlbiB0cmFuc2Zvcm1pbmcgcHJvamVjdGVkIGNvb3JkaW5hdGVzIGludG9cclxuXHQvLyBwaXhlbCBjb29yZGluYXRlcyBmb3IgYSBwYXJ0aWN1bGFyIHpvb20uIEZvciBleGFtcGxlLCBpdCByZXR1cm5zXHJcblx0Ly8gYDI1NiAqIDJeem9vbWAgZm9yIE1lcmNhdG9yLWJhc2VkIENSUy5cclxuXHRzY2FsZTogZnVuY3Rpb24gKHpvb20pIHtcclxuXHRcdHJldHVybiAyNTYgKiBNYXRoLnBvdygyLCB6b29tKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHpvb20oc2NhbGU6IE51bWJlcik6IE51bWJlclxyXG5cdC8vIEludmVyc2Ugb2YgYHNjYWxlKClgLCByZXR1cm5zIHRoZSB6b29tIGxldmVsIGNvcnJlc3BvbmRpbmcgdG8gYSBzY2FsZVxyXG5cdC8vIGZhY3RvciBvZiBgc2NhbGVgLlxyXG5cdHpvb206IGZ1bmN0aW9uIChzY2FsZSkge1xyXG5cdFx0cmV0dXJuIE1hdGgubG9nKHNjYWxlIC8gMjU2KSAvIE1hdGguTE4yO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0UHJvamVjdGVkQm91bmRzKHpvb206IE51bWJlcik6IEJvdW5kc1xyXG5cdC8vIFJldHVybnMgdGhlIHByb2plY3Rpb24ncyBib3VuZHMgc2NhbGVkIGFuZCB0cmFuc2Zvcm1lZCBmb3IgdGhlIHByb3ZpZGVkIGB6b29tYC5cclxuXHRnZXRQcm9qZWN0ZWRCb3VuZHM6IGZ1bmN0aW9uICh6b29tKSB7XHJcblx0XHRpZiAodGhpcy5pbmZpbml0ZSkgeyByZXR1cm4gbnVsbDsgfVxyXG5cclxuXHRcdHZhciBiID0gdGhpcy5wcm9qZWN0aW9uLmJvdW5kcyxcclxuXHRcdCAgICBzID0gdGhpcy5zY2FsZSh6b29tKSxcclxuXHRcdCAgICBtaW4gPSB0aGlzLnRyYW5zZm9ybWF0aW9uLnRyYW5zZm9ybShiLm1pbiwgcyksXHJcblx0XHQgICAgbWF4ID0gdGhpcy50cmFuc2Zvcm1hdGlvbi50cmFuc2Zvcm0oYi5tYXgsIHMpO1xyXG5cclxuXHRcdHJldHVybiBuZXcgQm91bmRzKG1pbiwgbWF4KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGRpc3RhbmNlKGxhdGxuZzE6IExhdExuZywgbGF0bG5nMjogTGF0TG5nKTogTnVtYmVyXHJcblx0Ly8gUmV0dXJucyB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0d28gZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzLlxyXG5cclxuXHQvLyBAcHJvcGVydHkgY29kZTogU3RyaW5nXHJcblx0Ly8gU3RhbmRhcmQgY29kZSBuYW1lIG9mIHRoZSBDUlMgcGFzc2VkIGludG8gV01TIHNlcnZpY2VzIChlLmcuIGAnRVBTRzozODU3J2ApXHJcblx0Ly9cclxuXHQvLyBAcHJvcGVydHkgd3JhcExuZzogTnVtYmVyW11cclxuXHQvLyBBbiBhcnJheSBvZiB0d28gbnVtYmVycyBkZWZpbmluZyB3aGV0aGVyIHRoZSBsb25naXR1ZGUgKGhvcml6b250YWwpIGNvb3JkaW5hdGVcclxuXHQvLyBheGlzIHdyYXBzIGFyb3VuZCBhIGdpdmVuIHJhbmdlIGFuZCBob3cuIERlZmF1bHRzIHRvIGBbLTE4MCwgMTgwXWAgaW4gbW9zdFxyXG5cdC8vIGdlb2dyYXBoaWNhbCBDUlNzLiBJZiBgdW5kZWZpbmVkYCwgdGhlIGxvbmdpdHVkZSBheGlzIGRvZXMgbm90IHdyYXAgYXJvdW5kLlxyXG5cdC8vXHJcblx0Ly8gQHByb3BlcnR5IHdyYXBMYXQ6IE51bWJlcltdXHJcblx0Ly8gTGlrZSBgd3JhcExuZ2AsIGJ1dCBmb3IgdGhlIGxhdGl0dWRlICh2ZXJ0aWNhbCkgYXhpcy5cclxuXHJcblx0Ly8gd3JhcExuZzogW21pbiwgbWF4XSxcclxuXHQvLyB3cmFwTGF0OiBbbWluLCBtYXhdLFxyXG5cclxuXHQvLyBAcHJvcGVydHkgaW5maW5pdGU6IEJvb2xlYW5cclxuXHQvLyBJZiB0cnVlLCB0aGUgY29vcmRpbmF0ZSBzcGFjZSB3aWxsIGJlIHVuYm91bmRlZCAoaW5maW5pdGUgaW4gYm90aCBheGVzKVxyXG5cdGluZmluaXRlOiBmYWxzZSxcclxuXHJcblx0Ly8gQG1ldGhvZCB3cmFwTGF0TG5nKGxhdGxuZzogTGF0TG5nKTogTGF0TG5nXHJcblx0Ly8gUmV0dXJucyBhIGBMYXRMbmdgIHdoZXJlIGxhdCBhbmQgbG5nIGhhcyBiZWVuIHdyYXBwZWQgYWNjb3JkaW5nIHRvIHRoZVxyXG5cdC8vIENSUydzIGB3cmFwTGF0YCBhbmQgYHdyYXBMbmdgIHByb3BlcnRpZXMsIGlmIHRoZXkgYXJlIG91dHNpZGUgdGhlIENSUydzIGJvdW5kcy5cclxuXHR3cmFwTGF0TG5nOiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHR2YXIgbG5nID0gdGhpcy53cmFwTG5nID8gd3JhcE51bShsYXRsbmcubG5nLCB0aGlzLndyYXBMbmcsIHRydWUpIDogbGF0bG5nLmxuZyxcclxuXHRcdCAgICBsYXQgPSB0aGlzLndyYXBMYXQgPyB3cmFwTnVtKGxhdGxuZy5sYXQsIHRoaXMud3JhcExhdCwgdHJ1ZSkgOiBsYXRsbmcubGF0LFxyXG5cdFx0ICAgIGFsdCA9IGxhdGxuZy5hbHQ7XHJcblxyXG5cdFx0cmV0dXJuIG5ldyBMYXRMbmcobGF0LCBsbmcsIGFsdCk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB3cmFwTGF0TG5nQm91bmRzKGJvdW5kczogTGF0TG5nQm91bmRzKTogTGF0TG5nQm91bmRzXHJcblx0Ly8gUmV0dXJucyBhIGBMYXRMbmdCb3VuZHNgIHdpdGggdGhlIHNhbWUgc2l6ZSBhcyB0aGUgZ2l2ZW4gb25lLCBlbnN1cmluZ1xyXG5cdC8vIHRoYXQgaXRzIGNlbnRlciBpcyB3aXRoaW4gdGhlIENSUydzIGJvdW5kcy5cclxuXHQvLyBPbmx5IGFjY2VwdHMgYWN0dWFsIGBMLkxhdExuZ0JvdW5kc2AgaW5zdGFuY2VzLCBub3QgYXJyYXlzLlxyXG5cdHdyYXBMYXRMbmdCb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMpIHtcclxuXHRcdHZhciBjZW50ZXIgPSBib3VuZHMuZ2V0Q2VudGVyKCksXHJcblx0XHQgICAgbmV3Q2VudGVyID0gdGhpcy53cmFwTGF0TG5nKGNlbnRlciksXHJcblx0XHQgICAgbGF0U2hpZnQgPSBjZW50ZXIubGF0IC0gbmV3Q2VudGVyLmxhdCxcclxuXHRcdCAgICBsbmdTaGlmdCA9IGNlbnRlci5sbmcgLSBuZXdDZW50ZXIubG5nO1xyXG5cclxuXHRcdGlmIChsYXRTaGlmdCA9PT0gMCAmJiBsbmdTaGlmdCA9PT0gMCkge1xyXG5cdFx0XHRyZXR1cm4gYm91bmRzO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBzdyA9IGJvdW5kcy5nZXRTb3V0aFdlc3QoKSxcclxuXHRcdCAgICBuZSA9IGJvdW5kcy5nZXROb3J0aEVhc3QoKSxcclxuXHRcdCAgICBuZXdTdyA9IG5ldyBMYXRMbmcoc3cubGF0IC0gbGF0U2hpZnQsIHN3LmxuZyAtIGxuZ1NoaWZ0KSxcclxuXHRcdCAgICBuZXdOZSA9IG5ldyBMYXRMbmcobmUubGF0IC0gbGF0U2hpZnQsIG5lLmxuZyAtIGxuZ1NoaWZ0KTtcclxuXHJcblx0XHRyZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhuZXdTdywgbmV3TmUpO1xyXG5cdH1cclxufTtcblxuLypcbiAqIEBuYW1lc3BhY2UgQ1JTXG4gKiBAY3JzIEwuQ1JTLkVhcnRoXG4gKlxuICogU2VydmVzIGFzIHRoZSBiYXNlIGZvciBDUlMgdGhhdCBhcmUgZ2xvYmFsIHN1Y2ggdGhhdCB0aGV5IGNvdmVyIHRoZSBlYXJ0aC5cbiAqIENhbiBvbmx5IGJlIHVzZWQgYXMgdGhlIGJhc2UgZm9yIG90aGVyIENSUyBhbmQgY2Fubm90IGJlIHVzZWQgZGlyZWN0bHksXG4gKiBzaW5jZSBpdCBkb2VzIG5vdCBoYXZlIGEgYGNvZGVgLCBgcHJvamVjdGlvbmAgb3IgYHRyYW5zZm9ybWF0aW9uYC4gYGRpc3RhbmNlKClgIHJldHVybnNcbiAqIG1ldGVycy5cbiAqL1xuXG52YXIgRWFydGggPSBleHRlbmQoe30sIENSUywge1xuXHR3cmFwTG5nOiBbLTE4MCwgMTgwXSxcblxuXHQvLyBNZWFuIEVhcnRoIFJhZGl1cywgYXMgcmVjb21tZW5kZWQgZm9yIHVzZSBieVxuXHQvLyB0aGUgSW50ZXJuYXRpb25hbCBVbmlvbiBvZiBHZW9kZXN5IGFuZCBHZW9waHlzaWNzLFxuXHQvLyBzZWUgaHR0cDovL3Jvc2V0dGFjb2RlLm9yZy93aWtpL0hhdmVyc2luZV9mb3JtdWxhXG5cdFI6IDYzNzEwMDAsXG5cblx0Ly8gZGlzdGFuY2UgYmV0d2VlbiB0d28gZ2VvZ3JhcGhpY2FsIHBvaW50cyB1c2luZyBzcGhlcmljYWwgbGF3IG9mIGNvc2luZXMgYXBwcm94aW1hdGlvblxuXHRkaXN0YW5jZTogZnVuY3Rpb24gKGxhdGxuZzEsIGxhdGxuZzIpIHtcblx0XHR2YXIgcmFkID0gTWF0aC5QSSAvIDE4MCxcblx0XHQgICAgbGF0MSA9IGxhdGxuZzEubGF0ICogcmFkLFxuXHRcdCAgICBsYXQyID0gbGF0bG5nMi5sYXQgKiByYWQsXG5cdFx0ICAgIHNpbkRMYXQgPSBNYXRoLnNpbigobGF0bG5nMi5sYXQgLSBsYXRsbmcxLmxhdCkgKiByYWQgLyAyKSxcblx0XHQgICAgc2luRExvbiA9IE1hdGguc2luKChsYXRsbmcyLmxuZyAtIGxhdGxuZzEubG5nKSAqIHJhZCAvIDIpLFxuXHRcdCAgICBhID0gc2luRExhdCAqIHNpbkRMYXQgKyBNYXRoLmNvcyhsYXQxKSAqIE1hdGguY29zKGxhdDIpICogc2luRExvbiAqIHNpbkRMb24sXG5cdFx0ICAgIGMgPSAyICogTWF0aC5hdGFuMihNYXRoLnNxcnQoYSksIE1hdGguc3FydCgxIC0gYSkpO1xuXHRcdHJldHVybiB0aGlzLlIgKiBjO1xuXHR9XG59KTtcblxuLypcclxuICogQG5hbWVzcGFjZSBQcm9qZWN0aW9uXHJcbiAqIEBwcm9qZWN0aW9uIEwuUHJvamVjdGlvbi5TcGhlcmljYWxNZXJjYXRvclxyXG4gKlxyXG4gKiBTcGhlcmljYWwgTWVyY2F0b3IgcHJvamVjdGlvbiDigJQgdGhlIG1vc3QgY29tbW9uIHByb2plY3Rpb24gZm9yIG9ubGluZSBtYXBzLFxyXG4gKiB1c2VkIGJ5IGFsbW9zdCBhbGwgZnJlZSBhbmQgY29tbWVyY2lhbCB0aWxlIHByb3ZpZGVycy4gQXNzdW1lcyB0aGF0IEVhcnRoIGlzXHJcbiAqIGEgc3BoZXJlLiBVc2VkIGJ5IHRoZSBgRVBTRzozODU3YCBDUlMuXHJcbiAqL1xyXG5cclxudmFyIFNwaGVyaWNhbE1lcmNhdG9yID0ge1xyXG5cclxuXHRSOiA2Mzc4MTM3LFxyXG5cdE1BWF9MQVRJVFVERTogODUuMDUxMTI4Nzc5OCxcclxuXHJcblx0cHJvamVjdDogZnVuY3Rpb24gKGxhdGxuZykge1xyXG5cdFx0dmFyIGQgPSBNYXRoLlBJIC8gMTgwLFxyXG5cdFx0ICAgIG1heCA9IHRoaXMuTUFYX0xBVElUVURFLFxyXG5cdFx0ICAgIGxhdCA9IE1hdGgubWF4KE1hdGgubWluKG1heCwgbGF0bG5nLmxhdCksIC1tYXgpLFxyXG5cdFx0ICAgIHNpbiA9IE1hdGguc2luKGxhdCAqIGQpO1xyXG5cclxuXHRcdHJldHVybiBuZXcgUG9pbnQoXHJcblx0XHRcdHRoaXMuUiAqIGxhdGxuZy5sbmcgKiBkLFxyXG5cdFx0XHR0aGlzLlIgKiBNYXRoLmxvZygoMSArIHNpbikgLyAoMSAtIHNpbikpIC8gMik7XHJcblx0fSxcclxuXHJcblx0dW5wcm9qZWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuXHRcdHZhciBkID0gMTgwIC8gTWF0aC5QSTtcclxuXHJcblx0XHRyZXR1cm4gbmV3IExhdExuZyhcclxuXHRcdFx0KDIgKiBNYXRoLmF0YW4oTWF0aC5leHAocG9pbnQueSAvIHRoaXMuUikpIC0gKE1hdGguUEkgLyAyKSkgKiBkLFxyXG5cdFx0XHRwb2ludC54ICogZCAvIHRoaXMuUik7XHJcblx0fSxcclxuXHJcblx0Ym91bmRzOiAoZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGQgPSA2Mzc4MTM3ICogTWF0aC5QSTtcclxuXHRcdHJldHVybiBuZXcgQm91bmRzKFstZCwgLWRdLCBbZCwgZF0pO1xyXG5cdH0pKClcclxufTtcblxuLypcclxuICogQGNsYXNzIFRyYW5zZm9ybWF0aW9uXHJcbiAqIEBha2EgTC5UcmFuc2Zvcm1hdGlvblxyXG4gKlxyXG4gKiBSZXByZXNlbnRzIGFuIGFmZmluZSB0cmFuc2Zvcm1hdGlvbjogYSBzZXQgb2YgY29lZmZpY2llbnRzIGBhYCwgYGJgLCBgY2AsIGBkYFxyXG4gKiBmb3IgdHJhbnNmb3JtaW5nIGEgcG9pbnQgb2YgYSBmb3JtIGAoeCwgeSlgIGludG8gYChhKnggKyBiLCBjKnkgKyBkKWAgYW5kIGRvaW5nXHJcbiAqIHRoZSByZXZlcnNlLiBVc2VkIGJ5IExlYWZsZXQgaW4gaXRzIHByb2plY3Rpb25zIGNvZGUuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciB0cmFuc2Zvcm1hdGlvbiA9IEwudHJhbnNmb3JtYXRpb24oMiwgNSwgLTEsIDEwKSxcclxuICogXHRwID0gTC5wb2ludCgxLCAyKSxcclxuICogXHRwMiA9IHRyYW5zZm9ybWF0aW9uLnRyYW5zZm9ybShwKSwgLy8gIEwucG9pbnQoNywgOClcclxuICogXHRwMyA9IHRyYW5zZm9ybWF0aW9uLnVudHJhbnNmb3JtKHAyKTsgLy8gIEwucG9pbnQoMSwgMilcclxuICogYGBgXHJcbiAqL1xyXG5cclxuXHJcbi8vIGZhY3RvcnkgbmV3IEwuVHJhbnNmb3JtYXRpb24oYTogTnVtYmVyLCBiOiBOdW1iZXIsIGM6IE51bWJlciwgZDogTnVtYmVyKVxyXG4vLyBDcmVhdGVzIGEgYFRyYW5zZm9ybWF0aW9uYCBvYmplY3Qgd2l0aCB0aGUgZ2l2ZW4gY29lZmZpY2llbnRzLlxyXG5mdW5jdGlvbiBUcmFuc2Zvcm1hdGlvbihhLCBiLCBjLCBkKSB7XHJcblx0aWYgKGlzQXJyYXkoYSkpIHtcclxuXHRcdC8vIHVzZSBhcnJheSBwcm9wZXJ0aWVzXHJcblx0XHR0aGlzLl9hID0gYVswXTtcclxuXHRcdHRoaXMuX2IgPSBhWzFdO1xyXG5cdFx0dGhpcy5fYyA9IGFbMl07XHJcblx0XHR0aGlzLl9kID0gYVszXTtcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblx0dGhpcy5fYSA9IGE7XHJcblx0dGhpcy5fYiA9IGI7XHJcblx0dGhpcy5fYyA9IGM7XHJcblx0dGhpcy5fZCA9IGQ7XHJcbn1cclxuXHJcblRyYW5zZm9ybWF0aW9uLnByb3RvdHlwZSA9IHtcclxuXHQvLyBAbWV0aG9kIHRyYW5zZm9ybShwb2ludDogUG9pbnQsIHNjYWxlPzogTnVtYmVyKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIGEgdHJhbnNmb3JtZWQgcG9pbnQsIG9wdGlvbmFsbHkgbXVsdGlwbGllZCBieSB0aGUgZ2l2ZW4gc2NhbGUuXHJcblx0Ly8gT25seSBhY2NlcHRzIGFjdHVhbCBgTC5Qb2ludGAgaW5zdGFuY2VzLCBub3QgYXJyYXlzLlxyXG5cdHRyYW5zZm9ybTogZnVuY3Rpb24gKHBvaW50LCBzY2FsZSkgeyAvLyAoUG9pbnQsIE51bWJlcikgLT4gUG9pbnRcclxuXHRcdHJldHVybiB0aGlzLl90cmFuc2Zvcm0ocG9pbnQuY2xvbmUoKSwgc2NhbGUpO1xyXG5cdH0sXHJcblxyXG5cdC8vIGRlc3RydWN0aXZlIHRyYW5zZm9ybSAoZmFzdGVyKVxyXG5cdF90cmFuc2Zvcm06IGZ1bmN0aW9uIChwb2ludCwgc2NhbGUpIHtcclxuXHRcdHNjYWxlID0gc2NhbGUgfHwgMTtcclxuXHRcdHBvaW50LnggPSBzY2FsZSAqICh0aGlzLl9hICogcG9pbnQueCArIHRoaXMuX2IpO1xyXG5cdFx0cG9pbnQueSA9IHNjYWxlICogKHRoaXMuX2MgKiBwb2ludC55ICsgdGhpcy5fZCk7XHJcblx0XHRyZXR1cm4gcG9pbnQ7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB1bnRyYW5zZm9ybShwb2ludDogUG9pbnQsIHNjYWxlPzogTnVtYmVyKTogUG9pbnRcclxuXHQvLyBSZXR1cm5zIHRoZSByZXZlcnNlIHRyYW5zZm9ybWF0aW9uIG9mIHRoZSBnaXZlbiBwb2ludCwgb3B0aW9uYWxseSBkaXZpZGVkXHJcblx0Ly8gYnkgdGhlIGdpdmVuIHNjYWxlLiBPbmx5IGFjY2VwdHMgYWN0dWFsIGBMLlBvaW50YCBpbnN0YW5jZXMsIG5vdCBhcnJheXMuXHJcblx0dW50cmFuc2Zvcm06IGZ1bmN0aW9uIChwb2ludCwgc2NhbGUpIHtcclxuXHRcdHNjYWxlID0gc2NhbGUgfHwgMTtcclxuXHRcdHJldHVybiBuZXcgUG9pbnQoXHJcblx0XHQgICAgICAgIChwb2ludC54IC8gc2NhbGUgLSB0aGlzLl9iKSAvIHRoaXMuX2EsXHJcblx0XHQgICAgICAgIChwb2ludC55IC8gc2NhbGUgLSB0aGlzLl9kKSAvIHRoaXMuX2MpO1xyXG5cdH1cclxufTtcclxuXHJcbi8vIGZhY3RvcnkgTC50cmFuc2Zvcm1hdGlvbihhOiBOdW1iZXIsIGI6IE51bWJlciwgYzogTnVtYmVyLCBkOiBOdW1iZXIpXHJcblxyXG4vLyBAZmFjdG9yeSBMLnRyYW5zZm9ybWF0aW9uKGE6IE51bWJlciwgYjogTnVtYmVyLCBjOiBOdW1iZXIsIGQ6IE51bWJlcilcclxuLy8gSW5zdGFudGlhdGVzIGEgVHJhbnNmb3JtYXRpb24gb2JqZWN0IHdpdGggdGhlIGdpdmVuIGNvZWZmaWNpZW50cy5cclxuXHJcbi8vIEBhbHRlcm5hdGl2ZVxyXG4vLyBAZmFjdG9yeSBMLnRyYW5zZm9ybWF0aW9uKGNvZWZmaWNpZW50czogQXJyYXkpOiBUcmFuc2Zvcm1hdGlvblxyXG4vLyBFeHBlY3RzIGFuIGNvZWZmaWNpZW50cyBhcnJheSBvZiB0aGUgZm9ybVxyXG4vLyBgW2E6IE51bWJlciwgYjogTnVtYmVyLCBjOiBOdW1iZXIsIGQ6IE51bWJlcl1gLlxyXG5cclxuZnVuY3Rpb24gdG9UcmFuc2Zvcm1hdGlvbihhLCBiLCBjLCBkKSB7XHJcblx0cmV0dXJuIG5ldyBUcmFuc2Zvcm1hdGlvbihhLCBiLCBjLCBkKTtcclxufVxuXG4vKlxyXG4gKiBAbmFtZXNwYWNlIENSU1xyXG4gKiBAY3JzIEwuQ1JTLkVQU0czODU3XHJcbiAqXHJcbiAqIFRoZSBtb3N0IGNvbW1vbiBDUlMgZm9yIG9ubGluZSBtYXBzLCB1c2VkIGJ5IGFsbW9zdCBhbGwgZnJlZSBhbmQgY29tbWVyY2lhbFxyXG4gKiB0aWxlIHByb3ZpZGVycy4gVXNlcyBTcGhlcmljYWwgTWVyY2F0b3IgcHJvamVjdGlvbi4gU2V0IGluIGJ5IGRlZmF1bHQgaW5cclxuICogTWFwJ3MgYGNyc2Agb3B0aW9uLlxyXG4gKi9cclxuXHJcbnZhciBFUFNHMzg1NyA9IGV4dGVuZCh7fSwgRWFydGgsIHtcclxuXHRjb2RlOiAnRVBTRzozODU3JyxcclxuXHRwcm9qZWN0aW9uOiBTcGhlcmljYWxNZXJjYXRvcixcclxuXHJcblx0dHJhbnNmb3JtYXRpb246IChmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgc2NhbGUgPSAwLjUgLyAoTWF0aC5QSSAqIFNwaGVyaWNhbE1lcmNhdG9yLlIpO1xyXG5cdFx0cmV0dXJuIHRvVHJhbnNmb3JtYXRpb24oc2NhbGUsIDAuNSwgLXNjYWxlLCAwLjUpO1xyXG5cdH0oKSlcclxufSk7XHJcblxyXG52YXIgRVBTRzkwMDkxMyA9IGV4dGVuZCh7fSwgRVBTRzM4NTcsIHtcclxuXHRjb2RlOiAnRVBTRzo5MDA5MTMnXHJcbn0pO1xuXG4vLyBAbmFtZXNwYWNlIFNWRzsgQHNlY3Rpb25cbi8vIFRoZXJlIGFyZSBzZXZlcmFsIHN0YXRpYyBmdW5jdGlvbnMgd2hpY2ggY2FuIGJlIGNhbGxlZCB3aXRob3V0IGluc3RhbnRpYXRpbmcgTC5TVkc6XG5cbi8vIEBmdW5jdGlvbiBjcmVhdGUobmFtZTogU3RyaW5nKTogU1ZHRWxlbWVudFxuLy8gUmV0dXJucyBhIGluc3RhbmNlIG9mIFtTVkdFbGVtZW50XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvU1ZHRWxlbWVudCksXG4vLyBjb3JyZXNwb25kaW5nIHRvIHRoZSBjbGFzcyBuYW1lIHBhc3NlZC4gRm9yIGV4YW1wbGUsIHVzaW5nICdsaW5lJyB3aWxsIHJldHVyblxuLy8gYW4gaW5zdGFuY2Ugb2YgW1NWR0xpbmVFbGVtZW50XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvU1ZHTGluZUVsZW1lbnQpLlxuZnVuY3Rpb24gc3ZnQ3JlYXRlKG5hbWUpIHtcblx0cmV0dXJuIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUygnaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnLCBuYW1lKTtcbn1cblxuLy8gQGZ1bmN0aW9uIHBvaW50c1RvUGF0aChyaW5nczogUG9pbnRbXSwgY2xvc2VkOiBCb29sZWFuKTogU3RyaW5nXG4vLyBHZW5lcmF0ZXMgYSBTVkcgcGF0aCBzdHJpbmcgZm9yIG11bHRpcGxlIHJpbmdzLCB3aXRoIGVhY2ggcmluZyB0dXJuaW5nXG4vLyBpbnRvIFwiTS4uTC4uTC4uXCIgaW5zdHJ1Y3Rpb25zXG5mdW5jdGlvbiBwb2ludHNUb1BhdGgocmluZ3MsIGNsb3NlZCkge1xuXHR2YXIgc3RyID0gJycsXG5cdGksIGosIGxlbiwgbGVuMiwgcG9pbnRzLCBwO1xuXG5cdGZvciAoaSA9IDAsIGxlbiA9IHJpbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0cG9pbnRzID0gcmluZ3NbaV07XG5cblx0XHRmb3IgKGogPSAwLCBsZW4yID0gcG9pbnRzLmxlbmd0aDsgaiA8IGxlbjI7IGorKykge1xuXHRcdFx0cCA9IHBvaW50c1tqXTtcblx0XHRcdHN0ciArPSAoaiA/ICdMJyA6ICdNJykgKyBwLnggKyAnICcgKyBwLnk7XG5cdFx0fVxuXG5cdFx0Ly8gY2xvc2VzIHRoZSByaW5nIGZvciBwb2x5Z29uczsgXCJ4XCIgaXMgVk1MIHN5bnRheFxuXHRcdHN0ciArPSBjbG9zZWQgPyAoc3ZnID8gJ3onIDogJ3gnKSA6ICcnO1xuXHR9XG5cblx0Ly8gU1ZHIGNvbXBsYWlucyBhYm91dCBlbXB0eSBwYXRoIHN0cmluZ3Ncblx0cmV0dXJuIHN0ciB8fCAnTTAgMCc7XG59XG5cbi8qXHJcbiAqIEBuYW1lc3BhY2UgQnJvd3NlclxyXG4gKiBAYWthIEwuQnJvd3NlclxyXG4gKlxyXG4gKiBBIG5hbWVzcGFjZSB3aXRoIHN0YXRpYyBwcm9wZXJ0aWVzIGZvciBicm93c2VyL2ZlYXR1cmUgZGV0ZWN0aW9uIHVzZWQgYnkgTGVhZmxldCBpbnRlcm5hbGx5LlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiBpZiAoTC5Ccm93c2VyLmllbHQ5KSB7XHJcbiAqICAgYWxlcnQoJ1VwZ3JhZGUgeW91ciBicm93c2VyLCBkdWRlIScpO1xyXG4gKiB9XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBzdHlsZSQxID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlO1xyXG5cclxuLy8gQHByb3BlcnR5IGllOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGFsbCBJbnRlcm5ldCBFeHBsb3JlciB2ZXJzaW9ucyAobm90IEVkZ2UpLlxyXG52YXIgaWUgPSAnQWN0aXZlWE9iamVjdCcgaW4gd2luZG93O1xyXG5cclxuLy8gQHByb3BlcnR5IGllbHQ5OiBCb29sZWFuOyBgdHJ1ZWAgZm9yIEludGVybmV0IEV4cGxvcmVyIHZlcnNpb25zIGxlc3MgdGhhbiA5LlxyXG52YXIgaWVsdDkgPSBpZSAmJiAhZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcjtcclxuXHJcbi8vIEBwcm9wZXJ0eSBlZGdlOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIHRoZSBFZGdlIHdlYiBicm93c2VyLlxyXG52YXIgZWRnZSA9ICdtc0xhdW5jaFVyaScgaW4gbmF2aWdhdG9yICYmICEoJ2RvY3VtZW50TW9kZScgaW4gZG9jdW1lbnQpO1xyXG5cclxuLy8gQHByb3BlcnR5IHdlYmtpdDogQm9vbGVhbjtcclxuLy8gYHRydWVgIGZvciB3ZWJraXQtYmFzZWQgYnJvd3NlcnMgbGlrZSBDaHJvbWUgYW5kIFNhZmFyaSAoaW5jbHVkaW5nIG1vYmlsZSB2ZXJzaW9ucykuXHJcbnZhciB3ZWJraXQgPSB1c2VyQWdlbnRDb250YWlucygnd2Via2l0Jyk7XHJcblxyXG4vLyBAcHJvcGVydHkgYW5kcm9pZDogQm9vbGVhblxyXG4vLyBgdHJ1ZWAgZm9yIGFueSBicm93c2VyIHJ1bm5pbmcgb24gYW4gQW5kcm9pZCBwbGF0Zm9ybS5cclxudmFyIGFuZHJvaWQgPSB1c2VyQWdlbnRDb250YWlucygnYW5kcm9pZCcpO1xyXG5cclxuLy8gQHByb3BlcnR5IGFuZHJvaWQyMzogQm9vbGVhbjsgYHRydWVgIGZvciBicm93c2VycyBydW5uaW5nIG9uIEFuZHJvaWQgMiBvciBBbmRyb2lkIDMuXHJcbnZhciBhbmRyb2lkMjMgPSB1c2VyQWdlbnRDb250YWlucygnYW5kcm9pZCAyJykgfHwgdXNlckFnZW50Q29udGFpbnMoJ2FuZHJvaWQgMycpO1xyXG5cclxuLyogU2VlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8xNzk2MTI2NiBmb3IgZGV0YWlscyBvbiBkZXRlY3Rpbmcgc3RvY2sgQW5kcm9pZCAqL1xyXG52YXIgd2Via2l0VmVyID0gcGFyc2VJbnQoL1dlYktpdFxcLyhbMC05XSspfCQvLmV4ZWMobmF2aWdhdG9yLnVzZXJBZ2VudClbMV0sIDEwKTsgLy8gYWxzbyBtYXRjaGVzIEFwcGxlV2ViS2l0XHJcbi8vIEBwcm9wZXJ0eSBhbmRyb2lkU3RvY2s6IEJvb2xlYW47IGB0cnVlYCBmb3IgdGhlIEFuZHJvaWQgc3RvY2sgYnJvd3NlciAoaS5lLiBub3QgQ2hyb21lKVxyXG52YXIgYW5kcm9pZFN0b2NrID0gYW5kcm9pZCAmJiB1c2VyQWdlbnRDb250YWlucygnR29vZ2xlJykgJiYgd2Via2l0VmVyIDwgNTM3ICYmICEoJ0F1ZGlvTm9kZScgaW4gd2luZG93KTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBvcGVyYTogQm9vbGVhbjsgYHRydWVgIGZvciB0aGUgT3BlcmEgYnJvd3NlclxyXG52YXIgb3BlcmEgPSAhIXdpbmRvdy5vcGVyYTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBjaHJvbWU6IEJvb2xlYW47IGB0cnVlYCBmb3IgdGhlIENocm9tZSBicm93c2VyLlxyXG52YXIgY2hyb21lID0gdXNlckFnZW50Q29udGFpbnMoJ2Nocm9tZScpO1xyXG5cclxuLy8gQHByb3BlcnR5IGdlY2tvOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGdlY2tvLWJhc2VkIGJyb3dzZXJzIGxpa2UgRmlyZWZveC5cclxudmFyIGdlY2tvID0gdXNlckFnZW50Q29udGFpbnMoJ2dlY2tvJykgJiYgIXdlYmtpdCAmJiAhb3BlcmEgJiYgIWllO1xyXG5cclxuLy8gQHByb3BlcnR5IHNhZmFyaTogQm9vbGVhbjsgYHRydWVgIGZvciB0aGUgU2FmYXJpIGJyb3dzZXIuXHJcbnZhciBzYWZhcmkgPSAhY2hyb21lICYmIHVzZXJBZ2VudENvbnRhaW5zKCdzYWZhcmknKTtcclxuXHJcbnZhciBwaGFudG9tID0gdXNlckFnZW50Q29udGFpbnMoJ3BoYW50b20nKTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBvcGVyYTEyOiBCb29sZWFuXHJcbi8vIGB0cnVlYCBmb3IgdGhlIE9wZXJhIGJyb3dzZXIgc3VwcG9ydGluZyBDU1MgdHJhbnNmb3JtcyAodmVyc2lvbiAxMiBvciBsYXRlcikuXHJcbnZhciBvcGVyYTEyID0gJ09UcmFuc2l0aW9uJyBpbiBzdHlsZSQxO1xyXG5cclxuLy8gQHByb3BlcnR5IHdpbjogQm9vbGVhbjsgYHRydWVgIHdoZW4gdGhlIGJyb3dzZXIgaXMgcnVubmluZyBpbiBhIFdpbmRvd3MgcGxhdGZvcm1cclxudmFyIHdpbiA9IG5hdmlnYXRvci5wbGF0Zm9ybS5pbmRleE9mKCdXaW4nKSA9PT0gMDtcclxuXHJcbi8vIEBwcm9wZXJ0eSBpZTNkOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGFsbCBJbnRlcm5ldCBFeHBsb3JlciB2ZXJzaW9ucyBzdXBwb3J0aW5nIENTUyB0cmFuc2Zvcm1zLlxyXG52YXIgaWUzZCA9IGllICYmICgndHJhbnNpdGlvbicgaW4gc3R5bGUkMSk7XHJcblxyXG4vLyBAcHJvcGVydHkgd2Via2l0M2Q6IEJvb2xlYW47IGB0cnVlYCBmb3Igd2Via2l0LWJhc2VkIGJyb3dzZXJzIHN1cHBvcnRpbmcgQ1NTIHRyYW5zZm9ybXMuXHJcbnZhciB3ZWJraXQzZCA9ICgnV2ViS2l0Q1NTTWF0cml4JyBpbiB3aW5kb3cpICYmICgnbTExJyBpbiBuZXcgd2luZG93LldlYktpdENTU01hdHJpeCgpKSAmJiAhYW5kcm9pZDIzO1xyXG5cclxuLy8gQHByb3BlcnR5IGdlY2tvM2Q6IEJvb2xlYW47IGB0cnVlYCBmb3IgZ2Vja28tYmFzZWQgYnJvd3NlcnMgc3VwcG9ydGluZyBDU1MgdHJhbnNmb3Jtcy5cclxudmFyIGdlY2tvM2QgPSAnTW96UGVyc3BlY3RpdmUnIGluIHN0eWxlJDE7XHJcblxyXG4vLyBAcHJvcGVydHkgYW55M2Q6IEJvb2xlYW5cclxuLy8gYHRydWVgIGZvciBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBDU1MgdHJhbnNmb3Jtcy5cclxudmFyIGFueTNkID0gIXdpbmRvdy5MX0RJU0FCTEVfM0QgJiYgKGllM2QgfHwgd2Via2l0M2QgfHwgZ2Vja28zZCkgJiYgIW9wZXJhMTIgJiYgIXBoYW50b207XHJcblxyXG4vLyBAcHJvcGVydHkgbW9iaWxlOiBCb29sZWFuOyBgdHJ1ZWAgZm9yIGFsbCBicm93c2VycyBydW5uaW5nIGluIGEgbW9iaWxlIGRldmljZS5cclxudmFyIG1vYmlsZSA9IHR5cGVvZiBvcmllbnRhdGlvbiAhPT0gJ3VuZGVmaW5lZCcgfHwgdXNlckFnZW50Q29udGFpbnMoJ21vYmlsZScpO1xyXG5cclxuLy8gQHByb3BlcnR5IG1vYmlsZVdlYmtpdDogQm9vbGVhbjsgYHRydWVgIGZvciBhbGwgd2Via2l0LWJhc2VkIGJyb3dzZXJzIGluIGEgbW9iaWxlIGRldmljZS5cclxudmFyIG1vYmlsZVdlYmtpdCA9IG1vYmlsZSAmJiB3ZWJraXQ7XHJcblxyXG4vLyBAcHJvcGVydHkgbW9iaWxlV2Via2l0M2Q6IEJvb2xlYW5cclxuLy8gYHRydWVgIGZvciBhbGwgd2Via2l0LWJhc2VkIGJyb3dzZXJzIGluIGEgbW9iaWxlIGRldmljZSBzdXBwb3J0aW5nIENTUyB0cmFuc2Zvcm1zLlxyXG52YXIgbW9iaWxlV2Via2l0M2QgPSBtb2JpbGUgJiYgd2Via2l0M2Q7XHJcblxyXG4vLyBAcHJvcGVydHkgbXNQb2ludGVyOiBCb29sZWFuXHJcbi8vIGB0cnVlYCBmb3IgYnJvd3NlcnMgaW1wbGVtZW50aW5nIHRoZSBNaWNyb3NvZnQgdG91Y2ggZXZlbnRzIG1vZGVsIChub3RhYmx5IElFMTApLlxyXG52YXIgbXNQb2ludGVyID0gIXdpbmRvdy5Qb2ludGVyRXZlbnQgJiYgd2luZG93Lk1TUG9pbnRlckV2ZW50O1xyXG5cclxuLy8gQHByb3BlcnR5IHBvaW50ZXI6IEJvb2xlYW5cclxuLy8gYHRydWVgIGZvciBhbGwgYnJvd3NlcnMgc3VwcG9ydGluZyBbcG9pbnRlciBldmVudHNdKGh0dHBzOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvZG40MzMyNDQlMjh2PXZzLjg1JTI5LmFzcHgpLlxyXG52YXIgcG9pbnRlciA9ICEhKHdpbmRvdy5Qb2ludGVyRXZlbnQgfHwgbXNQb2ludGVyKTtcclxuXHJcbi8vIEBwcm9wZXJ0eSB0b3VjaDogQm9vbGVhblxyXG4vLyBgdHJ1ZWAgZm9yIGFsbCBicm93c2VycyBzdXBwb3J0aW5nIFt0b3VjaCBldmVudHNdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9Ub3VjaF9ldmVudHMpLlxyXG4vLyBUaGlzIGRvZXMgbm90IG5lY2Vzc2FyaWx5IG1lYW4gdGhhdCB0aGUgYnJvd3NlciBpcyBydW5uaW5nIGluIGEgY29tcHV0ZXIgd2l0aFxyXG4vLyBhIHRvdWNoc2NyZWVuLCBpdCBvbmx5IG1lYW5zIHRoYXQgdGhlIGJyb3dzZXIgaXMgY2FwYWJsZSBvZiB1bmRlcnN0YW5kaW5nXHJcbi8vIHRvdWNoIGV2ZW50cy5cclxudmFyIHRvdWNoID0gIXdpbmRvdy5MX05PX1RPVUNIICYmIChwb2ludGVyIHx8ICdvbnRvdWNoc3RhcnQnIGluIHdpbmRvdyB8fFxyXG5cdFx0KHdpbmRvdy5Eb2N1bWVudFRvdWNoICYmIGRvY3VtZW50IGluc3RhbmNlb2Ygd2luZG93LkRvY3VtZW50VG91Y2gpKTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBtb2JpbGVPcGVyYTogQm9vbGVhbjsgYHRydWVgIGZvciB0aGUgT3BlcmEgYnJvd3NlciBpbiBhIG1vYmlsZSBkZXZpY2UuXHJcbnZhciBtb2JpbGVPcGVyYSA9IG1vYmlsZSAmJiBvcGVyYTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBtb2JpbGVHZWNrbzogQm9vbGVhblxyXG4vLyBgdHJ1ZWAgZm9yIGdlY2tvLWJhc2VkIGJyb3dzZXJzIHJ1bm5pbmcgaW4gYSBtb2JpbGUgZGV2aWNlLlxyXG52YXIgbW9iaWxlR2Vja28gPSBtb2JpbGUgJiYgZ2Vja287XHJcblxyXG4vLyBAcHJvcGVydHkgcmV0aW5hOiBCb29sZWFuXHJcbi8vIGB0cnVlYCBmb3IgYnJvd3NlcnMgb24gYSBoaWdoLXJlc29sdXRpb24gXCJyZXRpbmFcIiBzY3JlZW4uXHJcbnZhciByZXRpbmEgPSAod2luZG93LmRldmljZVBpeGVsUmF0aW8gfHwgKHdpbmRvdy5zY3JlZW4uZGV2aWNlWERQSSAvIHdpbmRvdy5zY3JlZW4ubG9naWNhbFhEUEkpKSA+IDE7XHJcblxyXG5cclxuLy8gQHByb3BlcnR5IGNhbnZhczogQm9vbGVhblxyXG4vLyBgdHJ1ZWAgd2hlbiB0aGUgYnJvd3NlciBzdXBwb3J0cyBbYDxjYW52YXM+YF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0NhbnZhc19BUEkpLlxyXG52YXIgY2FudmFzID0gKGZ1bmN0aW9uICgpIHtcclxuXHRyZXR1cm4gISFkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKS5nZXRDb250ZXh0O1xyXG59KCkpO1xyXG5cclxuLy8gQHByb3BlcnR5IHN2ZzogQm9vbGVhblxyXG4vLyBgdHJ1ZWAgd2hlbiB0aGUgYnJvd3NlciBzdXBwb3J0cyBbU1ZHXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcpLlxyXG52YXIgc3ZnID0gISEoZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TICYmIHN2Z0NyZWF0ZSgnc3ZnJykuY3JlYXRlU1ZHUmVjdCk7XHJcblxyXG4vLyBAcHJvcGVydHkgdm1sOiBCb29sZWFuXHJcbi8vIGB0cnVlYCBpZiB0aGUgYnJvd3NlciBzdXBwb3J0cyBbVk1MXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9WZWN0b3JfTWFya3VwX0xhbmd1YWdlKS5cclxudmFyIHZtbCA9ICFzdmcgJiYgKGZ1bmN0aW9uICgpIHtcclxuXHR0cnkge1xyXG5cdFx0dmFyIGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG5cdFx0ZGl2LmlubmVySFRNTCA9ICc8djpzaGFwZSBhZGo9XCIxXCIvPic7XHJcblxyXG5cdFx0dmFyIHNoYXBlID0gZGl2LmZpcnN0Q2hpbGQ7XHJcblx0XHRzaGFwZS5zdHlsZS5iZWhhdmlvciA9ICd1cmwoI2RlZmF1bHQjVk1MKSc7XHJcblxyXG5cdFx0cmV0dXJuIHNoYXBlICYmICh0eXBlb2Ygc2hhcGUuYWRqID09PSAnb2JqZWN0Jyk7XHJcblxyXG5cdH0gY2F0Y2ggKGUpIHtcclxuXHRcdHJldHVybiBmYWxzZTtcclxuXHR9XHJcbn0oKSk7XHJcblxyXG5cclxuZnVuY3Rpb24gdXNlckFnZW50Q29udGFpbnMoc3RyKSB7XHJcblx0cmV0dXJuIG5hdmlnYXRvci51c2VyQWdlbnQudG9Mb3dlckNhc2UoKS5pbmRleE9mKHN0cikgPj0gMDtcclxufVxyXG5cblxudmFyIEJyb3dzZXIgPSAoT2JqZWN0LmZyZWV6ZSB8fCBPYmplY3QpKHtcblx0aWU6IGllLFxuXHRpZWx0OTogaWVsdDksXG5cdGVkZ2U6IGVkZ2UsXG5cdHdlYmtpdDogd2Via2l0LFxuXHRhbmRyb2lkOiBhbmRyb2lkLFxuXHRhbmRyb2lkMjM6IGFuZHJvaWQyMyxcblx0YW5kcm9pZFN0b2NrOiBhbmRyb2lkU3RvY2ssXG5cdG9wZXJhOiBvcGVyYSxcblx0Y2hyb21lOiBjaHJvbWUsXG5cdGdlY2tvOiBnZWNrbyxcblx0c2FmYXJpOiBzYWZhcmksXG5cdHBoYW50b206IHBoYW50b20sXG5cdG9wZXJhMTI6IG9wZXJhMTIsXG5cdHdpbjogd2luLFxuXHRpZTNkOiBpZTNkLFxuXHR3ZWJraXQzZDogd2Via2l0M2QsXG5cdGdlY2tvM2Q6IGdlY2tvM2QsXG5cdGFueTNkOiBhbnkzZCxcblx0bW9iaWxlOiBtb2JpbGUsXG5cdG1vYmlsZVdlYmtpdDogbW9iaWxlV2Via2l0LFxuXHRtb2JpbGVXZWJraXQzZDogbW9iaWxlV2Via2l0M2QsXG5cdG1zUG9pbnRlcjogbXNQb2ludGVyLFxuXHRwb2ludGVyOiBwb2ludGVyLFxuXHR0b3VjaDogdG91Y2gsXG5cdG1vYmlsZU9wZXJhOiBtb2JpbGVPcGVyYSxcblx0bW9iaWxlR2Vja286IG1vYmlsZUdlY2tvLFxuXHRyZXRpbmE6IHJldGluYSxcblx0Y2FudmFzOiBjYW52YXMsXG5cdHN2Zzogc3ZnLFxuXHR2bWw6IHZtbFxufSk7XG5cbi8qXG4gKiBFeHRlbmRzIEwuRG9tRXZlbnQgdG8gcHJvdmlkZSB0b3VjaCBzdXBwb3J0IGZvciBJbnRlcm5ldCBFeHBsb3JlciBhbmQgV2luZG93cy1iYXNlZCBkZXZpY2VzLlxuICovXG5cblxudmFyIFBPSU5URVJfRE9XTiA9ICAgbXNQb2ludGVyID8gJ01TUG9pbnRlckRvd24nICAgOiAncG9pbnRlcmRvd24nO1xudmFyIFBPSU5URVJfTU9WRSA9ICAgbXNQb2ludGVyID8gJ01TUG9pbnRlck1vdmUnICAgOiAncG9pbnRlcm1vdmUnO1xudmFyIFBPSU5URVJfVVAgPSAgICAgbXNQb2ludGVyID8gJ01TUG9pbnRlclVwJyAgICAgOiAncG9pbnRlcnVwJztcbnZhciBQT0lOVEVSX0NBTkNFTCA9IG1zUG9pbnRlciA/ICdNU1BvaW50ZXJDYW5jZWwnIDogJ3BvaW50ZXJjYW5jZWwnO1xudmFyIFRBR19XSElURV9MSVNUID0gWydJTlBVVCcsICdTRUxFQ1QnLCAnT1BUSU9OJ107XG5cbnZhciBfcG9pbnRlcnMgPSB7fTtcbnZhciBfcG9pbnRlckRvY0xpc3RlbmVyID0gZmFsc2U7XG5cbi8vIERvbUV2ZW50LkRvdWJsZVRhcCBuZWVkcyB0byBrbm93IGFib3V0IHRoaXNcbnZhciBfcG9pbnRlcnNDb3VudCA9IDA7XG5cbi8vIFByb3ZpZGVzIGEgdG91Y2ggZXZlbnRzIHdyYXBwZXIgZm9yIChtcylwb2ludGVyIGV2ZW50cy5cbi8vIHJlZiBodHRwOi8vd3d3LnczLm9yZy9UUi9wb2ludGVyZXZlbnRzLyBodHRwczovL3d3dy53My5vcmcvQnVncy9QdWJsaWMvc2hvd19idWcuY2dpP2lkPTIyODkwXG5cbmZ1bmN0aW9uIGFkZFBvaW50ZXJMaXN0ZW5lcihvYmosIHR5cGUsIGhhbmRsZXIsIGlkKSB7XG5cdGlmICh0eXBlID09PSAndG91Y2hzdGFydCcpIHtcblx0XHRfYWRkUG9pbnRlclN0YXJ0KG9iaiwgaGFuZGxlciwgaWQpO1xuXG5cdH0gZWxzZSBpZiAodHlwZSA9PT0gJ3RvdWNobW92ZScpIHtcblx0XHRfYWRkUG9pbnRlck1vdmUob2JqLCBoYW5kbGVyLCBpZCk7XG5cblx0fSBlbHNlIGlmICh0eXBlID09PSAndG91Y2hlbmQnKSB7XG5cdFx0X2FkZFBvaW50ZXJFbmQob2JqLCBoYW5kbGVyLCBpZCk7XG5cdH1cblxuXHRyZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gcmVtb3ZlUG9pbnRlckxpc3RlbmVyKG9iaiwgdHlwZSwgaWQpIHtcblx0dmFyIGhhbmRsZXIgPSBvYmpbJ19sZWFmbGV0XycgKyB0eXBlICsgaWRdO1xuXG5cdGlmICh0eXBlID09PSAndG91Y2hzdGFydCcpIHtcblx0XHRvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcihQT0lOVEVSX0RPV04sIGhhbmRsZXIsIGZhbHNlKTtcblxuXHR9IGVsc2UgaWYgKHR5cGUgPT09ICd0b3VjaG1vdmUnKSB7XG5cdFx0b2JqLnJlbW92ZUV2ZW50TGlzdGVuZXIoUE9JTlRFUl9NT1ZFLCBoYW5kbGVyLCBmYWxzZSk7XG5cblx0fSBlbHNlIGlmICh0eXBlID09PSAndG91Y2hlbmQnKSB7XG5cdFx0b2JqLnJlbW92ZUV2ZW50TGlzdGVuZXIoUE9JTlRFUl9VUCwgaGFuZGxlciwgZmFsc2UpO1xuXHRcdG9iai5yZW1vdmVFdmVudExpc3RlbmVyKFBPSU5URVJfQ0FOQ0VMLCBoYW5kbGVyLCBmYWxzZSk7XG5cdH1cblxuXHRyZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gX2FkZFBvaW50ZXJTdGFydChvYmosIGhhbmRsZXIsIGlkKSB7XG5cdHZhciBvbkRvd24gPSBiaW5kKGZ1bmN0aW9uIChlKSB7XG5cdFx0aWYgKGUucG9pbnRlclR5cGUgIT09ICdtb3VzZScgJiYgZS5NU1BPSU5URVJfVFlQRV9NT1VTRSAmJiBlLnBvaW50ZXJUeXBlICE9PSBlLk1TUE9JTlRFUl9UWVBFX01PVVNFKSB7XG5cdFx0XHQvLyBJbiBJRTExLCBzb21lIHRvdWNoIGV2ZW50cyBuZWVkcyB0byBmaXJlIGZvciBmb3JtIGNvbnRyb2xzLCBvclxuXHRcdFx0Ly8gdGhlIGNvbnRyb2xzIHdpbGwgc3RvcCB3b3JraW5nLiBXZSBrZWVwIGEgd2hpdGVsaXN0IG9mIHRhZyBuYW1lcyB0aGF0XG5cdFx0XHQvLyBuZWVkIHRoZXNlIGV2ZW50cy4gRm9yIG90aGVyIHRhcmdldCB0YWdzLCB3ZSBwcmV2ZW50IGRlZmF1bHQgb24gdGhlIGV2ZW50LlxuXHRcdFx0aWYgKFRBR19XSElURV9MSVNULmluZGV4T2YoZS50YXJnZXQudGFnTmFtZSkgPCAwKSB7XG5cdFx0XHRcdHByZXZlbnREZWZhdWx0KGUpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdF9oYW5kbGVQb2ludGVyKGUsIGhhbmRsZXIpO1xuXHR9KTtcblxuXHRvYmpbJ19sZWFmbGV0X3RvdWNoc3RhcnQnICsgaWRdID0gb25Eb3duO1xuXHRvYmouYWRkRXZlbnRMaXN0ZW5lcihQT0lOVEVSX0RPV04sIG9uRG93biwgZmFsc2UpO1xuXG5cdC8vIG5lZWQgdG8ga2VlcCB0cmFjayBvZiB3aGF0IHBvaW50ZXJzIGFuZCBob3cgbWFueSBhcmUgYWN0aXZlIHRvIHByb3ZpZGUgZS50b3VjaGVzIGVtdWxhdGlvblxuXHRpZiAoIV9wb2ludGVyRG9jTGlzdGVuZXIpIHtcblx0XHQvLyB3ZSBsaXN0ZW4gZG9jdW1lbnRFbGVtZW50IGFzIGFueSBkcmFncyB0aGF0IGVuZCBieSBtb3ZpbmcgdGhlIHRvdWNoIG9mZiB0aGUgc2NyZWVuIGdldCBmaXJlZCB0aGVyZVxuXHRcdGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFBPSU5URVJfRE9XTiwgX2dsb2JhbFBvaW50ZXJEb3duLCB0cnVlKTtcblx0XHRkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihQT0lOVEVSX01PVkUsIF9nbG9iYWxQb2ludGVyTW92ZSwgdHJ1ZSk7XG5cdFx0ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoUE9JTlRFUl9VUCwgX2dsb2JhbFBvaW50ZXJVcCwgdHJ1ZSk7XG5cdFx0ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoUE9JTlRFUl9DQU5DRUwsIF9nbG9iYWxQb2ludGVyVXAsIHRydWUpO1xuXG5cdFx0X3BvaW50ZXJEb2NMaXN0ZW5lciA9IHRydWU7XG5cdH1cbn1cblxuZnVuY3Rpb24gX2dsb2JhbFBvaW50ZXJEb3duKGUpIHtcblx0X3BvaW50ZXJzW2UucG9pbnRlcklkXSA9IGU7XG5cdF9wb2ludGVyc0NvdW50Kys7XG59XG5cbmZ1bmN0aW9uIF9nbG9iYWxQb2ludGVyTW92ZShlKSB7XG5cdGlmIChfcG9pbnRlcnNbZS5wb2ludGVySWRdKSB7XG5cdFx0X3BvaW50ZXJzW2UucG9pbnRlcklkXSA9IGU7XG5cdH1cbn1cblxuZnVuY3Rpb24gX2dsb2JhbFBvaW50ZXJVcChlKSB7XG5cdGRlbGV0ZSBfcG9pbnRlcnNbZS5wb2ludGVySWRdO1xuXHRfcG9pbnRlcnNDb3VudC0tO1xufVxuXG5mdW5jdGlvbiBfaGFuZGxlUG9pbnRlcihlLCBoYW5kbGVyKSB7XG5cdGUudG91Y2hlcyA9IFtdO1xuXHRmb3IgKHZhciBpIGluIF9wb2ludGVycykge1xuXHRcdGUudG91Y2hlcy5wdXNoKF9wb2ludGVyc1tpXSk7XG5cdH1cblx0ZS5jaGFuZ2VkVG91Y2hlcyA9IFtlXTtcblxuXHRoYW5kbGVyKGUpO1xufVxuXG5mdW5jdGlvbiBfYWRkUG9pbnRlck1vdmUob2JqLCBoYW5kbGVyLCBpZCkge1xuXHR2YXIgb25Nb3ZlID0gZnVuY3Rpb24gKGUpIHtcblx0XHQvLyBkb24ndCBmaXJlIHRvdWNoIG1vdmVzIHdoZW4gbW91c2UgaXNuJ3QgZG93blxuXHRcdGlmICgoZS5wb2ludGVyVHlwZSA9PT0gZS5NU1BPSU5URVJfVFlQRV9NT1VTRSB8fCBlLnBvaW50ZXJUeXBlID09PSAnbW91c2UnKSAmJiBlLmJ1dHRvbnMgPT09IDApIHsgcmV0dXJuOyB9XG5cblx0XHRfaGFuZGxlUG9pbnRlcihlLCBoYW5kbGVyKTtcblx0fTtcblxuXHRvYmpbJ19sZWFmbGV0X3RvdWNobW92ZScgKyBpZF0gPSBvbk1vdmU7XG5cdG9iai5hZGRFdmVudExpc3RlbmVyKFBPSU5URVJfTU9WRSwgb25Nb3ZlLCBmYWxzZSk7XG59XG5cbmZ1bmN0aW9uIF9hZGRQb2ludGVyRW5kKG9iaiwgaGFuZGxlciwgaWQpIHtcblx0dmFyIG9uVXAgPSBmdW5jdGlvbiAoZSkge1xuXHRcdF9oYW5kbGVQb2ludGVyKGUsIGhhbmRsZXIpO1xuXHR9O1xuXG5cdG9ialsnX2xlYWZsZXRfdG91Y2hlbmQnICsgaWRdID0gb25VcDtcblx0b2JqLmFkZEV2ZW50TGlzdGVuZXIoUE9JTlRFUl9VUCwgb25VcCwgZmFsc2UpO1xuXHRvYmouYWRkRXZlbnRMaXN0ZW5lcihQT0lOVEVSX0NBTkNFTCwgb25VcCwgZmFsc2UpO1xufVxuXG4vKlxyXG4gKiBFeHRlbmRzIHRoZSBldmVudCBoYW5kbGluZyBjb2RlIHdpdGggZG91YmxlIHRhcCBzdXBwb3J0IGZvciBtb2JpbGUgYnJvd3NlcnMuXHJcbiAqL1xyXG5cclxudmFyIF90b3VjaHN0YXJ0ID0gbXNQb2ludGVyID8gJ01TUG9pbnRlckRvd24nIDogcG9pbnRlciA/ICdwb2ludGVyZG93bicgOiAndG91Y2hzdGFydCc7XHJcbnZhciBfdG91Y2hlbmQgPSBtc1BvaW50ZXIgPyAnTVNQb2ludGVyVXAnIDogcG9pbnRlciA/ICdwb2ludGVydXAnIDogJ3RvdWNoZW5kJztcclxudmFyIF9wcmUgPSAnX2xlYWZsZXRfJztcclxuXHJcbi8vIGluc3BpcmVkIGJ5IFplcHRvIHRvdWNoIGNvZGUgYnkgVGhvbWFzIEZ1Y2hzXHJcbmZ1bmN0aW9uIGFkZERvdWJsZVRhcExpc3RlbmVyKG9iaiwgaGFuZGxlciwgaWQpIHtcclxuXHR2YXIgbGFzdCwgdG91Y2gkJDEsXHJcblx0ICAgIGRvdWJsZVRhcCA9IGZhbHNlLFxyXG5cdCAgICBkZWxheSA9IDI1MDtcclxuXHJcblx0ZnVuY3Rpb24gb25Ub3VjaFN0YXJ0KGUpIHtcclxuXHRcdHZhciBjb3VudDtcclxuXHJcblx0XHRpZiAocG9pbnRlcikge1xyXG5cdFx0XHRpZiAoKCFlZGdlKSB8fCBlLnBvaW50ZXJUeXBlID09PSAnbW91c2UnKSB7IHJldHVybjsgfVxyXG5cdFx0XHRjb3VudCA9IF9wb2ludGVyc0NvdW50O1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0Y291bnQgPSBlLnRvdWNoZXMubGVuZ3RoO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChjb3VudCA+IDEpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0dmFyIG5vdyA9IERhdGUubm93KCksXHJcblx0XHQgICAgZGVsdGEgPSBub3cgLSAobGFzdCB8fCBub3cpO1xyXG5cclxuXHRcdHRvdWNoJCQxID0gZS50b3VjaGVzID8gZS50b3VjaGVzWzBdIDogZTtcclxuXHRcdGRvdWJsZVRhcCA9IChkZWx0YSA+IDAgJiYgZGVsdGEgPD0gZGVsYXkpO1xyXG5cdFx0bGFzdCA9IG5vdztcclxuXHR9XHJcblxyXG5cdGZ1bmN0aW9uIG9uVG91Y2hFbmQoZSkge1xyXG5cdFx0aWYgKGRvdWJsZVRhcCAmJiAhdG91Y2gkJDEuY2FuY2VsQnViYmxlKSB7XHJcblx0XHRcdGlmIChwb2ludGVyKSB7XHJcblx0XHRcdFx0aWYgKCghZWRnZSkgfHwgZS5wb2ludGVyVHlwZSA9PT0gJ21vdXNlJykgeyByZXR1cm47IH1cclxuXHRcdFx0XHQvLyB3b3JrIGFyb3VuZCAudHlwZSBiZWluZyByZWFkb25seSB3aXRoIE1TUG9pbnRlciogZXZlbnRzXHJcblx0XHRcdFx0dmFyIG5ld1RvdWNoID0ge30sXHJcblx0XHRcdFx0ICAgIHByb3AsIGk7XHJcblxyXG5cdFx0XHRcdGZvciAoaSBpbiB0b3VjaCQkMSkge1xyXG5cdFx0XHRcdFx0cHJvcCA9IHRvdWNoJCQxW2ldO1xyXG5cdFx0XHRcdFx0bmV3VG91Y2hbaV0gPSBwcm9wICYmIHByb3AuYmluZCA/IHByb3AuYmluZCh0b3VjaCQkMSkgOiBwcm9wO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHR0b3VjaCQkMSA9IG5ld1RvdWNoO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRvdWNoJCQxLnR5cGUgPSAnZGJsY2xpY2snO1xyXG5cdFx0XHRoYW5kbGVyKHRvdWNoJCQxKTtcclxuXHRcdFx0bGFzdCA9IG51bGw7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRvYmpbX3ByZSArIF90b3VjaHN0YXJ0ICsgaWRdID0gb25Ub3VjaFN0YXJ0O1xyXG5cdG9ialtfcHJlICsgX3RvdWNoZW5kICsgaWRdID0gb25Ub3VjaEVuZDtcclxuXHRvYmpbX3ByZSArICdkYmxjbGljaycgKyBpZF0gPSBoYW5kbGVyO1xyXG5cclxuXHRvYmouYWRkRXZlbnRMaXN0ZW5lcihfdG91Y2hzdGFydCwgb25Ub3VjaFN0YXJ0LCBmYWxzZSk7XHJcblx0b2JqLmFkZEV2ZW50TGlzdGVuZXIoX3RvdWNoZW5kLCBvblRvdWNoRW5kLCBmYWxzZSk7XHJcblxyXG5cdC8vIE9uIHNvbWUgcGxhdGZvcm1zIChub3RhYmx5LCBjaHJvbWU8NTUgb24gd2luMTAgKyB0b3VjaHNjcmVlbiArIG1vdXNlKSxcclxuXHQvLyB0aGUgYnJvd3NlciBkb2Vzbid0IGZpcmUgdG91Y2hlbmQvcG9pbnRlcnVwIGV2ZW50cyBidXQgZG9lcyBmaXJlXHJcblx0Ly8gbmF0aXZlIGRibGNsaWNrcy4gU2VlICM0MTI3LlxyXG5cdC8vIEVkZ2UgMTQgYWxzbyBmaXJlcyBuYXRpdmUgZGJsY2xpY2tzLCBidXQgb25seSBmb3IgcG9pbnRlclR5cGUgbW91c2UsIHNlZSAjNTE4MC5cclxuXHRvYmouYWRkRXZlbnRMaXN0ZW5lcignZGJsY2xpY2snLCBoYW5kbGVyLCBmYWxzZSk7XHJcblxyXG5cdHJldHVybiB0aGlzO1xyXG59XHJcblxyXG5mdW5jdGlvbiByZW1vdmVEb3VibGVUYXBMaXN0ZW5lcihvYmosIGlkKSB7XHJcblx0dmFyIHRvdWNoc3RhcnQgPSBvYmpbX3ByZSArIF90b3VjaHN0YXJ0ICsgaWRdLFxyXG5cdCAgICB0b3VjaGVuZCA9IG9ialtfcHJlICsgX3RvdWNoZW5kICsgaWRdLFxyXG5cdCAgICBkYmxjbGljayA9IG9ialtfcHJlICsgJ2RibGNsaWNrJyArIGlkXTtcclxuXHJcblx0b2JqLnJlbW92ZUV2ZW50TGlzdGVuZXIoX3RvdWNoc3RhcnQsIHRvdWNoc3RhcnQsIGZhbHNlKTtcclxuXHRvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcihfdG91Y2hlbmQsIHRvdWNoZW5kLCBmYWxzZSk7XHJcblx0aWYgKCFlZGdlKSB7XHJcblx0XHRvYmoucmVtb3ZlRXZlbnRMaXN0ZW5lcignZGJsY2xpY2snLCBkYmxjbGljaywgZmFsc2UpO1xyXG5cdH1cclxuXHJcblx0cmV0dXJuIHRoaXM7XHJcbn1cblxuLypcclxuICogQG5hbWVzcGFjZSBEb21FdmVudFxyXG4gKiBVdGlsaXR5IGZ1bmN0aW9ucyB0byB3b3JrIHdpdGggdGhlIFtET00gZXZlbnRzXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvRXZlbnQpLCB1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseS5cclxuICovXHJcblxyXG4vLyBJbnNwaXJlZCBieSBKb2huIFJlc2lnLCBEZWFuIEVkd2FyZHMgYW5kIFlVSSBhZGRFdmVudCBpbXBsZW1lbnRhdGlvbnMuXHJcblxyXG4vLyBAZnVuY3Rpb24gb24oZWw6IEhUTUxFbGVtZW50LCB0eXBlczogU3RyaW5nLCBmbjogRnVuY3Rpb24sIGNvbnRleHQ/OiBPYmplY3QpOiB0aGlzXHJcbi8vIEFkZHMgYSBsaXN0ZW5lciBmdW5jdGlvbiAoYGZuYCkgdG8gYSBwYXJ0aWN1bGFyIERPTSBldmVudCB0eXBlIG9mIHRoZVxyXG4vLyBlbGVtZW50IGBlbGAuIFlvdSBjYW4gb3B0aW9uYWxseSBzcGVjaWZ5IHRoZSBjb250ZXh0IG9mIHRoZSBsaXN0ZW5lclxyXG4vLyAob2JqZWN0IHRoZSBgdGhpc2Aga2V5d29yZCB3aWxsIHBvaW50IHRvKS4gWW91IGNhbiBhbHNvIHBhc3Mgc2V2ZXJhbFxyXG4vLyBzcGFjZS1zZXBhcmF0ZWQgdHlwZXMgKGUuZy4gYCdjbGljayBkYmxjbGljaydgKS5cclxuXHJcbi8vIEBhbHRlcm5hdGl2ZVxyXG4vLyBAZnVuY3Rpb24gb24oZWw6IEhUTUxFbGVtZW50LCBldmVudE1hcDogT2JqZWN0LCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG4vLyBBZGRzIGEgc2V0IG9mIHR5cGUvbGlzdGVuZXIgcGFpcnMsIGUuZy4gYHtjbGljazogb25DbGljaywgbW91c2Vtb3ZlOiBvbk1vdXNlTW92ZX1gXHJcbmZ1bmN0aW9uIG9uKG9iaiwgdHlwZXMsIGZuLCBjb250ZXh0KSB7XHJcblxyXG5cdGlmICh0eXBlb2YgdHlwZXMgPT09ICdvYmplY3QnKSB7XHJcblx0XHRmb3IgKHZhciB0eXBlIGluIHR5cGVzKSB7XHJcblx0XHRcdGFkZE9uZShvYmosIHR5cGUsIHR5cGVzW3R5cGVdLCBmbik7XHJcblx0XHR9XHJcblx0fSBlbHNlIHtcclxuXHRcdHR5cGVzID0gc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHR5cGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdGFkZE9uZShvYmosIHR5cGVzW2ldLCBmbiwgY29udGV4dCk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gdGhpcztcclxufVxyXG5cclxudmFyIGV2ZW50c0tleSA9ICdfbGVhZmxldF9ldmVudHMnO1xyXG5cclxuLy8gQGZ1bmN0aW9uIG9mZihlbDogSFRNTEVsZW1lbnQsIHR5cGVzOiBTdHJpbmcsIGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcclxuLy8gUmVtb3ZlcyBhIHByZXZpb3VzbHkgYWRkZWQgbGlzdGVuZXIgZnVuY3Rpb24uXHJcbi8vIE5vdGUgdGhhdCBpZiB5b3UgcGFzc2VkIGEgY3VzdG9tIGNvbnRleHQgdG8gb24sIHlvdSBtdXN0IHBhc3MgdGhlIHNhbWVcclxuLy8gY29udGV4dCB0byBgb2ZmYCBpbiBvcmRlciB0byByZW1vdmUgdGhlIGxpc3RlbmVyLlxyXG5cclxuLy8gQGFsdGVybmF0aXZlXHJcbi8vIEBmdW5jdGlvbiBvZmYoZWw6IEhUTUxFbGVtZW50LCBldmVudE1hcDogT2JqZWN0LCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG4vLyBSZW1vdmVzIGEgc2V0IG9mIHR5cGUvbGlzdGVuZXIgcGFpcnMsIGUuZy4gYHtjbGljazogb25DbGljaywgbW91c2Vtb3ZlOiBvbk1vdXNlTW92ZX1gXHJcbmZ1bmN0aW9uIG9mZihvYmosIHR5cGVzLCBmbiwgY29udGV4dCkge1xyXG5cclxuXHRpZiAodHlwZW9mIHR5cGVzID09PSAnb2JqZWN0Jykge1xyXG5cdFx0Zm9yICh2YXIgdHlwZSBpbiB0eXBlcykge1xyXG5cdFx0XHRyZW1vdmVPbmUob2JqLCB0eXBlLCB0eXBlc1t0eXBlXSwgZm4pO1xyXG5cdFx0fVxyXG5cdH0gZWxzZSBpZiAodHlwZXMpIHtcclxuXHRcdHR5cGVzID0gc3BsaXRXb3Jkcyh0eXBlcyk7XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IHR5cGVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdHJlbW92ZU9uZShvYmosIHR5cGVzW2ldLCBmbiwgY29udGV4dCk7XHJcblx0XHR9XHJcblx0fSBlbHNlIHtcclxuXHRcdGZvciAodmFyIGogaW4gb2JqW2V2ZW50c0tleV0pIHtcclxuXHRcdFx0cmVtb3ZlT25lKG9iaiwgaiwgb2JqW2V2ZW50c0tleV1bal0pO1xyXG5cdFx0fVxyXG5cdFx0ZGVsZXRlIG9ialtldmVudHNLZXldO1xyXG5cdH1cclxuXHJcblx0cmV0dXJuIHRoaXM7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGFkZE9uZShvYmosIHR5cGUsIGZuLCBjb250ZXh0KSB7XHJcblx0dmFyIGlkID0gdHlwZSArIHN0YW1wKGZuKSArIChjb250ZXh0ID8gJ18nICsgc3RhbXAoY29udGV4dCkgOiAnJyk7XHJcblxyXG5cdGlmIChvYmpbZXZlbnRzS2V5XSAmJiBvYmpbZXZlbnRzS2V5XVtpZF0pIHsgcmV0dXJuIHRoaXM7IH1cclxuXHJcblx0dmFyIGhhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xyXG5cdFx0cmV0dXJuIGZuLmNhbGwoY29udGV4dCB8fCBvYmosIGUgfHwgd2luZG93LmV2ZW50KTtcclxuXHR9O1xyXG5cclxuXHR2YXIgb3JpZ2luYWxIYW5kbGVyID0gaGFuZGxlcjtcclxuXHJcblx0aWYgKHBvaW50ZXIgJiYgdHlwZS5pbmRleE9mKCd0b3VjaCcpID09PSAwKSB7XHJcblx0XHQvLyBOZWVkcyBEb21FdmVudC5Qb2ludGVyLmpzXHJcblx0XHRhZGRQb2ludGVyTGlzdGVuZXIob2JqLCB0eXBlLCBoYW5kbGVyLCBpZCk7XHJcblxyXG5cdH0gZWxzZSBpZiAodG91Y2ggJiYgKHR5cGUgPT09ICdkYmxjbGljaycpICYmIGFkZERvdWJsZVRhcExpc3RlbmVyICYmXHJcblx0ICAgICAgICAgICAhKHBvaW50ZXIgJiYgY2hyb21lKSkge1xyXG5cdFx0Ly8gQ2hyb21lID41NSBkb2VzIG5vdCBuZWVkIHRoZSBzeW50aGV0aWMgZGJsY2xpY2tzIGZyb20gYWRkRG91YmxlVGFwTGlzdGVuZXJcclxuXHRcdC8vIFNlZSAjNTE4MFxyXG5cdFx0YWRkRG91YmxlVGFwTGlzdGVuZXIob2JqLCBoYW5kbGVyLCBpZCk7XHJcblxyXG5cdH0gZWxzZSBpZiAoJ2FkZEV2ZW50TGlzdGVuZXInIGluIG9iaikge1xyXG5cclxuXHRcdGlmICh0eXBlID09PSAnbW91c2V3aGVlbCcpIHtcclxuXHRcdFx0b2JqLmFkZEV2ZW50TGlzdGVuZXIoJ29ud2hlZWwnIGluIG9iaiA/ICd3aGVlbCcgOiAnbW91c2V3aGVlbCcsIGhhbmRsZXIsIGZhbHNlKTtcclxuXHJcblx0XHR9IGVsc2UgaWYgKCh0eXBlID09PSAnbW91c2VlbnRlcicpIHx8ICh0eXBlID09PSAnbW91c2VsZWF2ZScpKSB7XHJcblx0XHRcdGhhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHRcdGUgPSBlIHx8IHdpbmRvdy5ldmVudDtcclxuXHRcdFx0XHRpZiAoaXNFeHRlcm5hbFRhcmdldChvYmosIGUpKSB7XHJcblx0XHRcdFx0XHRvcmlnaW5hbEhhbmRsZXIoZSk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9O1xyXG5cdFx0XHRvYmouYWRkRXZlbnRMaXN0ZW5lcih0eXBlID09PSAnbW91c2VlbnRlcicgPyAnbW91c2VvdmVyJyA6ICdtb3VzZW91dCcsIGhhbmRsZXIsIGZhbHNlKTtcclxuXHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRpZiAodHlwZSA9PT0gJ2NsaWNrJyAmJiBhbmRyb2lkKSB7XHJcblx0XHRcdFx0aGFuZGxlciA9IGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdFx0XHRmaWx0ZXJDbGljayhlLCBvcmlnaW5hbEhhbmRsZXIpO1xyXG5cdFx0XHRcdH07XHJcblx0XHRcdH1cclxuXHRcdFx0b2JqLmFkZEV2ZW50TGlzdGVuZXIodHlwZSwgaGFuZGxlciwgZmFsc2UpO1xyXG5cdFx0fVxyXG5cclxuXHR9IGVsc2UgaWYgKCdhdHRhY2hFdmVudCcgaW4gb2JqKSB7XHJcblx0XHRvYmouYXR0YWNoRXZlbnQoJ29uJyArIHR5cGUsIGhhbmRsZXIpO1xyXG5cdH1cclxuXHJcblx0b2JqW2V2ZW50c0tleV0gPSBvYmpbZXZlbnRzS2V5XSB8fCB7fTtcclxuXHRvYmpbZXZlbnRzS2V5XVtpZF0gPSBoYW5kbGVyO1xyXG59XHJcblxyXG5mdW5jdGlvbiByZW1vdmVPbmUob2JqLCB0eXBlLCBmbiwgY29udGV4dCkge1xyXG5cclxuXHR2YXIgaWQgPSB0eXBlICsgc3RhbXAoZm4pICsgKGNvbnRleHQgPyAnXycgKyBzdGFtcChjb250ZXh0KSA6ICcnKSxcclxuXHQgICAgaGFuZGxlciA9IG9ialtldmVudHNLZXldICYmIG9ialtldmVudHNLZXldW2lkXTtcclxuXHJcblx0aWYgKCFoYW5kbGVyKSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG5cdGlmIChwb2ludGVyICYmIHR5cGUuaW5kZXhPZigndG91Y2gnKSA9PT0gMCkge1xyXG5cdFx0cmVtb3ZlUG9pbnRlckxpc3RlbmVyKG9iaiwgdHlwZSwgaWQpO1xyXG5cclxuXHR9IGVsc2UgaWYgKHRvdWNoICYmICh0eXBlID09PSAnZGJsY2xpY2snKSAmJiByZW1vdmVEb3VibGVUYXBMaXN0ZW5lciAmJlxyXG5cdCAgICAgICAgICAgIShwb2ludGVyICYmIGNocm9tZSkpIHtcclxuXHRcdHJlbW92ZURvdWJsZVRhcExpc3RlbmVyKG9iaiwgaWQpO1xyXG5cclxuXHR9IGVsc2UgaWYgKCdyZW1vdmVFdmVudExpc3RlbmVyJyBpbiBvYmopIHtcclxuXHJcblx0XHRpZiAodHlwZSA9PT0gJ21vdXNld2hlZWwnKSB7XHJcblx0XHRcdG9iai5yZW1vdmVFdmVudExpc3RlbmVyKCdvbndoZWVsJyBpbiBvYmogPyAnd2hlZWwnIDogJ21vdXNld2hlZWwnLCBoYW5kbGVyLCBmYWxzZSk7XHJcblxyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0b2JqLnJlbW92ZUV2ZW50TGlzdGVuZXIoXHJcblx0XHRcdFx0dHlwZSA9PT0gJ21vdXNlZW50ZXInID8gJ21vdXNlb3ZlcicgOlxyXG5cdFx0XHRcdHR5cGUgPT09ICdtb3VzZWxlYXZlJyA/ICdtb3VzZW91dCcgOiB0eXBlLCBoYW5kbGVyLCBmYWxzZSk7XHJcblx0XHR9XHJcblxyXG5cdH0gZWxzZSBpZiAoJ2RldGFjaEV2ZW50JyBpbiBvYmopIHtcclxuXHRcdG9iai5kZXRhY2hFdmVudCgnb24nICsgdHlwZSwgaGFuZGxlcik7XHJcblx0fVxyXG5cclxuXHRvYmpbZXZlbnRzS2V5XVtpZF0gPSBudWxsO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gc3RvcFByb3BhZ2F0aW9uKGV2OiBET01FdmVudCk6IHRoaXNcclxuLy8gU3RvcCB0aGUgZ2l2ZW4gZXZlbnQgZnJvbSBwcm9wYWdhdGlvbiB0byBwYXJlbnQgZWxlbWVudHMuIFVzZWQgaW5zaWRlIHRoZSBsaXN0ZW5lciBmdW5jdGlvbnM6XHJcbi8vIGBgYGpzXHJcbi8vIEwuRG9tRXZlbnQub24oZGl2LCAnY2xpY2snLCBmdW5jdGlvbiAoZXYpIHtcclxuLy8gXHRMLkRvbUV2ZW50LnN0b3BQcm9wYWdhdGlvbihldik7XHJcbi8vIH0pO1xyXG4vLyBgYGBcclxuZnVuY3Rpb24gc3RvcFByb3BhZ2F0aW9uKGUpIHtcclxuXHJcblx0aWYgKGUuc3RvcFByb3BhZ2F0aW9uKSB7XHJcblx0XHRlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cdH0gZWxzZSBpZiAoZS5vcmlnaW5hbEV2ZW50KSB7ICAvLyBJbiBjYXNlIG9mIExlYWZsZXQgZXZlbnQuXHJcblx0XHRlLm9yaWdpbmFsRXZlbnQuX3N0b3BwZWQgPSB0cnVlO1xyXG5cdH0gZWxzZSB7XHJcblx0XHRlLmNhbmNlbEJ1YmJsZSA9IHRydWU7XHJcblx0fVxyXG5cdHNraXBwZWQoZSk7XHJcblxyXG5cdHJldHVybiB0aGlzO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gZGlzYWJsZVNjcm9sbFByb3BhZ2F0aW9uKGVsOiBIVE1MRWxlbWVudCk6IHRoaXNcclxuLy8gQWRkcyBgc3RvcFByb3BhZ2F0aW9uYCB0byB0aGUgZWxlbWVudCdzIGAnbW91c2V3aGVlbCdgIGV2ZW50cyAocGx1cyBicm93c2VyIHZhcmlhbnRzKS5cclxuZnVuY3Rpb24gZGlzYWJsZVNjcm9sbFByb3BhZ2F0aW9uKGVsKSB7XHJcblx0YWRkT25lKGVsLCAnbW91c2V3aGVlbCcsIHN0b3BQcm9wYWdhdGlvbik7XHJcblx0cmV0dXJuIHRoaXM7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbihlbDogSFRNTEVsZW1lbnQpOiB0aGlzXHJcbi8vIEFkZHMgYHN0b3BQcm9wYWdhdGlvbmAgdG8gdGhlIGVsZW1lbnQncyBgJ2NsaWNrJ2AsIGAnZG91YmxlY2xpY2snYCxcclxuLy8gYCdtb3VzZWRvd24nYCBhbmQgYCd0b3VjaHN0YXJ0J2AgZXZlbnRzIChwbHVzIGJyb3dzZXIgdmFyaWFudHMpLlxyXG5mdW5jdGlvbiBkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbihlbCkge1xyXG5cdG9uKGVsLCAnbW91c2Vkb3duIHRvdWNoc3RhcnQgZGJsY2xpY2snLCBzdG9wUHJvcGFnYXRpb24pO1xyXG5cdGFkZE9uZShlbCwgJ2NsaWNrJywgZmFrZVN0b3ApO1xyXG5cdHJldHVybiB0aGlzO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gcHJldmVudERlZmF1bHQoZXY6IERPTUV2ZW50KTogdGhpc1xyXG4vLyBQcmV2ZW50cyB0aGUgZGVmYXVsdCBhY3Rpb24gb2YgdGhlIERPTSBFdmVudCBgZXZgIGZyb20gaGFwcGVuaW5nIChzdWNoIGFzXHJcbi8vIGZvbGxvd2luZyBhIGxpbmsgaW4gdGhlIGhyZWYgb2YgdGhlIGEgZWxlbWVudCwgb3IgZG9pbmcgYSBQT1NUIHJlcXVlc3RcclxuLy8gd2l0aCBwYWdlIHJlbG9hZCB3aGVuIGEgYDxmb3JtPmAgaXMgc3VibWl0dGVkKS5cclxuLy8gVXNlIGl0IGluc2lkZSBsaXN0ZW5lciBmdW5jdGlvbnMuXHJcbmZ1bmN0aW9uIHByZXZlbnREZWZhdWx0KGUpIHtcclxuXHRpZiAoZS5wcmV2ZW50RGVmYXVsdCkge1xyXG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdH0gZWxzZSB7XHJcblx0XHRlLnJldHVyblZhbHVlID0gZmFsc2U7XHJcblx0fVxyXG5cdHJldHVybiB0aGlzO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gc3RvcChldjogRE9NRXZlbnQpOiB0aGlzXHJcbi8vIERvZXMgYHN0b3BQcm9wYWdhdGlvbmAgYW5kIGBwcmV2ZW50RGVmYXVsdGAgYXQgdGhlIHNhbWUgdGltZS5cclxuZnVuY3Rpb24gc3RvcChlKSB7XHJcblx0cHJldmVudERlZmF1bHQoZSk7XHJcblx0c3RvcFByb3BhZ2F0aW9uKGUpO1xyXG5cdHJldHVybiB0aGlzO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gZ2V0TW91c2VQb3NpdGlvbihldjogRE9NRXZlbnQsIGNvbnRhaW5lcj86IEhUTUxFbGVtZW50KTogUG9pbnRcclxuLy8gR2V0cyBub3JtYWxpemVkIG1vdXNlIHBvc2l0aW9uIGZyb20gYSBET00gZXZlbnQgcmVsYXRpdmUgdG8gdGhlXHJcbi8vIGBjb250YWluZXJgIG9yIHRvIHRoZSB3aG9sZSBwYWdlIGlmIG5vdCBzcGVjaWZpZWQuXHJcbmZ1bmN0aW9uIGdldE1vdXNlUG9zaXRpb24oZSwgY29udGFpbmVyKSB7XHJcblx0aWYgKCFjb250YWluZXIpIHtcclxuXHRcdHJldHVybiBuZXcgUG9pbnQoZS5jbGllbnRYLCBlLmNsaWVudFkpO1xyXG5cdH1cclxuXHJcblx0dmFyIHJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XHJcblxyXG5cdHZhciBzY2FsZVggPSByZWN0LndpZHRoIC8gY29udGFpbmVyLm9mZnNldFdpZHRoIHx8IDE7XHJcblx0dmFyIHNjYWxlWSA9IHJlY3QuaGVpZ2h0IC8gY29udGFpbmVyLm9mZnNldEhlaWdodCB8fCAxO1xyXG5cdHJldHVybiBuZXcgUG9pbnQoXHJcblx0XHRlLmNsaWVudFggLyBzY2FsZVggLSByZWN0LmxlZnQgLSBjb250YWluZXIuY2xpZW50TGVmdCxcclxuXHRcdGUuY2xpZW50WSAvIHNjYWxlWSAtIHJlY3QudG9wIC0gY29udGFpbmVyLmNsaWVudFRvcCk7XHJcbn1cclxuXHJcbi8vIENocm9tZSBvbiBXaW4gc2Nyb2xscyBkb3VibGUgdGhlIHBpeGVscyBhcyBpbiBvdGhlciBwbGF0Zm9ybXMgKHNlZSAjNDUzOCksXHJcbi8vIGFuZCBGaXJlZm94IHNjcm9sbHMgZGV2aWNlIHBpeGVscywgbm90IENTUyBwaXhlbHNcclxudmFyIHdoZWVsUHhGYWN0b3IgPVxyXG5cdCh3aW4gJiYgY2hyb21lKSA/IDIgKiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyA6XHJcblx0Z2Vja28gPyB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyA6IDE7XHJcblxyXG4vLyBAZnVuY3Rpb24gZ2V0V2hlZWxEZWx0YShldjogRE9NRXZlbnQpOiBOdW1iZXJcclxuLy8gR2V0cyBub3JtYWxpemVkIHdoZWVsIGRlbHRhIGZyb20gYSBtb3VzZXdoZWVsIERPTSBldmVudCwgaW4gdmVydGljYWxcclxuLy8gcGl4ZWxzIHNjcm9sbGVkIChuZWdhdGl2ZSBpZiBzY3JvbGxpbmcgZG93bikuXHJcbi8vIEV2ZW50cyBmcm9tIHBvaW50aW5nIGRldmljZXMgd2l0aG91dCBwcmVjaXNlIHNjcm9sbGluZyBhcmUgbWFwcGVkIHRvXHJcbi8vIGEgYmVzdCBndWVzcyBvZiA2MCBwaXhlbHMuXHJcbmZ1bmN0aW9uIGdldFdoZWVsRGVsdGEoZSkge1xyXG5cdHJldHVybiAoZWRnZSkgPyBlLndoZWVsRGVsdGFZIC8gMiA6IC8vIERvbid0IHRydXN0IHdpbmRvdy1nZW9tZXRyeS1iYXNlZCBkZWx0YVxyXG5cdCAgICAgICAoZS5kZWx0YVkgJiYgZS5kZWx0YU1vZGUgPT09IDApID8gLWUuZGVsdGFZIC8gd2hlZWxQeEZhY3RvciA6IC8vIFBpeGVsc1xyXG5cdCAgICAgICAoZS5kZWx0YVkgJiYgZS5kZWx0YU1vZGUgPT09IDEpID8gLWUuZGVsdGFZICogMjAgOiAvLyBMaW5lc1xyXG5cdCAgICAgICAoZS5kZWx0YVkgJiYgZS5kZWx0YU1vZGUgPT09IDIpID8gLWUuZGVsdGFZICogNjAgOiAvLyBQYWdlc1xyXG5cdCAgICAgICAoZS5kZWx0YVggfHwgZS5kZWx0YVopID8gMCA6XHQvLyBTa2lwIGhvcml6b250YWwvZGVwdGggd2hlZWwgZXZlbnRzXHJcblx0ICAgICAgIGUud2hlZWxEZWx0YSA/IChlLndoZWVsRGVsdGFZIHx8IGUud2hlZWxEZWx0YSkgLyAyIDogLy8gTGVnYWN5IElFIHBpeGVsc1xyXG5cdCAgICAgICAoZS5kZXRhaWwgJiYgTWF0aC5hYnMoZS5kZXRhaWwpIDwgMzI3NjUpID8gLWUuZGV0YWlsICogMjAgOiAvLyBMZWdhY3kgTW96IGxpbmVzXHJcblx0ICAgICAgIGUuZGV0YWlsID8gZS5kZXRhaWwgLyAtMzI3NjUgKiA2MCA6IC8vIExlZ2FjeSBNb3ogcGFnZXNcclxuXHQgICAgICAgMDtcclxufVxyXG5cclxudmFyIHNraXBFdmVudHMgPSB7fTtcclxuXHJcbmZ1bmN0aW9uIGZha2VTdG9wKGUpIHtcclxuXHQvLyBmYWtlcyBzdG9wUHJvcGFnYXRpb24gYnkgc2V0dGluZyBhIHNwZWNpYWwgZXZlbnQgZmxhZywgY2hlY2tlZC9yZXNldCB3aXRoIHNraXBwZWQoZSlcclxuXHRza2lwRXZlbnRzW2UudHlwZV0gPSB0cnVlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBza2lwcGVkKGUpIHtcclxuXHR2YXIgZXZlbnRzID0gc2tpcEV2ZW50c1tlLnR5cGVdO1xyXG5cdC8vIHJlc2V0IHdoZW4gY2hlY2tpbmcsIGFzIGl0J3Mgb25seSB1c2VkIGluIG1hcCBjb250YWluZXIgYW5kIHByb3BhZ2F0ZXMgb3V0c2lkZSBvZiB0aGUgbWFwXHJcblx0c2tpcEV2ZW50c1tlLnR5cGVdID0gZmFsc2U7XHJcblx0cmV0dXJuIGV2ZW50cztcclxufVxyXG5cclxuLy8gY2hlY2sgaWYgZWxlbWVudCByZWFsbHkgbGVmdC9lbnRlcmVkIHRoZSBldmVudCB0YXJnZXQgKGZvciBtb3VzZWVudGVyL21vdXNlbGVhdmUpXHJcbmZ1bmN0aW9uIGlzRXh0ZXJuYWxUYXJnZXQoZWwsIGUpIHtcclxuXHJcblx0dmFyIHJlbGF0ZWQgPSBlLnJlbGF0ZWRUYXJnZXQ7XHJcblxyXG5cdGlmICghcmVsYXRlZCkgeyByZXR1cm4gdHJ1ZTsgfVxyXG5cclxuXHR0cnkge1xyXG5cdFx0d2hpbGUgKHJlbGF0ZWQgJiYgKHJlbGF0ZWQgIT09IGVsKSkge1xyXG5cdFx0XHRyZWxhdGVkID0gcmVsYXRlZC5wYXJlbnROb2RlO1xyXG5cdFx0fVxyXG5cdH0gY2F0Y2ggKGVycikge1xyXG5cdFx0cmV0dXJuIGZhbHNlO1xyXG5cdH1cclxuXHRyZXR1cm4gKHJlbGF0ZWQgIT09IGVsKTtcclxufVxyXG5cclxudmFyIGxhc3RDbGljaztcclxuXHJcbi8vIHRoaXMgaXMgYSBob3JyaWJsZSB3b3JrYXJvdW5kIGZvciBhIGJ1ZyBpbiBBbmRyb2lkIHdoZXJlIGEgc2luZ2xlIHRvdWNoIHRyaWdnZXJzIHR3byBjbGljayBldmVudHNcclxuZnVuY3Rpb24gZmlsdGVyQ2xpY2soZSwgaGFuZGxlcikge1xyXG5cdHZhciB0aW1lU3RhbXAgPSAoZS50aW1lU3RhbXAgfHwgKGUub3JpZ2luYWxFdmVudCAmJiBlLm9yaWdpbmFsRXZlbnQudGltZVN0YW1wKSksXHJcblx0ICAgIGVsYXBzZWQgPSBsYXN0Q2xpY2sgJiYgKHRpbWVTdGFtcCAtIGxhc3RDbGljayk7XHJcblxyXG5cdC8vIGFyZSB0aGV5IGNsb3NlciB0b2dldGhlciB0aGFuIDUwMG1zIHlldCBtb3JlIHRoYW4gMTAwbXM/XHJcblx0Ly8gQW5kcm9pZCB0eXBpY2FsbHkgdHJpZ2dlcnMgdGhlbSB+MzAwbXMgYXBhcnQgd2hpbGUgbXVsdGlwbGUgbGlzdGVuZXJzXHJcblx0Ly8gb24gdGhlIHNhbWUgZXZlbnQgc2hvdWxkIGJlIHRyaWdnZXJlZCBmYXIgZmFzdGVyO1xyXG5cdC8vIG9yIGNoZWNrIGlmIGNsaWNrIGlzIHNpbXVsYXRlZCBvbiB0aGUgZWxlbWVudCwgYW5kIGlmIGl0IGlzLCByZWplY3QgYW55IG5vbi1zaW11bGF0ZWQgZXZlbnRzXHJcblxyXG5cdGlmICgoZWxhcHNlZCAmJiBlbGFwc2VkID4gMTAwICYmIGVsYXBzZWQgPCA1MDApIHx8IChlLnRhcmdldC5fc2ltdWxhdGVkQ2xpY2sgJiYgIWUuX3NpbXVsYXRlZCkpIHtcclxuXHRcdHN0b3AoZSk7XHJcblx0XHRyZXR1cm47XHJcblx0fVxyXG5cdGxhc3RDbGljayA9IHRpbWVTdGFtcDtcclxuXHJcblx0aGFuZGxlcihlKTtcclxufVxyXG5cclxuXHJcblxuXG52YXIgRG9tRXZlbnQgPSAoT2JqZWN0LmZyZWV6ZSB8fCBPYmplY3QpKHtcblx0b246IG9uLFxuXHRvZmY6IG9mZixcblx0c3RvcFByb3BhZ2F0aW9uOiBzdG9wUHJvcGFnYXRpb24sXG5cdGRpc2FibGVTY3JvbGxQcm9wYWdhdGlvbjogZGlzYWJsZVNjcm9sbFByb3BhZ2F0aW9uLFxuXHRkaXNhYmxlQ2xpY2tQcm9wYWdhdGlvbjogZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24sXG5cdHByZXZlbnREZWZhdWx0OiBwcmV2ZW50RGVmYXVsdCxcblx0c3RvcDogc3RvcCxcblx0Z2V0TW91c2VQb3NpdGlvbjogZ2V0TW91c2VQb3NpdGlvbixcblx0Z2V0V2hlZWxEZWx0YTogZ2V0V2hlZWxEZWx0YSxcblx0ZmFrZVN0b3A6IGZha2VTdG9wLFxuXHRza2lwcGVkOiBza2lwcGVkLFxuXHRpc0V4dGVybmFsVGFyZ2V0OiBpc0V4dGVybmFsVGFyZ2V0LFxuXHRhZGRMaXN0ZW5lcjogb24sXG5cdHJlbW92ZUxpc3RlbmVyOiBvZmZcbn0pO1xuXG4vKlxyXG4gKiBAbmFtZXNwYWNlIERvbVV0aWxcclxuICpcclxuICogVXRpbGl0eSBmdW5jdGlvbnMgdG8gd29yayB3aXRoIHRoZSBbRE9NXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvRG9jdW1lbnRfT2JqZWN0X01vZGVsKVxyXG4gKiB0cmVlLCB1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseS5cclxuICpcclxuICogTW9zdCBmdW5jdGlvbnMgZXhwZWN0aW5nIG9yIHJldHVybmluZyBhIGBIVE1MRWxlbWVudGAgYWxzbyB3b3JrIGZvclxyXG4gKiBTVkcgZWxlbWVudHMuIFRoZSBvbmx5IGRpZmZlcmVuY2UgaXMgdGhhdCBjbGFzc2VzIHJlZmVyIHRvIENTUyBjbGFzc2VzXHJcbiAqIGluIEhUTUwgYW5kIFNWRyBjbGFzc2VzIGluIFNWRy5cclxuICovXHJcblxyXG5cclxuLy8gQHByb3BlcnR5IFRSQU5TRk9STTogU3RyaW5nXHJcbi8vIFZlbmRvci1wcmVmaXhlZCB0cmFuc2Zvcm0gc3R5bGUgbmFtZSAoZS5nLiBgJ3dlYmtpdFRyYW5zZm9ybSdgIGZvciBXZWJLaXQpLlxyXG52YXIgVFJBTlNGT1JNID0gdGVzdFByb3AoXHJcblx0Wyd0cmFuc2Zvcm0nLCAnV2Via2l0VHJhbnNmb3JtJywgJ09UcmFuc2Zvcm0nLCAnTW96VHJhbnNmb3JtJywgJ21zVHJhbnNmb3JtJ10pO1xyXG5cclxuLy8gd2Via2l0VHJhbnNpdGlvbiBjb21lcyBmaXJzdCBiZWNhdXNlIHNvbWUgYnJvd3NlciB2ZXJzaW9ucyB0aGF0IGRyb3AgdmVuZG9yIHByZWZpeCBkb24ndCBkb1xyXG4vLyB0aGUgc2FtZSBmb3IgdGhlIHRyYW5zaXRpb25lbmQgZXZlbnQsIGluIHBhcnRpY3VsYXIgdGhlIEFuZHJvaWQgNC4xIHN0b2NrIGJyb3dzZXJcclxuXHJcbi8vIEBwcm9wZXJ0eSBUUkFOU0lUSU9OOiBTdHJpbmdcclxuLy8gVmVuZG9yLXByZWZpeGVkIHRyYW5zaXRpb24gc3R5bGUgbmFtZS5cclxudmFyIFRSQU5TSVRJT04gPSB0ZXN0UHJvcChcclxuXHRbJ3dlYmtpdFRyYW5zaXRpb24nLCAndHJhbnNpdGlvbicsICdPVHJhbnNpdGlvbicsICdNb3pUcmFuc2l0aW9uJywgJ21zVHJhbnNpdGlvbiddKTtcclxuXHJcbi8vIEBwcm9wZXJ0eSBUUkFOU0lUSU9OX0VORDogU3RyaW5nXHJcbi8vIFZlbmRvci1wcmVmaXhlZCB0cmFuc2l0aW9uZW5kIGV2ZW50IG5hbWUuXHJcbnZhciBUUkFOU0lUSU9OX0VORCA9XHJcblx0VFJBTlNJVElPTiA9PT0gJ3dlYmtpdFRyYW5zaXRpb24nIHx8IFRSQU5TSVRJT04gPT09ICdPVHJhbnNpdGlvbicgPyBUUkFOU0lUSU9OICsgJ0VuZCcgOiAndHJhbnNpdGlvbmVuZCc7XHJcblxyXG5cclxuLy8gQGZ1bmN0aW9uIGdldChpZDogU3RyaW5nfEhUTUxFbGVtZW50KTogSFRNTEVsZW1lbnRcclxuLy8gUmV0dXJucyBhbiBlbGVtZW50IGdpdmVuIGl0cyBET00gaWQsIG9yIHJldHVybnMgdGhlIGVsZW1lbnQgaXRzZWxmXHJcbi8vIGlmIGl0IHdhcyBwYXNzZWQgZGlyZWN0bHkuXHJcbmZ1bmN0aW9uIGdldChpZCkge1xyXG5cdHJldHVybiB0eXBlb2YgaWQgPT09ICdzdHJpbmcnID8gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpIDogaWQ7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBnZXRTdHlsZShlbDogSFRNTEVsZW1lbnQsIHN0eWxlQXR0cmliOiBTdHJpbmcpOiBTdHJpbmdcclxuLy8gUmV0dXJucyB0aGUgdmFsdWUgZm9yIGEgY2VydGFpbiBzdHlsZSBhdHRyaWJ1dGUgb24gYW4gZWxlbWVudCxcclxuLy8gaW5jbHVkaW5nIGNvbXB1dGVkIHZhbHVlcyBvciB2YWx1ZXMgc2V0IHRocm91Z2ggQ1NTLlxyXG5mdW5jdGlvbiBnZXRTdHlsZShlbCwgc3R5bGUpIHtcclxuXHR2YXIgdmFsdWUgPSBlbC5zdHlsZVtzdHlsZV0gfHwgKGVsLmN1cnJlbnRTdHlsZSAmJiBlbC5jdXJyZW50U3R5bGVbc3R5bGVdKTtcclxuXHJcblx0aWYgKCghdmFsdWUgfHwgdmFsdWUgPT09ICdhdXRvJykgJiYgZG9jdW1lbnQuZGVmYXVsdFZpZXcpIHtcclxuXHRcdHZhciBjc3MgPSBkb2N1bWVudC5kZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKGVsLCBudWxsKTtcclxuXHRcdHZhbHVlID0gY3NzID8gY3NzW3N0eWxlXSA6IG51bGw7XHJcblx0fVxyXG5cdHJldHVybiB2YWx1ZSA9PT0gJ2F1dG8nID8gbnVsbCA6IHZhbHVlO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gY3JlYXRlKHRhZ05hbWU6IFN0cmluZywgY2xhc3NOYW1lPzogU3RyaW5nLCBjb250YWluZXI/OiBIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50XHJcbi8vIENyZWF0ZXMgYW4gSFRNTCBlbGVtZW50IHdpdGggYHRhZ05hbWVgLCBzZXRzIGl0cyBjbGFzcyB0byBgY2xhc3NOYW1lYCwgYW5kIG9wdGlvbmFsbHkgYXBwZW5kcyBpdCB0byBgY29udGFpbmVyYCBlbGVtZW50LlxyXG5mdW5jdGlvbiBjcmVhdGUkMSh0YWdOYW1lLCBjbGFzc05hbWUsIGNvbnRhaW5lcikge1xyXG5cdHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQodGFnTmFtZSk7XHJcblx0ZWwuY2xhc3NOYW1lID0gY2xhc3NOYW1lIHx8ICcnO1xyXG5cclxuXHRpZiAoY29udGFpbmVyKSB7XHJcblx0XHRjb250YWluZXIuYXBwZW5kQ2hpbGQoZWwpO1xyXG5cdH1cclxuXHRyZXR1cm4gZWw7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiByZW1vdmUoZWw6IEhUTUxFbGVtZW50KVxyXG4vLyBSZW1vdmVzIGBlbGAgZnJvbSBpdHMgcGFyZW50IGVsZW1lbnRcclxuZnVuY3Rpb24gcmVtb3ZlKGVsKSB7XHJcblx0dmFyIHBhcmVudCA9IGVsLnBhcmVudE5vZGU7XHJcblx0aWYgKHBhcmVudCkge1xyXG5cdFx0cGFyZW50LnJlbW92ZUNoaWxkKGVsKTtcclxuXHR9XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBlbXB0eShlbDogSFRNTEVsZW1lbnQpXHJcbi8vIFJlbW92ZXMgYWxsIG9mIGBlbGAncyBjaGlsZHJlbiBlbGVtZW50cyBmcm9tIGBlbGBcclxuZnVuY3Rpb24gZW1wdHkoZWwpIHtcclxuXHR3aGlsZSAoZWwuZmlyc3RDaGlsZCkge1xyXG5cdFx0ZWwucmVtb3ZlQ2hpbGQoZWwuZmlyc3RDaGlsZCk7XHJcblx0fVxyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gdG9Gcm9udChlbDogSFRNTEVsZW1lbnQpXHJcbi8vIE1ha2VzIGBlbGAgdGhlIGxhc3QgY2hpbGQgb2YgaXRzIHBhcmVudCwgc28gaXQgcmVuZGVycyBpbiBmcm9udCBvZiB0aGUgb3RoZXIgY2hpbGRyZW4uXHJcbmZ1bmN0aW9uIHRvRnJvbnQoZWwpIHtcclxuXHR2YXIgcGFyZW50ID0gZWwucGFyZW50Tm9kZTtcclxuXHRpZiAocGFyZW50Lmxhc3RDaGlsZCAhPT0gZWwpIHtcclxuXHRcdHBhcmVudC5hcHBlbmRDaGlsZChlbCk7XHJcblx0fVxyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gdG9CYWNrKGVsOiBIVE1MRWxlbWVudClcclxuLy8gTWFrZXMgYGVsYCB0aGUgZmlyc3QgY2hpbGQgb2YgaXRzIHBhcmVudCwgc28gaXQgcmVuZGVycyBiZWhpbmQgdGhlIG90aGVyIGNoaWxkcmVuLlxyXG5mdW5jdGlvbiB0b0JhY2soZWwpIHtcclxuXHR2YXIgcGFyZW50ID0gZWwucGFyZW50Tm9kZTtcclxuXHRpZiAocGFyZW50LmZpcnN0Q2hpbGQgIT09IGVsKSB7XHJcblx0XHRwYXJlbnQuaW5zZXJ0QmVmb3JlKGVsLCBwYXJlbnQuZmlyc3RDaGlsZCk7XHJcblx0fVxyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gaGFzQ2xhc3MoZWw6IEhUTUxFbGVtZW50LCBuYW1lOiBTdHJpbmcpOiBCb29sZWFuXHJcbi8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBlbGVtZW50J3MgY2xhc3MgYXR0cmlidXRlIGNvbnRhaW5zIGBuYW1lYC5cclxuZnVuY3Rpb24gaGFzQ2xhc3MoZWwsIG5hbWUpIHtcclxuXHRpZiAoZWwuY2xhc3NMaXN0ICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdHJldHVybiBlbC5jbGFzc0xpc3QuY29udGFpbnMobmFtZSk7XHJcblx0fVxyXG5cdHZhciBjbGFzc05hbWUgPSBnZXRDbGFzcyhlbCk7XHJcblx0cmV0dXJuIGNsYXNzTmFtZS5sZW5ndGggPiAwICYmIG5ldyBSZWdFeHAoJyhefFxcXFxzKScgKyBuYW1lICsgJyhcXFxcc3wkKScpLnRlc3QoY2xhc3NOYW1lKTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGFkZENsYXNzKGVsOiBIVE1MRWxlbWVudCwgbmFtZTogU3RyaW5nKVxyXG4vLyBBZGRzIGBuYW1lYCB0byB0aGUgZWxlbWVudCdzIGNsYXNzIGF0dHJpYnV0ZS5cclxuZnVuY3Rpb24gYWRkQ2xhc3MoZWwsIG5hbWUpIHtcclxuXHRpZiAoZWwuY2xhc3NMaXN0ICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdHZhciBjbGFzc2VzID0gc3BsaXRXb3JkcyhuYW1lKTtcclxuXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBjbGFzc2VzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdGVsLmNsYXNzTGlzdC5hZGQoY2xhc3Nlc1tpXSk7XHJcblx0XHR9XHJcblx0fSBlbHNlIGlmICghaGFzQ2xhc3MoZWwsIG5hbWUpKSB7XHJcblx0XHR2YXIgY2xhc3NOYW1lID0gZ2V0Q2xhc3MoZWwpO1xyXG5cdFx0c2V0Q2xhc3MoZWwsIChjbGFzc05hbWUgPyBjbGFzc05hbWUgKyAnICcgOiAnJykgKyBuYW1lKTtcclxuXHR9XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiByZW1vdmVDbGFzcyhlbDogSFRNTEVsZW1lbnQsIG5hbWU6IFN0cmluZylcclxuLy8gUmVtb3ZlcyBgbmFtZWAgZnJvbSB0aGUgZWxlbWVudCdzIGNsYXNzIGF0dHJpYnV0ZS5cclxuZnVuY3Rpb24gcmVtb3ZlQ2xhc3MoZWwsIG5hbWUpIHtcclxuXHRpZiAoZWwuY2xhc3NMaXN0ICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdGVsLmNsYXNzTGlzdC5yZW1vdmUobmFtZSk7XHJcblx0fSBlbHNlIHtcclxuXHRcdHNldENsYXNzKGVsLCB0cmltKCgnICcgKyBnZXRDbGFzcyhlbCkgKyAnICcpLnJlcGxhY2UoJyAnICsgbmFtZSArICcgJywgJyAnKSkpO1xyXG5cdH1cclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHNldENsYXNzKGVsOiBIVE1MRWxlbWVudCwgbmFtZTogU3RyaW5nKVxyXG4vLyBTZXRzIHRoZSBlbGVtZW50J3MgY2xhc3MuXHJcbmZ1bmN0aW9uIHNldENsYXNzKGVsLCBuYW1lKSB7XHJcblx0aWYgKGVsLmNsYXNzTmFtZS5iYXNlVmFsID09PSB1bmRlZmluZWQpIHtcclxuXHRcdGVsLmNsYXNzTmFtZSA9IG5hbWU7XHJcblx0fSBlbHNlIHtcclxuXHRcdC8vIGluIGNhc2Ugb2YgU1ZHIGVsZW1lbnRcclxuXHRcdGVsLmNsYXNzTmFtZS5iYXNlVmFsID0gbmFtZTtcclxuXHR9XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBnZXRDbGFzcyhlbDogSFRNTEVsZW1lbnQpOiBTdHJpbmdcclxuLy8gUmV0dXJucyB0aGUgZWxlbWVudCdzIGNsYXNzLlxyXG5mdW5jdGlvbiBnZXRDbGFzcyhlbCkge1xyXG5cdHJldHVybiBlbC5jbGFzc05hbWUuYmFzZVZhbCA9PT0gdW5kZWZpbmVkID8gZWwuY2xhc3NOYW1lIDogZWwuY2xhc3NOYW1lLmJhc2VWYWw7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBzZXRPcGFjaXR5KGVsOiBIVE1MRWxlbWVudCwgb3BhY2l0eTogTnVtYmVyKVxyXG4vLyBTZXQgdGhlIG9wYWNpdHkgb2YgYW4gZWxlbWVudCAoaW5jbHVkaW5nIG9sZCBJRSBzdXBwb3J0KS5cclxuLy8gYG9wYWNpdHlgIG11c3QgYmUgYSBudW1iZXIgZnJvbSBgMGAgdG8gYDFgLlxyXG5mdW5jdGlvbiBzZXRPcGFjaXR5KGVsLCB2YWx1ZSkge1xyXG5cdGlmICgnb3BhY2l0eScgaW4gZWwuc3R5bGUpIHtcclxuXHRcdGVsLnN0eWxlLm9wYWNpdHkgPSB2YWx1ZTtcclxuXHR9IGVsc2UgaWYgKCdmaWx0ZXInIGluIGVsLnN0eWxlKSB7XHJcblx0XHRfc2V0T3BhY2l0eUlFKGVsLCB2YWx1ZSk7XHJcblx0fVxyXG59XHJcblxyXG5mdW5jdGlvbiBfc2V0T3BhY2l0eUlFKGVsLCB2YWx1ZSkge1xyXG5cdHZhciBmaWx0ZXIgPSBmYWxzZSxcclxuXHQgICAgZmlsdGVyTmFtZSA9ICdEWEltYWdlVHJhbnNmb3JtLk1pY3Jvc29mdC5BbHBoYSc7XHJcblxyXG5cdC8vIGZpbHRlcnMgY29sbGVjdGlvbiB0aHJvd3MgYW4gZXJyb3IgaWYgd2UgdHJ5IHRvIHJldHJpZXZlIGEgZmlsdGVyIHRoYXQgZG9lc24ndCBleGlzdFxyXG5cdHRyeSB7XHJcblx0XHRmaWx0ZXIgPSBlbC5maWx0ZXJzLml0ZW0oZmlsdGVyTmFtZSk7XHJcblx0fSBjYXRjaCAoZSkge1xyXG5cdFx0Ly8gZG9uJ3Qgc2V0IG9wYWNpdHkgdG8gMSBpZiB3ZSBoYXZlbid0IGFscmVhZHkgc2V0IGFuIG9wYWNpdHksXHJcblx0XHQvLyBpdCBpc24ndCBuZWVkZWQgYW5kIGJyZWFrcyB0cmFuc3BhcmVudCBwbmdzLlxyXG5cdFx0aWYgKHZhbHVlID09PSAxKSB7IHJldHVybjsgfVxyXG5cdH1cclxuXHJcblx0dmFsdWUgPSBNYXRoLnJvdW5kKHZhbHVlICogMTAwKTtcclxuXHJcblx0aWYgKGZpbHRlcikge1xyXG5cdFx0ZmlsdGVyLkVuYWJsZWQgPSAodmFsdWUgIT09IDEwMCk7XHJcblx0XHRmaWx0ZXIuT3BhY2l0eSA9IHZhbHVlO1xyXG5cdH0gZWxzZSB7XHJcblx0XHRlbC5zdHlsZS5maWx0ZXIgKz0gJyBwcm9naWQ6JyArIGZpbHRlck5hbWUgKyAnKG9wYWNpdHk9JyArIHZhbHVlICsgJyknO1xyXG5cdH1cclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIHRlc3RQcm9wKHByb3BzOiBTdHJpbmdbXSk6IFN0cmluZ3xmYWxzZVxyXG4vLyBHb2VzIHRocm91Z2ggdGhlIGFycmF5IG9mIHN0eWxlIG5hbWVzIGFuZCByZXR1cm5zIHRoZSBmaXJzdCBuYW1lXHJcbi8vIHRoYXQgaXMgYSB2YWxpZCBzdHlsZSBuYW1lIGZvciBhbiBlbGVtZW50LiBJZiBubyBzdWNoIG5hbWUgaXMgZm91bmQsXHJcbi8vIGl0IHJldHVybnMgZmFsc2UuIFVzZWZ1bCBmb3IgdmVuZG9yLXByZWZpeGVkIHN0eWxlcyBsaWtlIGB0cmFuc2Zvcm1gLlxyXG5mdW5jdGlvbiB0ZXN0UHJvcChwcm9wcykge1xyXG5cdHZhciBzdHlsZSA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZTtcclxuXHJcblx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykge1xyXG5cdFx0aWYgKHByb3BzW2ldIGluIHN0eWxlKSB7XHJcblx0XHRcdHJldHVybiBwcm9wc1tpXTtcclxuXHRcdH1cclxuXHR9XHJcblx0cmV0dXJuIGZhbHNlO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gc2V0VHJhbnNmb3JtKGVsOiBIVE1MRWxlbWVudCwgb2Zmc2V0OiBQb2ludCwgc2NhbGU/OiBOdW1iZXIpXHJcbi8vIFJlc2V0cyB0aGUgM0QgQ1NTIHRyYW5zZm9ybSBvZiBgZWxgIHNvIGl0IGlzIHRyYW5zbGF0ZWQgYnkgYG9mZnNldGAgcGl4ZWxzXHJcbi8vIGFuZCBvcHRpb25hbGx5IHNjYWxlZCBieSBgc2NhbGVgLiBEb2VzIG5vdCBoYXZlIGFuIGVmZmVjdCBpZiB0aGVcclxuLy8gYnJvd3NlciBkb2Vzbid0IHN1cHBvcnQgM0QgQ1NTIHRyYW5zZm9ybXMuXHJcbmZ1bmN0aW9uIHNldFRyYW5zZm9ybShlbCwgb2Zmc2V0LCBzY2FsZSkge1xyXG5cdHZhciBwb3MgPSBvZmZzZXQgfHwgbmV3IFBvaW50KDAsIDApO1xyXG5cclxuXHRlbC5zdHlsZVtUUkFOU0ZPUk1dID1cclxuXHRcdChpZTNkID9cclxuXHRcdFx0J3RyYW5zbGF0ZSgnICsgcG9zLnggKyAncHgsJyArIHBvcy55ICsgJ3B4KScgOlxyXG5cdFx0XHQndHJhbnNsYXRlM2QoJyArIHBvcy54ICsgJ3B4LCcgKyBwb3MueSArICdweCwwKScpICtcclxuXHRcdChzY2FsZSA/ICcgc2NhbGUoJyArIHNjYWxlICsgJyknIDogJycpO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gc2V0UG9zaXRpb24oZWw6IEhUTUxFbGVtZW50LCBwb3NpdGlvbjogUG9pbnQpXHJcbi8vIFNldHMgdGhlIHBvc2l0aW9uIG9mIGBlbGAgdG8gY29vcmRpbmF0ZXMgc3BlY2lmaWVkIGJ5IGBwb3NpdGlvbmAsXHJcbi8vIHVzaW5nIENTUyB0cmFuc2xhdGUgb3IgdG9wL2xlZnQgcG9zaXRpb25pbmcgZGVwZW5kaW5nIG9uIHRoZSBicm93c2VyXHJcbi8vICh1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseSB0byBwb3NpdGlvbiBpdHMgbGF5ZXJzKS5cclxuZnVuY3Rpb24gc2V0UG9zaXRpb24oZWwsIHBvaW50KSB7XHJcblxyXG5cdC8qZXNsaW50LWRpc2FibGUgKi9cclxuXHRlbC5fbGVhZmxldF9wb3MgPSBwb2ludDtcclxuXHQvKiBlc2xpbnQtZW5hYmxlICovXHJcblxyXG5cdGlmIChhbnkzZCkge1xyXG5cdFx0c2V0VHJhbnNmb3JtKGVsLCBwb2ludCk7XHJcblx0fSBlbHNlIHtcclxuXHRcdGVsLnN0eWxlLmxlZnQgPSBwb2ludC54ICsgJ3B4JztcclxuXHRcdGVsLnN0eWxlLnRvcCA9IHBvaW50LnkgKyAncHgnO1xyXG5cdH1cclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGdldFBvc2l0aW9uKGVsOiBIVE1MRWxlbWVudCk6IFBvaW50XHJcbi8vIFJldHVybnMgdGhlIGNvb3JkaW5hdGVzIG9mIGFuIGVsZW1lbnQgcHJldmlvdXNseSBwb3NpdGlvbmVkIHdpdGggc2V0UG9zaXRpb24uXHJcbmZ1bmN0aW9uIGdldFBvc2l0aW9uKGVsKSB7XHJcblx0Ly8gdGhpcyBtZXRob2QgaXMgb25seSB1c2VkIGZvciBlbGVtZW50cyBwcmV2aW91c2x5IHBvc2l0aW9uZWQgdXNpbmcgc2V0UG9zaXRpb24sXHJcblx0Ly8gc28gaXQncyBzYWZlIHRvIGNhY2hlIHRoZSBwb3NpdGlvbiBmb3IgcGVyZm9ybWFuY2VcclxuXHJcblx0cmV0dXJuIGVsLl9sZWFmbGV0X3BvcyB8fCBuZXcgUG9pbnQoMCwgMCk7XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBkaXNhYmxlVGV4dFNlbGVjdGlvbigpXHJcbi8vIFByZXZlbnRzIHRoZSB1c2VyIGZyb20gZ2VuZXJhdGluZyBgc2VsZWN0c3RhcnRgIERPTSBldmVudHMsIHVzdWFsbHkgZ2VuZXJhdGVkXHJcbi8vIHdoZW4gdGhlIHVzZXIgZHJhZ3MgdGhlIG1vdXNlIHRocm91Z2ggYSBwYWdlIHdpdGggdGV4dC4gVXNlZCBpbnRlcm5hbGx5XHJcbi8vIGJ5IExlYWZsZXQgdG8gb3ZlcnJpZGUgdGhlIGJlaGF2aW91ciBvZiBhbnkgY2xpY2stYW5kLWRyYWcgaW50ZXJhY3Rpb24gb25cclxuLy8gdGhlIG1hcC4gQWZmZWN0cyBkcmFnIGludGVyYWN0aW9ucyBvbiB0aGUgd2hvbGUgZG9jdW1lbnQuXHJcblxyXG4vLyBAZnVuY3Rpb24gZW5hYmxlVGV4dFNlbGVjdGlvbigpXHJcbi8vIENhbmNlbHMgdGhlIGVmZmVjdHMgb2YgYSBwcmV2aW91cyBbYEwuRG9tVXRpbC5kaXNhYmxlVGV4dFNlbGVjdGlvbmBdKCNkb211dGlsLWRpc2FibGV0ZXh0c2VsZWN0aW9uKS5cclxudmFyIGRpc2FibGVUZXh0U2VsZWN0aW9uO1xyXG52YXIgZW5hYmxlVGV4dFNlbGVjdGlvbjtcclxudmFyIF91c2VyU2VsZWN0O1xyXG5pZiAoJ29uc2VsZWN0c3RhcnQnIGluIGRvY3VtZW50KSB7XHJcblx0ZGlzYWJsZVRleHRTZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRvbih3aW5kb3csICdzZWxlY3RzdGFydCcsIHByZXZlbnREZWZhdWx0KTtcclxuXHR9O1xyXG5cdGVuYWJsZVRleHRTZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRvZmYod2luZG93LCAnc2VsZWN0c3RhcnQnLCBwcmV2ZW50RGVmYXVsdCk7XHJcblx0fTtcclxufSBlbHNlIHtcclxuXHR2YXIgdXNlclNlbGVjdFByb3BlcnR5ID0gdGVzdFByb3AoXHJcblx0XHRbJ3VzZXJTZWxlY3QnLCAnV2Via2l0VXNlclNlbGVjdCcsICdPVXNlclNlbGVjdCcsICdNb3pVc2VyU2VsZWN0JywgJ21zVXNlclNlbGVjdCddKTtcclxuXHJcblx0ZGlzYWJsZVRleHRTZWxlY3Rpb24gPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAodXNlclNlbGVjdFByb3BlcnR5KSB7XHJcblx0XHRcdHZhciBzdHlsZSA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZTtcclxuXHRcdFx0X3VzZXJTZWxlY3QgPSBzdHlsZVt1c2VyU2VsZWN0UHJvcGVydHldO1xyXG5cdFx0XHRzdHlsZVt1c2VyU2VsZWN0UHJvcGVydHldID0gJ25vbmUnO1xyXG5cdFx0fVxyXG5cdH07XHJcblx0ZW5hYmxlVGV4dFNlbGVjdGlvbiA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh1c2VyU2VsZWN0UHJvcGVydHkpIHtcclxuXHRcdFx0ZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlW3VzZXJTZWxlY3RQcm9wZXJ0eV0gPSBfdXNlclNlbGVjdDtcclxuXHRcdFx0X3VzZXJTZWxlY3QgPSB1bmRlZmluZWQ7XHJcblx0XHR9XHJcblx0fTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGRpc2FibGVJbWFnZURyYWcoKVxyXG4vLyBBcyBbYEwuRG9tVXRpbC5kaXNhYmxlVGV4dFNlbGVjdGlvbmBdKCNkb211dGlsLWRpc2FibGV0ZXh0c2VsZWN0aW9uKSwgYnV0XHJcbi8vIGZvciBgZHJhZ3N0YXJ0YCBET00gZXZlbnRzLCB1c3VhbGx5IGdlbmVyYXRlZCB3aGVuIHRoZSB1c2VyIGRyYWdzIGFuIGltYWdlLlxyXG5mdW5jdGlvbiBkaXNhYmxlSW1hZ2VEcmFnKCkge1xyXG5cdG9uKHdpbmRvdywgJ2RyYWdzdGFydCcsIHByZXZlbnREZWZhdWx0KTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGVuYWJsZUltYWdlRHJhZygpXHJcbi8vIENhbmNlbHMgdGhlIGVmZmVjdHMgb2YgYSBwcmV2aW91cyBbYEwuRG9tVXRpbC5kaXNhYmxlSW1hZ2VEcmFnYF0oI2RvbXV0aWwtZGlzYWJsZXRleHRzZWxlY3Rpb24pLlxyXG5mdW5jdGlvbiBlbmFibGVJbWFnZURyYWcoKSB7XHJcblx0b2ZmKHdpbmRvdywgJ2RyYWdzdGFydCcsIHByZXZlbnREZWZhdWx0KTtcclxufVxyXG5cclxudmFyIF9vdXRsaW5lRWxlbWVudDtcbnZhciBfb3V0bGluZVN0eWxlO1xyXG4vLyBAZnVuY3Rpb24gcHJldmVudE91dGxpbmUoZWw6IEhUTUxFbGVtZW50KVxyXG4vLyBNYWtlcyB0aGUgW291dGxpbmVdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0NTUy9vdXRsaW5lKVxyXG4vLyBvZiB0aGUgZWxlbWVudCBgZWxgIGludmlzaWJsZS4gVXNlZCBpbnRlcm5hbGx5IGJ5IExlYWZsZXQgdG8gcHJldmVudFxyXG4vLyBmb2N1c2FibGUgZWxlbWVudHMgZnJvbSBkaXNwbGF5aW5nIGFuIG91dGxpbmUgd2hlbiB0aGUgdXNlciBwZXJmb3JtcyBhXHJcbi8vIGRyYWcgaW50ZXJhY3Rpb24gb24gdGhlbS5cclxuZnVuY3Rpb24gcHJldmVudE91dGxpbmUoZWxlbWVudCkge1xyXG5cdHdoaWxlIChlbGVtZW50LnRhYkluZGV4ID09PSAtMSkge1xyXG5cdFx0ZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcclxuXHR9XHJcblx0aWYgKCFlbGVtZW50LnN0eWxlKSB7IHJldHVybjsgfVxyXG5cdHJlc3RvcmVPdXRsaW5lKCk7XHJcblx0X291dGxpbmVFbGVtZW50ID0gZWxlbWVudDtcclxuXHRfb3V0bGluZVN0eWxlID0gZWxlbWVudC5zdHlsZS5vdXRsaW5lO1xyXG5cdGVsZW1lbnQuc3R5bGUub3V0bGluZSA9ICdub25lJztcclxuXHRvbih3aW5kb3csICdrZXlkb3duJywgcmVzdG9yZU91dGxpbmUpO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gcmVzdG9yZU91dGxpbmUoKVxyXG4vLyBDYW5jZWxzIHRoZSBlZmZlY3RzIG9mIGEgcHJldmlvdXMgW2BMLkRvbVV0aWwucHJldmVudE91dGxpbmVgXSgpLlxyXG5mdW5jdGlvbiByZXN0b3JlT3V0bGluZSgpIHtcclxuXHRpZiAoIV9vdXRsaW5lRWxlbWVudCkgeyByZXR1cm47IH1cclxuXHRfb3V0bGluZUVsZW1lbnQuc3R5bGUub3V0bGluZSA9IF9vdXRsaW5lU3R5bGU7XHJcblx0X291dGxpbmVFbGVtZW50ID0gdW5kZWZpbmVkO1xyXG5cdF9vdXRsaW5lU3R5bGUgPSB1bmRlZmluZWQ7XHJcblx0b2ZmKHdpbmRvdywgJ2tleWRvd24nLCByZXN0b3JlT3V0bGluZSk7XHJcbn1cclxuXG5cbnZhciBEb21VdGlsID0gKE9iamVjdC5mcmVlemUgfHwgT2JqZWN0KSh7XG5cdFRSQU5TRk9STTogVFJBTlNGT1JNLFxuXHRUUkFOU0lUSU9OOiBUUkFOU0lUSU9OLFxuXHRUUkFOU0lUSU9OX0VORDogVFJBTlNJVElPTl9FTkQsXG5cdGdldDogZ2V0LFxuXHRnZXRTdHlsZTogZ2V0U3R5bGUsXG5cdGNyZWF0ZTogY3JlYXRlJDEsXG5cdHJlbW92ZTogcmVtb3ZlLFxuXHRlbXB0eTogZW1wdHksXG5cdHRvRnJvbnQ6IHRvRnJvbnQsXG5cdHRvQmFjazogdG9CYWNrLFxuXHRoYXNDbGFzczogaGFzQ2xhc3MsXG5cdGFkZENsYXNzOiBhZGRDbGFzcyxcblx0cmVtb3ZlQ2xhc3M6IHJlbW92ZUNsYXNzLFxuXHRzZXRDbGFzczogc2V0Q2xhc3MsXG5cdGdldENsYXNzOiBnZXRDbGFzcyxcblx0c2V0T3BhY2l0eTogc2V0T3BhY2l0eSxcblx0dGVzdFByb3A6IHRlc3RQcm9wLFxuXHRzZXRUcmFuc2Zvcm06IHNldFRyYW5zZm9ybSxcblx0c2V0UG9zaXRpb246IHNldFBvc2l0aW9uLFxuXHRnZXRQb3NpdGlvbjogZ2V0UG9zaXRpb24sXG5cdGRpc2FibGVUZXh0U2VsZWN0aW9uOiBkaXNhYmxlVGV4dFNlbGVjdGlvbixcblx0ZW5hYmxlVGV4dFNlbGVjdGlvbjogZW5hYmxlVGV4dFNlbGVjdGlvbixcblx0ZGlzYWJsZUltYWdlRHJhZzogZGlzYWJsZUltYWdlRHJhZyxcblx0ZW5hYmxlSW1hZ2VEcmFnOiBlbmFibGVJbWFnZURyYWcsXG5cdHByZXZlbnRPdXRsaW5lOiBwcmV2ZW50T3V0bGluZSxcblx0cmVzdG9yZU91dGxpbmU6IHJlc3RvcmVPdXRsaW5lXG59KTtcblxuLypcbiAqIEBjbGFzcyBQb3NBbmltYXRpb25cbiAqIEBha2EgTC5Qb3NBbmltYXRpb25cbiAqIEBpbmhlcml0cyBFdmVudGVkXG4gKiBVc2VkIGludGVybmFsbHkgZm9yIHBhbm5pbmcgYW5pbWF0aW9ucywgdXRpbGl6aW5nIENTUzMgVHJhbnNpdGlvbnMgZm9yIG1vZGVybiBicm93c2VycyBhbmQgYSB0aW1lciBmYWxsYmFjayBmb3IgSUU2LTkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYGpzXG4gKiB2YXIgZnggPSBuZXcgTC5Qb3NBbmltYXRpb24oKTtcbiAqIGZ4LnJ1bihlbCwgWzMwMCwgNTAwXSwgMC41KTtcbiAqIGBgYFxuICpcbiAqIEBjb25zdHJ1Y3RvciBMLlBvc0FuaW1hdGlvbigpXG4gKiBDcmVhdGVzIGEgYFBvc0FuaW1hdGlvbmAgb2JqZWN0LlxuICpcbiAqL1xuXG52YXIgUG9zQW5pbWF0aW9uID0gRXZlbnRlZC5leHRlbmQoe1xuXG5cdC8vIEBtZXRob2QgcnVuKGVsOiBIVE1MRWxlbWVudCwgbmV3UG9zOiBQb2ludCwgZHVyYXRpb24/OiBOdW1iZXIsIGVhc2VMaW5lYXJpdHk/OiBOdW1iZXIpXG5cdC8vIFJ1biBhbiBhbmltYXRpb24gb2YgYSBnaXZlbiBlbGVtZW50IHRvIGEgbmV3IHBvc2l0aW9uLCBvcHRpb25hbGx5IHNldHRpbmdcblx0Ly8gZHVyYXRpb24gaW4gc2Vjb25kcyAoYDAuMjVgIGJ5IGRlZmF1bHQpIGFuZCBlYXNpbmcgbGluZWFyaXR5IGZhY3RvciAoM3JkXG5cdC8vIGFyZ3VtZW50IG9mIHRoZSBbY3ViaWMgYmV6aWVyIGN1cnZlXShodHRwOi8vY3ViaWMtYmV6aWVyLmNvbS8jMCwwLC41LDEpLFxuXHQvLyBgMC41YCBieSBkZWZhdWx0KS5cblx0cnVuOiBmdW5jdGlvbiAoZWwsIG5ld1BvcywgZHVyYXRpb24sIGVhc2VMaW5lYXJpdHkpIHtcblx0XHR0aGlzLnN0b3AoKTtcblxuXHRcdHRoaXMuX2VsID0gZWw7XG5cdFx0dGhpcy5faW5Qcm9ncmVzcyA9IHRydWU7XG5cdFx0dGhpcy5fZHVyYXRpb24gPSBkdXJhdGlvbiB8fCAwLjI1O1xuXHRcdHRoaXMuX2Vhc2VPdXRQb3dlciA9IDEgLyBNYXRoLm1heChlYXNlTGluZWFyaXR5IHx8IDAuNSwgMC4yKTtcblxuXHRcdHRoaXMuX3N0YXJ0UG9zID0gZ2V0UG9zaXRpb24oZWwpO1xuXHRcdHRoaXMuX29mZnNldCA9IG5ld1Bvcy5zdWJ0cmFjdCh0aGlzLl9zdGFydFBvcyk7XG5cdFx0dGhpcy5fc3RhcnRUaW1lID0gK25ldyBEYXRlKCk7XG5cblx0XHQvLyBAZXZlbnQgc3RhcnQ6IEV2ZW50XG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgYW5pbWF0aW9uIHN0YXJ0c1xuXHRcdHRoaXMuZmlyZSgnc3RhcnQnKTtcblxuXHRcdHRoaXMuX2FuaW1hdGUoKTtcblx0fSxcblxuXHQvLyBAbWV0aG9kIHN0b3AoKVxuXHQvLyBTdG9wcyB0aGUgYW5pbWF0aW9uIChpZiBjdXJyZW50bHkgcnVubmluZykuXG5cdHN0b3A6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoIXRoaXMuX2luUHJvZ3Jlc3MpIHsgcmV0dXJuOyB9XG5cblx0XHR0aGlzLl9zdGVwKHRydWUpO1xuXHRcdHRoaXMuX2NvbXBsZXRlKCk7XG5cdH0sXG5cblx0X2FuaW1hdGU6IGZ1bmN0aW9uICgpIHtcblx0XHQvLyBhbmltYXRpb24gbG9vcFxuXHRcdHRoaXMuX2FuaW1JZCA9IHJlcXVlc3RBbmltRnJhbWUodGhpcy5fYW5pbWF0ZSwgdGhpcyk7XG5cdFx0dGhpcy5fc3RlcCgpO1xuXHR9LFxuXG5cdF9zdGVwOiBmdW5jdGlvbiAocm91bmQpIHtcblx0XHR2YXIgZWxhcHNlZCA9ICgrbmV3IERhdGUoKSkgLSB0aGlzLl9zdGFydFRpbWUsXG5cdFx0ICAgIGR1cmF0aW9uID0gdGhpcy5fZHVyYXRpb24gKiAxMDAwO1xuXG5cdFx0aWYgKGVsYXBzZWQgPCBkdXJhdGlvbikge1xuXHRcdFx0dGhpcy5fcnVuRnJhbWUodGhpcy5fZWFzZU91dChlbGFwc2VkIC8gZHVyYXRpb24pLCByb3VuZCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX3J1bkZyYW1lKDEpO1xuXHRcdFx0dGhpcy5fY29tcGxldGUoKTtcblx0XHR9XG5cdH0sXG5cblx0X3J1bkZyYW1lOiBmdW5jdGlvbiAocHJvZ3Jlc3MsIHJvdW5kKSB7XG5cdFx0dmFyIHBvcyA9IHRoaXMuX3N0YXJ0UG9zLmFkZCh0aGlzLl9vZmZzZXQubXVsdGlwbHlCeShwcm9ncmVzcykpO1xuXHRcdGlmIChyb3VuZCkge1xuXHRcdFx0cG9zLl9yb3VuZCgpO1xuXHRcdH1cblx0XHRzZXRQb3NpdGlvbih0aGlzLl9lbCwgcG9zKTtcblxuXHRcdC8vIEBldmVudCBzdGVwOiBFdmVudFxuXHRcdC8vIEZpcmVkIGNvbnRpbnVvdXNseSBkdXJpbmcgdGhlIGFuaW1hdGlvbi5cblx0XHR0aGlzLmZpcmUoJ3N0ZXAnKTtcblx0fSxcblxuXHRfY29tcGxldGU6IGZ1bmN0aW9uICgpIHtcblx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fYW5pbUlkKTtcblxuXHRcdHRoaXMuX2luUHJvZ3Jlc3MgPSBmYWxzZTtcblx0XHQvLyBAZXZlbnQgZW5kOiBFdmVudFxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIGFuaW1hdGlvbiBlbmRzLlxuXHRcdHRoaXMuZmlyZSgnZW5kJyk7XG5cdH0sXG5cblx0X2Vhc2VPdXQ6IGZ1bmN0aW9uICh0KSB7XG5cdFx0cmV0dXJuIDEgLSBNYXRoLnBvdygxIC0gdCwgdGhpcy5fZWFzZU91dFBvd2VyKTtcblx0fVxufSk7XG5cbi8qXHJcbiAqIEBjbGFzcyBNYXBcclxuICogQGFrYSBMLk1hcFxyXG4gKiBAaW5oZXJpdHMgRXZlbnRlZFxyXG4gKlxyXG4gKiBUaGUgY2VudHJhbCBjbGFzcyBvZiB0aGUgQVBJIOKAlCBpdCBpcyB1c2VkIHRvIGNyZWF0ZSBhIG1hcCBvbiBhIHBhZ2UgYW5kIG1hbmlwdWxhdGUgaXQuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIC8vIGluaXRpYWxpemUgdGhlIG1hcCBvbiB0aGUgXCJtYXBcIiBkaXYgd2l0aCBhIGdpdmVuIGNlbnRlciBhbmQgem9vbVxyXG4gKiB2YXIgbWFwID0gTC5tYXAoJ21hcCcsIHtcclxuICogXHRjZW50ZXI6IFs1MS41MDUsIC0wLjA5XSxcclxuICogXHR6b29tOiAxM1xyXG4gKiB9KTtcclxuICogYGBgXHJcbiAqXHJcbiAqL1xyXG5cclxudmFyIE1hcCA9IEV2ZW50ZWQuZXh0ZW5kKHtcclxuXHJcblx0b3B0aW9uczoge1xyXG5cdFx0Ly8gQHNlY3Rpb24gTWFwIFN0YXRlIE9wdGlvbnNcclxuXHRcdC8vIEBvcHRpb24gY3JzOiBDUlMgPSBMLkNSUy5FUFNHMzg1N1xyXG5cdFx0Ly8gVGhlIFtDb29yZGluYXRlIFJlZmVyZW5jZSBTeXN0ZW1dKCNjcnMpIHRvIHVzZS4gRG9uJ3QgY2hhbmdlIHRoaXMgaWYgeW91J3JlIG5vdFxyXG5cdFx0Ly8gc3VyZSB3aGF0IGl0IG1lYW5zLlxyXG5cdFx0Y3JzOiBFUFNHMzg1NyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGNlbnRlcjogTGF0TG5nID0gdW5kZWZpbmVkXHJcblx0XHQvLyBJbml0aWFsIGdlb2dyYXBoaWMgY2VudGVyIG9mIHRoZSBtYXBcclxuXHRcdGNlbnRlcjogdW5kZWZpbmVkLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gem9vbTogTnVtYmVyID0gdW5kZWZpbmVkXHJcblx0XHQvLyBJbml0aWFsIG1hcCB6b29tIGxldmVsXHJcblx0XHR6b29tOiB1bmRlZmluZWQsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBtaW5ab29tOiBOdW1iZXIgPSAqXHJcblx0XHQvLyBNaW5pbXVtIHpvb20gbGV2ZWwgb2YgdGhlIG1hcC5cclxuXHRcdC8vIElmIG5vdCBzcGVjaWZpZWQgYW5kIGF0IGxlYXN0IG9uZSBgR3JpZExheWVyYCBvciBgVGlsZUxheWVyYCBpcyBpbiB0aGUgbWFwLFxyXG5cdFx0Ly8gdGhlIGxvd2VzdCBvZiB0aGVpciBgbWluWm9vbWAgb3B0aW9ucyB3aWxsIGJlIHVzZWQgaW5zdGVhZC5cclxuXHRcdG1pblpvb206IHVuZGVmaW5lZCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIG1heFpvb206IE51bWJlciA9ICpcclxuXHRcdC8vIE1heGltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwLlxyXG5cdFx0Ly8gSWYgbm90IHNwZWNpZmllZCBhbmQgYXQgbGVhc3Qgb25lIGBHcmlkTGF5ZXJgIG9yIGBUaWxlTGF5ZXJgIGlzIGluIHRoZSBtYXAsXHJcblx0XHQvLyB0aGUgaGlnaGVzdCBvZiB0aGVpciBgbWF4Wm9vbWAgb3B0aW9ucyB3aWxsIGJlIHVzZWQgaW5zdGVhZC5cclxuXHRcdG1heFpvb206IHVuZGVmaW5lZCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGxheWVyczogTGF5ZXJbXSA9IFtdXHJcblx0XHQvLyBBcnJheSBvZiBsYXllcnMgdGhhdCB3aWxsIGJlIGFkZGVkIHRvIHRoZSBtYXAgaW5pdGlhbGx5XHJcblx0XHRsYXllcnM6IFtdLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gbWF4Qm91bmRzOiBMYXRMbmdCb3VuZHMgPSBudWxsXHJcblx0XHQvLyBXaGVuIHRoaXMgb3B0aW9uIGlzIHNldCwgdGhlIG1hcCByZXN0cmljdHMgdGhlIHZpZXcgdG8gdGhlIGdpdmVuXHJcblx0XHQvLyBnZW9ncmFwaGljYWwgYm91bmRzLCBib3VuY2luZyB0aGUgdXNlciBiYWNrIGlmIHRoZSB1c2VyIHRyaWVzIHRvIHBhblxyXG5cdFx0Ly8gb3V0c2lkZSB0aGUgdmlldy4gVG8gc2V0IHRoZSByZXN0cmljdGlvbiBkeW5hbWljYWxseSwgdXNlXHJcblx0XHQvLyBbYHNldE1heEJvdW5kc2BdKCNtYXAtc2V0bWF4Ym91bmRzKSBtZXRob2QuXHJcblx0XHRtYXhCb3VuZHM6IHVuZGVmaW5lZCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHJlbmRlcmVyOiBSZW5kZXJlciA9ICpcclxuXHRcdC8vIFRoZSBkZWZhdWx0IG1ldGhvZCBmb3IgZHJhd2luZyB2ZWN0b3IgbGF5ZXJzIG9uIHRoZSBtYXAuIGBMLlNWR2BcclxuXHRcdC8vIG9yIGBMLkNhbnZhc2AgYnkgZGVmYXVsdCBkZXBlbmRpbmcgb24gYnJvd3NlciBzdXBwb3J0LlxyXG5cdFx0cmVuZGVyZXI6IHVuZGVmaW5lZCxcclxuXHJcblxyXG5cdFx0Ly8gQHNlY3Rpb24gQW5pbWF0aW9uIE9wdGlvbnNcclxuXHRcdC8vIEBvcHRpb24gem9vbUFuaW1hdGlvbjogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIFdoZXRoZXIgdGhlIG1hcCB6b29tIGFuaW1hdGlvbiBpcyBlbmFibGVkLiBCeSBkZWZhdWx0IGl0J3MgZW5hYmxlZFxyXG5cdFx0Ly8gaW4gYWxsIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBDU1MzIFRyYW5zaXRpb25zIGV4Y2VwdCBBbmRyb2lkLlxyXG5cdFx0em9vbUFuaW1hdGlvbjogdHJ1ZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHpvb21BbmltYXRpb25UaHJlc2hvbGQ6IE51bWJlciA9IDRcclxuXHRcdC8vIFdvbid0IGFuaW1hdGUgem9vbSBpZiB0aGUgem9vbSBkaWZmZXJlbmNlIGV4Y2VlZHMgdGhpcyB2YWx1ZS5cclxuXHRcdHpvb21BbmltYXRpb25UaHJlc2hvbGQ6IDQsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBmYWRlQW5pbWF0aW9uOiBCb29sZWFuID0gdHJ1ZVxyXG5cdFx0Ly8gV2hldGhlciB0aGUgdGlsZSBmYWRlIGFuaW1hdGlvbiBpcyBlbmFibGVkLiBCeSBkZWZhdWx0IGl0J3MgZW5hYmxlZFxyXG5cdFx0Ly8gaW4gYWxsIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBDU1MzIFRyYW5zaXRpb25zIGV4Y2VwdCBBbmRyb2lkLlxyXG5cdFx0ZmFkZUFuaW1hdGlvbjogdHJ1ZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIG1hcmtlclpvb21BbmltYXRpb246IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBXaGV0aGVyIG1hcmtlcnMgYW5pbWF0ZSB0aGVpciB6b29tIHdpdGggdGhlIHpvb20gYW5pbWF0aW9uLCBpZiBkaXNhYmxlZFxyXG5cdFx0Ly8gdGhleSB3aWxsIGRpc2FwcGVhciBmb3IgdGhlIGxlbmd0aCBvZiB0aGUgYW5pbWF0aW9uLiBCeSBkZWZhdWx0IGl0J3NcclxuXHRcdC8vIGVuYWJsZWQgaW4gYWxsIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBDU1MzIFRyYW5zaXRpb25zIGV4Y2VwdCBBbmRyb2lkLlxyXG5cdFx0bWFya2VyWm9vbUFuaW1hdGlvbjogdHJ1ZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHRyYW5zZm9ybTNETGltaXQ6IE51bWJlciA9IDJeMjNcclxuXHRcdC8vIERlZmluZXMgdGhlIG1heGltdW0gc2l6ZSBvZiBhIENTUyB0cmFuc2xhdGlvbiB0cmFuc2Zvcm0uIFRoZSBkZWZhdWx0XHJcblx0XHQvLyB2YWx1ZSBzaG91bGQgbm90IGJlIGNoYW5nZWQgdW5sZXNzIGEgd2ViIGJyb3dzZXIgcG9zaXRpb25zIGxheWVycyBpblxyXG5cdFx0Ly8gdGhlIHdyb25nIHBsYWNlIGFmdGVyIGRvaW5nIGEgbGFyZ2UgYHBhbkJ5YC5cclxuXHRcdHRyYW5zZm9ybTNETGltaXQ6IDgzODg2MDgsIC8vIFByZWNpc2lvbiBsaW1pdCBvZiBhIDMyLWJpdCBmbG9hdFxyXG5cclxuXHRcdC8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcclxuXHRcdC8vIEBvcHRpb24gem9vbVNuYXA6IE51bWJlciA9IDFcclxuXHRcdC8vIEZvcmNlcyB0aGUgbWFwJ3Mgem9vbSBsZXZlbCB0byBhbHdheXMgYmUgYSBtdWx0aXBsZSBvZiB0aGlzLCBwYXJ0aWN1bGFybHlcclxuXHRcdC8vIHJpZ2h0IGFmdGVyIGEgW2BmaXRCb3VuZHMoKWBdKCNtYXAtZml0Ym91bmRzKSBvciBhIHBpbmNoLXpvb20uXHJcblx0XHQvLyBCeSBkZWZhdWx0LCB0aGUgem9vbSBsZXZlbCBzbmFwcyB0byB0aGUgbmVhcmVzdCBpbnRlZ2VyOyBsb3dlciB2YWx1ZXNcclxuXHRcdC8vIChlLmcuIGAwLjVgIG9yIGAwLjFgKSBhbGxvdyBmb3IgZ3JlYXRlciBncmFudWxhcml0eS4gQSB2YWx1ZSBvZiBgMGBcclxuXHRcdC8vIG1lYW5zIHRoZSB6b29tIGxldmVsIHdpbGwgbm90IGJlIHNuYXBwZWQgYWZ0ZXIgYGZpdEJvdW5kc2Agb3IgYSBwaW5jaC16b29tLlxyXG5cdFx0em9vbVNuYXA6IDEsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB6b29tRGVsdGE6IE51bWJlciA9IDFcclxuXHRcdC8vIENvbnRyb2xzIGhvdyBtdWNoIHRoZSBtYXAncyB6b29tIGxldmVsIHdpbGwgY2hhbmdlIGFmdGVyIGFcclxuXHRcdC8vIFtgem9vbUluKClgXSgjbWFwLXpvb21pbiksIFtgem9vbU91dCgpYF0oI21hcC16b29tb3V0KSwgcHJlc3NpbmcgYCtgXHJcblx0XHQvLyBvciBgLWAgb24gdGhlIGtleWJvYXJkLCBvciB1c2luZyB0aGUgW3pvb20gY29udHJvbHNdKCNjb250cm9sLXpvb20pLlxyXG5cdFx0Ly8gVmFsdWVzIHNtYWxsZXIgdGhhbiBgMWAgKGUuZy4gYDAuNWApIGFsbG93IGZvciBncmVhdGVyIGdyYW51bGFyaXR5LlxyXG5cdFx0em9vbURlbHRhOiAxLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gdHJhY2tSZXNpemU6IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBXaGV0aGVyIHRoZSBtYXAgYXV0b21hdGljYWxseSBoYW5kbGVzIGJyb3dzZXIgd2luZG93IHJlc2l6ZSB0byB1cGRhdGUgaXRzZWxmLlxyXG5cdFx0dHJhY2tSZXNpemU6IHRydWVcclxuXHR9LFxyXG5cclxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAoaWQsIG9wdGlvbnMpIHsgLy8gKEhUTUxFbGVtZW50IG9yIFN0cmluZywgT2JqZWN0KVxyXG5cdFx0b3B0aW9ucyA9IHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblxyXG5cdFx0dGhpcy5faW5pdENvbnRhaW5lcihpZCk7XHJcblx0XHR0aGlzLl9pbml0TGF5b3V0KCk7XHJcblxyXG5cdFx0Ly8gaGFjayBmb3IgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMTk4MFxyXG5cdFx0dGhpcy5fb25SZXNpemUgPSBiaW5kKHRoaXMuX29uUmVzaXplLCB0aGlzKTtcclxuXHJcblx0XHR0aGlzLl9pbml0RXZlbnRzKCk7XHJcblxyXG5cdFx0aWYgKG9wdGlvbnMubWF4Qm91bmRzKSB7XHJcblx0XHRcdHRoaXMuc2V0TWF4Qm91bmRzKG9wdGlvbnMubWF4Qm91bmRzKTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAob3B0aW9ucy56b29tICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0dGhpcy5fem9vbSA9IHRoaXMuX2xpbWl0Wm9vbShvcHRpb25zLnpvb20pO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChvcHRpb25zLmNlbnRlciAmJiBvcHRpb25zLnpvb20gIT09IHVuZGVmaW5lZCkge1xyXG5cdFx0XHR0aGlzLnNldFZpZXcodG9MYXRMbmcob3B0aW9ucy5jZW50ZXIpLCBvcHRpb25zLnpvb20sIHtyZXNldDogdHJ1ZX0pO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2hhbmRsZXJzID0gW107XHJcblx0XHR0aGlzLl9sYXllcnMgPSB7fTtcclxuXHRcdHRoaXMuX3pvb21Cb3VuZExheWVycyA9IHt9O1xyXG5cdFx0dGhpcy5fc2l6ZUNoYW5nZWQgPSB0cnVlO1xyXG5cclxuXHRcdHRoaXMuY2FsbEluaXRIb29rcygpO1xyXG5cclxuXHRcdC8vIGRvbid0IGFuaW1hdGUgb24gYnJvd3NlcnMgd2l0aG91dCBoYXJkd2FyZS1hY2NlbGVyYXRlZCB0cmFuc2l0aW9ucyBvciBvbGQgQW5kcm9pZC9PcGVyYVxyXG5cdFx0dGhpcy5fem9vbUFuaW1hdGVkID0gVFJBTlNJVElPTiAmJiBhbnkzZCAmJiAhbW9iaWxlT3BlcmEgJiZcclxuXHRcdFx0XHR0aGlzLm9wdGlvbnMuem9vbUFuaW1hdGlvbjtcclxuXHJcblx0XHQvLyB6b29tIHRyYW5zaXRpb25zIHJ1biB3aXRoIHRoZSBzYW1lIGR1cmF0aW9uIGZvciBhbGwgbGF5ZXJzLCBzbyBpZiBvbmUgb2YgdHJhbnNpdGlvbmVuZCBldmVudHNcclxuXHRcdC8vIGhhcHBlbnMgYWZ0ZXIgc3RhcnRpbmcgem9vbSBhbmltYXRpb24gKHByb3BhZ2F0aW5nIHRvIHRoZSBtYXAgcGFuZSksIHdlIGtub3cgdGhhdCBpdCBlbmRlZCBnbG9iYWxseVxyXG5cdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xyXG5cdFx0XHR0aGlzLl9jcmVhdGVBbmltUHJveHkoKTtcclxuXHRcdFx0b24odGhpcy5fcHJveHksIFRSQU5TSVRJT05fRU5ELCB0aGlzLl9jYXRjaFRyYW5zaXRpb25FbmQsIHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2FkZExheWVycyh0aGlzLm9wdGlvbnMubGF5ZXJzKTtcclxuXHR9LFxyXG5cclxuXHJcblx0Ly8gQHNlY3Rpb24gTWV0aG9kcyBmb3IgbW9kaWZ5aW5nIG1hcCBzdGF0ZVxyXG5cclxuXHQvLyBAbWV0aG9kIHNldFZpZXcoY2VudGVyOiBMYXRMbmcsIHpvb206IE51bWJlciwgb3B0aW9ucz86IFpvb20vcGFuIG9wdGlvbnMpOiB0aGlzXHJcblx0Ly8gU2V0cyB0aGUgdmlldyBvZiB0aGUgbWFwIChnZW9ncmFwaGljYWwgY2VudGVyIGFuZCB6b29tKSB3aXRoIHRoZSBnaXZlblxyXG5cdC8vIGFuaW1hdGlvbiBvcHRpb25zLlxyXG5cdHNldFZpZXc6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIG9wdGlvbnMpIHtcclxuXHJcblx0XHR6b29tID0gem9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fem9vbSA6IHRoaXMuX2xpbWl0Wm9vbSh6b29tKTtcclxuXHRcdGNlbnRlciA9IHRoaXMuX2xpbWl0Q2VudGVyKHRvTGF0TG5nKGNlbnRlciksIHpvb20sIHRoaXMub3B0aW9ucy5tYXhCb3VuZHMpO1xyXG5cdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XHJcblxyXG5cdFx0dGhpcy5fc3RvcCgpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9sb2FkZWQgJiYgIW9wdGlvbnMucmVzZXQgJiYgb3B0aW9ucyAhPT0gdHJ1ZSkge1xyXG5cclxuXHRcdFx0aWYgKG9wdGlvbnMuYW5pbWF0ZSAhPT0gdW5kZWZpbmVkKSB7XHJcblx0XHRcdFx0b3B0aW9ucy56b29tID0gZXh0ZW5kKHthbmltYXRlOiBvcHRpb25zLmFuaW1hdGV9LCBvcHRpb25zLnpvb20pO1xyXG5cdFx0XHRcdG9wdGlvbnMucGFuID0gZXh0ZW5kKHthbmltYXRlOiBvcHRpb25zLmFuaW1hdGUsIGR1cmF0aW9uOiBvcHRpb25zLmR1cmF0aW9ufSwgb3B0aW9ucy5wYW4pO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyB0cnkgYW5pbWF0aW5nIHBhbiBvciB6b29tXHJcblx0XHRcdHZhciBtb3ZlZCA9ICh0aGlzLl96b29tICE9PSB6b29tKSA/XHJcblx0XHRcdFx0dGhpcy5fdHJ5QW5pbWF0ZWRab29tICYmIHRoaXMuX3RyeUFuaW1hdGVkWm9vbShjZW50ZXIsIHpvb20sIG9wdGlvbnMuem9vbSkgOlxyXG5cdFx0XHRcdHRoaXMuX3RyeUFuaW1hdGVkUGFuKGNlbnRlciwgb3B0aW9ucy5wYW4pO1xyXG5cclxuXHRcdFx0aWYgKG1vdmVkKSB7XHJcblx0XHRcdFx0Ly8gcHJldmVudCByZXNpemUgaGFuZGxlciBjYWxsLCB0aGUgdmlldyB3aWxsIHJlZnJlc2ggYWZ0ZXIgYW5pbWF0aW9uIGFueXdheVxyXG5cdFx0XHRcdGNsZWFyVGltZW91dCh0aGlzLl9zaXplVGltZXIpO1xyXG5cdFx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gYW5pbWF0aW9uIGRpZG4ndCBzdGFydCwganVzdCByZXNldCB0aGUgbWFwIHZpZXdcclxuXHRcdHRoaXMuX3Jlc2V0VmlldyhjZW50ZXIsIHpvb20pO1xyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0Wm9vbSh6b29tOiBOdW1iZXIsIG9wdGlvbnM/OiBab29tL3BhbiBvcHRpb25zKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIHpvb20gb2YgdGhlIG1hcC5cclxuXHRzZXRab29tOiBmdW5jdGlvbiAoem9vbSwgb3B0aW9ucykge1xyXG5cdFx0aWYgKCF0aGlzLl9sb2FkZWQpIHtcclxuXHRcdFx0dGhpcy5fem9vbSA9IHpvb207XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXMuc2V0Vmlldyh0aGlzLmdldENlbnRlcigpLCB6b29tLCB7em9vbTogb3B0aW9uc30pO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgem9vbUluKGRlbHRhPzogTnVtYmVyLCBvcHRpb25zPzogWm9vbSBvcHRpb25zKTogdGhpc1xyXG5cdC8vIEluY3JlYXNlcyB0aGUgem9vbSBvZiB0aGUgbWFwIGJ5IGBkZWx0YWAgKFtgem9vbURlbHRhYF0oI21hcC16b29tZGVsdGEpIGJ5IGRlZmF1bHQpLlxyXG5cdHpvb21JbjogZnVuY3Rpb24gKGRlbHRhLCBvcHRpb25zKSB7XHJcblx0XHRkZWx0YSA9IGRlbHRhIHx8IChhbnkzZCA/IHRoaXMub3B0aW9ucy56b29tRGVsdGEgOiAxKTtcclxuXHRcdHJldHVybiB0aGlzLnNldFpvb20odGhpcy5fem9vbSArIGRlbHRhLCBvcHRpb25zKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHpvb21PdXQoZGVsdGE/OiBOdW1iZXIsIG9wdGlvbnM/OiBab29tIG9wdGlvbnMpOiB0aGlzXHJcblx0Ly8gRGVjcmVhc2VzIHRoZSB6b29tIG9mIHRoZSBtYXAgYnkgYGRlbHRhYCAoW2B6b29tRGVsdGFgXSgjbWFwLXpvb21kZWx0YSkgYnkgZGVmYXVsdCkuXHJcblx0em9vbU91dDogZnVuY3Rpb24gKGRlbHRhLCBvcHRpb25zKSB7XHJcblx0XHRkZWx0YSA9IGRlbHRhIHx8IChhbnkzZCA/IHRoaXMub3B0aW9ucy56b29tRGVsdGEgOiAxKTtcclxuXHRcdHJldHVybiB0aGlzLnNldFpvb20odGhpcy5fem9vbSAtIGRlbHRhLCBvcHRpb25zKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNldFpvb21Bcm91bmQobGF0bG5nOiBMYXRMbmcsIHpvb206IE51bWJlciwgb3B0aW9uczogWm9vbSBvcHRpb25zKTogdGhpc1xyXG5cdC8vIFpvb21zIHRoZSBtYXAgd2hpbGUga2VlcGluZyBhIHNwZWNpZmllZCBnZW9ncmFwaGljYWwgcG9pbnQgb24gdGhlIG1hcFxyXG5cdC8vIHN0YXRpb25hcnkgKGUuZy4gdXNlZCBpbnRlcm5hbGx5IGZvciBzY3JvbGwgem9vbSBhbmQgZG91YmxlLWNsaWNrIHpvb20pLlxyXG5cdC8vIEBhbHRlcm5hdGl2ZVxyXG5cdC8vIEBtZXRob2Qgc2V0Wm9vbUFyb3VuZChvZmZzZXQ6IFBvaW50LCB6b29tOiBOdW1iZXIsIG9wdGlvbnM6IFpvb20gb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBab29tcyB0aGUgbWFwIHdoaWxlIGtlZXBpbmcgYSBzcGVjaWZpZWQgcGl4ZWwgb24gdGhlIG1hcCAocmVsYXRpdmUgdG8gdGhlIHRvcC1sZWZ0IGNvcm5lcikgc3RhdGlvbmFyeS5cclxuXHRzZXRab29tQXJvdW5kOiBmdW5jdGlvbiAobGF0bG5nLCB6b29tLCBvcHRpb25zKSB7XHJcblx0XHR2YXIgc2NhbGUgPSB0aGlzLmdldFpvb21TY2FsZSh6b29tKSxcclxuXHRcdCAgICB2aWV3SGFsZiA9IHRoaXMuZ2V0U2l6ZSgpLmRpdmlkZUJ5KDIpLFxyXG5cdFx0ICAgIGNvbnRhaW5lclBvaW50ID0gbGF0bG5nIGluc3RhbmNlb2YgUG9pbnQgPyBsYXRsbmcgOiB0aGlzLmxhdExuZ1RvQ29udGFpbmVyUG9pbnQobGF0bG5nKSxcclxuXHJcblx0XHQgICAgY2VudGVyT2Zmc2V0ID0gY29udGFpbmVyUG9pbnQuc3VidHJhY3Qodmlld0hhbGYpLm11bHRpcGx5QnkoMSAtIDEgLyBzY2FsZSksXHJcblx0XHQgICAgbmV3Q2VudGVyID0gdGhpcy5jb250YWluZXJQb2ludFRvTGF0TG5nKHZpZXdIYWxmLmFkZChjZW50ZXJPZmZzZXQpKTtcclxuXHJcblx0XHRyZXR1cm4gdGhpcy5zZXRWaWV3KG5ld0NlbnRlciwgem9vbSwge3pvb206IG9wdGlvbnN9KTtcclxuXHR9LFxyXG5cclxuXHRfZ2V0Qm91bmRzQ2VudGVyWm9vbTogZnVuY3Rpb24gKGJvdW5kcywgb3B0aW9ucykge1xyXG5cclxuXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xyXG5cdFx0Ym91bmRzID0gYm91bmRzLmdldEJvdW5kcyA/IGJvdW5kcy5nZXRCb3VuZHMoKSA6IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG5cdFx0dmFyIHBhZGRpbmdUTCA9IHRvUG9pbnQob3B0aW9ucy5wYWRkaW5nVG9wTGVmdCB8fCBvcHRpb25zLnBhZGRpbmcgfHwgWzAsIDBdKSxcclxuXHRcdCAgICBwYWRkaW5nQlIgPSB0b1BvaW50KG9wdGlvbnMucGFkZGluZ0JvdHRvbVJpZ2h0IHx8IG9wdGlvbnMucGFkZGluZyB8fCBbMCwgMF0pLFxyXG5cclxuXHRcdCAgICB6b29tID0gdGhpcy5nZXRCb3VuZHNab29tKGJvdW5kcywgZmFsc2UsIHBhZGRpbmdUTC5hZGQocGFkZGluZ0JSKSk7XHJcblxyXG5cdFx0em9vbSA9ICh0eXBlb2Ygb3B0aW9ucy5tYXhab29tID09PSAnbnVtYmVyJykgPyBNYXRoLm1pbihvcHRpb25zLm1heFpvb20sIHpvb20pIDogem9vbTtcclxuXHJcblx0XHRpZiAoem9vbSA9PT0gSW5maW5pdHkpIHtcclxuXHRcdFx0cmV0dXJuIHtcclxuXHRcdFx0XHRjZW50ZXI6IGJvdW5kcy5nZXRDZW50ZXIoKSxcclxuXHRcdFx0XHR6b29tOiB6b29tXHJcblx0XHRcdH07XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIHBhZGRpbmdPZmZzZXQgPSBwYWRkaW5nQlIuc3VidHJhY3QocGFkZGluZ1RMKS5kaXZpZGVCeSgyKSxcclxuXHJcblx0XHQgICAgc3dQb2ludCA9IHRoaXMucHJvamVjdChib3VuZHMuZ2V0U291dGhXZXN0KCksIHpvb20pLFxyXG5cdFx0ICAgIG5lUG9pbnQgPSB0aGlzLnByb2plY3QoYm91bmRzLmdldE5vcnRoRWFzdCgpLCB6b29tKSxcclxuXHRcdCAgICBjZW50ZXIgPSB0aGlzLnVucHJvamVjdChzd1BvaW50LmFkZChuZVBvaW50KS5kaXZpZGVCeSgyKS5hZGQocGFkZGluZ09mZnNldCksIHpvb20pO1xyXG5cclxuXHRcdHJldHVybiB7XHJcblx0XHRcdGNlbnRlcjogY2VudGVyLFxyXG5cdFx0XHR6b29tOiB6b29tXHJcblx0XHR9O1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZml0Qm91bmRzKGJvdW5kczogTGF0TG5nQm91bmRzLCBvcHRpb25zPzogZml0Qm91bmRzIG9wdGlvbnMpOiB0aGlzXHJcblx0Ly8gU2V0cyBhIG1hcCB2aWV3IHRoYXQgY29udGFpbnMgdGhlIGdpdmVuIGdlb2dyYXBoaWNhbCBib3VuZHMgd2l0aCB0aGVcclxuXHQvLyBtYXhpbXVtIHpvb20gbGV2ZWwgcG9zc2libGUuXHJcblx0Zml0Qm91bmRzOiBmdW5jdGlvbiAoYm91bmRzLCBvcHRpb25zKSB7XHJcblxyXG5cdFx0Ym91bmRzID0gdG9MYXRMbmdCb3VuZHMoYm91bmRzKTtcclxuXHJcblx0XHRpZiAoIWJvdW5kcy5pc1ZhbGlkKCkpIHtcclxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdCb3VuZHMgYXJlIG5vdCB2YWxpZC4nKTtcclxuXHRcdH1cclxuXHJcblx0XHR2YXIgdGFyZ2V0ID0gdGhpcy5fZ2V0Qm91bmRzQ2VudGVyWm9vbShib3VuZHMsIG9wdGlvbnMpO1xyXG5cdFx0cmV0dXJuIHRoaXMuc2V0Vmlldyh0YXJnZXQuY2VudGVyLCB0YXJnZXQuem9vbSwgb3B0aW9ucyk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBmaXRXb3JsZChvcHRpb25zPzogZml0Qm91bmRzIG9wdGlvbnMpOiB0aGlzXHJcblx0Ly8gU2V0cyBhIG1hcCB2aWV3IHRoYXQgbW9zdGx5IGNvbnRhaW5zIHRoZSB3aG9sZSB3b3JsZCB3aXRoIHRoZSBtYXhpbXVtXHJcblx0Ly8gem9vbSBsZXZlbCBwb3NzaWJsZS5cclxuXHRmaXRXb3JsZDogZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuXHRcdHJldHVybiB0aGlzLmZpdEJvdW5kcyhbWy05MCwgLTE4MF0sIFs5MCwgMTgwXV0sIG9wdGlvbnMpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgcGFuVG8obGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBQYW4gb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBQYW5zIHRoZSBtYXAgdG8gYSBnaXZlbiBjZW50ZXIuXHJcblx0cGFuVG86IGZ1bmN0aW9uIChjZW50ZXIsIG9wdGlvbnMpIHsgLy8gKExhdExuZylcclxuXHRcdHJldHVybiB0aGlzLnNldFZpZXcoY2VudGVyLCB0aGlzLl96b29tLCB7cGFuOiBvcHRpb25zfSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBwYW5CeShvZmZzZXQ6IFBvaW50LCBvcHRpb25zPzogUGFuIG9wdGlvbnMpOiB0aGlzXHJcblx0Ly8gUGFucyB0aGUgbWFwIGJ5IGEgZ2l2ZW4gbnVtYmVyIG9mIHBpeGVscyAoYW5pbWF0ZWQpLlxyXG5cdHBhbkJ5OiBmdW5jdGlvbiAob2Zmc2V0LCBvcHRpb25zKSB7XHJcblx0XHRvZmZzZXQgPSB0b1BvaW50KG9mZnNldCkucm91bmQoKTtcclxuXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xyXG5cclxuXHRcdGlmICghb2Zmc2V0LnggJiYgIW9mZnNldC55KSB7XHJcblx0XHRcdHJldHVybiB0aGlzLmZpcmUoJ21vdmVlbmQnKTtcclxuXHRcdH1cclxuXHRcdC8vIElmIHdlIHBhbiB0b28gZmFyLCBDaHJvbWUgZ2V0cyBpc3N1ZXMgd2l0aCB0aWxlc1xyXG5cdFx0Ly8gYW5kIG1ha2VzIHRoZW0gZGlzYXBwZWFyIG9yIGFwcGVhciBpbiB0aGUgd3JvbmcgcGxhY2UgKHNsaWdodGx5IG9mZnNldCkgIzI2MDJcclxuXHRcdGlmIChvcHRpb25zLmFuaW1hdGUgIT09IHRydWUgJiYgIXRoaXMuZ2V0U2l6ZSgpLmNvbnRhaW5zKG9mZnNldCkpIHtcclxuXHRcdFx0dGhpcy5fcmVzZXRWaWV3KHRoaXMudW5wcm9qZWN0KHRoaXMucHJvamVjdCh0aGlzLmdldENlbnRlcigpKS5hZGQob2Zmc2V0KSksIHRoaXMuZ2V0Wm9vbSgpKTtcclxuXHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCF0aGlzLl9wYW5BbmltKSB7XHJcblx0XHRcdHRoaXMuX3BhbkFuaW0gPSBuZXcgUG9zQW5pbWF0aW9uKCk7XHJcblxyXG5cdFx0XHR0aGlzLl9wYW5BbmltLm9uKHtcclxuXHRcdFx0XHQnc3RlcCc6IHRoaXMuX29uUGFuVHJhbnNpdGlvblN0ZXAsXHJcblx0XHRcdFx0J2VuZCc6IHRoaXMuX29uUGFuVHJhbnNpdGlvbkVuZFxyXG5cdFx0XHR9LCB0aGlzKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBkb24ndCBmaXJlIG1vdmVzdGFydCBpZiBhbmltYXRpbmcgaW5lcnRpYVxyXG5cdFx0aWYgKCFvcHRpb25zLm5vTW92ZVN0YXJ0KSB7XHJcblx0XHRcdHRoaXMuZmlyZSgnbW92ZXN0YXJ0Jyk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gYW5pbWF0ZSBwYW4gdW5sZXNzIGFuaW1hdGU6IGZhbHNlIHNwZWNpZmllZFxyXG5cdFx0aWYgKG9wdGlvbnMuYW5pbWF0ZSAhPT0gZmFsc2UpIHtcclxuXHRcdFx0YWRkQ2xhc3ModGhpcy5fbWFwUGFuZSwgJ2xlYWZsZXQtcGFuLWFuaW0nKTtcclxuXHJcblx0XHRcdHZhciBuZXdQb3MgPSB0aGlzLl9nZXRNYXBQYW5lUG9zKCkuc3VidHJhY3Qob2Zmc2V0KS5yb3VuZCgpO1xyXG5cdFx0XHR0aGlzLl9wYW5BbmltLnJ1bih0aGlzLl9tYXBQYW5lLCBuZXdQb3MsIG9wdGlvbnMuZHVyYXRpb24gfHwgMC4yNSwgb3B0aW9ucy5lYXNlTGluZWFyaXR5KTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdHRoaXMuX3Jhd1BhbkJ5KG9mZnNldCk7XHJcblx0XHRcdHRoaXMuZmlyZSgnbW92ZScpLmZpcmUoJ21vdmVlbmQnKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGZseVRvKGxhdGxuZzogTGF0TG5nLCB6b29tPzogTnVtYmVyLCBvcHRpb25zPzogWm9vbS9wYW4gb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBTZXRzIHRoZSB2aWV3IG9mIHRoZSBtYXAgKGdlb2dyYXBoaWNhbCBjZW50ZXIgYW5kIHpvb20pIHBlcmZvcm1pbmcgYSBzbW9vdGhcclxuXHQvLyBwYW4tem9vbSBhbmltYXRpb24uXHJcblx0Zmx5VG86IGZ1bmN0aW9uICh0YXJnZXRDZW50ZXIsIHRhcmdldFpvb20sIG9wdGlvbnMpIHtcclxuXHJcblx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcclxuXHRcdGlmIChvcHRpb25zLmFuaW1hdGUgPT09IGZhbHNlIHx8ICFhbnkzZCkge1xyXG5cdFx0XHRyZXR1cm4gdGhpcy5zZXRWaWV3KHRhcmdldENlbnRlciwgdGFyZ2V0Wm9vbSwgb3B0aW9ucyk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fc3RvcCgpO1xyXG5cclxuXHRcdHZhciBmcm9tID0gdGhpcy5wcm9qZWN0KHRoaXMuZ2V0Q2VudGVyKCkpLFxyXG5cdFx0ICAgIHRvID0gdGhpcy5wcm9qZWN0KHRhcmdldENlbnRlciksXHJcblx0XHQgICAgc2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpLFxyXG5cdFx0ICAgIHN0YXJ0Wm9vbSA9IHRoaXMuX3pvb207XHJcblxyXG5cdFx0dGFyZ2V0Q2VudGVyID0gdG9MYXRMbmcodGFyZ2V0Q2VudGVyKTtcclxuXHRcdHRhcmdldFpvb20gPSB0YXJnZXRab29tID09PSB1bmRlZmluZWQgPyBzdGFydFpvb20gOiB0YXJnZXRab29tO1xyXG5cclxuXHRcdHZhciB3MCA9IE1hdGgubWF4KHNpemUueCwgc2l6ZS55KSxcclxuXHRcdCAgICB3MSA9IHcwICogdGhpcy5nZXRab29tU2NhbGUoc3RhcnRab29tLCB0YXJnZXRab29tKSxcclxuXHRcdCAgICB1MSA9ICh0by5kaXN0YW5jZVRvKGZyb20pKSB8fCAxLFxyXG5cdFx0ICAgIHJobyA9IDEuNDIsXHJcblx0XHQgICAgcmhvMiA9IHJobyAqIHJobztcclxuXHJcblx0XHRmdW5jdGlvbiByKGkpIHtcclxuXHRcdFx0dmFyIHMxID0gaSA/IC0xIDogMSxcclxuXHRcdFx0ICAgIHMyID0gaSA/IHcxIDogdzAsXHJcblx0XHRcdCAgICB0MSA9IHcxICogdzEgLSB3MCAqIHcwICsgczEgKiByaG8yICogcmhvMiAqIHUxICogdTEsXHJcblx0XHRcdCAgICBiMSA9IDIgKiBzMiAqIHJobzIgKiB1MSxcclxuXHRcdFx0ICAgIGIgPSB0MSAvIGIxLFxyXG5cdFx0XHQgICAgc3EgPSBNYXRoLnNxcnQoYiAqIGIgKyAxKSAtIGI7XHJcblxyXG5cdFx0XHQgICAgLy8gd29ya2Fyb3VuZCBmb3IgZmxvYXRpbmcgcG9pbnQgcHJlY2lzaW9uIGJ1ZyB3aGVuIHNxID0gMCwgbG9nID0gLUluZmluaXRlLFxyXG5cdFx0XHQgICAgLy8gdGh1cyB0cmlnZ2VyaW5nIGFuIGluZmluaXRlIGxvb3AgaW4gZmx5VG9cclxuXHRcdFx0ICAgIHZhciBsb2cgPSBzcSA8IDAuMDAwMDAwMDAxID8gLTE4IDogTWF0aC5sb2coc3EpO1xyXG5cclxuXHRcdFx0cmV0dXJuIGxvZztcclxuXHRcdH1cclxuXHJcblx0XHRmdW5jdGlvbiBzaW5oKG4pIHsgcmV0dXJuIChNYXRoLmV4cChuKSAtIE1hdGguZXhwKC1uKSkgLyAyOyB9XHJcblx0XHRmdW5jdGlvbiBjb3NoKG4pIHsgcmV0dXJuIChNYXRoLmV4cChuKSArIE1hdGguZXhwKC1uKSkgLyAyOyB9XHJcblx0XHRmdW5jdGlvbiB0YW5oKG4pIHsgcmV0dXJuIHNpbmgobikgLyBjb3NoKG4pOyB9XHJcblxyXG5cdFx0dmFyIHIwID0gcigwKTtcclxuXHJcblx0XHRmdW5jdGlvbiB3KHMpIHsgcmV0dXJuIHcwICogKGNvc2gocjApIC8gY29zaChyMCArIHJobyAqIHMpKTsgfVxyXG5cdFx0ZnVuY3Rpb24gdShzKSB7IHJldHVybiB3MCAqIChjb3NoKHIwKSAqIHRhbmgocjAgKyByaG8gKiBzKSAtIHNpbmgocjApKSAvIHJobzI7IH1cclxuXHJcblx0XHRmdW5jdGlvbiBlYXNlT3V0KHQpIHsgcmV0dXJuIDEgLSBNYXRoLnBvdygxIC0gdCwgMS41KTsgfVxyXG5cclxuXHRcdHZhciBzdGFydCA9IERhdGUubm93KCksXHJcblx0XHQgICAgUyA9IChyKDEpIC0gcjApIC8gcmhvLFxyXG5cdFx0ICAgIGR1cmF0aW9uID0gb3B0aW9ucy5kdXJhdGlvbiA/IDEwMDAgKiBvcHRpb25zLmR1cmF0aW9uIDogMTAwMCAqIFMgKiAwLjg7XHJcblxyXG5cdFx0ZnVuY3Rpb24gZnJhbWUoKSB7XHJcblx0XHRcdHZhciB0ID0gKERhdGUubm93KCkgLSBzdGFydCkgLyBkdXJhdGlvbixcclxuXHRcdFx0ICAgIHMgPSBlYXNlT3V0KHQpICogUztcclxuXHJcblx0XHRcdGlmICh0IDw9IDEpIHtcclxuXHRcdFx0XHR0aGlzLl9mbHlUb0ZyYW1lID0gcmVxdWVzdEFuaW1GcmFtZShmcmFtZSwgdGhpcyk7XHJcblxyXG5cdFx0XHRcdHRoaXMuX21vdmUoXHJcblx0XHRcdFx0XHR0aGlzLnVucHJvamVjdChmcm9tLmFkZCh0by5zdWJ0cmFjdChmcm9tKS5tdWx0aXBseUJ5KHUocykgLyB1MSkpLCBzdGFydFpvb20pLFxyXG5cdFx0XHRcdFx0dGhpcy5nZXRTY2FsZVpvb20odzAgLyB3KHMpLCBzdGFydFpvb20pLFxyXG5cdFx0XHRcdFx0e2ZseVRvOiB0cnVlfSk7XHJcblxyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdHRoaXNcclxuXHRcdFx0XHRcdC5fbW92ZSh0YXJnZXRDZW50ZXIsIHRhcmdldFpvb20pXHJcblx0XHRcdFx0XHQuX21vdmVFbmQodHJ1ZSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9tb3ZlU3RhcnQodHJ1ZSwgb3B0aW9ucy5ub01vdmVTdGFydCk7XHJcblxyXG5cdFx0ZnJhbWUuY2FsbCh0aGlzKTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZmx5VG9Cb3VuZHMoYm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBmaXRCb3VuZHMgb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBTZXRzIHRoZSB2aWV3IG9mIHRoZSBtYXAgd2l0aCBhIHNtb290aCBhbmltYXRpb24gbGlrZSBbYGZseVRvYF0oI21hcC1mbHl0byksXHJcblx0Ly8gYnV0IHRha2VzIGEgYm91bmRzIHBhcmFtZXRlciBsaWtlIFtgZml0Qm91bmRzYF0oI21hcC1maXRib3VuZHMpLlxyXG5cdGZseVRvQm91bmRzOiBmdW5jdGlvbiAoYm91bmRzLCBvcHRpb25zKSB7XHJcblx0XHR2YXIgdGFyZ2V0ID0gdGhpcy5fZ2V0Qm91bmRzQ2VudGVyWm9vbShib3VuZHMsIG9wdGlvbnMpO1xyXG5cdFx0cmV0dXJuIHRoaXMuZmx5VG8odGFyZ2V0LmNlbnRlciwgdGFyZ2V0Lnpvb20sIG9wdGlvbnMpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0TWF4Qm91bmRzKGJvdW5kczogQm91bmRzKTogdGhpc1xyXG5cdC8vIFJlc3RyaWN0cyB0aGUgbWFwIHZpZXcgdG8gdGhlIGdpdmVuIGJvdW5kcyAoc2VlIHRoZSBbbWF4Qm91bmRzXSgjbWFwLW1heGJvdW5kcykgb3B0aW9uKS5cclxuXHRzZXRNYXhCb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMpIHtcclxuXHRcdGJvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG5cdFx0aWYgKCFib3VuZHMuaXNWYWxpZCgpKSB7XHJcblx0XHRcdHRoaXMub3B0aW9ucy5tYXhCb3VuZHMgPSBudWxsO1xyXG5cdFx0XHRyZXR1cm4gdGhpcy5vZmYoJ21vdmVlbmQnLCB0aGlzLl9wYW5JbnNpZGVNYXhCb3VuZHMpO1xyXG5cdFx0fSBlbHNlIGlmICh0aGlzLm9wdGlvbnMubWF4Qm91bmRzKSB7XHJcblx0XHRcdHRoaXMub2ZmKCdtb3ZlZW5kJywgdGhpcy5fcGFuSW5zaWRlTWF4Qm91bmRzKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLm9wdGlvbnMubWF4Qm91bmRzID0gYm91bmRzO1xyXG5cclxuXHRcdGlmICh0aGlzLl9sb2FkZWQpIHtcclxuXHRcdFx0dGhpcy5fcGFuSW5zaWRlTWF4Qm91bmRzKCk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXMub24oJ21vdmVlbmQnLCB0aGlzLl9wYW5JbnNpZGVNYXhCb3VuZHMpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0TWluWm9vbSh6b29tOiBOdW1iZXIpOiB0aGlzXHJcblx0Ly8gU2V0cyB0aGUgbG93ZXIgbGltaXQgZm9yIHRoZSBhdmFpbGFibGUgem9vbSBsZXZlbHMgKHNlZSB0aGUgW21pblpvb21dKCNtYXAtbWluem9vbSkgb3B0aW9uKS5cclxuXHRzZXRNaW5ab29tOiBmdW5jdGlvbiAoem9vbSkge1xyXG5cdFx0dmFyIG9sZFpvb20gPSB0aGlzLm9wdGlvbnMubWluWm9vbTtcclxuXHRcdHRoaXMub3B0aW9ucy5taW5ab29tID0gem9vbTtcclxuXHJcblx0XHRpZiAodGhpcy5fbG9hZGVkICYmIG9sZFpvb20gIT09IHpvb20pIHtcclxuXHRcdFx0dGhpcy5maXJlKCd6b29tbGV2ZWxzY2hhbmdlJyk7XHJcblxyXG5cdFx0XHRpZiAodGhpcy5nZXRab29tKCkgPCB0aGlzLm9wdGlvbnMubWluWm9vbSkge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLnNldFpvb20oem9vbSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNldE1heFpvb20oem9vbTogTnVtYmVyKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIHVwcGVyIGxpbWl0IGZvciB0aGUgYXZhaWxhYmxlIHpvb20gbGV2ZWxzIChzZWUgdGhlIFttYXhab29tXSgjbWFwLW1heHpvb20pIG9wdGlvbikuXHJcblx0c2V0TWF4Wm9vbTogZnVuY3Rpb24gKHpvb20pIHtcclxuXHRcdHZhciBvbGRab29tID0gdGhpcy5vcHRpb25zLm1heFpvb207XHJcblx0XHR0aGlzLm9wdGlvbnMubWF4Wm9vbSA9IHpvb207XHJcblxyXG5cdFx0aWYgKHRoaXMuX2xvYWRlZCAmJiBvbGRab29tICE9PSB6b29tKSB7XHJcblx0XHRcdHRoaXMuZmlyZSgnem9vbWxldmVsc2NoYW5nZScpO1xyXG5cclxuXHRcdFx0aWYgKHRoaXMuZ2V0Wm9vbSgpID4gdGhpcy5vcHRpb25zLm1heFpvb20pIHtcclxuXHRcdFx0XHRyZXR1cm4gdGhpcy5zZXRab29tKHpvb20pO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBwYW5JbnNpZGVCb3VuZHMoYm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBQYW4gb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBQYW5zIHRoZSBtYXAgdG8gdGhlIGNsb3Nlc3QgdmlldyB0aGF0IHdvdWxkIGxpZSBpbnNpZGUgdGhlIGdpdmVuIGJvdW5kcyAoaWYgaXQncyBub3QgYWxyZWFkeSksIGNvbnRyb2xsaW5nIHRoZSBhbmltYXRpb24gdXNpbmcgdGhlIG9wdGlvbnMgc3BlY2lmaWMsIGlmIGFueS5cclxuXHRwYW5JbnNpZGVCb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMsIG9wdGlvbnMpIHtcclxuXHRcdHRoaXMuX2VuZm9yY2luZ0JvdW5kcyA9IHRydWU7XHJcblx0XHR2YXIgY2VudGVyID0gdGhpcy5nZXRDZW50ZXIoKSxcclxuXHRcdCAgICBuZXdDZW50ZXIgPSB0aGlzLl9saW1pdENlbnRlcihjZW50ZXIsIHRoaXMuX3pvb20sIHRvTGF0TG5nQm91bmRzKGJvdW5kcykpO1xyXG5cclxuXHRcdGlmICghY2VudGVyLmVxdWFscyhuZXdDZW50ZXIpKSB7XHJcblx0XHRcdHRoaXMucGFuVG8obmV3Q2VudGVyLCBvcHRpb25zKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9lbmZvcmNpbmdCb3VuZHMgPSBmYWxzZTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgaW52YWxpZGF0ZVNpemUob3B0aW9uczogWm9vbS9wYW4gb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBDaGVja3MgaWYgdGhlIG1hcCBjb250YWluZXIgc2l6ZSBjaGFuZ2VkIGFuZCB1cGRhdGVzIHRoZSBtYXAgaWYgc28g4oCUXHJcblx0Ly8gY2FsbCBpdCBhZnRlciB5b3UndmUgY2hhbmdlZCB0aGUgbWFwIHNpemUgZHluYW1pY2FsbHksIGFsc28gYW5pbWF0aW5nXHJcblx0Ly8gcGFuIGJ5IGRlZmF1bHQuIElmIGBvcHRpb25zLnBhbmAgaXMgYGZhbHNlYCwgcGFubmluZyB3aWxsIG5vdCBvY2N1ci5cclxuXHQvLyBJZiBgb3B0aW9ucy5kZWJvdW5jZU1vdmVlbmRgIGlzIGB0cnVlYCwgaXQgd2lsbCBkZWxheSBgbW92ZWVuZGAgZXZlbnQgc29cclxuXHQvLyB0aGF0IGl0IGRvZXNuJ3QgaGFwcGVuIG9mdGVuIGV2ZW4gaWYgdGhlIG1ldGhvZCBpcyBjYWxsZWQgbWFueVxyXG5cdC8vIHRpbWVzIGluIGEgcm93LlxyXG5cclxuXHQvLyBAYWx0ZXJuYXRpdmVcclxuXHQvLyBAbWV0aG9kIGludmFsaWRhdGVTaXplKGFuaW1hdGU6IEJvb2xlYW4pOiB0aGlzXHJcblx0Ly8gQ2hlY2tzIGlmIHRoZSBtYXAgY29udGFpbmVyIHNpemUgY2hhbmdlZCBhbmQgdXBkYXRlcyB0aGUgbWFwIGlmIHNvIOKAlFxyXG5cdC8vIGNhbGwgaXQgYWZ0ZXIgeW91J3ZlIGNoYW5nZWQgdGhlIG1hcCBzaXplIGR5bmFtaWNhbGx5LCBhbHNvIGFuaW1hdGluZ1xyXG5cdC8vIHBhbiBieSBkZWZhdWx0LlxyXG5cdGludmFsaWRhdGVTaXplOiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG5cdFx0aWYgKCF0aGlzLl9sb2FkZWQpIHsgcmV0dXJuIHRoaXM7IH1cclxuXHJcblx0XHRvcHRpb25zID0gZXh0ZW5kKHtcclxuXHRcdFx0YW5pbWF0ZTogZmFsc2UsXHJcblx0XHRcdHBhbjogdHJ1ZVxyXG5cdFx0fSwgb3B0aW9ucyA9PT0gdHJ1ZSA/IHthbmltYXRlOiB0cnVlfSA6IG9wdGlvbnMpO1xyXG5cclxuXHRcdHZhciBvbGRTaXplID0gdGhpcy5nZXRTaXplKCk7XHJcblx0XHR0aGlzLl9zaXplQ2hhbmdlZCA9IHRydWU7XHJcblx0XHR0aGlzLl9sYXN0Q2VudGVyID0gbnVsbDtcclxuXHJcblx0XHR2YXIgbmV3U2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpLFxyXG5cdFx0ICAgIG9sZENlbnRlciA9IG9sZFNpemUuZGl2aWRlQnkoMikucm91bmQoKSxcclxuXHRcdCAgICBuZXdDZW50ZXIgPSBuZXdTaXplLmRpdmlkZUJ5KDIpLnJvdW5kKCksXHJcblx0XHQgICAgb2Zmc2V0ID0gb2xkQ2VudGVyLnN1YnRyYWN0KG5ld0NlbnRlcik7XHJcblxyXG5cdFx0aWYgKCFvZmZzZXQueCAmJiAhb2Zmc2V0LnkpIHsgcmV0dXJuIHRoaXM7IH1cclxuXHJcblx0XHRpZiAob3B0aW9ucy5hbmltYXRlICYmIG9wdGlvbnMucGFuKSB7XHJcblx0XHRcdHRoaXMucGFuQnkob2Zmc2V0KTtcclxuXHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRpZiAob3B0aW9ucy5wYW4pIHtcclxuXHRcdFx0XHR0aGlzLl9yYXdQYW5CeShvZmZzZXQpO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR0aGlzLmZpcmUoJ21vdmUnKTtcclxuXHJcblx0XHRcdGlmIChvcHRpb25zLmRlYm91bmNlTW92ZWVuZCkge1xyXG5cdFx0XHRcdGNsZWFyVGltZW91dCh0aGlzLl9zaXplVGltZXIpO1xyXG5cdFx0XHRcdHRoaXMuX3NpemVUaW1lciA9IHNldFRpbWVvdXQoYmluZCh0aGlzLmZpcmUsIHRoaXMsICdtb3ZlZW5kJyksIDIwMCk7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0dGhpcy5maXJlKCdtb3ZlZW5kJyk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHQvLyBAc2VjdGlvbiBNYXAgc3RhdGUgY2hhbmdlIGV2ZW50c1xyXG5cdFx0Ly8gQGV2ZW50IHJlc2l6ZTogUmVzaXplRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcCBpcyByZXNpemVkLlxyXG5cdFx0cmV0dXJuIHRoaXMuZmlyZSgncmVzaXplJywge1xyXG5cdFx0XHRvbGRTaXplOiBvbGRTaXplLFxyXG5cdFx0XHRuZXdTaXplOiBuZXdTaXplXHJcblx0XHR9KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAc2VjdGlvbiBNZXRob2RzIGZvciBtb2RpZnlpbmcgbWFwIHN0YXRlXHJcblx0Ly8gQG1ldGhvZCBzdG9wKCk6IHRoaXNcclxuXHQvLyBTdG9wcyB0aGUgY3VycmVudGx5IHJ1bm5pbmcgYHBhblRvYCBvciBgZmx5VG9gIGFuaW1hdGlvbiwgaWYgYW55LlxyXG5cdHN0b3A6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuc2V0Wm9vbSh0aGlzLl9saW1pdFpvb20odGhpcy5fem9vbSkpO1xyXG5cdFx0aWYgKCF0aGlzLm9wdGlvbnMuem9vbVNuYXApIHtcclxuXHRcdFx0dGhpcy5maXJlKCd2aWV3cmVzZXQnKTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzLl9zdG9wKCk7XHJcblx0fSxcclxuXHJcblx0Ly8gQHNlY3Rpb24gR2VvbG9jYXRpb24gbWV0aG9kc1xyXG5cdC8vIEBtZXRob2QgbG9jYXRlKG9wdGlvbnM/OiBMb2NhdGUgb3B0aW9ucyk6IHRoaXNcclxuXHQvLyBUcmllcyB0byBsb2NhdGUgdGhlIHVzZXIgdXNpbmcgdGhlIEdlb2xvY2F0aW9uIEFQSSwgZmlyaW5nIGEgW2Bsb2NhdGlvbmZvdW5kYF0oI21hcC1sb2NhdGlvbmZvdW5kKVxyXG5cdC8vIGV2ZW50IHdpdGggbG9jYXRpb24gZGF0YSBvbiBzdWNjZXNzIG9yIGEgW2Bsb2NhdGlvbmVycm9yYF0oI21hcC1sb2NhdGlvbmVycm9yKSBldmVudCBvbiBmYWlsdXJlLFxyXG5cdC8vIGFuZCBvcHRpb25hbGx5IHNldHMgdGhlIG1hcCB2aWV3IHRvIHRoZSB1c2VyJ3MgbG9jYXRpb24gd2l0aCByZXNwZWN0IHRvXHJcblx0Ly8gZGV0ZWN0aW9uIGFjY3VyYWN5IChvciB0byB0aGUgd29ybGQgdmlldyBpZiBnZW9sb2NhdGlvbiBmYWlsZWQpLlxyXG5cdC8vIE5vdGUgdGhhdCwgaWYgeW91ciBwYWdlIGRvZXNuJ3QgdXNlIEhUVFBTLCB0aGlzIG1ldGhvZCB3aWxsIGZhaWwgaW5cclxuXHQvLyBtb2Rlcm4gYnJvd3NlcnMgKFtDaHJvbWUgNTAgYW5kIG5ld2VyXShodHRwczovL3NpdGVzLmdvb2dsZS5jb20vYS9jaHJvbWl1bS5vcmcvZGV2L0hvbWUvY2hyb21pdW0tc2VjdXJpdHkvZGVwcmVjYXRpbmctcG93ZXJmdWwtZmVhdHVyZXMtb24taW5zZWN1cmUtb3JpZ2lucykpXHJcblx0Ly8gU2VlIGBMb2NhdGUgb3B0aW9uc2AgZm9yIG1vcmUgZGV0YWlscy5cclxuXHRsb2NhdGU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblxyXG5cdFx0b3B0aW9ucyA9IHRoaXMuX2xvY2F0ZU9wdGlvbnMgPSBleHRlbmQoe1xyXG5cdFx0XHR0aW1lb3V0OiAxMDAwMCxcclxuXHRcdFx0d2F0Y2g6IGZhbHNlXHJcblx0XHRcdC8vIHNldFZpZXc6IGZhbHNlXHJcblx0XHRcdC8vIG1heFpvb206IDxOdW1iZXI+XHJcblx0XHRcdC8vIG1heGltdW1BZ2U6IDBcclxuXHRcdFx0Ly8gZW5hYmxlSGlnaEFjY3VyYWN5OiBmYWxzZVxyXG5cdFx0fSwgb3B0aW9ucyk7XHJcblxyXG5cdFx0aWYgKCEoJ2dlb2xvY2F0aW9uJyBpbiBuYXZpZ2F0b3IpKSB7XHJcblx0XHRcdHRoaXMuX2hhbmRsZUdlb2xvY2F0aW9uRXJyb3Ioe1xyXG5cdFx0XHRcdGNvZGU6IDAsXHJcblx0XHRcdFx0bWVzc2FnZTogJ0dlb2xvY2F0aW9uIG5vdCBzdXBwb3J0ZWQuJ1xyXG5cdFx0XHR9KTtcclxuXHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIG9uUmVzcG9uc2UgPSBiaW5kKHRoaXMuX2hhbmRsZUdlb2xvY2F0aW9uUmVzcG9uc2UsIHRoaXMpLFxyXG5cdFx0ICAgIG9uRXJyb3IgPSBiaW5kKHRoaXMuX2hhbmRsZUdlb2xvY2F0aW9uRXJyb3IsIHRoaXMpO1xyXG5cclxuXHRcdGlmIChvcHRpb25zLndhdGNoKSB7XHJcblx0XHRcdHRoaXMuX2xvY2F0aW9uV2F0Y2hJZCA9XHJcblx0XHRcdCAgICAgICAgbmF2aWdhdG9yLmdlb2xvY2F0aW9uLndhdGNoUG9zaXRpb24ob25SZXNwb25zZSwgb25FcnJvciwgb3B0aW9ucyk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRuYXZpZ2F0b3IuZ2VvbG9jYXRpb24uZ2V0Q3VycmVudFBvc2l0aW9uKG9uUmVzcG9uc2UsIG9uRXJyb3IsIG9wdGlvbnMpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzdG9wTG9jYXRlKCk6IHRoaXNcclxuXHQvLyBTdG9wcyB3YXRjaGluZyBsb2NhdGlvbiBwcmV2aW91c2x5IGluaXRpYXRlZCBieSBgbWFwLmxvY2F0ZSh7d2F0Y2g6IHRydWV9KWBcclxuXHQvLyBhbmQgYWJvcnRzIHJlc2V0dGluZyB0aGUgbWFwIHZpZXcgaWYgbWFwLmxvY2F0ZSB3YXMgY2FsbGVkIHdpdGhcclxuXHQvLyBge3NldFZpZXc6IHRydWV9YC5cclxuXHRzdG9wTG9jYXRlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAobmF2aWdhdG9yLmdlb2xvY2F0aW9uICYmIG5hdmlnYXRvci5nZW9sb2NhdGlvbi5jbGVhcldhdGNoKSB7XHJcblx0XHRcdG5hdmlnYXRvci5nZW9sb2NhdGlvbi5jbGVhcldhdGNoKHRoaXMuX2xvY2F0aW9uV2F0Y2hJZCk7XHJcblx0XHR9XHJcblx0XHRpZiAodGhpcy5fbG9jYXRlT3B0aW9ucykge1xyXG5cdFx0XHR0aGlzLl9sb2NhdGVPcHRpb25zLnNldFZpZXcgPSBmYWxzZTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdF9oYW5kbGVHZW9sb2NhdGlvbkVycm9yOiBmdW5jdGlvbiAoZXJyb3IpIHtcclxuXHRcdHZhciBjID0gZXJyb3IuY29kZSxcclxuXHRcdCAgICBtZXNzYWdlID0gZXJyb3IubWVzc2FnZSB8fFxyXG5cdFx0ICAgICAgICAgICAgKGMgPT09IDEgPyAncGVybWlzc2lvbiBkZW5pZWQnIDpcclxuXHRcdCAgICAgICAgICAgIChjID09PSAyID8gJ3Bvc2l0aW9uIHVuYXZhaWxhYmxlJyA6ICd0aW1lb3V0JykpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9sb2NhdGVPcHRpb25zLnNldFZpZXcgJiYgIXRoaXMuX2xvYWRlZCkge1xyXG5cdFx0XHR0aGlzLmZpdFdvcmxkKCk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQHNlY3Rpb24gTG9jYXRpb24gZXZlbnRzXHJcblx0XHQvLyBAZXZlbnQgbG9jYXRpb25lcnJvcjogRXJyb3JFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiBnZW9sb2NhdGlvbiAodXNpbmcgdGhlIFtgbG9jYXRlYF0oI21hcC1sb2NhdGUpIG1ldGhvZCkgZmFpbGVkLlxyXG5cdFx0dGhpcy5maXJlKCdsb2NhdGlvbmVycm9yJywge1xyXG5cdFx0XHRjb2RlOiBjLFxyXG5cdFx0XHRtZXNzYWdlOiAnR2VvbG9jYXRpb24gZXJyb3I6ICcgKyBtZXNzYWdlICsgJy4nXHJcblx0XHR9KTtcclxuXHR9LFxyXG5cclxuXHRfaGFuZGxlR2VvbG9jYXRpb25SZXNwb25zZTogZnVuY3Rpb24gKHBvcykge1xyXG5cdFx0dmFyIGxhdCA9IHBvcy5jb29yZHMubGF0aXR1ZGUsXHJcblx0XHQgICAgbG5nID0gcG9zLmNvb3Jkcy5sb25naXR1ZGUsXHJcblx0XHQgICAgbGF0bG5nID0gbmV3IExhdExuZyhsYXQsIGxuZyksXHJcblx0XHQgICAgYm91bmRzID0gbGF0bG5nLnRvQm91bmRzKHBvcy5jb29yZHMuYWNjdXJhY3kpLFxyXG5cdFx0ICAgIG9wdGlvbnMgPSB0aGlzLl9sb2NhdGVPcHRpb25zO1xyXG5cclxuXHRcdGlmIChvcHRpb25zLnNldFZpZXcpIHtcclxuXHRcdFx0dmFyIHpvb20gPSB0aGlzLmdldEJvdW5kc1pvb20oYm91bmRzKTtcclxuXHRcdFx0dGhpcy5zZXRWaWV3KGxhdGxuZywgb3B0aW9ucy5tYXhab29tID8gTWF0aC5taW4oem9vbSwgb3B0aW9ucy5tYXhab29tKSA6IHpvb20pO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBkYXRhID0ge1xyXG5cdFx0XHRsYXRsbmc6IGxhdGxuZyxcclxuXHRcdFx0Ym91bmRzOiBib3VuZHMsXHJcblx0XHRcdHRpbWVzdGFtcDogcG9zLnRpbWVzdGFtcFxyXG5cdFx0fTtcclxuXHJcblx0XHRmb3IgKHZhciBpIGluIHBvcy5jb29yZHMpIHtcclxuXHRcdFx0aWYgKHR5cGVvZiBwb3MuY29vcmRzW2ldID09PSAnbnVtYmVyJykge1xyXG5cdFx0XHRcdGRhdGFbaV0gPSBwb3MuY29vcmRzW2ldO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQGV2ZW50IGxvY2F0aW9uZm91bmQ6IExvY2F0aW9uRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gZ2VvbG9jYXRpb24gKHVzaW5nIHRoZSBbYGxvY2F0ZWBdKCNtYXAtbG9jYXRlKSBtZXRob2QpXHJcblx0XHQvLyB3ZW50IHN1Y2Nlc3NmdWxseS5cclxuXHRcdHRoaXMuZmlyZSgnbG9jYXRpb25mb3VuZCcsIGRhdGEpO1xyXG5cdH0sXHJcblxyXG5cdC8vIFRPRE8gQXBwcm9wcmlhdGUgZG9jcyBzZWN0aW9uP1xyXG5cdC8vIEBzZWN0aW9uIE90aGVyIE1ldGhvZHNcclxuXHQvLyBAbWV0aG9kIGFkZEhhbmRsZXIobmFtZTogU3RyaW5nLCBIYW5kbGVyQ2xhc3M6IEZ1bmN0aW9uKTogdGhpc1xyXG5cdC8vIEFkZHMgYSBuZXcgYEhhbmRsZXJgIHRvIHRoZSBtYXAsIGdpdmVuIGl0cyBuYW1lIGFuZCBjb25zdHJ1Y3RvciBmdW5jdGlvbi5cclxuXHRhZGRIYW5kbGVyOiBmdW5jdGlvbiAobmFtZSwgSGFuZGxlckNsYXNzKSB7XHJcblx0XHRpZiAoIUhhbmRsZXJDbGFzcykgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdHZhciBoYW5kbGVyID0gdGhpc1tuYW1lXSA9IG5ldyBIYW5kbGVyQ2xhc3ModGhpcyk7XHJcblxyXG5cdFx0dGhpcy5faGFuZGxlcnMucHVzaChoYW5kbGVyKTtcclxuXHJcblx0XHRpZiAodGhpcy5vcHRpb25zW25hbWVdKSB7XHJcblx0XHRcdGhhbmRsZXIuZW5hYmxlKCk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCByZW1vdmUoKTogdGhpc1xyXG5cdC8vIERlc3Ryb3lzIHRoZSBtYXAgYW5kIGNsZWFycyBhbGwgcmVsYXRlZCBldmVudCBsaXN0ZW5lcnMuXHJcblx0cmVtb3ZlOiBmdW5jdGlvbiAoKSB7XHJcblxyXG5cdFx0dGhpcy5faW5pdEV2ZW50cyh0cnVlKTtcclxuXHJcblx0XHRpZiAodGhpcy5fY29udGFpbmVySWQgIT09IHRoaXMuX2NvbnRhaW5lci5fbGVhZmxldF9pZCkge1xyXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01hcCBjb250YWluZXIgaXMgYmVpbmcgcmV1c2VkIGJ5IGFub3RoZXIgaW5zdGFuY2UnKTtcclxuXHRcdH1cclxuXHJcblx0XHR0cnkge1xyXG5cdFx0XHQvLyB0aHJvd3MgZXJyb3IgaW4gSUU2LThcclxuXHRcdFx0ZGVsZXRlIHRoaXMuX2NvbnRhaW5lci5fbGVhZmxldF9pZDtcclxuXHRcdFx0ZGVsZXRlIHRoaXMuX2NvbnRhaW5lcklkO1xyXG5cdFx0fSBjYXRjaCAoZSkge1xyXG5cdFx0XHQvKmVzbGludC1kaXNhYmxlICovXHJcblx0XHRcdHRoaXMuX2NvbnRhaW5lci5fbGVhZmxldF9pZCA9IHVuZGVmaW5lZDtcclxuXHRcdFx0LyogZXNsaW50LWVuYWJsZSAqL1xyXG5cdFx0XHR0aGlzLl9jb250YWluZXJJZCA9IHVuZGVmaW5lZDtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAodGhpcy5fbG9jYXRpb25XYXRjaElkICE9PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0dGhpcy5zdG9wTG9jYXRlKCk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fc3RvcCgpO1xyXG5cclxuXHRcdHJlbW92ZSh0aGlzLl9tYXBQYW5lKTtcclxuXHJcblx0XHRpZiAodGhpcy5fY2xlYXJDb250cm9sUG9zKSB7XHJcblx0XHRcdHRoaXMuX2NsZWFyQ29udHJvbFBvcygpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2NsZWFySGFuZGxlcnMoKTtcclxuXHJcblx0XHRpZiAodGhpcy5fbG9hZGVkKSB7XHJcblx0XHRcdC8vIEBzZWN0aW9uIE1hcCBzdGF0ZSBjaGFuZ2UgZXZlbnRzXHJcblx0XHRcdC8vIEBldmVudCB1bmxvYWQ6IEV2ZW50XHJcblx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcCBpcyBkZXN0cm95ZWQgd2l0aCBbcmVtb3ZlXSgjbWFwLXJlbW92ZSkgbWV0aG9kLlxyXG5cdFx0XHR0aGlzLmZpcmUoJ3VubG9hZCcpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBpO1xyXG5cdFx0Zm9yIChpIGluIHRoaXMuX2xheWVycykge1xyXG5cdFx0XHR0aGlzLl9sYXllcnNbaV0ucmVtb3ZlKCk7XHJcblx0XHR9XHJcblx0XHRmb3IgKGkgaW4gdGhpcy5fcGFuZXMpIHtcclxuXHRcdFx0cmVtb3ZlKHRoaXMuX3BhbmVzW2ldKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9sYXllcnMgPSBbXTtcclxuXHRcdHRoaXMuX3BhbmVzID0gW107XHJcblx0XHRkZWxldGUgdGhpcy5fbWFwUGFuZTtcclxuXHRcdGRlbGV0ZSB0aGlzLl9yZW5kZXJlcjtcclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAc2VjdGlvbiBPdGhlciBNZXRob2RzXHJcblx0Ly8gQG1ldGhvZCBjcmVhdGVQYW5lKG5hbWU6IFN0cmluZywgY29udGFpbmVyPzogSFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudFxyXG5cdC8vIENyZWF0ZXMgYSBuZXcgW21hcCBwYW5lXSgjbWFwLXBhbmUpIHdpdGggdGhlIGdpdmVuIG5hbWUgaWYgaXQgZG9lc24ndCBleGlzdCBhbHJlYWR5LFxyXG5cdC8vIHRoZW4gcmV0dXJucyBpdC4gVGhlIHBhbmUgaXMgY3JlYXRlZCBhcyBhIGNoaWxkIG9mIGBjb250YWluZXJgLCBvclxyXG5cdC8vIGFzIGEgY2hpbGQgb2YgdGhlIG1haW4gbWFwIHBhbmUgaWYgbm90IHNldC5cclxuXHRjcmVhdGVQYW5lOiBmdW5jdGlvbiAobmFtZSwgY29udGFpbmVyKSB7XHJcblx0XHR2YXIgY2xhc3NOYW1lID0gJ2xlYWZsZXQtcGFuZScgKyAobmFtZSA/ICcgbGVhZmxldC0nICsgbmFtZS5yZXBsYWNlKCdQYW5lJywgJycpICsgJy1wYW5lJyA6ICcnKSxcclxuXHRcdCAgICBwYW5lID0gY3JlYXRlJDEoJ2RpdicsIGNsYXNzTmFtZSwgY29udGFpbmVyIHx8IHRoaXMuX21hcFBhbmUpO1xyXG5cclxuXHRcdGlmIChuYW1lKSB7XHJcblx0XHRcdHRoaXMuX3BhbmVzW25hbWVdID0gcGFuZTtcclxuXHRcdH1cclxuXHRcdHJldHVybiBwYW5lO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBzZWN0aW9uIE1ldGhvZHMgZm9yIEdldHRpbmcgTWFwIFN0YXRlXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0Q2VudGVyKCk6IExhdExuZ1xyXG5cdC8vIFJldHVybnMgdGhlIGdlb2dyYXBoaWNhbCBjZW50ZXIgb2YgdGhlIG1hcCB2aWV3XHJcblx0Z2V0Q2VudGVyOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR0aGlzLl9jaGVja0lmTG9hZGVkKCk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX2xhc3RDZW50ZXIgJiYgIXRoaXMuX21vdmVkKCkpIHtcclxuXHRcdFx0cmV0dXJuIHRoaXMuX2xhc3RDZW50ZXI7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcy5sYXllclBvaW50VG9MYXRMbmcodGhpcy5fZ2V0Q2VudGVyTGF5ZXJQb2ludCgpKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldFpvb20oKTogTnVtYmVyXHJcblx0Ly8gUmV0dXJucyB0aGUgY3VycmVudCB6b29tIGxldmVsIG9mIHRoZSBtYXAgdmlld1xyXG5cdGdldFpvb206IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl96b29tO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0Qm91bmRzKCk6IExhdExuZ0JvdW5kc1xyXG5cdC8vIFJldHVybnMgdGhlIGdlb2dyYXBoaWNhbCBib3VuZHMgdmlzaWJsZSBpbiB0aGUgY3VycmVudCBtYXAgdmlld1xyXG5cdGdldEJvdW5kczogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGJvdW5kcyA9IHRoaXMuZ2V0UGl4ZWxCb3VuZHMoKSxcclxuXHRcdCAgICBzdyA9IHRoaXMudW5wcm9qZWN0KGJvdW5kcy5nZXRCb3R0b21MZWZ0KCkpLFxyXG5cdFx0ICAgIG5lID0gdGhpcy51bnByb2plY3QoYm91bmRzLmdldFRvcFJpZ2h0KCkpO1xyXG5cclxuXHRcdHJldHVybiBuZXcgTGF0TG5nQm91bmRzKHN3LCBuZSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRNaW5ab29tKCk6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIG1pbmltdW0gem9vbSBsZXZlbCBvZiB0aGUgbWFwIChpZiBzZXQgaW4gdGhlIGBtaW5ab29tYCBvcHRpb24gb2YgdGhlIG1hcCBvciBvZiBhbnkgbGF5ZXJzKSwgb3IgYDBgIGJ5IGRlZmF1bHQuXHJcblx0Z2V0TWluWm9vbTogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5taW5ab29tID09PSB1bmRlZmluZWQgPyB0aGlzLl9sYXllcnNNaW5ab29tIHx8IDAgOiB0aGlzLm9wdGlvbnMubWluWm9vbTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldE1heFpvb20oKTogTnVtYmVyXHJcblx0Ly8gUmV0dXJucyB0aGUgbWF4aW11bSB6b29tIGxldmVsIG9mIHRoZSBtYXAgKGlmIHNldCBpbiB0aGUgYG1heFpvb21gIG9wdGlvbiBvZiB0aGUgbWFwIG9yIG9mIGFueSBsYXllcnMpLlxyXG5cdGdldE1heFpvb206IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLm9wdGlvbnMubWF4Wm9vbSA9PT0gdW5kZWZpbmVkID9cclxuXHRcdFx0KHRoaXMuX2xheWVyc01heFpvb20gPT09IHVuZGVmaW5lZCA/IEluZmluaXR5IDogdGhpcy5fbGF5ZXJzTWF4Wm9vbSkgOlxyXG5cdFx0XHR0aGlzLm9wdGlvbnMubWF4Wm9vbTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldEJvdW5kc1pvb20oYm91bmRzOiBMYXRMbmdCb3VuZHMsIGluc2lkZT86IEJvb2xlYW4pOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBtYXhpbXVtIHpvb20gbGV2ZWwgb24gd2hpY2ggdGhlIGdpdmVuIGJvdW5kcyBmaXQgdG8gdGhlIG1hcFxyXG5cdC8vIHZpZXcgaW4gaXRzIGVudGlyZXR5LiBJZiBgaW5zaWRlYCAob3B0aW9uYWwpIGlzIHNldCB0byBgdHJ1ZWAsIHRoZSBtZXRob2RcclxuXHQvLyBpbnN0ZWFkIHJldHVybnMgdGhlIG1pbmltdW0gem9vbSBsZXZlbCBvbiB3aGljaCB0aGUgbWFwIHZpZXcgZml0cyBpbnRvXHJcblx0Ly8gdGhlIGdpdmVuIGJvdW5kcyBpbiBpdHMgZW50aXJldHkuXHJcblx0Z2V0Qm91bmRzWm9vbTogZnVuY3Rpb24gKGJvdW5kcywgaW5zaWRlLCBwYWRkaW5nKSB7IC8vIChMYXRMbmdCb3VuZHNbLCBCb29sZWFuLCBQb2ludF0pIC0+IE51bWJlclxyXG5cdFx0Ym91bmRzID0gdG9MYXRMbmdCb3VuZHMoYm91bmRzKTtcclxuXHRcdHBhZGRpbmcgPSB0b1BvaW50KHBhZGRpbmcgfHwgWzAsIDBdKTtcclxuXHJcblx0XHR2YXIgem9vbSA9IHRoaXMuZ2V0Wm9vbSgpIHx8IDAsXHJcblx0XHQgICAgbWluID0gdGhpcy5nZXRNaW5ab29tKCksXHJcblx0XHQgICAgbWF4ID0gdGhpcy5nZXRNYXhab29tKCksXHJcblx0XHQgICAgbncgPSBib3VuZHMuZ2V0Tm9ydGhXZXN0KCksXHJcblx0XHQgICAgc2UgPSBib3VuZHMuZ2V0U291dGhFYXN0KCksXHJcblx0XHQgICAgc2l6ZSA9IHRoaXMuZ2V0U2l6ZSgpLnN1YnRyYWN0KHBhZGRpbmcpLFxyXG5cdFx0ICAgIGJvdW5kc1NpemUgPSB0b0JvdW5kcyh0aGlzLnByb2plY3Qoc2UsIHpvb20pLCB0aGlzLnByb2plY3QobncsIHpvb20pKS5nZXRTaXplKCksXHJcblx0XHQgICAgc25hcCA9IGFueTNkID8gdGhpcy5vcHRpb25zLnpvb21TbmFwIDogMSxcclxuXHRcdCAgICBzY2FsZXggPSBzaXplLnggLyBib3VuZHNTaXplLngsXHJcblx0XHQgICAgc2NhbGV5ID0gc2l6ZS55IC8gYm91bmRzU2l6ZS55LFxyXG5cdFx0ICAgIHNjYWxlID0gaW5zaWRlID8gTWF0aC5tYXgoc2NhbGV4LCBzY2FsZXkpIDogTWF0aC5taW4oc2NhbGV4LCBzY2FsZXkpO1xyXG5cclxuXHRcdHpvb20gPSB0aGlzLmdldFNjYWxlWm9vbShzY2FsZSwgem9vbSk7XHJcblxyXG5cdFx0aWYgKHNuYXApIHtcclxuXHRcdFx0em9vbSA9IE1hdGgucm91bmQoem9vbSAvIChzbmFwIC8gMTAwKSkgKiAoc25hcCAvIDEwMCk7IC8vIGRvbid0IGp1bXAgaWYgd2l0aGluIDElIG9mIGEgc25hcCBsZXZlbFxyXG5cdFx0XHR6b29tID0gaW5zaWRlID8gTWF0aC5jZWlsKHpvb20gLyBzbmFwKSAqIHNuYXAgOiBNYXRoLmZsb29yKHpvb20gLyBzbmFwKSAqIHNuYXA7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIE1hdGgubWF4KG1pbiwgTWF0aC5taW4obWF4LCB6b29tKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRTaXplKCk6IFBvaW50XHJcblx0Ly8gUmV0dXJucyB0aGUgY3VycmVudCBzaXplIG9mIHRoZSBtYXAgY29udGFpbmVyIChpbiBwaXhlbHMpLlxyXG5cdGdldFNpemU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICghdGhpcy5fc2l6ZSB8fCB0aGlzLl9zaXplQ2hhbmdlZCkge1xyXG5cdFx0XHR0aGlzLl9zaXplID0gbmV3IFBvaW50KFxyXG5cdFx0XHRcdHRoaXMuX2NvbnRhaW5lci5jbGllbnRXaWR0aCB8fCAwLFxyXG5cdFx0XHRcdHRoaXMuX2NvbnRhaW5lci5jbGllbnRIZWlnaHQgfHwgMCk7XHJcblxyXG5cdFx0XHR0aGlzLl9zaXplQ2hhbmdlZCA9IGZhbHNlO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXMuX3NpemUuY2xvbmUoKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldFBpeGVsQm91bmRzKCk6IEJvdW5kc1xyXG5cdC8vIFJldHVybnMgdGhlIGJvdW5kcyBvZiB0aGUgY3VycmVudCBtYXAgdmlldyBpbiBwcm9qZWN0ZWQgcGl4ZWxcclxuXHQvLyBjb29yZGluYXRlcyAoc29tZXRpbWVzIHVzZWZ1bCBpbiBsYXllciBhbmQgb3ZlcmxheSBpbXBsZW1lbnRhdGlvbnMpLlxyXG5cdGdldFBpeGVsQm91bmRzOiBmdW5jdGlvbiAoY2VudGVyLCB6b29tKSB7XHJcblx0XHR2YXIgdG9wTGVmdFBvaW50ID0gdGhpcy5fZ2V0VG9wTGVmdFBvaW50KGNlbnRlciwgem9vbSk7XHJcblx0XHRyZXR1cm4gbmV3IEJvdW5kcyh0b3BMZWZ0UG9pbnQsIHRvcExlZnRQb2ludC5hZGQodGhpcy5nZXRTaXplKCkpKTtcclxuXHR9LFxyXG5cclxuXHQvLyBUT0RPOiBDaGVjayBzZW1hbnRpY3MgLSBpc24ndCB0aGUgcGl4ZWwgb3JpZ2luIHRoZSAwLDAgY29vcmQgcmVsYXRpdmUgdG9cclxuXHQvLyB0aGUgbWFwIHBhbmU/IFwibGVmdCBwb2ludCBvZiB0aGUgbWFwIGxheWVyXCIgY2FuIGJlIGNvbmZ1c2luZywgc3BlY2lhbGx5XHJcblx0Ly8gc2luY2UgdGhlcmUgY2FuIGJlIG5lZ2F0aXZlIG9mZnNldHMuXHJcblx0Ly8gQG1ldGhvZCBnZXRQaXhlbE9yaWdpbigpOiBQb2ludFxyXG5cdC8vIFJldHVybnMgdGhlIHByb2plY3RlZCBwaXhlbCBjb29yZGluYXRlcyBvZiB0aGUgdG9wIGxlZnQgcG9pbnQgb2ZcclxuXHQvLyB0aGUgbWFwIGxheWVyICh1c2VmdWwgaW4gY3VzdG9tIGxheWVyIGFuZCBvdmVybGF5IGltcGxlbWVudGF0aW9ucykuXHJcblx0Z2V0UGl4ZWxPcmlnaW46IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX2NoZWNrSWZMb2FkZWQoKTtcclxuXHRcdHJldHVybiB0aGlzLl9waXhlbE9yaWdpbjtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldFBpeGVsV29ybGRCb3VuZHMoem9vbT86IE51bWJlcik6IEJvdW5kc1xyXG5cdC8vIFJldHVybnMgdGhlIHdvcmxkJ3MgYm91bmRzIGluIHBpeGVsIGNvb3JkaW5hdGVzIGZvciB6b29tIGxldmVsIGB6b29tYC5cclxuXHQvLyBJZiBgem9vbWAgaXMgb21pdHRlZCwgdGhlIG1hcCdzIGN1cnJlbnQgem9vbSBsZXZlbCBpcyB1c2VkLlxyXG5cdGdldFBpeGVsV29ybGRCb3VuZHM6IGZ1bmN0aW9uICh6b29tKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5nZXRQcm9qZWN0ZWRCb3VuZHMoem9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5nZXRab29tKCkgOiB6b29tKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAc2VjdGlvbiBPdGhlciBNZXRob2RzXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0UGFuZShwYW5lOiBTdHJpbmd8SFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudFxyXG5cdC8vIFJldHVybnMgYSBbbWFwIHBhbmVdKCNtYXAtcGFuZSksIGdpdmVuIGl0cyBuYW1lIG9yIGl0cyBIVE1MIGVsZW1lbnQgKGl0cyBpZGVudGl0eSkuXHJcblx0Z2V0UGFuZTogZnVuY3Rpb24gKHBhbmUpIHtcclxuXHRcdHJldHVybiB0eXBlb2YgcGFuZSA9PT0gJ3N0cmluZycgPyB0aGlzLl9wYW5lc1twYW5lXSA6IHBhbmU7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRQYW5lcygpOiBPYmplY3RcclxuXHQvLyBSZXR1cm5zIGEgcGxhaW4gb2JqZWN0IGNvbnRhaW5pbmcgdGhlIG5hbWVzIG9mIGFsbCBbcGFuZXNdKCNtYXAtcGFuZSkgYXMga2V5cyBhbmRcclxuXHQvLyB0aGUgcGFuZXMgYXMgdmFsdWVzLlxyXG5cdGdldFBhbmVzOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fcGFuZXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRDb250YWluZXI6IEhUTUxFbGVtZW50XHJcblx0Ly8gUmV0dXJucyB0aGUgSFRNTCBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIG1hcC5cclxuXHRnZXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9jb250YWluZXI7XHJcblx0fSxcclxuXHJcblxyXG5cdC8vIEBzZWN0aW9uIENvbnZlcnNpb24gTWV0aG9kc1xyXG5cclxuXHQvLyBAbWV0aG9kIGdldFpvb21TY2FsZSh0b1pvb206IE51bWJlciwgZnJvbVpvb206IE51bWJlcik6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIHNjYWxlIGZhY3RvciB0byBiZSBhcHBsaWVkIHRvIGEgbWFwIHRyYW5zaXRpb24gZnJvbSB6b29tIGxldmVsXHJcblx0Ly8gYGZyb21ab29tYCB0byBgdG9ab29tYC4gVXNlZCBpbnRlcm5hbGx5IHRvIGhlbHAgd2l0aCB6b29tIGFuaW1hdGlvbnMuXHJcblx0Z2V0Wm9vbVNjYWxlOiBmdW5jdGlvbiAodG9ab29tLCBmcm9tWm9vbSkge1xyXG5cdFx0Ly8gVE9ETyByZXBsYWNlIHdpdGggdW5pdmVyc2FsIGltcGxlbWVudGF0aW9uIGFmdGVyIHJlZmFjdG9yaW5nIHByb2plY3Rpb25zXHJcblx0XHR2YXIgY3JzID0gdGhpcy5vcHRpb25zLmNycztcclxuXHRcdGZyb21ab29tID0gZnJvbVpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuX3pvb20gOiBmcm9tWm9vbTtcclxuXHRcdHJldHVybiBjcnMuc2NhbGUodG9ab29tKSAvIGNycy5zY2FsZShmcm9tWm9vbSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRTY2FsZVpvb20oc2NhbGU6IE51bWJlciwgZnJvbVpvb206IE51bWJlcik6IE51bWJlclxyXG5cdC8vIFJldHVybnMgdGhlIHpvb20gbGV2ZWwgdGhhdCB0aGUgbWFwIHdvdWxkIGVuZCB1cCBhdCwgaWYgaXQgaXMgYXQgYGZyb21ab29tYFxyXG5cdC8vIGxldmVsIGFuZCBldmVyeXRoaW5nIGlzIHNjYWxlZCBieSBhIGZhY3RvciBvZiBgc2NhbGVgLiBJbnZlcnNlIG9mXHJcblx0Ly8gW2BnZXRab29tU2NhbGVgXSgjbWFwLWdldFpvb21TY2FsZSkuXHJcblx0Z2V0U2NhbGVab29tOiBmdW5jdGlvbiAoc2NhbGUsIGZyb21ab29tKSB7XHJcblx0XHR2YXIgY3JzID0gdGhpcy5vcHRpb25zLmNycztcclxuXHRcdGZyb21ab29tID0gZnJvbVpvb20gPT09IHVuZGVmaW5lZCA/IHRoaXMuX3pvb20gOiBmcm9tWm9vbTtcclxuXHRcdHZhciB6b29tID0gY3JzLnpvb20oc2NhbGUgKiBjcnMuc2NhbGUoZnJvbVpvb20pKTtcclxuXHRcdHJldHVybiBpc05hTih6b29tKSA/IEluZmluaXR5IDogem9vbTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHByb2plY3QobGF0bG5nOiBMYXRMbmcsIHpvb206IE51bWJlcik6IFBvaW50XHJcblx0Ly8gUHJvamVjdHMgYSBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZSBgTGF0TG5nYCBhY2NvcmRpbmcgdG8gdGhlIHByb2plY3Rpb25cclxuXHQvLyBvZiB0aGUgbWFwJ3MgQ1JTLCB0aGVuIHNjYWxlcyBpdCBhY2NvcmRpbmcgdG8gYHpvb21gIGFuZCB0aGUgQ1JTJ3NcclxuXHQvLyBgVHJhbnNmb3JtYXRpb25gLiBUaGUgcmVzdWx0IGlzIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG9cclxuXHQvLyB0aGUgQ1JTIG9yaWdpbi5cclxuXHRwcm9qZWN0OiBmdW5jdGlvbiAobGF0bG5nLCB6b29tKSB7XHJcblx0XHR6b29tID0gem9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fem9vbSA6IHpvb207XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5sYXRMbmdUb1BvaW50KHRvTGF0TG5nKGxhdGxuZyksIHpvb20pO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgdW5wcm9qZWN0KHBvaW50OiBQb2ludCwgem9vbTogTnVtYmVyKTogTGF0TG5nXHJcblx0Ly8gSW52ZXJzZSBvZiBbYHByb2plY3RgXSgjbWFwLXByb2plY3QpLlxyXG5cdHVucHJvamVjdDogZnVuY3Rpb24gKHBvaW50LCB6b29tKSB7XHJcblx0XHR6b29tID0gem9vbSA9PT0gdW5kZWZpbmVkID8gdGhpcy5fem9vbSA6IHpvb207XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy5wb2ludFRvTGF0TG5nKHRvUG9pbnQocG9pbnQpLCB6b29tKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGxheWVyUG9pbnRUb0xhdExuZyhwb2ludDogUG9pbnQpOiBMYXRMbmdcclxuXHQvLyBHaXZlbiBhIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLFxyXG5cdC8vIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGUgKGZvciB0aGUgY3VycmVudCB6b29tIGxldmVsKS5cclxuXHRsYXllclBvaW50VG9MYXRMbmc6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0dmFyIHByb2plY3RlZFBvaW50ID0gdG9Qb2ludChwb2ludCkuYWRkKHRoaXMuZ2V0UGl4ZWxPcmlnaW4oKSk7XHJcblx0XHRyZXR1cm4gdGhpcy51bnByb2plY3QocHJvamVjdGVkUG9pbnQpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgbGF0TG5nVG9MYXllclBvaW50KGxhdGxuZzogTGF0TG5nKTogUG9pbnRcclxuXHQvLyBHaXZlbiBhIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlLCByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIHBpeGVsIGNvb3JkaW5hdGVcclxuXHQvLyByZWxhdGl2ZSB0byB0aGUgW29yaWdpbiBwaXhlbF0oI21hcC1nZXRwaXhlbG9yaWdpbikuXHJcblx0bGF0TG5nVG9MYXllclBvaW50OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHR2YXIgcHJvamVjdGVkUG9pbnQgPSB0aGlzLnByb2plY3QodG9MYXRMbmcobGF0bG5nKSkuX3JvdW5kKCk7XHJcblx0XHRyZXR1cm4gcHJvamVjdGVkUG9pbnQuX3N1YnRyYWN0KHRoaXMuZ2V0UGl4ZWxPcmlnaW4oKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB3cmFwTGF0TG5nKGxhdGxuZzogTGF0TG5nKTogTGF0TG5nXHJcblx0Ly8gUmV0dXJucyBhIGBMYXRMbmdgIHdoZXJlIGBsYXRgIGFuZCBgbG5nYCBoYXMgYmVlbiB3cmFwcGVkIGFjY29yZGluZyB0byB0aGVcclxuXHQvLyBtYXAncyBDUlMncyBgd3JhcExhdGAgYW5kIGB3cmFwTG5nYCBwcm9wZXJ0aWVzLCBpZiB0aGV5IGFyZSBvdXRzaWRlIHRoZVxyXG5cdC8vIENSUydzIGJvdW5kcy5cclxuXHQvLyBCeSBkZWZhdWx0IHRoaXMgbWVhbnMgbG9uZ2l0dWRlIGlzIHdyYXBwZWQgYXJvdW5kIHRoZSBkYXRlbGluZSBzbyBpdHNcclxuXHQvLyB2YWx1ZSBpcyBiZXR3ZWVuIC0xODAgYW5kICsxODAgZGVncmVlcy5cclxuXHR3cmFwTGF0TG5nOiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy53cmFwTGF0TG5nKHRvTGF0TG5nKGxhdGxuZykpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgd3JhcExhdExuZ0JvdW5kcyhib3VuZHM6IExhdExuZ0JvdW5kcyk6IExhdExuZ0JvdW5kc1xyXG5cdC8vIFJldHVybnMgYSBgTGF0TG5nQm91bmRzYCB3aXRoIHRoZSBzYW1lIHNpemUgYXMgdGhlIGdpdmVuIG9uZSwgZW5zdXJpbmcgdGhhdFxyXG5cdC8vIGl0cyBjZW50ZXIgaXMgd2l0aGluIHRoZSBDUlMncyBib3VuZHMuXHJcblx0Ly8gQnkgZGVmYXVsdCB0aGlzIG1lYW5zIHRoZSBjZW50ZXIgbG9uZ2l0dWRlIGlzIHdyYXBwZWQgYXJvdW5kIHRoZSBkYXRlbGluZSBzbyBpdHNcclxuXHQvLyB2YWx1ZSBpcyBiZXR3ZWVuIC0xODAgYW5kICsxODAgZGVncmVlcywgYW5kIHRoZSBtYWpvcml0eSBvZiB0aGUgYm91bmRzXHJcblx0Ly8gb3ZlcmxhcHMgdGhlIENSUydzIGJvdW5kcy5cclxuXHR3cmFwTGF0TG5nQm91bmRzOiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmNycy53cmFwTGF0TG5nQm91bmRzKHRvTGF0TG5nQm91bmRzKGxhdGxuZykpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZGlzdGFuY2UobGF0bG5nMTogTGF0TG5nLCBsYXRsbmcyOiBMYXRMbmcpOiBOdW1iZXJcclxuXHQvLyBSZXR1cm5zIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHR3byBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZXMgYWNjb3JkaW5nIHRvXHJcblx0Ly8gdGhlIG1hcCdzIENSUy4gQnkgZGVmYXVsdCB0aGlzIG1lYXN1cmVzIGRpc3RhbmNlIGluIG1ldGVycy5cclxuXHRkaXN0YW5jZTogZnVuY3Rpb24gKGxhdGxuZzEsIGxhdGxuZzIpIHtcclxuXHRcdHJldHVybiB0aGlzLm9wdGlvbnMuY3JzLmRpc3RhbmNlKHRvTGF0TG5nKGxhdGxuZzEpLCB0b0xhdExuZyhsYXRsbmcyKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBjb250YWluZXJQb2ludFRvTGF5ZXJQb2ludChwb2ludDogUG9pbnQpOiBQb2ludFxyXG5cdC8vIEdpdmVuIGEgcGl4ZWwgY29vcmRpbmF0ZSByZWxhdGl2ZSB0byB0aGUgbWFwIGNvbnRhaW5lciwgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZ1xyXG5cdC8vIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIFtvcmlnaW4gcGl4ZWxdKCNtYXAtZ2V0cGl4ZWxvcmlnaW4pLlxyXG5cdGNvbnRhaW5lclBvaW50VG9MYXllclBvaW50OiBmdW5jdGlvbiAocG9pbnQpIHsgLy8gKFBvaW50KVxyXG5cdFx0cmV0dXJuIHRvUG9pbnQocG9pbnQpLnN1YnRyYWN0KHRoaXMuX2dldE1hcFBhbmVQb3MoKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBsYXllclBvaW50VG9Db250YWluZXJQb2ludChwb2ludDogUG9pbnQpOiBQb2ludFxyXG5cdC8vIEdpdmVuIGEgcGl4ZWwgY29vcmRpbmF0ZSByZWxhdGl2ZSB0byB0aGUgW29yaWdpbiBwaXhlbF0oI21hcC1nZXRwaXhlbG9yaWdpbiksXHJcblx0Ly8gcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZSBtYXAgY29udGFpbmVyLlxyXG5cdGxheWVyUG9pbnRUb0NvbnRhaW5lclBvaW50OiBmdW5jdGlvbiAocG9pbnQpIHsgLy8gKFBvaW50KVxyXG5cdFx0cmV0dXJuIHRvUG9pbnQocG9pbnQpLmFkZCh0aGlzLl9nZXRNYXBQYW5lUG9zKCkpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY29udGFpbmVyUG9pbnRUb0xhdExuZyhwb2ludDogUG9pbnQpOiBMYXRMbmdcclxuXHQvLyBHaXZlbiBhIHBpeGVsIGNvb3JkaW5hdGUgcmVsYXRpdmUgdG8gdGhlIG1hcCBjb250YWluZXIsIHJldHVybnNcclxuXHQvLyB0aGUgY29ycmVzcG9uZGluZyBnZW9ncmFwaGljYWwgY29vcmRpbmF0ZSAoZm9yIHRoZSBjdXJyZW50IHpvb20gbGV2ZWwpLlxyXG5cdGNvbnRhaW5lclBvaW50VG9MYXRMbmc6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0dmFyIGxheWVyUG9pbnQgPSB0aGlzLmNvbnRhaW5lclBvaW50VG9MYXllclBvaW50KHRvUG9pbnQocG9pbnQpKTtcclxuXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0xhdExuZyhsYXllclBvaW50KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGxhdExuZ1RvQ29udGFpbmVyUG9pbnQobGF0bG5nOiBMYXRMbmcpOiBQb2ludFxyXG5cdC8vIEdpdmVuIGEgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGUsIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgcGl4ZWwgY29vcmRpbmF0ZVxyXG5cdC8vIHJlbGF0aXZlIHRvIHRoZSBtYXAgY29udGFpbmVyLlxyXG5cdGxhdExuZ1RvQ29udGFpbmVyUG9pbnQ6IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0NvbnRhaW5lclBvaW50KHRoaXMubGF0TG5nVG9MYXllclBvaW50KHRvTGF0TG5nKGxhdGxuZykpKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIG1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGV2OiBNb3VzZUV2ZW50KTogUG9pbnRcclxuXHQvLyBHaXZlbiBhIE1vdXNlRXZlbnQgb2JqZWN0LCByZXR1cm5zIHRoZSBwaXhlbCBjb29yZGluYXRlIHJlbGF0aXZlIHRvIHRoZVxyXG5cdC8vIG1hcCBjb250YWluZXIgd2hlcmUgdGhlIGV2ZW50IHRvb2sgcGxhY2UuXHJcblx0bW91c2VFdmVudFRvQ29udGFpbmVyUG9pbnQ6IGZ1bmN0aW9uIChlKSB7XHJcblx0XHRyZXR1cm4gZ2V0TW91c2VQb3NpdGlvbihlLCB0aGlzLl9jb250YWluZXIpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgbW91c2VFdmVudFRvTGF5ZXJQb2ludChldjogTW91c2VFdmVudCk6IFBvaW50XHJcblx0Ly8gR2l2ZW4gYSBNb3VzZUV2ZW50IG9iamVjdCwgcmV0dXJucyB0aGUgcGl4ZWwgY29vcmRpbmF0ZSByZWxhdGl2ZSB0b1xyXG5cdC8vIHRoZSBbb3JpZ2luIHBpeGVsXSgjbWFwLWdldHBpeGVsb3JpZ2luKSB3aGVyZSB0aGUgZXZlbnQgdG9vayBwbGFjZS5cclxuXHRtb3VzZUV2ZW50VG9MYXllclBvaW50OiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0cmV0dXJuIHRoaXMuY29udGFpbmVyUG9pbnRUb0xheWVyUG9pbnQodGhpcy5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBtb3VzZUV2ZW50VG9MYXRMbmcoZXY6IE1vdXNlRXZlbnQpOiBMYXRMbmdcclxuXHQvLyBHaXZlbiBhIE1vdXNlRXZlbnQgb2JqZWN0LCByZXR1cm5zIGdlb2dyYXBoaWNhbCBjb29yZGluYXRlIHdoZXJlIHRoZVxyXG5cdC8vIGV2ZW50IHRvb2sgcGxhY2UuXHJcblx0bW91c2VFdmVudFRvTGF0TG5nOiBmdW5jdGlvbiAoZSkgeyAvLyAoTW91c2VFdmVudClcclxuXHRcdHJldHVybiB0aGlzLmxheWVyUG9pbnRUb0xhdExuZyh0aGlzLm1vdXNlRXZlbnRUb0xheWVyUG9pbnQoZSkpO1xyXG5cdH0sXHJcblxyXG5cclxuXHQvLyBtYXAgaW5pdGlhbGl6YXRpb24gbWV0aG9kc1xyXG5cclxuXHRfaW5pdENvbnRhaW5lcjogZnVuY3Rpb24gKGlkKSB7XHJcblx0XHR2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyID0gZ2V0KGlkKTtcclxuXHJcblx0XHRpZiAoIWNvbnRhaW5lcikge1xyXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01hcCBjb250YWluZXIgbm90IGZvdW5kLicpO1xyXG5cdFx0fSBlbHNlIGlmIChjb250YWluZXIuX2xlYWZsZXRfaWQpIHtcclxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdNYXAgY29udGFpbmVyIGlzIGFscmVhZHkgaW5pdGlhbGl6ZWQuJyk7XHJcblx0XHR9XHJcblxyXG5cdFx0b24oY29udGFpbmVyLCAnc2Nyb2xsJywgdGhpcy5fb25TY3JvbGwsIHRoaXMpO1xyXG5cdFx0dGhpcy5fY29udGFpbmVySWQgPSBzdGFtcChjb250YWluZXIpO1xyXG5cdH0sXHJcblxyXG5cdF9pbml0TGF5b3V0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyO1xyXG5cclxuXHRcdHRoaXMuX2ZhZGVBbmltYXRlZCA9IHRoaXMub3B0aW9ucy5mYWRlQW5pbWF0aW9uICYmIGFueTNkO1xyXG5cclxuXHRcdGFkZENsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtY29udGFpbmVyJyArXHJcblx0XHRcdCh0b3VjaCA/ICcgbGVhZmxldC10b3VjaCcgOiAnJykgK1xyXG5cdFx0XHQocmV0aW5hID8gJyBsZWFmbGV0LXJldGluYScgOiAnJykgK1xyXG5cdFx0XHQoaWVsdDkgPyAnIGxlYWZsZXQtb2xkaWUnIDogJycpICtcclxuXHRcdFx0KHNhZmFyaSA/ICcgbGVhZmxldC1zYWZhcmknIDogJycpICtcclxuXHRcdFx0KHRoaXMuX2ZhZGVBbmltYXRlZCA/ICcgbGVhZmxldC1mYWRlLWFuaW0nIDogJycpKTtcclxuXHJcblx0XHR2YXIgcG9zaXRpb24gPSBnZXRTdHlsZShjb250YWluZXIsICdwb3NpdGlvbicpO1xyXG5cclxuXHRcdGlmIChwb3NpdGlvbiAhPT0gJ2Fic29sdXRlJyAmJiBwb3NpdGlvbiAhPT0gJ3JlbGF0aXZlJyAmJiBwb3NpdGlvbiAhPT0gJ2ZpeGVkJykge1xyXG5cdFx0XHRjb250YWluZXIuc3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2luaXRQYW5lcygpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9pbml0Q29udHJvbFBvcykge1xyXG5cdFx0XHR0aGlzLl9pbml0Q29udHJvbFBvcygpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9pbml0UGFuZXM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBwYW5lcyA9IHRoaXMuX3BhbmVzID0ge307XHJcblx0XHR0aGlzLl9wYW5lUmVuZGVyZXJzID0ge307XHJcblxyXG5cdFx0Ly8gQHNlY3Rpb25cclxuXHRcdC8vXHJcblx0XHQvLyBQYW5lcyBhcmUgRE9NIGVsZW1lbnRzIHVzZWQgdG8gY29udHJvbCB0aGUgb3JkZXJpbmcgb2YgbGF5ZXJzIG9uIHRoZSBtYXAuIFlvdVxyXG5cdFx0Ly8gY2FuIGFjY2VzcyBwYW5lcyB3aXRoIFtgbWFwLmdldFBhbmVgXSgjbWFwLWdldHBhbmUpIG9yXHJcblx0XHQvLyBbYG1hcC5nZXRQYW5lc2BdKCNtYXAtZ2V0cGFuZXMpIG1ldGhvZHMuIE5ldyBwYW5lcyBjYW4gYmUgY3JlYXRlZCB3aXRoIHRoZVxyXG5cdFx0Ly8gW2BtYXAuY3JlYXRlUGFuZWBdKCNtYXAtY3JlYXRlcGFuZSkgbWV0aG9kLlxyXG5cdFx0Ly9cclxuXHRcdC8vIEV2ZXJ5IG1hcCBoYXMgdGhlIGZvbGxvd2luZyBkZWZhdWx0IHBhbmVzIHRoYXQgZGlmZmVyIG9ubHkgaW4gekluZGV4LlxyXG5cdFx0Ly9cclxuXHRcdC8vIEBwYW5lIG1hcFBhbmU6IEhUTUxFbGVtZW50ID0gJ2F1dG8nXHJcblx0XHQvLyBQYW5lIHRoYXQgY29udGFpbnMgYWxsIG90aGVyIG1hcCBwYW5lc1xyXG5cclxuXHRcdHRoaXMuX21hcFBhbmUgPSB0aGlzLmNyZWF0ZVBhbmUoJ21hcFBhbmUnLCB0aGlzLl9jb250YWluZXIpO1xyXG5cdFx0c2V0UG9zaXRpb24odGhpcy5fbWFwUGFuZSwgbmV3IFBvaW50KDAsIDApKTtcclxuXHJcblx0XHQvLyBAcGFuZSB0aWxlUGFuZTogSFRNTEVsZW1lbnQgPSAyMDBcclxuXHRcdC8vIFBhbmUgZm9yIGBHcmlkTGF5ZXJgcyBhbmQgYFRpbGVMYXllcmBzXHJcblx0XHR0aGlzLmNyZWF0ZVBhbmUoJ3RpbGVQYW5lJyk7XHJcblx0XHQvLyBAcGFuZSBvdmVybGF5UGFuZTogSFRNTEVsZW1lbnQgPSA0MDBcclxuXHRcdC8vIFBhbmUgZm9yIHZlY3RvcnMgKGBQYXRoYHMsIGxpa2UgYFBvbHlsaW5lYHMgYW5kIGBQb2x5Z29uYHMpLCBgSW1hZ2VPdmVybGF5YHMgYW5kIGBWaWRlb092ZXJsYXlgc1xyXG5cdFx0dGhpcy5jcmVhdGVQYW5lKCdzaGFkb3dQYW5lJyk7XHJcblx0XHQvLyBAcGFuZSBzaGFkb3dQYW5lOiBIVE1MRWxlbWVudCA9IDUwMFxyXG5cdFx0Ly8gUGFuZSBmb3Igb3ZlcmxheSBzaGFkb3dzIChlLmcuIGBNYXJrZXJgIHNoYWRvd3MpXHJcblx0XHR0aGlzLmNyZWF0ZVBhbmUoJ292ZXJsYXlQYW5lJyk7XHJcblx0XHQvLyBAcGFuZSBtYXJrZXJQYW5lOiBIVE1MRWxlbWVudCA9IDYwMFxyXG5cdFx0Ly8gUGFuZSBmb3IgYEljb25gcyBvZiBgTWFya2VyYHNcclxuXHRcdHRoaXMuY3JlYXRlUGFuZSgnbWFya2VyUGFuZScpO1xyXG5cdFx0Ly8gQHBhbmUgdG9vbHRpcFBhbmU6IEhUTUxFbGVtZW50ID0gNjUwXHJcblx0XHQvLyBQYW5lIGZvciBgVG9vbHRpcGBzLlxyXG5cdFx0dGhpcy5jcmVhdGVQYW5lKCd0b29sdGlwUGFuZScpO1xyXG5cdFx0Ly8gQHBhbmUgcG9wdXBQYW5lOiBIVE1MRWxlbWVudCA9IDcwMFxyXG5cdFx0Ly8gUGFuZSBmb3IgYFBvcHVwYHMuXHJcblx0XHR0aGlzLmNyZWF0ZVBhbmUoJ3BvcHVwUGFuZScpO1xyXG5cclxuXHRcdGlmICghdGhpcy5vcHRpb25zLm1hcmtlclpvb21BbmltYXRpb24pIHtcclxuXHRcdFx0YWRkQ2xhc3MocGFuZXMubWFya2VyUGFuZSwgJ2xlYWZsZXQtem9vbS1oaWRlJyk7XHJcblx0XHRcdGFkZENsYXNzKHBhbmVzLnNoYWRvd1BhbmUsICdsZWFmbGV0LXpvb20taGlkZScpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cclxuXHQvLyBwcml2YXRlIG1ldGhvZHMgdGhhdCBtb2RpZnkgbWFwIHN0YXRlXHJcblxyXG5cdC8vIEBzZWN0aW9uIE1hcCBzdGF0ZSBjaGFuZ2UgZXZlbnRzXHJcblx0X3Jlc2V0VmlldzogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xyXG5cdFx0c2V0UG9zaXRpb24odGhpcy5fbWFwUGFuZSwgbmV3IFBvaW50KDAsIDApKTtcclxuXHJcblx0XHR2YXIgbG9hZGluZyA9ICF0aGlzLl9sb2FkZWQ7XHJcblx0XHR0aGlzLl9sb2FkZWQgPSB0cnVlO1xyXG5cdFx0em9vbSA9IHRoaXMuX2xpbWl0Wm9vbSh6b29tKTtcclxuXHJcblx0XHR0aGlzLmZpcmUoJ3ZpZXdwcmVyZXNldCcpO1xyXG5cclxuXHRcdHZhciB6b29tQ2hhbmdlZCA9IHRoaXMuX3pvb20gIT09IHpvb207XHJcblx0XHR0aGlzXHJcblx0XHRcdC5fbW92ZVN0YXJ0KHpvb21DaGFuZ2VkLCBmYWxzZSlcclxuXHRcdFx0Ll9tb3ZlKGNlbnRlciwgem9vbSlcclxuXHRcdFx0Ll9tb3ZlRW5kKHpvb21DaGFuZ2VkKTtcclxuXHJcblx0XHQvLyBAZXZlbnQgdmlld3Jlc2V0OiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIG5lZWRzIHRvIHJlZHJhdyBpdHMgY29udGVudCAodGhpcyB1c3VhbGx5IGhhcHBlbnNcclxuXHRcdC8vIG9uIG1hcCB6b29tIG9yIGxvYWQpLiBWZXJ5IHVzZWZ1bCBmb3IgY3JlYXRpbmcgY3VzdG9tIG92ZXJsYXlzLlxyXG5cdFx0dGhpcy5maXJlKCd2aWV3cmVzZXQnKTtcclxuXHJcblx0XHQvLyBAZXZlbnQgbG9hZDogRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIG1hcCBpcyBpbml0aWFsaXplZCAod2hlbiBpdHMgY2VudGVyIGFuZCB6b29tIGFyZSBzZXRcclxuXHRcdC8vIGZvciB0aGUgZmlyc3QgdGltZSkuXHJcblx0XHRpZiAobG9hZGluZykge1xyXG5cdFx0XHR0aGlzLmZpcmUoJ2xvYWQnKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfbW92ZVN0YXJ0OiBmdW5jdGlvbiAoem9vbUNoYW5nZWQsIG5vTW92ZVN0YXJ0KSB7XHJcblx0XHQvLyBAZXZlbnQgem9vbXN0YXJ0OiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIHpvb20gaXMgYWJvdXQgdG8gY2hhbmdlIChlLmcuIGJlZm9yZSB6b29tIGFuaW1hdGlvbikuXHJcblx0XHQvLyBAZXZlbnQgbW92ZXN0YXJ0OiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdmlldyBvZiB0aGUgbWFwIHN0YXJ0cyBjaGFuZ2luZyAoZS5nLiB1c2VyIHN0YXJ0cyBkcmFnZ2luZyB0aGUgbWFwKS5cclxuXHRcdGlmICh6b29tQ2hhbmdlZCkge1xyXG5cdFx0XHR0aGlzLmZpcmUoJ3pvb21zdGFydCcpO1xyXG5cdFx0fVxyXG5cdFx0aWYgKCFub01vdmVTdGFydCkge1xyXG5cdFx0XHR0aGlzLmZpcmUoJ21vdmVzdGFydCcpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0X21vdmU6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIGRhdGEpIHtcclxuXHRcdGlmICh6b29tID09PSB1bmRlZmluZWQpIHtcclxuXHRcdFx0em9vbSA9IHRoaXMuX3pvb207XHJcblx0XHR9XHJcblx0XHR2YXIgem9vbUNoYW5nZWQgPSB0aGlzLl96b29tICE9PSB6b29tO1xyXG5cclxuXHRcdHRoaXMuX3pvb20gPSB6b29tO1xyXG5cdFx0dGhpcy5fbGFzdENlbnRlciA9IGNlbnRlcjtcclxuXHRcdHRoaXMuX3BpeGVsT3JpZ2luID0gdGhpcy5fZ2V0TmV3UGl4ZWxPcmlnaW4oY2VudGVyKTtcclxuXHJcblx0XHQvLyBAZXZlbnQgem9vbTogRXZlbnRcclxuXHRcdC8vIEZpcmVkIHJlcGVhdGVkbHkgZHVyaW5nIGFueSBjaGFuZ2UgaW4gem9vbSBsZXZlbCwgaW5jbHVkaW5nIHpvb21cclxuXHRcdC8vIGFuZCBmbHkgYW5pbWF0aW9ucy5cclxuXHRcdGlmICh6b29tQ2hhbmdlZCB8fCAoZGF0YSAmJiBkYXRhLnBpbmNoKSkge1x0Ly8gQWx3YXlzIGZpcmUgJ3pvb20nIGlmIHBpbmNoaW5nIGJlY2F1c2UgIzM1MzBcclxuXHRcdFx0dGhpcy5maXJlKCd6b29tJywgZGF0YSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQGV2ZW50IG1vdmU6IEV2ZW50XHJcblx0XHQvLyBGaXJlZCByZXBlYXRlZGx5IGR1cmluZyBhbnkgbW92ZW1lbnQgb2YgdGhlIG1hcCwgaW5jbHVkaW5nIHBhbiBhbmRcclxuXHRcdC8vIGZseSBhbmltYXRpb25zLlxyXG5cdFx0cmV0dXJuIHRoaXMuZmlyZSgnbW92ZScsIGRhdGEpO1xyXG5cdH0sXHJcblxyXG5cdF9tb3ZlRW5kOiBmdW5jdGlvbiAoem9vbUNoYW5nZWQpIHtcclxuXHRcdC8vIEBldmVudCB6b29tZW5kOiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIGhhcyBjaGFuZ2VkLCBhZnRlciBhbnkgYW5pbWF0aW9ucy5cclxuXHRcdGlmICh6b29tQ2hhbmdlZCkge1xyXG5cdFx0XHR0aGlzLmZpcmUoJ3pvb21lbmQnKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBAZXZlbnQgbW92ZWVuZDogRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIGNlbnRlciBvZiB0aGUgbWFwIHN0b3BzIGNoYW5naW5nIChlLmcuIHVzZXIgc3RvcHBlZFxyXG5cdFx0Ly8gZHJhZ2dpbmcgdGhlIG1hcCkuXHJcblx0XHRyZXR1cm4gdGhpcy5maXJlKCdtb3ZlZW5kJyk7XHJcblx0fSxcclxuXHJcblx0X3N0b3A6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9mbHlUb0ZyYW1lKTtcclxuXHRcdGlmICh0aGlzLl9wYW5BbmltKSB7XHJcblx0XHRcdHRoaXMuX3BhbkFuaW0uc3RvcCgpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0X3Jhd1BhbkJ5OiBmdW5jdGlvbiAob2Zmc2V0KSB7XHJcblx0XHRzZXRQb3NpdGlvbih0aGlzLl9tYXBQYW5lLCB0aGlzLl9nZXRNYXBQYW5lUG9zKCkuc3VidHJhY3Qob2Zmc2V0KSk7XHJcblx0fSxcclxuXHJcblx0X2dldFpvb21TcGFuOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5nZXRNYXhab29tKCkgLSB0aGlzLmdldE1pblpvb20oKTtcclxuXHR9LFxyXG5cclxuXHRfcGFuSW5zaWRlTWF4Qm91bmRzOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAoIXRoaXMuX2VuZm9yY2luZ0JvdW5kcykge1xyXG5cdFx0XHR0aGlzLnBhbkluc2lkZUJvdW5kcyh0aGlzLm9wdGlvbnMubWF4Qm91bmRzKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfY2hlY2tJZkxvYWRlZDogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKCF0aGlzLl9sb2FkZWQpIHtcclxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdTZXQgbWFwIGNlbnRlciBhbmQgem9vbSBmaXJzdC4nKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHQvLyBET00gZXZlbnQgaGFuZGxpbmdcclxuXHJcblx0Ly8gQHNlY3Rpb24gSW50ZXJhY3Rpb24gZXZlbnRzXHJcblx0X2luaXRFdmVudHM6IGZ1bmN0aW9uIChyZW1vdmUkJDEpIHtcclxuXHRcdHRoaXMuX3RhcmdldHMgPSB7fTtcclxuXHRcdHRoaXMuX3RhcmdldHNbc3RhbXAodGhpcy5fY29udGFpbmVyKV0gPSB0aGlzO1xyXG5cclxuXHRcdHZhciBvbk9mZiA9IHJlbW92ZSQkMSA/IG9mZiA6IG9uO1xyXG5cclxuXHRcdC8vIEBldmVudCBjbGljazogTW91c2VFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBjbGlja3MgKG9yIHRhcHMpIHRoZSBtYXAuXHJcblx0XHQvLyBAZXZlbnQgZGJsY2xpY2s6IE1vdXNlRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgZG91YmxlLWNsaWNrcyAob3IgZG91YmxlLXRhcHMpIHRoZSBtYXAuXHJcblx0XHQvLyBAZXZlbnQgbW91c2Vkb3duOiBNb3VzZUV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSB1c2VyIHB1c2hlcyB0aGUgbW91c2UgYnV0dG9uIG9uIHRoZSBtYXAuXHJcblx0XHQvLyBAZXZlbnQgbW91c2V1cDogTW91c2VFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciByZWxlYXNlcyB0aGUgbW91c2UgYnV0dG9uIG9uIHRoZSBtYXAuXHJcblx0XHQvLyBAZXZlbnQgbW91c2VvdmVyOiBNb3VzZUV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSBtb3VzZSBlbnRlcnMgdGhlIG1hcC5cclxuXHRcdC8vIEBldmVudCBtb3VzZW91dDogTW91c2VFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbW91c2UgbGVhdmVzIHRoZSBtYXAuXHJcblx0XHQvLyBAZXZlbnQgbW91c2Vtb3ZlOiBNb3VzZUV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGlsZSB0aGUgbW91c2UgbW92ZXMgb3ZlciB0aGUgbWFwLlxyXG5cdFx0Ly8gQGV2ZW50IGNvbnRleHRtZW51OiBNb3VzZUV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSB1c2VyIHB1c2hlcyB0aGUgcmlnaHQgbW91c2UgYnV0dG9uIG9uIHRoZSBtYXAsIHByZXZlbnRzXHJcblx0XHQvLyBkZWZhdWx0IGJyb3dzZXIgY29udGV4dCBtZW51IGZyb20gc2hvd2luZyBpZiB0aGVyZSBhcmUgbGlzdGVuZXJzIG9uXHJcblx0XHQvLyB0aGlzIGV2ZW50LiBBbHNvIGZpcmVkIG9uIG1vYmlsZSB3aGVuIHRoZSB1c2VyIGhvbGRzIGEgc2luZ2xlIHRvdWNoXHJcblx0XHQvLyBmb3IgYSBzZWNvbmQgKGFsc28gY2FsbGVkIGxvbmcgcHJlc3MpLlxyXG5cdFx0Ly8gQGV2ZW50IGtleXByZXNzOiBLZXlib2FyZEV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSB1c2VyIHByZXNzZXMgYSBrZXkgZnJvbSB0aGUga2V5Ym9hcmQgd2hpbGUgdGhlIG1hcCBpcyBmb2N1c2VkLlxyXG5cdFx0b25PZmYodGhpcy5fY29udGFpbmVyLCAnY2xpY2sgZGJsY2xpY2sgbW91c2Vkb3duIG1vdXNldXAgJyArXHJcblx0XHRcdCdtb3VzZW92ZXIgbW91c2VvdXQgbW91c2Vtb3ZlIGNvbnRleHRtZW51IGtleXByZXNzJywgdGhpcy5faGFuZGxlRE9NRXZlbnQsIHRoaXMpO1xyXG5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMudHJhY2tSZXNpemUpIHtcclxuXHRcdFx0b25PZmYod2luZG93LCAncmVzaXplJywgdGhpcy5fb25SZXNpemUsIHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChhbnkzZCAmJiB0aGlzLm9wdGlvbnMudHJhbnNmb3JtM0RMaW1pdCkge1xyXG5cdFx0XHQocmVtb3ZlJCQxID8gdGhpcy5vZmYgOiB0aGlzLm9uKS5jYWxsKHRoaXMsICdtb3ZlZW5kJywgdGhpcy5fb25Nb3ZlRW5kKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfb25SZXNpemU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9yZXNpemVSZXF1ZXN0KTtcclxuXHRcdHRoaXMuX3Jlc2l6ZVJlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lKFxyXG5cdFx0ICAgICAgICBmdW5jdGlvbiAoKSB7IHRoaXMuaW52YWxpZGF0ZVNpemUoe2RlYm91bmNlTW92ZWVuZDogdHJ1ZX0pOyB9LCB0aGlzKTtcclxuXHR9LFxyXG5cclxuXHRfb25TY3JvbGw6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX2NvbnRhaW5lci5zY3JvbGxUb3AgID0gMDtcclxuXHRcdHRoaXMuX2NvbnRhaW5lci5zY3JvbGxMZWZ0ID0gMDtcclxuXHR9LFxyXG5cclxuXHRfb25Nb3ZlRW5kOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgcG9zID0gdGhpcy5fZ2V0TWFwUGFuZVBvcygpO1xyXG5cdFx0aWYgKE1hdGgubWF4KE1hdGguYWJzKHBvcy54KSwgTWF0aC5hYnMocG9zLnkpKSA+PSB0aGlzLm9wdGlvbnMudHJhbnNmb3JtM0RMaW1pdCkge1xyXG5cdFx0XHQvLyBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD0xMjAzODczIGJ1dCBXZWJraXQgYWxzbyBoYXZlXHJcblx0XHRcdC8vIGEgcGl4ZWwgb2Zmc2V0IG9uIHZlcnkgaGlnaCB2YWx1ZXMsIHNlZTogaHR0cDovL2pzZmlkZGxlLm5ldC9kZzZyNWhoYi9cclxuXHRcdFx0dGhpcy5fcmVzZXRWaWV3KHRoaXMuZ2V0Q2VudGVyKCksIHRoaXMuZ2V0Wm9vbSgpKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfZmluZEV2ZW50VGFyZ2V0czogZnVuY3Rpb24gKGUsIHR5cGUpIHtcclxuXHRcdHZhciB0YXJnZXRzID0gW10sXHJcblx0XHQgICAgdGFyZ2V0LFxyXG5cdFx0ICAgIGlzSG92ZXIgPSB0eXBlID09PSAnbW91c2VvdXQnIHx8IHR5cGUgPT09ICdtb3VzZW92ZXInLFxyXG5cdFx0ICAgIHNyYyA9IGUudGFyZ2V0IHx8IGUuc3JjRWxlbWVudCxcclxuXHRcdCAgICBkcmFnZ2luZyA9IGZhbHNlO1xyXG5cclxuXHRcdHdoaWxlIChzcmMpIHtcclxuXHRcdFx0dGFyZ2V0ID0gdGhpcy5fdGFyZ2V0c1tzdGFtcChzcmMpXTtcclxuXHRcdFx0aWYgKHRhcmdldCAmJiAodHlwZSA9PT0gJ2NsaWNrJyB8fCB0eXBlID09PSAncHJlY2xpY2snKSAmJiAhZS5fc2ltdWxhdGVkICYmIHRoaXMuX2RyYWdnYWJsZU1vdmVkKHRhcmdldCkpIHtcclxuXHRcdFx0XHQvLyBQcmV2ZW50IGZpcmluZyBjbGljayBhZnRlciB5b3UganVzdCBkcmFnZ2VkIGFuIG9iamVjdC5cclxuXHRcdFx0XHRkcmFnZ2luZyA9IHRydWU7XHJcblx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKHRhcmdldCAmJiB0YXJnZXQubGlzdGVucyh0eXBlLCB0cnVlKSkge1xyXG5cdFx0XHRcdGlmIChpc0hvdmVyICYmICFpc0V4dGVybmFsVGFyZ2V0KHNyYywgZSkpIHsgYnJlYWs7IH1cclxuXHRcdFx0XHR0YXJnZXRzLnB1c2godGFyZ2V0KTtcclxuXHRcdFx0XHRpZiAoaXNIb3ZlcikgeyBicmVhazsgfVxyXG5cdFx0XHR9XHJcblx0XHRcdGlmIChzcmMgPT09IHRoaXMuX2NvbnRhaW5lcikgeyBicmVhazsgfVxyXG5cdFx0XHRzcmMgPSBzcmMucGFyZW50Tm9kZTtcclxuXHRcdH1cclxuXHRcdGlmICghdGFyZ2V0cy5sZW5ndGggJiYgIWRyYWdnaW5nICYmICFpc0hvdmVyICYmIGlzRXh0ZXJuYWxUYXJnZXQoc3JjLCBlKSkge1xyXG5cdFx0XHR0YXJnZXRzID0gW3RoaXNdO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRhcmdldHM7XHJcblx0fSxcclxuXHJcblx0X2hhbmRsZURPTUV2ZW50OiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0aWYgKCF0aGlzLl9sb2FkZWQgfHwgc2tpcHBlZChlKSkgeyByZXR1cm47IH1cclxuXHJcblx0XHR2YXIgdHlwZSA9IGUudHlwZTtcclxuXHJcblx0XHRpZiAodHlwZSA9PT0gJ21vdXNlZG93bicgfHwgdHlwZSA9PT0gJ2tleXByZXNzJykge1xyXG5cdFx0XHQvLyBwcmV2ZW50cyBvdXRsaW5lIHdoZW4gY2xpY2tpbmcgb24ga2V5Ym9hcmQtZm9jdXNhYmxlIGVsZW1lbnRcclxuXHRcdFx0cHJldmVudE91dGxpbmUoZS50YXJnZXQgfHwgZS5zcmNFbGVtZW50KTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9maXJlRE9NRXZlbnQoZSwgdHlwZSk7XHJcblx0fSxcclxuXHJcblx0X21vdXNlRXZlbnRzOiBbJ2NsaWNrJywgJ2RibGNsaWNrJywgJ21vdXNlb3ZlcicsICdtb3VzZW91dCcsICdjb250ZXh0bWVudSddLFxyXG5cclxuXHRfZmlyZURPTUV2ZW50OiBmdW5jdGlvbiAoZSwgdHlwZSwgdGFyZ2V0cykge1xyXG5cclxuXHRcdGlmIChlLnR5cGUgPT09ICdjbGljaycpIHtcclxuXHRcdFx0Ly8gRmlyZSBhIHN5bnRoZXRpYyAncHJlY2xpY2snIGV2ZW50IHdoaWNoIHByb3BhZ2F0ZXMgdXAgKG1haW5seSBmb3IgY2xvc2luZyBwb3B1cHMpLlxyXG5cdFx0XHQvLyBAZXZlbnQgcHJlY2xpY2s6IE1vdXNlRXZlbnRcclxuXHRcdFx0Ly8gRmlyZWQgYmVmb3JlIG1vdXNlIGNsaWNrIG9uIHRoZSBtYXAgKHNvbWV0aW1lcyB1c2VmdWwgd2hlbiB5b3VcclxuXHRcdFx0Ly8gd2FudCBzb21ldGhpbmcgdG8gaGFwcGVuIG9uIGNsaWNrIGJlZm9yZSBhbnkgZXhpc3RpbmcgY2xpY2tcclxuXHRcdFx0Ly8gaGFuZGxlcnMgc3RhcnQgcnVubmluZykuXHJcblx0XHRcdHZhciBzeW50aCA9IGV4dGVuZCh7fSwgZSk7XHJcblx0XHRcdHN5bnRoLnR5cGUgPSAncHJlY2xpY2snO1xyXG5cdFx0XHR0aGlzLl9maXJlRE9NRXZlbnQoc3ludGgsIHN5bnRoLnR5cGUsIHRhcmdldHMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChlLl9zdG9wcGVkKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdC8vIEZpbmQgdGhlIGxheWVyIHRoZSBldmVudCBpcyBwcm9wYWdhdGluZyBmcm9tIGFuZCBpdHMgcGFyZW50cy5cclxuXHRcdHRhcmdldHMgPSAodGFyZ2V0cyB8fCBbXSkuY29uY2F0KHRoaXMuX2ZpbmRFdmVudFRhcmdldHMoZSwgdHlwZSkpO1xyXG5cclxuXHRcdGlmICghdGFyZ2V0cy5sZW5ndGgpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0dmFyIHRhcmdldCA9IHRhcmdldHNbMF07XHJcblx0XHRpZiAodHlwZSA9PT0gJ2NvbnRleHRtZW51JyAmJiB0YXJnZXQubGlzdGVucyh0eXBlLCB0cnVlKSkge1xyXG5cdFx0XHRwcmV2ZW50RGVmYXVsdChlKTtcclxuXHRcdH1cclxuXHJcblx0XHR2YXIgZGF0YSA9IHtcclxuXHRcdFx0b3JpZ2luYWxFdmVudDogZVxyXG5cdFx0fTtcclxuXHJcblx0XHRpZiAoZS50eXBlICE9PSAna2V5cHJlc3MnKSB7XHJcblx0XHRcdHZhciBpc01hcmtlciA9IHRhcmdldC5nZXRMYXRMbmcgJiYgKCF0YXJnZXQuX3JhZGl1cyB8fCB0YXJnZXQuX3JhZGl1cyA8PSAxMCk7XHJcblx0XHRcdGRhdGEuY29udGFpbmVyUG9pbnQgPSBpc01hcmtlciA/XHJcblx0XHRcdFx0dGhpcy5sYXRMbmdUb0NvbnRhaW5lclBvaW50KHRhcmdldC5nZXRMYXRMbmcoKSkgOiB0aGlzLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUpO1xyXG5cdFx0XHRkYXRhLmxheWVyUG9pbnQgPSB0aGlzLmNvbnRhaW5lclBvaW50VG9MYXllclBvaW50KGRhdGEuY29udGFpbmVyUG9pbnQpO1xyXG5cdFx0XHRkYXRhLmxhdGxuZyA9IGlzTWFya2VyID8gdGFyZ2V0LmdldExhdExuZygpIDogdGhpcy5sYXllclBvaW50VG9MYXRMbmcoZGF0YS5sYXllclBvaW50KTtcclxuXHRcdH1cclxuXHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRhcmdldHMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0dGFyZ2V0c1tpXS5maXJlKHR5cGUsIGRhdGEsIHRydWUpO1xyXG5cdFx0XHRpZiAoZGF0YS5vcmlnaW5hbEV2ZW50Ll9zdG9wcGVkIHx8XHJcblx0XHRcdFx0KHRhcmdldHNbaV0ub3B0aW9ucy5idWJibGluZ01vdXNlRXZlbnRzID09PSBmYWxzZSAmJiBpbmRleE9mKHRoaXMuX21vdXNlRXZlbnRzLCB0eXBlKSAhPT0gLTEpKSB7IHJldHVybjsgfVxyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9kcmFnZ2FibGVNb3ZlZDogZnVuY3Rpb24gKG9iaikge1xyXG5cdFx0b2JqID0gb2JqLmRyYWdnaW5nICYmIG9iai5kcmFnZ2luZy5lbmFibGVkKCkgPyBvYmogOiB0aGlzO1xyXG5cdFx0cmV0dXJuIChvYmouZHJhZ2dpbmcgJiYgb2JqLmRyYWdnaW5nLm1vdmVkKCkpIHx8ICh0aGlzLmJveFpvb20gJiYgdGhpcy5ib3hab29tLm1vdmVkKCkpO1xyXG5cdH0sXHJcblxyXG5cdF9jbGVhckhhbmRsZXJzOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gdGhpcy5faGFuZGxlcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0dGhpcy5faGFuZGxlcnNbaV0uZGlzYWJsZSgpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdC8vIEBzZWN0aW9uIE90aGVyIE1ldGhvZHNcclxuXHJcblx0Ly8gQG1ldGhvZCB3aGVuUmVhZHkoZm46IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG5cdC8vIFJ1bnMgdGhlIGdpdmVuIGZ1bmN0aW9uIGBmbmAgd2hlbiB0aGUgbWFwIGdldHMgaW5pdGlhbGl6ZWQgd2l0aFxyXG5cdC8vIGEgdmlldyAoY2VudGVyIGFuZCB6b29tKSBhbmQgYXQgbGVhc3Qgb25lIGxheWVyLCBvciBpbW1lZGlhdGVseVxyXG5cdC8vIGlmIGl0J3MgYWxyZWFkeSBpbml0aWFsaXplZCwgb3B0aW9uYWxseSBwYXNzaW5nIGEgZnVuY3Rpb24gY29udGV4dC5cclxuXHR3aGVuUmVhZHk6IGZ1bmN0aW9uIChjYWxsYmFjaywgY29udGV4dCkge1xyXG5cdFx0aWYgKHRoaXMuX2xvYWRlZCkge1xyXG5cdFx0XHRjYWxsYmFjay5jYWxsKGNvbnRleHQgfHwgdGhpcywge3RhcmdldDogdGhpc30pO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0dGhpcy5vbignbG9hZCcsIGNhbGxiYWNrLCBjb250ZXh0KTtcclxuXHRcdH1cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cclxuXHQvLyBwcml2YXRlIG1ldGhvZHMgZm9yIGdldHRpbmcgbWFwIHN0YXRlXHJcblxyXG5cdF9nZXRNYXBQYW5lUG9zOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gZ2V0UG9zaXRpb24odGhpcy5fbWFwUGFuZSkgfHwgbmV3IFBvaW50KDAsIDApO1xyXG5cdH0sXHJcblxyXG5cdF9tb3ZlZDogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIHBvcyA9IHRoaXMuX2dldE1hcFBhbmVQb3MoKTtcclxuXHRcdHJldHVybiBwb3MgJiYgIXBvcy5lcXVhbHMoWzAsIDBdKTtcclxuXHR9LFxyXG5cclxuXHRfZ2V0VG9wTGVmdFBvaW50OiBmdW5jdGlvbiAoY2VudGVyLCB6b29tKSB7XHJcblx0XHR2YXIgcGl4ZWxPcmlnaW4gPSBjZW50ZXIgJiYgem9vbSAhPT0gdW5kZWZpbmVkID9cclxuXHRcdFx0dGhpcy5fZ2V0TmV3UGl4ZWxPcmlnaW4oY2VudGVyLCB6b29tKSA6XHJcblx0XHRcdHRoaXMuZ2V0UGl4ZWxPcmlnaW4oKTtcclxuXHRcdHJldHVybiBwaXhlbE9yaWdpbi5zdWJ0cmFjdCh0aGlzLl9nZXRNYXBQYW5lUG9zKCkpO1xyXG5cdH0sXHJcblxyXG5cdF9nZXROZXdQaXhlbE9yaWdpbjogZnVuY3Rpb24gKGNlbnRlciwgem9vbSkge1xyXG5cdFx0dmFyIHZpZXdIYWxmID0gdGhpcy5nZXRTaXplKCkuX2RpdmlkZUJ5KDIpO1xyXG5cdFx0cmV0dXJuIHRoaXMucHJvamVjdChjZW50ZXIsIHpvb20pLl9zdWJ0cmFjdCh2aWV3SGFsZikuX2FkZCh0aGlzLl9nZXRNYXBQYW5lUG9zKCkpLl9yb3VuZCgpO1xyXG5cdH0sXHJcblxyXG5cdF9sYXRMbmdUb05ld0xheWVyUG9pbnQ6IGZ1bmN0aW9uIChsYXRsbmcsIHpvb20sIGNlbnRlcikge1xyXG5cdFx0dmFyIHRvcExlZnQgPSB0aGlzLl9nZXROZXdQaXhlbE9yaWdpbihjZW50ZXIsIHpvb20pO1xyXG5cdFx0cmV0dXJuIHRoaXMucHJvamVjdChsYXRsbmcsIHpvb20pLl9zdWJ0cmFjdCh0b3BMZWZ0KTtcclxuXHR9LFxyXG5cclxuXHRfbGF0TG5nQm91bmRzVG9OZXdMYXllckJvdW5kczogZnVuY3Rpb24gKGxhdExuZ0JvdW5kcywgem9vbSwgY2VudGVyKSB7XHJcblx0XHR2YXIgdG9wTGVmdCA9IHRoaXMuX2dldE5ld1BpeGVsT3JpZ2luKGNlbnRlciwgem9vbSk7XHJcblx0XHRyZXR1cm4gdG9Cb3VuZHMoW1xyXG5cdFx0XHR0aGlzLnByb2plY3QobGF0TG5nQm91bmRzLmdldFNvdXRoV2VzdCgpLCB6b29tKS5fc3VidHJhY3QodG9wTGVmdCksXHJcblx0XHRcdHRoaXMucHJvamVjdChsYXRMbmdCb3VuZHMuZ2V0Tm9ydGhXZXN0KCksIHpvb20pLl9zdWJ0cmFjdCh0b3BMZWZ0KSxcclxuXHRcdFx0dGhpcy5wcm9qZWN0KGxhdExuZ0JvdW5kcy5nZXRTb3V0aEVhc3QoKSwgem9vbSkuX3N1YnRyYWN0KHRvcExlZnQpLFxyXG5cdFx0XHR0aGlzLnByb2plY3QobGF0TG5nQm91bmRzLmdldE5vcnRoRWFzdCgpLCB6b29tKS5fc3VidHJhY3QodG9wTGVmdClcclxuXHRcdF0pO1xyXG5cdH0sXHJcblxyXG5cdC8vIGxheWVyIHBvaW50IG9mIHRoZSBjdXJyZW50IGNlbnRlclxyXG5cdF9nZXRDZW50ZXJMYXllclBvaW50OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5jb250YWluZXJQb2ludFRvTGF5ZXJQb2ludCh0aGlzLmdldFNpemUoKS5fZGl2aWRlQnkoMikpO1xyXG5cdH0sXHJcblxyXG5cdC8vIG9mZnNldCBvZiB0aGUgc3BlY2lmaWVkIHBsYWNlIHRvIHRoZSBjdXJyZW50IGNlbnRlciBpbiBwaXhlbHNcclxuXHRfZ2V0Q2VudGVyT2Zmc2V0OiBmdW5jdGlvbiAobGF0bG5nKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5sYXRMbmdUb0xheWVyUG9pbnQobGF0bG5nKS5zdWJ0cmFjdCh0aGlzLl9nZXRDZW50ZXJMYXllclBvaW50KCkpO1xyXG5cdH0sXHJcblxyXG5cdC8vIGFkanVzdCBjZW50ZXIgZm9yIHZpZXcgdG8gZ2V0IGluc2lkZSBib3VuZHNcclxuXHRfbGltaXRDZW50ZXI6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20sIGJvdW5kcykge1xyXG5cclxuXHRcdGlmICghYm91bmRzKSB7IHJldHVybiBjZW50ZXI7IH1cclxuXHJcblx0XHR2YXIgY2VudGVyUG9pbnQgPSB0aGlzLnByb2plY3QoY2VudGVyLCB6b29tKSxcclxuXHRcdCAgICB2aWV3SGFsZiA9IHRoaXMuZ2V0U2l6ZSgpLmRpdmlkZUJ5KDIpLFxyXG5cdFx0ICAgIHZpZXdCb3VuZHMgPSBuZXcgQm91bmRzKGNlbnRlclBvaW50LnN1YnRyYWN0KHZpZXdIYWxmKSwgY2VudGVyUG9pbnQuYWRkKHZpZXdIYWxmKSksXHJcblx0XHQgICAgb2Zmc2V0ID0gdGhpcy5fZ2V0Qm91bmRzT2Zmc2V0KHZpZXdCb3VuZHMsIGJvdW5kcywgem9vbSk7XHJcblxyXG5cdFx0Ly8gSWYgb2Zmc2V0IGlzIGxlc3MgdGhhbiBhIHBpeGVsLCBpZ25vcmUuXHJcblx0XHQvLyBUaGlzIHByZXZlbnRzIHVuc3RhYmxlIHByb2plY3Rpb25zIGZyb20gZ2V0dGluZyBpbnRvXHJcblx0XHQvLyBhbiBpbmZpbml0ZSBsb29wIG9mIHRpbnkgb2Zmc2V0cy5cclxuXHRcdGlmIChvZmZzZXQucm91bmQoKS5lcXVhbHMoWzAsIDBdKSkge1xyXG5cdFx0XHRyZXR1cm4gY2VudGVyO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzLnVucHJvamVjdChjZW50ZXJQb2ludC5hZGQob2Zmc2V0KSwgem9vbSk7XHJcblx0fSxcclxuXHJcblx0Ly8gYWRqdXN0IG9mZnNldCBmb3IgdmlldyB0byBnZXQgaW5zaWRlIGJvdW5kc1xyXG5cdF9saW1pdE9mZnNldDogZnVuY3Rpb24gKG9mZnNldCwgYm91bmRzKSB7XHJcblx0XHRpZiAoIWJvdW5kcykgeyByZXR1cm4gb2Zmc2V0OyB9XHJcblxyXG5cdFx0dmFyIHZpZXdCb3VuZHMgPSB0aGlzLmdldFBpeGVsQm91bmRzKCksXHJcblx0XHQgICAgbmV3Qm91bmRzID0gbmV3IEJvdW5kcyh2aWV3Qm91bmRzLm1pbi5hZGQob2Zmc2V0KSwgdmlld0JvdW5kcy5tYXguYWRkKG9mZnNldCkpO1xyXG5cclxuXHRcdHJldHVybiBvZmZzZXQuYWRkKHRoaXMuX2dldEJvdW5kc09mZnNldChuZXdCb3VuZHMsIGJvdW5kcykpO1xyXG5cdH0sXHJcblxyXG5cdC8vIHJldHVybnMgb2Zmc2V0IG5lZWRlZCBmb3IgcHhCb3VuZHMgdG8gZ2V0IGluc2lkZSBtYXhCb3VuZHMgYXQgYSBzcGVjaWZpZWQgem9vbVxyXG5cdF9nZXRCb3VuZHNPZmZzZXQ6IGZ1bmN0aW9uIChweEJvdW5kcywgbWF4Qm91bmRzLCB6b29tKSB7XHJcblx0XHR2YXIgcHJvamVjdGVkTWF4Qm91bmRzID0gdG9Cb3VuZHMoXHJcblx0XHQgICAgICAgIHRoaXMucHJvamVjdChtYXhCb3VuZHMuZ2V0Tm9ydGhFYXN0KCksIHpvb20pLFxyXG5cdFx0ICAgICAgICB0aGlzLnByb2plY3QobWF4Qm91bmRzLmdldFNvdXRoV2VzdCgpLCB6b29tKVxyXG5cdFx0ICAgICksXHJcblx0XHQgICAgbWluT2Zmc2V0ID0gcHJvamVjdGVkTWF4Qm91bmRzLm1pbi5zdWJ0cmFjdChweEJvdW5kcy5taW4pLFxyXG5cdFx0ICAgIG1heE9mZnNldCA9IHByb2plY3RlZE1heEJvdW5kcy5tYXguc3VidHJhY3QocHhCb3VuZHMubWF4KSxcclxuXHJcblx0XHQgICAgZHggPSB0aGlzLl9yZWJvdW5kKG1pbk9mZnNldC54LCAtbWF4T2Zmc2V0LngpLFxyXG5cdFx0ICAgIGR5ID0gdGhpcy5fcmVib3VuZChtaW5PZmZzZXQueSwgLW1heE9mZnNldC55KTtcclxuXHJcblx0XHRyZXR1cm4gbmV3IFBvaW50KGR4LCBkeSk7XHJcblx0fSxcclxuXHJcblx0X3JlYm91bmQ6IGZ1bmN0aW9uIChsZWZ0LCByaWdodCkge1xyXG5cdFx0cmV0dXJuIGxlZnQgKyByaWdodCA+IDAgP1xyXG5cdFx0XHRNYXRoLnJvdW5kKGxlZnQgLSByaWdodCkgLyAyIDpcclxuXHRcdFx0TWF0aC5tYXgoMCwgTWF0aC5jZWlsKGxlZnQpKSAtIE1hdGgubWF4KDAsIE1hdGguZmxvb3IocmlnaHQpKTtcclxuXHR9LFxyXG5cclxuXHRfbGltaXRab29tOiBmdW5jdGlvbiAoem9vbSkge1xyXG5cdFx0dmFyIG1pbiA9IHRoaXMuZ2V0TWluWm9vbSgpLFxyXG5cdFx0ICAgIG1heCA9IHRoaXMuZ2V0TWF4Wm9vbSgpLFxyXG5cdFx0ICAgIHNuYXAgPSBhbnkzZCA/IHRoaXMub3B0aW9ucy56b29tU25hcCA6IDE7XHJcblx0XHRpZiAoc25hcCkge1xyXG5cdFx0XHR6b29tID0gTWF0aC5yb3VuZCh6b29tIC8gc25hcCkgKiBzbmFwO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIE1hdGgubWF4KG1pbiwgTWF0aC5taW4obWF4LCB6b29tKSk7XHJcblx0fSxcclxuXHJcblx0X29uUGFuVHJhbnNpdGlvblN0ZXA6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuZmlyZSgnbW92ZScpO1xyXG5cdH0sXHJcblxyXG5cdF9vblBhblRyYW5zaXRpb25FbmQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJlbW92ZUNsYXNzKHRoaXMuX21hcFBhbmUsICdsZWFmbGV0LXBhbi1hbmltJyk7XHJcblx0XHR0aGlzLmZpcmUoJ21vdmVlbmQnKTtcclxuXHR9LFxyXG5cclxuXHRfdHJ5QW5pbWF0ZWRQYW46IGZ1bmN0aW9uIChjZW50ZXIsIG9wdGlvbnMpIHtcclxuXHRcdC8vIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbmV3IGFuZCBjdXJyZW50IGNlbnRlcnMgaW4gcGl4ZWxzXHJcblx0XHR2YXIgb2Zmc2V0ID0gdGhpcy5fZ2V0Q2VudGVyT2Zmc2V0KGNlbnRlcikuX3RydW5jKCk7XHJcblxyXG5cdFx0Ly8gZG9uJ3QgYW5pbWF0ZSB0b28gZmFyIHVubGVzcyBhbmltYXRlOiB0cnVlIHNwZWNpZmllZCBpbiBvcHRpb25zXHJcblx0XHRpZiAoKG9wdGlvbnMgJiYgb3B0aW9ucy5hbmltYXRlKSAhPT0gdHJ1ZSAmJiAhdGhpcy5nZXRTaXplKCkuY29udGFpbnMob2Zmc2V0KSkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcblx0XHR0aGlzLnBhbkJ5KG9mZnNldCwgb3B0aW9ucyk7XHJcblxyXG5cdFx0cmV0dXJuIHRydWU7XHJcblx0fSxcclxuXHJcblx0X2NyZWF0ZUFuaW1Qcm94eTogZnVuY3Rpb24gKCkge1xyXG5cclxuXHRcdHZhciBwcm94eSA9IHRoaXMuX3Byb3h5ID0gY3JlYXRlJDEoJ2RpdicsICdsZWFmbGV0LXByb3h5IGxlYWZsZXQtem9vbS1hbmltYXRlZCcpO1xyXG5cdFx0dGhpcy5fcGFuZXMubWFwUGFuZS5hcHBlbmRDaGlsZChwcm94eSk7XHJcblxyXG5cdFx0dGhpcy5vbignem9vbWFuaW0nLCBmdW5jdGlvbiAoZSkge1xyXG5cdFx0XHR2YXIgcHJvcCA9IFRSQU5TRk9STSxcclxuXHRcdFx0ICAgIHRyYW5zZm9ybSA9IHRoaXMuX3Byb3h5LnN0eWxlW3Byb3BdO1xyXG5cclxuXHRcdFx0c2V0VHJhbnNmb3JtKHRoaXMuX3Byb3h5LCB0aGlzLnByb2plY3QoZS5jZW50ZXIsIGUuem9vbSksIHRoaXMuZ2V0Wm9vbVNjYWxlKGUuem9vbSwgMSkpO1xyXG5cclxuXHRcdFx0Ly8gd29ya2Fyb3VuZCBmb3IgY2FzZSB3aGVuIHRyYW5zZm9ybSBpcyB0aGUgc2FtZSBhbmQgc28gdHJhbnNpdGlvbmVuZCBldmVudCBpcyBub3QgZmlyZWRcclxuXHRcdFx0aWYgKHRyYW5zZm9ybSA9PT0gdGhpcy5fcHJveHkuc3R5bGVbcHJvcF0gJiYgdGhpcy5fYW5pbWF0aW5nWm9vbSkge1xyXG5cdFx0XHRcdHRoaXMuX29uWm9vbVRyYW5zaXRpb25FbmQoKTtcclxuXHRcdFx0fVxyXG5cdFx0fSwgdGhpcyk7XHJcblxyXG5cdFx0dGhpcy5vbignbG9hZCBtb3ZlZW5kJywgZnVuY3Rpb24gKCkge1xyXG5cdFx0XHR2YXIgYyA9IHRoaXMuZ2V0Q2VudGVyKCksXHJcblx0XHRcdCAgICB6ID0gdGhpcy5nZXRab29tKCk7XHJcblx0XHRcdHNldFRyYW5zZm9ybSh0aGlzLl9wcm94eSwgdGhpcy5wcm9qZWN0KGMsIHopLCB0aGlzLmdldFpvb21TY2FsZSh6LCAxKSk7XHJcblx0XHR9LCB0aGlzKTtcclxuXHJcblx0XHR0aGlzLl9vbigndW5sb2FkJywgdGhpcy5fZGVzdHJveUFuaW1Qcm94eSwgdGhpcyk7XHJcblx0fSxcclxuXHJcblx0X2Rlc3Ryb3lBbmltUHJveHk6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJlbW92ZSh0aGlzLl9wcm94eSk7XHJcblx0XHRkZWxldGUgdGhpcy5fcHJveHk7XHJcblx0fSxcclxuXHJcblx0X2NhdGNoVHJhbnNpdGlvbkVuZDogZnVuY3Rpb24gKGUpIHtcclxuXHRcdGlmICh0aGlzLl9hbmltYXRpbmdab29tICYmIGUucHJvcGVydHlOYW1lLmluZGV4T2YoJ3RyYW5zZm9ybScpID49IDApIHtcclxuXHRcdFx0dGhpcy5fb25ab29tVHJhbnNpdGlvbkVuZCgpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9ub3RoaW5nVG9BbmltYXRlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gIXRoaXMuX2NvbnRhaW5lci5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCdsZWFmbGV0LXpvb20tYW5pbWF0ZWQnKS5sZW5ndGg7XHJcblx0fSxcclxuXHJcblx0X3RyeUFuaW1hdGVkWm9vbTogZnVuY3Rpb24gKGNlbnRlciwgem9vbSwgb3B0aW9ucykge1xyXG5cclxuXHRcdGlmICh0aGlzLl9hbmltYXRpbmdab29tKSB7IHJldHVybiB0cnVlOyB9XHJcblxyXG5cdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XHJcblxyXG5cdFx0Ly8gZG9uJ3QgYW5pbWF0ZSBpZiBkaXNhYmxlZCwgbm90IHN1cHBvcnRlZCBvciB6b29tIGRpZmZlcmVuY2UgaXMgdG9vIGxhcmdlXHJcblx0XHRpZiAoIXRoaXMuX3pvb21BbmltYXRlZCB8fCBvcHRpb25zLmFuaW1hdGUgPT09IGZhbHNlIHx8IHRoaXMuX25vdGhpbmdUb0FuaW1hdGUoKSB8fFxyXG5cdFx0ICAgICAgICBNYXRoLmFicyh6b29tIC0gdGhpcy5fem9vbSkgPiB0aGlzLm9wdGlvbnMuem9vbUFuaW1hdGlvblRocmVzaG9sZCkgeyByZXR1cm4gZmFsc2U7IH1cclxuXHJcblx0XHQvLyBvZmZzZXQgaXMgdGhlIHBpeGVsIGNvb3JkcyBvZiB0aGUgem9vbSBvcmlnaW4gcmVsYXRpdmUgdG8gdGhlIGN1cnJlbnQgY2VudGVyXHJcblx0XHR2YXIgc2NhbGUgPSB0aGlzLmdldFpvb21TY2FsZSh6b29tKSxcclxuXHRcdCAgICBvZmZzZXQgPSB0aGlzLl9nZXRDZW50ZXJPZmZzZXQoY2VudGVyKS5fZGl2aWRlQnkoMSAtIDEgLyBzY2FsZSk7XHJcblxyXG5cdFx0Ly8gZG9uJ3QgYW5pbWF0ZSBpZiB0aGUgem9vbSBvcmlnaW4gaXNuJ3Qgd2l0aGluIG9uZSBzY3JlZW4gZnJvbSB0aGUgY3VycmVudCBjZW50ZXIsIHVubGVzcyBmb3JjZWRcclxuXHRcdGlmIChvcHRpb25zLmFuaW1hdGUgIT09IHRydWUgJiYgIXRoaXMuZ2V0U2l6ZSgpLmNvbnRhaW5zKG9mZnNldCkpIHsgcmV0dXJuIGZhbHNlOyB9XHJcblxyXG5cdFx0cmVxdWVzdEFuaW1GcmFtZShmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHRoaXNcclxuXHRcdFx0ICAgIC5fbW92ZVN0YXJ0KHRydWUsIGZhbHNlKVxyXG5cdFx0XHQgICAgLl9hbmltYXRlWm9vbShjZW50ZXIsIHpvb20sIHRydWUpO1xyXG5cdFx0fSwgdGhpcyk7XHJcblxyXG5cdFx0cmV0dXJuIHRydWU7XHJcblx0fSxcclxuXHJcblx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAoY2VudGVyLCB6b29tLCBzdGFydEFuaW0sIG5vVXBkYXRlKSB7XHJcblx0XHRpZiAoIXRoaXMuX21hcFBhbmUpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0aWYgKHN0YXJ0QW5pbSkge1xyXG5cdFx0XHR0aGlzLl9hbmltYXRpbmdab29tID0gdHJ1ZTtcclxuXHJcblx0XHRcdC8vIHJlbWVtYmVyIHdoYXQgY2VudGVyL3pvb20gdG8gc2V0IGFmdGVyIGFuaW1hdGlvblxyXG5cdFx0XHR0aGlzLl9hbmltYXRlVG9DZW50ZXIgPSBjZW50ZXI7XHJcblx0XHRcdHRoaXMuX2FuaW1hdGVUb1pvb20gPSB6b29tO1xyXG5cclxuXHRcdFx0YWRkQ2xhc3ModGhpcy5fbWFwUGFuZSwgJ2xlYWZsZXQtem9vbS1hbmltJyk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQGV2ZW50IHpvb21hbmltOiBab29tQW5pbUV2ZW50XHJcblx0XHQvLyBGaXJlZCBvbiBldmVyeSBmcmFtZSBvZiBhIHpvb20gYW5pbWF0aW9uXHJcblx0XHR0aGlzLmZpcmUoJ3pvb21hbmltJywge1xyXG5cdFx0XHRjZW50ZXI6IGNlbnRlcixcclxuXHRcdFx0em9vbTogem9vbSxcclxuXHRcdFx0bm9VcGRhdGU6IG5vVXBkYXRlXHJcblx0XHR9KTtcclxuXHJcblx0XHQvLyBXb3JrIGFyb3VuZCB3ZWJraXQgbm90IGZpcmluZyAndHJhbnNpdGlvbmVuZCcsIHNlZSBodHRwczovL2dpdGh1Yi5jb20vTGVhZmxldC9MZWFmbGV0L2lzc3Vlcy8zNjg5LCAyNjkzXHJcblx0XHRzZXRUaW1lb3V0KGJpbmQodGhpcy5fb25ab29tVHJhbnNpdGlvbkVuZCwgdGhpcyksIDI1MCk7XHJcblx0fSxcclxuXHJcblx0X29uWm9vbVRyYW5zaXRpb25FbmQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICghdGhpcy5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm47IH1cclxuXHJcblx0XHRpZiAodGhpcy5fbWFwUGFuZSkge1xyXG5cdFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9tYXBQYW5lLCAnbGVhZmxldC16b29tLWFuaW0nKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9hbmltYXRpbmdab29tID0gZmFsc2U7XHJcblxyXG5cdFx0dGhpcy5fbW92ZSh0aGlzLl9hbmltYXRlVG9DZW50ZXIsIHRoaXMuX2FuaW1hdGVUb1pvb20pO1xyXG5cclxuXHRcdC8vIFRoaXMgYW5pbSBmcmFtZSBzaG91bGQgcHJldmVudCBhbiBvYnNjdXJlIGlPUyB3ZWJraXQgdGlsZSBsb2FkaW5nIHJhY2UgY29uZGl0aW9uLlxyXG5cdFx0cmVxdWVzdEFuaW1GcmFtZShmdW5jdGlvbiAoKSB7XHJcblx0XHRcdHRoaXMuX21vdmVFbmQodHJ1ZSk7XHJcblx0XHR9LCB0aGlzKTtcclxuXHR9XHJcbn0pO1xyXG5cclxuLy8gQHNlY3Rpb25cclxuXHJcbi8vIEBmYWN0b3J5IEwubWFwKGlkOiBTdHJpbmcsIG9wdGlvbnM/OiBNYXAgb3B0aW9ucylcclxuLy8gSW5zdGFudGlhdGVzIGEgbWFwIG9iamVjdCBnaXZlbiB0aGUgRE9NIElEIG9mIGEgYDxkaXY+YCBlbGVtZW50XHJcbi8vIGFuZCBvcHRpb25hbGx5IGFuIG9iamVjdCBsaXRlcmFsIHdpdGggYE1hcCBvcHRpb25zYC5cclxuLy9cclxuLy8gQGFsdGVybmF0aXZlXHJcbi8vIEBmYWN0b3J5IEwubWFwKGVsOiBIVE1MRWxlbWVudCwgb3B0aW9ucz86IE1hcCBvcHRpb25zKVxyXG4vLyBJbnN0YW50aWF0ZXMgYSBtYXAgb2JqZWN0IGdpdmVuIGFuIGluc3RhbmNlIG9mIGEgYDxkaXY+YCBIVE1MIGVsZW1lbnRcclxuLy8gYW5kIG9wdGlvbmFsbHkgYW4gb2JqZWN0IGxpdGVyYWwgd2l0aCBgTWFwIG9wdGlvbnNgLlxyXG5mdW5jdGlvbiBjcmVhdGVNYXAoaWQsIG9wdGlvbnMpIHtcclxuXHRyZXR1cm4gbmV3IE1hcChpZCwgb3B0aW9ucyk7XHJcbn1cblxuLypcclxuICogQGNsYXNzIENvbnRyb2xcclxuICogQGFrYSBMLkNvbnRyb2xcclxuICogQGluaGVyaXRzIENsYXNzXHJcbiAqXHJcbiAqIEwuQ29udHJvbCBpcyBhIGJhc2UgY2xhc3MgZm9yIGltcGxlbWVudGluZyBtYXAgY29udHJvbHMuIEhhbmRsZXMgcG9zaXRpb25pbmcuXHJcbiAqIEFsbCBvdGhlciBjb250cm9scyBleHRlbmQgZnJvbSB0aGlzIGNsYXNzLlxyXG4gKi9cclxuXHJcbnZhciBDb250cm9sID0gQ2xhc3MuZXh0ZW5kKHtcclxuXHQvLyBAc2VjdGlvblxyXG5cdC8vIEBha2EgQ29udHJvbCBvcHRpb25zXHJcblx0b3B0aW9uczoge1xyXG5cdFx0Ly8gQG9wdGlvbiBwb3NpdGlvbjogU3RyaW5nID0gJ3RvcHJpZ2h0J1xyXG5cdFx0Ly8gVGhlIHBvc2l0aW9uIG9mIHRoZSBjb250cm9sIChvbmUgb2YgdGhlIG1hcCBjb3JuZXJzKS4gUG9zc2libGUgdmFsdWVzIGFyZSBgJ3RvcGxlZnQnYCxcclxuXHRcdC8vIGAndG9wcmlnaHQnYCwgYCdib3R0b21sZWZ0J2Agb3IgYCdib3R0b21yaWdodCdgXHJcblx0XHRwb3NpdGlvbjogJ3RvcHJpZ2h0J1xyXG5cdH0sXHJcblxyXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cdH0sXHJcblxyXG5cdC8qIEBzZWN0aW9uXHJcblx0ICogQ2xhc3NlcyBleHRlbmRpbmcgTC5Db250cm9sIHdpbGwgaW5oZXJpdCB0aGUgZm9sbG93aW5nIG1ldGhvZHM6XHJcblx0ICpcclxuXHQgKiBAbWV0aG9kIGdldFBvc2l0aW9uOiBzdHJpbmdcclxuXHQgKiBSZXR1cm5zIHRoZSBwb3NpdGlvbiBvZiB0aGUgY29udHJvbC5cclxuXHQgKi9cclxuXHRnZXRQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5wb3NpdGlvbjtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNldFBvc2l0aW9uKHBvc2l0aW9uOiBzdHJpbmcpOiB0aGlzXHJcblx0Ly8gU2V0cyB0aGUgcG9zaXRpb24gb2YgdGhlIGNvbnRyb2wuXHJcblx0c2V0UG9zaXRpb246IGZ1bmN0aW9uIChwb3NpdGlvbikge1xyXG5cdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcclxuXHJcblx0XHRpZiAobWFwKSB7XHJcblx0XHRcdG1hcC5yZW1vdmVDb250cm9sKHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMub3B0aW9ucy5wb3NpdGlvbiA9IHBvc2l0aW9uO1xyXG5cclxuXHRcdGlmIChtYXApIHtcclxuXHRcdFx0bWFwLmFkZENvbnRyb2wodGhpcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRDb250YWluZXI6IEhUTUxFbGVtZW50XHJcblx0Ly8gUmV0dXJucyB0aGUgSFRNTEVsZW1lbnQgdGhhdCBjb250YWlucyB0aGUgY29udHJvbC5cclxuXHRnZXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9jb250YWluZXI7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBhZGRUbyhtYXA6IE1hcCk6IHRoaXNcclxuXHQvLyBBZGRzIHRoZSBjb250cm9sIHRvIHRoZSBnaXZlbiBtYXAuXHJcblx0YWRkVG86IGZ1bmN0aW9uIChtYXApIHtcclxuXHRcdHRoaXMucmVtb3ZlKCk7XHJcblx0XHR0aGlzLl9tYXAgPSBtYXA7XHJcblxyXG5cdFx0dmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lciA9IHRoaXMub25BZGQobWFwKSxcclxuXHRcdCAgICBwb3MgPSB0aGlzLmdldFBvc2l0aW9uKCksXHJcblx0XHQgICAgY29ybmVyID0gbWFwLl9jb250cm9sQ29ybmVyc1twb3NdO1xyXG5cclxuXHRcdGFkZENsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtY29udHJvbCcpO1xyXG5cclxuXHRcdGlmIChwb3MuaW5kZXhPZignYm90dG9tJykgIT09IC0xKSB7XHJcblx0XHRcdGNvcm5lci5pbnNlcnRCZWZvcmUoY29udGFpbmVyLCBjb3JuZXIuZmlyc3RDaGlsZCk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRjb3JuZXIuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHJlbW92ZTogdGhpc1xyXG5cdC8vIFJlbW92ZXMgdGhlIGNvbnRyb2wgZnJvbSB0aGUgbWFwIGl0IGlzIGN1cnJlbnRseSBhY3RpdmUgb24uXHJcblx0cmVtb3ZlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAoIXRoaXMuX21hcCkge1xyXG5cdFx0XHRyZXR1cm4gdGhpcztcclxuXHRcdH1cclxuXHJcblx0XHRyZW1vdmUodGhpcy5fY29udGFpbmVyKTtcclxuXHJcblx0XHRpZiAodGhpcy5vblJlbW92ZSkge1xyXG5cdFx0XHR0aGlzLm9uUmVtb3ZlKHRoaXMuX21hcCk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fbWFwID0gbnVsbDtcclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRfcmVmb2N1c09uTWFwOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0Ly8gaWYgbWFwIGV4aXN0cyBhbmQgZXZlbnQgaXMgbm90IGEga2V5Ym9hcmQgZXZlbnRcclxuXHRcdGlmICh0aGlzLl9tYXAgJiYgZSAmJiBlLnNjcmVlblggPiAwICYmIGUuc2NyZWVuWSA+IDApIHtcclxuXHRcdFx0dGhpcy5fbWFwLmdldENvbnRhaW5lcigpLmZvY3VzKCk7XHJcblx0XHR9XHJcblx0fVxyXG59KTtcclxuXHJcbnZhciBjb250cm9sID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcclxuXHRyZXR1cm4gbmV3IENvbnRyb2wob3B0aW9ucyk7XHJcbn07XHJcblxyXG4vKiBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xyXG4gKiBAdW5pbmhlcml0YWJsZVxyXG4gKlxyXG4gKiBFdmVyeSBjb250cm9sIHNob3VsZCBleHRlbmQgZnJvbSBgTC5Db250cm9sYCBhbmQgKHJlLSlpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBtZXRob2RzLlxyXG4gKlxyXG4gKiBAbWV0aG9kIG9uQWRkKG1hcDogTWFwKTogSFRNTEVsZW1lbnRcclxuICogU2hvdWxkIHJldHVybiB0aGUgY29udGFpbmVyIERPTSBlbGVtZW50IGZvciB0aGUgY29udHJvbCBhbmQgYWRkIGxpc3RlbmVycyBvbiByZWxldmFudCBtYXAgZXZlbnRzLiBDYWxsZWQgb24gW2Bjb250cm9sLmFkZFRvKG1hcClgXSgjY29udHJvbC1hZGRUbykuXHJcbiAqXHJcbiAqIEBtZXRob2Qgb25SZW1vdmUobWFwOiBNYXApXHJcbiAqIE9wdGlvbmFsIG1ldGhvZC4gU2hvdWxkIGNvbnRhaW4gYWxsIGNsZWFuIHVwIGNvZGUgdGhhdCByZW1vdmVzIHRoZSBsaXN0ZW5lcnMgcHJldmlvdXNseSBhZGRlZCBpbiBbYG9uQWRkYF0oI2NvbnRyb2wtb25hZGQpLiBDYWxsZWQgb24gW2Bjb250cm9sLnJlbW92ZSgpYF0oI2NvbnRyb2wtcmVtb3ZlKS5cclxuICovXHJcblxyXG4vKiBAbmFtZXNwYWNlIE1hcFxyXG4gKiBAc2VjdGlvbiBNZXRob2RzIGZvciBMYXllcnMgYW5kIENvbnRyb2xzXHJcbiAqL1xyXG5NYXAuaW5jbHVkZSh7XHJcblx0Ly8gQG1ldGhvZCBhZGRDb250cm9sKGNvbnRyb2w6IENvbnRyb2wpOiB0aGlzXHJcblx0Ly8gQWRkcyB0aGUgZ2l2ZW4gY29udHJvbCB0byB0aGUgbWFwXHJcblx0YWRkQ29udHJvbDogZnVuY3Rpb24gKGNvbnRyb2wpIHtcclxuXHRcdGNvbnRyb2wuYWRkVG8odGhpcyk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHJlbW92ZUNvbnRyb2woY29udHJvbDogQ29udHJvbCk6IHRoaXNcclxuXHQvLyBSZW1vdmVzIHRoZSBnaXZlbiBjb250cm9sIGZyb20gdGhlIG1hcFxyXG5cdHJlbW92ZUNvbnRyb2w6IGZ1bmN0aW9uIChjb250cm9sKSB7XHJcblx0XHRjb250cm9sLnJlbW92ZSgpO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0X2luaXRDb250cm9sUG9zOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgY29ybmVycyA9IHRoaXMuX2NvbnRyb2xDb3JuZXJzID0ge30sXHJcblx0XHQgICAgbCA9ICdsZWFmbGV0LScsXHJcblx0XHQgICAgY29udGFpbmVyID0gdGhpcy5fY29udHJvbENvbnRhaW5lciA9XHJcblx0XHQgICAgICAgICAgICBjcmVhdGUkMSgnZGl2JywgbCArICdjb250cm9sLWNvbnRhaW5lcicsIHRoaXMuX2NvbnRhaW5lcik7XHJcblxyXG5cdFx0ZnVuY3Rpb24gY3JlYXRlQ29ybmVyKHZTaWRlLCBoU2lkZSkge1xyXG5cdFx0XHR2YXIgY2xhc3NOYW1lID0gbCArIHZTaWRlICsgJyAnICsgbCArIGhTaWRlO1xyXG5cclxuXHRcdFx0Y29ybmVyc1t2U2lkZSArIGhTaWRlXSA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUsIGNvbnRhaW5lcik7XHJcblx0XHR9XHJcblxyXG5cdFx0Y3JlYXRlQ29ybmVyKCd0b3AnLCAnbGVmdCcpO1xyXG5cdFx0Y3JlYXRlQ29ybmVyKCd0b3AnLCAncmlnaHQnKTtcclxuXHRcdGNyZWF0ZUNvcm5lcignYm90dG9tJywgJ2xlZnQnKTtcclxuXHRcdGNyZWF0ZUNvcm5lcignYm90dG9tJywgJ3JpZ2h0Jyk7XHJcblx0fSxcclxuXHJcblx0X2NsZWFyQ29udHJvbFBvczogZnVuY3Rpb24gKCkge1xyXG5cdFx0Zm9yICh2YXIgaSBpbiB0aGlzLl9jb250cm9sQ29ybmVycykge1xyXG5cdFx0XHRyZW1vdmUodGhpcy5fY29udHJvbENvcm5lcnNbaV0pO1xyXG5cdFx0fVxyXG5cdFx0cmVtb3ZlKHRoaXMuX2NvbnRyb2xDb250YWluZXIpO1xyXG5cdFx0ZGVsZXRlIHRoaXMuX2NvbnRyb2xDb3JuZXJzO1xyXG5cdFx0ZGVsZXRlIHRoaXMuX2NvbnRyb2xDb250YWluZXI7XHJcblx0fVxyXG59KTtcblxuLypcclxuICogQGNsYXNzIENvbnRyb2wuTGF5ZXJzXHJcbiAqIEBha2EgTC5Db250cm9sLkxheWVyc1xyXG4gKiBAaW5oZXJpdHMgQ29udHJvbFxyXG4gKlxyXG4gKiBUaGUgbGF5ZXJzIGNvbnRyb2wgZ2l2ZXMgdXNlcnMgdGhlIGFiaWxpdHkgdG8gc3dpdGNoIGJldHdlZW4gZGlmZmVyZW50IGJhc2UgbGF5ZXJzIGFuZCBzd2l0Y2ggb3ZlcmxheXMgb24vb2ZmIChjaGVjayBvdXQgdGhlIFtkZXRhaWxlZCBleGFtcGxlXShodHRwOi8vbGVhZmxldGpzLmNvbS9leGFtcGxlcy9sYXllcnMtY29udHJvbC8pKS4gRXh0ZW5kcyBgQ29udHJvbGAuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBiYXNlTGF5ZXJzID0ge1xyXG4gKiBcdFwiTWFwYm94XCI6IG1hcGJveCxcclxuICogXHRcIk9wZW5TdHJlZXRNYXBcIjogb3NtXHJcbiAqIH07XHJcbiAqXHJcbiAqIHZhciBvdmVybGF5cyA9IHtcclxuICogXHRcIk1hcmtlclwiOiBtYXJrZXIsXHJcbiAqIFx0XCJSb2Fkc1wiOiByb2Fkc0xheWVyXHJcbiAqIH07XHJcbiAqXHJcbiAqIEwuY29udHJvbC5sYXllcnMoYmFzZUxheWVycywgb3ZlcmxheXMpLmFkZFRvKG1hcCk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBUaGUgYGJhc2VMYXllcnNgIGFuZCBgb3ZlcmxheXNgIHBhcmFtZXRlcnMgYXJlIG9iamVjdCBsaXRlcmFscyB3aXRoIGxheWVyIG5hbWVzIGFzIGtleXMgYW5kIGBMYXllcmAgb2JqZWN0cyBhcyB2YWx1ZXM6XHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHtcclxuICogICAgIFwiPHNvbWVOYW1lMT5cIjogbGF5ZXIxLFxyXG4gKiAgICAgXCI8c29tZU5hbWUyPlwiOiBsYXllcjJcclxuICogfVxyXG4gKiBgYGBcclxuICpcclxuICogVGhlIGxheWVyIG5hbWVzIGNhbiBjb250YWluIEhUTUwsIHdoaWNoIGFsbG93cyB5b3UgdG8gYWRkIGFkZGl0aW9uYWwgc3R5bGluZyB0byB0aGUgaXRlbXM6XHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHtcIjxpbWcgc3JjPSdteS1sYXllci1pY29uJyAvPiA8c3BhbiBjbGFzcz0nbXktbGF5ZXItaXRlbSc+TXkgTGF5ZXI8L3NwYW4+XCI6IG15TGF5ZXJ9XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBMYXllcnMgPSBDb250cm9sLmV4dGVuZCh7XHJcblx0Ly8gQHNlY3Rpb25cclxuXHQvLyBAYWthIENvbnRyb2wuTGF5ZXJzIG9wdGlvbnNcclxuXHRvcHRpb25zOiB7XHJcblx0XHQvLyBAb3B0aW9uIGNvbGxhcHNlZDogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIElmIGB0cnVlYCwgdGhlIGNvbnRyb2wgd2lsbCBiZSBjb2xsYXBzZWQgaW50byBhbiBpY29uIGFuZCBleHBhbmRlZCBvbiBtb3VzZSBob3ZlciBvciB0b3VjaC5cclxuXHRcdGNvbGxhcHNlZDogdHJ1ZSxcclxuXHRcdHBvc2l0aW9uOiAndG9wcmlnaHQnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gYXV0b1pJbmRleDogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIElmIGB0cnVlYCwgdGhlIGNvbnRyb2wgd2lsbCBhc3NpZ24gekluZGV4ZXMgaW4gaW5jcmVhc2luZyBvcmRlciB0byBhbGwgb2YgaXRzIGxheWVycyBzbyB0aGF0IHRoZSBvcmRlciBpcyBwcmVzZXJ2ZWQgd2hlbiBzd2l0Y2hpbmcgdGhlbSBvbi9vZmYuXHJcblx0XHRhdXRvWkluZGV4OiB0cnVlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gaGlkZVNpbmdsZUJhc2U6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gSWYgYHRydWVgLCB0aGUgYmFzZSBsYXllcnMgaW4gdGhlIGNvbnRyb2wgd2lsbCBiZSBoaWRkZW4gd2hlbiB0aGVyZSBpcyBvbmx5IG9uZS5cclxuXHRcdGhpZGVTaW5nbGVCYXNlOiBmYWxzZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHNvcnRMYXllcnM6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gV2hldGhlciB0byBzb3J0IHRoZSBsYXllcnMuIFdoZW4gYGZhbHNlYCwgbGF5ZXJzIHdpbGwga2VlcCB0aGUgb3JkZXJcclxuXHRcdC8vIGluIHdoaWNoIHRoZXkgd2VyZSBhZGRlZCB0byB0aGUgY29udHJvbC5cclxuXHRcdHNvcnRMYXllcnM6IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gc29ydEZ1bmN0aW9uOiBGdW5jdGlvbiA9ICpcclxuXHRcdC8vIEEgW2NvbXBhcmUgZnVuY3Rpb25dKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L3NvcnQpXHJcblx0XHQvLyB0aGF0IHdpbGwgYmUgdXNlZCBmb3Igc29ydGluZyB0aGUgbGF5ZXJzLCB3aGVuIGBzb3J0TGF5ZXJzYCBpcyBgdHJ1ZWAuXHJcblx0XHQvLyBUaGUgZnVuY3Rpb24gcmVjZWl2ZXMgYm90aCB0aGUgYEwuTGF5ZXJgIGluc3RhbmNlcyBhbmQgdGhlaXIgbmFtZXMsIGFzIGluXHJcblx0XHQvLyBgc29ydEZ1bmN0aW9uKGxheWVyQSwgbGF5ZXJCLCBuYW1lQSwgbmFtZUIpYC5cclxuXHRcdC8vIEJ5IGRlZmF1bHQsIGl0IHNvcnRzIGxheWVycyBhbHBoYWJldGljYWxseSBieSB0aGVpciBuYW1lLlxyXG5cdFx0c29ydEZ1bmN0aW9uOiBmdW5jdGlvbiAobGF5ZXJBLCBsYXllckIsIG5hbWVBLCBuYW1lQikge1xyXG5cdFx0XHRyZXR1cm4gbmFtZUEgPCBuYW1lQiA/IC0xIDogKG5hbWVCIDwgbmFtZUEgPyAxIDogMCk7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGJhc2VMYXllcnMsIG92ZXJsYXlzLCBvcHRpb25zKSB7XHJcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuXHRcdHRoaXMuX2xheWVyQ29udHJvbElucHV0cyA9IFtdO1xyXG5cdFx0dGhpcy5fbGF5ZXJzID0gW107XHJcblx0XHR0aGlzLl9sYXN0WkluZGV4ID0gMDtcclxuXHRcdHRoaXMuX2hhbmRsaW5nQ2xpY2sgPSBmYWxzZTtcclxuXHJcblx0XHRmb3IgKHZhciBpIGluIGJhc2VMYXllcnMpIHtcclxuXHRcdFx0dGhpcy5fYWRkTGF5ZXIoYmFzZUxheWVyc1tpXSwgaSk7XHJcblx0XHR9XHJcblxyXG5cdFx0Zm9yIChpIGluIG92ZXJsYXlzKSB7XHJcblx0XHRcdHRoaXMuX2FkZExheWVyKG92ZXJsYXlzW2ldLCBpLCB0cnVlKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0dGhpcy5faW5pdExheW91dCgpO1xyXG5cdFx0dGhpcy5fdXBkYXRlKCk7XHJcblxyXG5cdFx0dGhpcy5fbWFwID0gbWFwO1xyXG5cdFx0bWFwLm9uKCd6b29tZW5kJywgdGhpcy5fY2hlY2tEaXNhYmxlZExheWVycywgdGhpcyk7XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl9sYXllcnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0dGhpcy5fbGF5ZXJzW2ldLmxheWVyLm9uKCdhZGQgcmVtb3ZlJywgdGhpcy5fb25MYXllckNoYW5nZSwgdGhpcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXMuX2NvbnRhaW5lcjtcclxuXHR9LFxyXG5cclxuXHRhZGRUbzogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0Q29udHJvbC5wcm90b3R5cGUuYWRkVG8uY2FsbCh0aGlzLCBtYXApO1xyXG5cdFx0Ly8gVHJpZ2dlciBleHBhbmQgYWZ0ZXIgTGF5ZXJzIENvbnRyb2wgaGFzIGJlZW4gaW5zZXJ0ZWQgaW50byBET00gc28gdGhhdCBpcyBub3cgaGFzIGFuIGFjdHVhbCBoZWlnaHQuXHJcblx0XHRyZXR1cm4gdGhpcy5fZXhwYW5kSWZOb3RDb2xsYXBzZWQoKTtcclxuXHR9LFxyXG5cclxuXHRvblJlbW92ZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0dGhpcy5fbWFwLm9mZignem9vbWVuZCcsIHRoaXMuX2NoZWNrRGlzYWJsZWRMYXllcnMsIHRoaXMpO1xyXG5cclxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fbGF5ZXJzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdHRoaXMuX2xheWVyc1tpXS5sYXllci5vZmYoJ2FkZCByZW1vdmUnLCB0aGlzLl9vbkxheWVyQ2hhbmdlLCB0aGlzKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGFkZEJhc2VMYXllcihsYXllcjogTGF5ZXIsIG5hbWU6IFN0cmluZyk6IHRoaXNcclxuXHQvLyBBZGRzIGEgYmFzZSBsYXllciAocmFkaW8gYnV0dG9uIGVudHJ5KSB3aXRoIHRoZSBnaXZlbiBuYW1lIHRvIHRoZSBjb250cm9sLlxyXG5cdGFkZEJhc2VMYXllcjogZnVuY3Rpb24gKGxheWVyLCBuYW1lKSB7XHJcblx0XHR0aGlzLl9hZGRMYXllcihsYXllciwgbmFtZSk7XHJcblx0XHRyZXR1cm4gKHRoaXMuX21hcCkgPyB0aGlzLl91cGRhdGUoKSA6IHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBhZGRPdmVybGF5KGxheWVyOiBMYXllciwgbmFtZTogU3RyaW5nKTogdGhpc1xyXG5cdC8vIEFkZHMgYW4gb3ZlcmxheSAoY2hlY2tib3ggZW50cnkpIHdpdGggdGhlIGdpdmVuIG5hbWUgdG8gdGhlIGNvbnRyb2wuXHJcblx0YWRkT3ZlcmxheTogZnVuY3Rpb24gKGxheWVyLCBuYW1lKSB7XHJcblx0XHR0aGlzLl9hZGRMYXllcihsYXllciwgbmFtZSwgdHJ1ZSk7XHJcblx0XHRyZXR1cm4gKHRoaXMuX21hcCkgPyB0aGlzLl91cGRhdGUoKSA6IHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCByZW1vdmVMYXllcihsYXllcjogTGF5ZXIpOiB0aGlzXHJcblx0Ly8gUmVtb3ZlIHRoZSBnaXZlbiBsYXllciBmcm9tIHRoZSBjb250cm9sLlxyXG5cdHJlbW92ZUxheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHRcdGxheWVyLm9mZignYWRkIHJlbW92ZScsIHRoaXMuX29uTGF5ZXJDaGFuZ2UsIHRoaXMpO1xyXG5cclxuXHRcdHZhciBvYmogPSB0aGlzLl9nZXRMYXllcihzdGFtcChsYXllcikpO1xyXG5cdFx0aWYgKG9iaikge1xyXG5cdFx0XHR0aGlzLl9sYXllcnMuc3BsaWNlKHRoaXMuX2xheWVycy5pbmRleE9mKG9iaiksIDEpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuICh0aGlzLl9tYXApID8gdGhpcy5fdXBkYXRlKCkgOiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZXhwYW5kKCk6IHRoaXNcclxuXHQvLyBFeHBhbmQgdGhlIGNvbnRyb2wgY29udGFpbmVyIGlmIGNvbGxhcHNlZC5cclxuXHRleHBhbmQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGFkZENsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtZXhwYW5kZWQnKTtcclxuXHRcdHRoaXMuX2Zvcm0uc3R5bGUuaGVpZ2h0ID0gbnVsbDtcclxuXHRcdHZhciBhY2NlcHRhYmxlSGVpZ2h0ID0gdGhpcy5fbWFwLmdldFNpemUoKS55IC0gKHRoaXMuX2NvbnRhaW5lci5vZmZzZXRUb3AgKyA1MCk7XHJcblx0XHRpZiAoYWNjZXB0YWJsZUhlaWdodCA8IHRoaXMuX2Zvcm0uY2xpZW50SGVpZ2h0KSB7XHJcblx0XHRcdGFkZENsYXNzKHRoaXMuX2Zvcm0sICdsZWFmbGV0LWNvbnRyb2wtbGF5ZXJzLXNjcm9sbGJhcicpO1xyXG5cdFx0XHR0aGlzLl9mb3JtLnN0eWxlLmhlaWdodCA9IGFjY2VwdGFibGVIZWlnaHQgKyAncHgnO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fZm9ybSwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtc2Nyb2xsYmFyJyk7XHJcblx0XHR9XHJcblx0XHR0aGlzLl9jaGVja0Rpc2FibGVkTGF5ZXJzKCk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGNvbGxhcHNlKCk6IHRoaXNcclxuXHQvLyBDb2xsYXBzZSB0aGUgY29udHJvbCBjb250YWluZXIgaWYgZXhwYW5kZWQuXHJcblx0Y29sbGFwc2U6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJlbW92ZUNsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY29udHJvbC1sYXllcnMtZXhwYW5kZWQnKTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdF9pbml0TGF5b3V0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgY2xhc3NOYW1lID0gJ2xlYWZsZXQtY29udHJvbC1sYXllcnMnLFxyXG5cdFx0ICAgIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRhaW5lciA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUpLFxyXG5cdFx0ICAgIGNvbGxhcHNlZCA9IHRoaXMub3B0aW9ucy5jb2xsYXBzZWQ7XHJcblxyXG5cdFx0Ly8gbWFrZXMgdGhpcyB3b3JrIG9uIElFIHRvdWNoIGRldmljZXMgYnkgc3RvcHBpbmcgaXQgZnJvbSBmaXJpbmcgYSBtb3VzZW91dCBldmVudCB3aGVuIHRoZSB0b3VjaCBpcyByZWxlYXNlZFxyXG5cdFx0Y29udGFpbmVyLnNldEF0dHJpYnV0ZSgnYXJpYS1oYXNwb3B1cCcsIHRydWUpO1xyXG5cclxuXHRcdGRpc2FibGVDbGlja1Byb3BhZ2F0aW9uKGNvbnRhaW5lcik7XHJcblx0XHRkaXNhYmxlU2Nyb2xsUHJvcGFnYXRpb24oY29udGFpbmVyKTtcclxuXHJcblx0XHR2YXIgZm9ybSA9IHRoaXMuX2Zvcm0gPSBjcmVhdGUkMSgnZm9ybScsIGNsYXNzTmFtZSArICctbGlzdCcpO1xyXG5cclxuXHRcdGlmIChjb2xsYXBzZWQpIHtcclxuXHRcdFx0dGhpcy5fbWFwLm9uKCdjbGljaycsIHRoaXMuY29sbGFwc2UsIHRoaXMpO1xyXG5cclxuXHRcdFx0aWYgKCFhbmRyb2lkKSB7XHJcblx0XHRcdFx0b24oY29udGFpbmVyLCB7XHJcblx0XHRcdFx0XHRtb3VzZWVudGVyOiB0aGlzLmV4cGFuZCxcclxuXHRcdFx0XHRcdG1vdXNlbGVhdmU6IHRoaXMuY29sbGFwc2VcclxuXHRcdFx0XHR9LCB0aGlzKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBsaW5rID0gdGhpcy5fbGF5ZXJzTGluayA9IGNyZWF0ZSQxKCdhJywgY2xhc3NOYW1lICsgJy10b2dnbGUnLCBjb250YWluZXIpO1xyXG5cdFx0bGluay5ocmVmID0gJyMnO1xyXG5cdFx0bGluay50aXRsZSA9ICdMYXllcnMnO1xyXG5cclxuXHRcdGlmICh0b3VjaCkge1xyXG5cdFx0XHRvbihsaW5rLCAnY2xpY2snLCBzdG9wKTtcclxuXHRcdFx0b24obGluaywgJ2NsaWNrJywgdGhpcy5leHBhbmQsIHRoaXMpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0b24obGluaywgJ2ZvY3VzJywgdGhpcy5leHBhbmQsIHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICghY29sbGFwc2VkKSB7XHJcblx0XHRcdHRoaXMuZXhwYW5kKCk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fYmFzZUxheWVyc0xpc3QgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lICsgJy1iYXNlJywgZm9ybSk7XHJcblx0XHR0aGlzLl9zZXBhcmF0b3IgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lICsgJy1zZXBhcmF0b3InLCBmb3JtKTtcclxuXHRcdHRoaXMuX292ZXJsYXlzTGlzdCA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUgKyAnLW92ZXJsYXlzJywgZm9ybSk7XHJcblxyXG5cdFx0Y29udGFpbmVyLmFwcGVuZENoaWxkKGZvcm0pO1xyXG5cdH0sXHJcblxyXG5cdF9nZXRMYXllcjogZnVuY3Rpb24gKGlkKSB7XHJcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX2xheWVycy5sZW5ndGg7IGkrKykge1xyXG5cclxuXHRcdFx0aWYgKHRoaXMuX2xheWVyc1tpXSAmJiBzdGFtcCh0aGlzLl9sYXllcnNbaV0ubGF5ZXIpID09PSBpZCkge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLl9sYXllcnNbaV07XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfYWRkTGF5ZXI6IGZ1bmN0aW9uIChsYXllciwgbmFtZSwgb3ZlcmxheSkge1xyXG5cdFx0aWYgKHRoaXMuX21hcCkge1xyXG5cdFx0XHRsYXllci5vbignYWRkIHJlbW92ZScsIHRoaXMuX29uTGF5ZXJDaGFuZ2UsIHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2xheWVycy5wdXNoKHtcclxuXHRcdFx0bGF5ZXI6IGxheWVyLFxyXG5cdFx0XHRuYW1lOiBuYW1lLFxyXG5cdFx0XHRvdmVybGF5OiBvdmVybGF5XHJcblx0XHR9KTtcclxuXHJcblx0XHRpZiAodGhpcy5vcHRpb25zLnNvcnRMYXllcnMpIHtcclxuXHRcdFx0dGhpcy5fbGF5ZXJzLnNvcnQoYmluZChmdW5jdGlvbiAoYSwgYikge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLm9wdGlvbnMuc29ydEZ1bmN0aW9uKGEubGF5ZXIsIGIubGF5ZXIsIGEubmFtZSwgYi5uYW1lKTtcclxuXHRcdFx0fSwgdGhpcykpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuYXV0b1pJbmRleCAmJiBsYXllci5zZXRaSW5kZXgpIHtcclxuXHRcdFx0dGhpcy5fbGFzdFpJbmRleCsrO1xyXG5cdFx0XHRsYXllci5zZXRaSW5kZXgodGhpcy5fbGFzdFpJbmRleCk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fZXhwYW5kSWZOb3RDb2xsYXBzZWQoKTtcclxuXHR9LFxyXG5cclxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAoIXRoaXMuX2NvbnRhaW5lcikgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdGVtcHR5KHRoaXMuX2Jhc2VMYXllcnNMaXN0KTtcclxuXHRcdGVtcHR5KHRoaXMuX292ZXJsYXlzTGlzdCk7XHJcblxyXG5cdFx0dGhpcy5fbGF5ZXJDb250cm9sSW5wdXRzID0gW107XHJcblx0XHR2YXIgYmFzZUxheWVyc1ByZXNlbnQsIG92ZXJsYXlzUHJlc2VudCwgaSwgb2JqLCBiYXNlTGF5ZXJzQ291bnQgPSAwO1xyXG5cclxuXHRcdGZvciAoaSA9IDA7IGkgPCB0aGlzLl9sYXllcnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0b2JqID0gdGhpcy5fbGF5ZXJzW2ldO1xyXG5cdFx0XHR0aGlzLl9hZGRJdGVtKG9iaik7XHJcblx0XHRcdG92ZXJsYXlzUHJlc2VudCA9IG92ZXJsYXlzUHJlc2VudCB8fCBvYmoub3ZlcmxheTtcclxuXHRcdFx0YmFzZUxheWVyc1ByZXNlbnQgPSBiYXNlTGF5ZXJzUHJlc2VudCB8fCAhb2JqLm92ZXJsYXk7XHJcblx0XHRcdGJhc2VMYXllcnNDb3VudCArPSAhb2JqLm92ZXJsYXkgPyAxIDogMDtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBIaWRlIGJhc2UgbGF5ZXJzIHNlY3Rpb24gaWYgdGhlcmUncyBvbmx5IG9uZSBsYXllci5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuaGlkZVNpbmdsZUJhc2UpIHtcclxuXHRcdFx0YmFzZUxheWVyc1ByZXNlbnQgPSBiYXNlTGF5ZXJzUHJlc2VudCAmJiBiYXNlTGF5ZXJzQ291bnQgPiAxO1xyXG5cdFx0XHR0aGlzLl9iYXNlTGF5ZXJzTGlzdC5zdHlsZS5kaXNwbGF5ID0gYmFzZUxheWVyc1ByZXNlbnQgPyAnJyA6ICdub25lJztcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9zZXBhcmF0b3Iuc3R5bGUuZGlzcGxheSA9IG92ZXJsYXlzUHJlc2VudCAmJiBiYXNlTGF5ZXJzUHJlc2VudCA/ICcnIDogJ25vbmUnO1xyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdF9vbkxheWVyQ2hhbmdlOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0aWYgKCF0aGlzLl9oYW5kbGluZ0NsaWNrKSB7XHJcblx0XHRcdHRoaXMuX3VwZGF0ZSgpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBvYmogPSB0aGlzLl9nZXRMYXllcihzdGFtcChlLnRhcmdldCkpO1xyXG5cclxuXHRcdC8vIEBuYW1lc3BhY2UgTWFwXHJcblx0XHQvLyBAc2VjdGlvbiBMYXllciBldmVudHNcclxuXHRcdC8vIEBldmVudCBiYXNlbGF5ZXJjaGFuZ2U6IExheWVyc0NvbnRyb2xFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgYmFzZSBsYXllciBpcyBjaGFuZ2VkIHRocm91Z2ggdGhlIFtsYXllciBjb250cm9sXSgjY29udHJvbC1sYXllcnMpLlxyXG5cdFx0Ly8gQGV2ZW50IG92ZXJsYXlhZGQ6IExheWVyc0NvbnRyb2xFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiBhbiBvdmVybGF5IGlzIHNlbGVjdGVkIHRocm91Z2ggdGhlIFtsYXllciBjb250cm9sXSgjY29udHJvbC1sYXllcnMpLlxyXG5cdFx0Ly8gQGV2ZW50IG92ZXJsYXlyZW1vdmU6IExheWVyc0NvbnRyb2xFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiBhbiBvdmVybGF5IGlzIGRlc2VsZWN0ZWQgdGhyb3VnaCB0aGUgW2xheWVyIGNvbnRyb2xdKCNjb250cm9sLWxheWVycykuXHJcblx0XHQvLyBAbmFtZXNwYWNlIENvbnRyb2wuTGF5ZXJzXHJcblx0XHR2YXIgdHlwZSA9IG9iai5vdmVybGF5ID9cclxuXHRcdFx0KGUudHlwZSA9PT0gJ2FkZCcgPyAnb3ZlcmxheWFkZCcgOiAnb3ZlcmxheXJlbW92ZScpIDpcclxuXHRcdFx0KGUudHlwZSA9PT0gJ2FkZCcgPyAnYmFzZWxheWVyY2hhbmdlJyA6IG51bGwpO1xyXG5cclxuXHRcdGlmICh0eXBlKSB7XHJcblx0XHRcdHRoaXMuX21hcC5maXJlKHR5cGUsIG9iaik7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0Ly8gSUU3IGJ1Z3Mgb3V0IGlmIHlvdSBjcmVhdGUgYSByYWRpbyBkeW5hbWljYWxseSwgc28geW91IGhhdmUgdG8gZG8gaXQgdGhpcyBoYWNreSB3YXkgKHNlZSBodHRwOi8vYml0Lmx5L1BxWUxCZSlcclxuXHRfY3JlYXRlUmFkaW9FbGVtZW50OiBmdW5jdGlvbiAobmFtZSwgY2hlY2tlZCkge1xyXG5cclxuXHRcdHZhciByYWRpb0h0bWwgPSAnPGlucHV0IHR5cGU9XCJyYWRpb1wiIGNsYXNzPVwibGVhZmxldC1jb250cm9sLWxheWVycy1zZWxlY3RvclwiIG5hbWU9XCInICtcclxuXHRcdFx0XHRuYW1lICsgJ1wiJyArIChjaGVja2VkID8gJyBjaGVja2VkPVwiY2hlY2tlZFwiJyA6ICcnKSArICcvPic7XHJcblxyXG5cdFx0dmFyIHJhZGlvRnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcclxuXHRcdHJhZGlvRnJhZ21lbnQuaW5uZXJIVE1MID0gcmFkaW9IdG1sO1xyXG5cclxuXHRcdHJldHVybiByYWRpb0ZyYWdtZW50LmZpcnN0Q2hpbGQ7XHJcblx0fSxcclxuXHJcblx0X2FkZEl0ZW06IGZ1bmN0aW9uIChvYmopIHtcclxuXHRcdHZhciBsYWJlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xhYmVsJyksXHJcblx0XHQgICAgY2hlY2tlZCA9IHRoaXMuX21hcC5oYXNMYXllcihvYmoubGF5ZXIpLFxyXG5cdFx0ICAgIGlucHV0O1xyXG5cclxuXHRcdGlmIChvYmoub3ZlcmxheSkge1xyXG5cdFx0XHRpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lucHV0Jyk7XHJcblx0XHRcdGlucHV0LnR5cGUgPSAnY2hlY2tib3gnO1xyXG5cdFx0XHRpbnB1dC5jbGFzc05hbWUgPSAnbGVhZmxldC1jb250cm9sLWxheWVycy1zZWxlY3Rvcic7XHJcblx0XHRcdGlucHV0LmRlZmF1bHRDaGVja2VkID0gY2hlY2tlZDtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGlucHV0ID0gdGhpcy5fY3JlYXRlUmFkaW9FbGVtZW50KCdsZWFmbGV0LWJhc2UtbGF5ZXJzJywgY2hlY2tlZCk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fbGF5ZXJDb250cm9sSW5wdXRzLnB1c2goaW5wdXQpO1xyXG5cdFx0aW5wdXQubGF5ZXJJZCA9IHN0YW1wKG9iai5sYXllcik7XHJcblxyXG5cdFx0b24oaW5wdXQsICdjbGljaycsIHRoaXMuX29uSW5wdXRDbGljaywgdGhpcyk7XHJcblxyXG5cdFx0dmFyIG5hbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XHJcblx0XHRuYW1lLmlubmVySFRNTCA9ICcgJyArIG9iai5uYW1lO1xyXG5cclxuXHRcdC8vIEhlbHBzIGZyb20gcHJldmVudGluZyBsYXllciBjb250cm9sIGZsaWNrZXIgd2hlbiBjaGVja2JveGVzIGFyZSBkaXNhYmxlZFxyXG5cdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMjc3MVxyXG5cdFx0dmFyIGhvbGRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xyXG5cclxuXHRcdGxhYmVsLmFwcGVuZENoaWxkKGhvbGRlcik7XHJcblx0XHRob2xkZXIuYXBwZW5kQ2hpbGQoaW5wdXQpO1xyXG5cdFx0aG9sZGVyLmFwcGVuZENoaWxkKG5hbWUpO1xyXG5cclxuXHRcdHZhciBjb250YWluZXIgPSBvYmoub3ZlcmxheSA/IHRoaXMuX292ZXJsYXlzTGlzdCA6IHRoaXMuX2Jhc2VMYXllcnNMaXN0O1xyXG5cdFx0Y29udGFpbmVyLmFwcGVuZENoaWxkKGxhYmVsKTtcclxuXHJcblx0XHR0aGlzLl9jaGVja0Rpc2FibGVkTGF5ZXJzKCk7XHJcblx0XHRyZXR1cm4gbGFiZWw7XHJcblx0fSxcclxuXHJcblx0X29uSW5wdXRDbGljazogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGlucHV0cyA9IHRoaXMuX2xheWVyQ29udHJvbElucHV0cyxcclxuXHRcdCAgICBpbnB1dCwgbGF5ZXI7XHJcblx0XHR2YXIgYWRkZWRMYXllcnMgPSBbXSxcclxuXHRcdCAgICByZW1vdmVkTGF5ZXJzID0gW107XHJcblxyXG5cdFx0dGhpcy5faGFuZGxpbmdDbGljayA9IHRydWU7XHJcblxyXG5cdFx0Zm9yICh2YXIgaSA9IGlucHV0cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xyXG5cdFx0XHRpbnB1dCA9IGlucHV0c1tpXTtcclxuXHRcdFx0bGF5ZXIgPSB0aGlzLl9nZXRMYXllcihpbnB1dC5sYXllcklkKS5sYXllcjtcclxuXHJcblx0XHRcdGlmIChpbnB1dC5jaGVja2VkKSB7XHJcblx0XHRcdFx0YWRkZWRMYXllcnMucHVzaChsYXllcik7XHJcblx0XHRcdH0gZWxzZSBpZiAoIWlucHV0LmNoZWNrZWQpIHtcclxuXHRcdFx0XHRyZW1vdmVkTGF5ZXJzLnB1c2gobGF5ZXIpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gQnVnZml4IGlzc3VlIDIzMTg6IFNob3VsZCByZW1vdmUgYWxsIG9sZCBsYXllcnMgYmVmb3JlIHJlYWRkaW5nIG5ldyBvbmVzXHJcblx0XHRmb3IgKGkgPSAwOyBpIDwgcmVtb3ZlZExheWVycy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRpZiAodGhpcy5fbWFwLmhhc0xheWVyKHJlbW92ZWRMYXllcnNbaV0pKSB7XHJcblx0XHRcdFx0dGhpcy5fbWFwLnJlbW92ZUxheWVyKHJlbW92ZWRMYXllcnNbaV0pO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRmb3IgKGkgPSAwOyBpIDwgYWRkZWRMYXllcnMubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0aWYgKCF0aGlzLl9tYXAuaGFzTGF5ZXIoYWRkZWRMYXllcnNbaV0pKSB7XHJcblx0XHRcdFx0dGhpcy5fbWFwLmFkZExheWVyKGFkZGVkTGF5ZXJzW2ldKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2hhbmRsaW5nQ2xpY2sgPSBmYWxzZTtcclxuXHJcblx0XHR0aGlzLl9yZWZvY3VzT25NYXAoKTtcclxuXHR9LFxyXG5cclxuXHRfY2hlY2tEaXNhYmxlZExheWVyczogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGlucHV0cyA9IHRoaXMuX2xheWVyQ29udHJvbElucHV0cyxcclxuXHRcdCAgICBpbnB1dCxcclxuXHRcdCAgICBsYXllcixcclxuXHRcdCAgICB6b29tID0gdGhpcy5fbWFwLmdldFpvb20oKTtcclxuXHJcblx0XHRmb3IgKHZhciBpID0gaW5wdXRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcblx0XHRcdGlucHV0ID0gaW5wdXRzW2ldO1xyXG5cdFx0XHRsYXllciA9IHRoaXMuX2dldExheWVyKGlucHV0LmxheWVySWQpLmxheWVyO1xyXG5cdFx0XHRpbnB1dC5kaXNhYmxlZCA9IChsYXllci5vcHRpb25zLm1pblpvb20gIT09IHVuZGVmaW5lZCAmJiB6b29tIDwgbGF5ZXIub3B0aW9ucy5taW5ab29tKSB8fFxyXG5cdFx0XHQgICAgICAgICAgICAgICAgIChsYXllci5vcHRpb25zLm1heFpvb20gIT09IHVuZGVmaW5lZCAmJiB6b29tID4gbGF5ZXIub3B0aW9ucy5tYXhab29tKTtcclxuXHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X2V4cGFuZElmTm90Q29sbGFwc2VkOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAodGhpcy5fbWFwICYmICF0aGlzLm9wdGlvbnMuY29sbGFwc2VkKSB7XHJcblx0XHRcdHRoaXMuZXhwYW5kKCk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRfZXhwYW5kOiBmdW5jdGlvbiAoKSB7XHJcblx0XHQvLyBCYWNrd2FyZCBjb21wYXRpYmlsaXR5LCByZW1vdmUgbWUgaW4gMS4xLlxyXG5cdFx0cmV0dXJuIHRoaXMuZXhwYW5kKCk7XHJcblx0fSxcclxuXHJcblx0X2NvbGxhcHNlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHQvLyBCYWNrd2FyZCBjb21wYXRpYmlsaXR5LCByZW1vdmUgbWUgaW4gMS4xLlxyXG5cdFx0cmV0dXJuIHRoaXMuY29sbGFwc2UoKTtcclxuXHR9XHJcblxyXG59KTtcclxuXHJcblxyXG4vLyBAZmFjdG9yeSBMLmNvbnRyb2wubGF5ZXJzKGJhc2VsYXllcnM/OiBPYmplY3QsIG92ZXJsYXlzPzogT2JqZWN0LCBvcHRpb25zPzogQ29udHJvbC5MYXllcnMgb3B0aW9ucylcclxuLy8gQ3JlYXRlcyBhbiBhdHRyaWJ1dGlvbiBjb250cm9sIHdpdGggdGhlIGdpdmVuIGxheWVycy4gQmFzZSBsYXllcnMgd2lsbCBiZSBzd2l0Y2hlZCB3aXRoIHJhZGlvIGJ1dHRvbnMsIHdoaWxlIG92ZXJsYXlzIHdpbGwgYmUgc3dpdGNoZWQgd2l0aCBjaGVja2JveGVzLiBOb3RlIHRoYXQgYWxsIGJhc2UgbGF5ZXJzIHNob3VsZCBiZSBwYXNzZWQgaW4gdGhlIGJhc2UgbGF5ZXJzIG9iamVjdCwgYnV0IG9ubHkgb25lIHNob3VsZCBiZSBhZGRlZCB0byB0aGUgbWFwIGR1cmluZyBtYXAgaW5zdGFudGlhdGlvbi5cclxudmFyIGxheWVycyA9IGZ1bmN0aW9uIChiYXNlTGF5ZXJzLCBvdmVybGF5cywgb3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgTGF5ZXJzKGJhc2VMYXllcnMsIG92ZXJsYXlzLCBvcHRpb25zKTtcclxufTtcblxuLypcclxuICogQGNsYXNzIENvbnRyb2wuWm9vbVxyXG4gKiBAYWthIEwuQ29udHJvbC5ab29tXHJcbiAqIEBpbmhlcml0cyBDb250cm9sXHJcbiAqXHJcbiAqIEEgYmFzaWMgem9vbSBjb250cm9sIHdpdGggdHdvIGJ1dHRvbnMgKHpvb20gaW4gYW5kIHpvb20gb3V0KS4gSXQgaXMgcHV0IG9uIHRoZSBtYXAgYnkgZGVmYXVsdCB1bmxlc3MgeW91IHNldCBpdHMgW2B6b29tQ29udHJvbGAgb3B0aW9uXSgjbWFwLXpvb21jb250cm9sKSB0byBgZmFsc2VgLiBFeHRlbmRzIGBDb250cm9sYC5cclxuICovXHJcblxyXG52YXIgWm9vbSA9IENvbnRyb2wuZXh0ZW5kKHtcclxuXHQvLyBAc2VjdGlvblxyXG5cdC8vIEBha2EgQ29udHJvbC5ab29tIG9wdGlvbnNcclxuXHRvcHRpb25zOiB7XHJcblx0XHRwb3NpdGlvbjogJ3RvcGxlZnQnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gem9vbUluVGV4dDogU3RyaW5nID0gJysnXHJcblx0XHQvLyBUaGUgdGV4dCBzZXQgb24gdGhlICd6b29tIGluJyBidXR0b24uXHJcblx0XHR6b29tSW5UZXh0OiAnKycsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB6b29tSW5UaXRsZTogU3RyaW5nID0gJ1pvb20gaW4nXHJcblx0XHQvLyBUaGUgdGl0bGUgc2V0IG9uIHRoZSAnem9vbSBpbicgYnV0dG9uLlxyXG5cdFx0em9vbUluVGl0bGU6ICdab29tIGluJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHpvb21PdXRUZXh0OiBTdHJpbmcgPSAnJiN4MjIxMjsnXHJcblx0XHQvLyBUaGUgdGV4dCBzZXQgb24gdGhlICd6b29tIG91dCcgYnV0dG9uLlxyXG5cdFx0em9vbU91dFRleHQ6ICcmI3gyMjEyOycsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB6b29tT3V0VGl0bGU6IFN0cmluZyA9ICdab29tIG91dCdcclxuXHRcdC8vIFRoZSB0aXRsZSBzZXQgb24gdGhlICd6b29tIG91dCcgYnV0dG9uLlxyXG5cdFx0em9vbU91dFRpdGxlOiAnWm9vbSBvdXQnXHJcblx0fSxcclxuXHJcblx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuXHRcdHZhciB6b29tTmFtZSA9ICdsZWFmbGV0LWNvbnRyb2wtem9vbScsXHJcblx0XHQgICAgY29udGFpbmVyID0gY3JlYXRlJDEoJ2RpdicsIHpvb21OYW1lICsgJyBsZWFmbGV0LWJhcicpLFxyXG5cdFx0ICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XHJcblxyXG5cdFx0dGhpcy5fem9vbUluQnV0dG9uICA9IHRoaXMuX2NyZWF0ZUJ1dHRvbihvcHRpb25zLnpvb21JblRleHQsIG9wdGlvbnMuem9vbUluVGl0bGUsXHJcblx0XHQgICAgICAgIHpvb21OYW1lICsgJy1pbicsICBjb250YWluZXIsIHRoaXMuX3pvb21Jbik7XHJcblx0XHR0aGlzLl96b29tT3V0QnV0dG9uID0gdGhpcy5fY3JlYXRlQnV0dG9uKG9wdGlvbnMuem9vbU91dFRleHQsIG9wdGlvbnMuem9vbU91dFRpdGxlLFxyXG5cdFx0ICAgICAgICB6b29tTmFtZSArICctb3V0JywgY29udGFpbmVyLCB0aGlzLl96b29tT3V0KTtcclxuXHJcblx0XHR0aGlzLl91cGRhdGVEaXNhYmxlZCgpO1xyXG5cdFx0bWFwLm9uKCd6b29tZW5kIHpvb21sZXZlbHNjaGFuZ2UnLCB0aGlzLl91cGRhdGVEaXNhYmxlZCwgdGhpcyk7XHJcblxyXG5cdFx0cmV0dXJuIGNvbnRhaW5lcjtcclxuXHR9LFxyXG5cclxuXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0bWFwLm9mZignem9vbWVuZCB6b29tbGV2ZWxzY2hhbmdlJywgdGhpcy5fdXBkYXRlRGlzYWJsZWQsIHRoaXMpO1xyXG5cdH0sXHJcblxyXG5cdGRpc2FibGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX2Rpc2FibGVkID0gdHJ1ZTtcclxuXHRcdHRoaXMuX3VwZGF0ZURpc2FibGVkKCk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRlbmFibGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX2Rpc2FibGVkID0gZmFsc2U7XHJcblx0XHR0aGlzLl91cGRhdGVEaXNhYmxlZCgpO1xyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0X3pvb21JbjogZnVuY3Rpb24gKGUpIHtcclxuXHRcdGlmICghdGhpcy5fZGlzYWJsZWQgJiYgdGhpcy5fbWFwLl96b29tIDwgdGhpcy5fbWFwLmdldE1heFpvb20oKSkge1xyXG5cdFx0XHR0aGlzLl9tYXAuem9vbUluKHRoaXMuX21hcC5vcHRpb25zLnpvb21EZWx0YSAqIChlLnNoaWZ0S2V5ID8gMyA6IDEpKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfem9vbU91dDogZnVuY3Rpb24gKGUpIHtcclxuXHRcdGlmICghdGhpcy5fZGlzYWJsZWQgJiYgdGhpcy5fbWFwLl96b29tID4gdGhpcy5fbWFwLmdldE1pblpvb20oKSkge1xyXG5cdFx0XHR0aGlzLl9tYXAuem9vbU91dCh0aGlzLl9tYXAub3B0aW9ucy56b29tRGVsdGEgKiAoZS5zaGlmdEtleSA/IDMgOiAxKSk7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X2NyZWF0ZUJ1dHRvbjogZnVuY3Rpb24gKGh0bWwsIHRpdGxlLCBjbGFzc05hbWUsIGNvbnRhaW5lciwgZm4pIHtcclxuXHRcdHZhciBsaW5rID0gY3JlYXRlJDEoJ2EnLCBjbGFzc05hbWUsIGNvbnRhaW5lcik7XHJcblx0XHRsaW5rLmlubmVySFRNTCA9IGh0bWw7XHJcblx0XHRsaW5rLmhyZWYgPSAnIyc7XHJcblx0XHRsaW5rLnRpdGxlID0gdGl0bGU7XHJcblxyXG5cdFx0LypcclxuXHRcdCAqIFdpbGwgZm9yY2Ugc2NyZWVuIHJlYWRlcnMgbGlrZSBWb2ljZU92ZXIgdG8gcmVhZCB0aGlzIGFzIFwiWm9vbSBpbiAtIGJ1dHRvblwiXHJcblx0XHQgKi9cclxuXHRcdGxpbmsuc2V0QXR0cmlidXRlKCdyb2xlJywgJ2J1dHRvbicpO1xyXG5cdFx0bGluay5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCB0aXRsZSk7XHJcblxyXG5cdFx0ZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24obGluayk7XHJcblx0XHRvbihsaW5rLCAnY2xpY2snLCBzdG9wKTtcclxuXHRcdG9uKGxpbmssICdjbGljaycsIGZuLCB0aGlzKTtcclxuXHRcdG9uKGxpbmssICdjbGljaycsIHRoaXMuX3JlZm9jdXNPbk1hcCwgdGhpcyk7XHJcblxyXG5cdFx0cmV0dXJuIGxpbms7XHJcblx0fSxcclxuXHJcblx0X3VwZGF0ZURpc2FibGVkOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxyXG5cdFx0ICAgIGNsYXNzTmFtZSA9ICdsZWFmbGV0LWRpc2FibGVkJztcclxuXHJcblx0XHRyZW1vdmVDbGFzcyh0aGlzLl96b29tSW5CdXR0b24sIGNsYXNzTmFtZSk7XHJcblx0XHRyZW1vdmVDbGFzcyh0aGlzLl96b29tT3V0QnV0dG9uLCBjbGFzc05hbWUpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9kaXNhYmxlZCB8fCBtYXAuX3pvb20gPT09IG1hcC5nZXRNaW5ab29tKCkpIHtcclxuXHRcdFx0YWRkQ2xhc3ModGhpcy5fem9vbU91dEJ1dHRvbiwgY2xhc3NOYW1lKTtcclxuXHRcdH1cclxuXHRcdGlmICh0aGlzLl9kaXNhYmxlZCB8fCBtYXAuX3pvb20gPT09IG1hcC5nZXRNYXhab29tKCkpIHtcclxuXHRcdFx0YWRkQ2xhc3ModGhpcy5fem9vbUluQnV0dG9uLCBjbGFzc05hbWUpO1xyXG5cdFx0fVxyXG5cdH1cclxufSk7XHJcblxyXG4vLyBAbmFtZXNwYWNlIE1hcFxyXG4vLyBAc2VjdGlvbiBDb250cm9sIG9wdGlvbnNcclxuLy8gQG9wdGlvbiB6b29tQ29udHJvbDogQm9vbGVhbiA9IHRydWVcclxuLy8gV2hldGhlciBhIFt6b29tIGNvbnRyb2xdKCNjb250cm9sLXpvb20pIGlzIGFkZGVkIHRvIHRoZSBtYXAgYnkgZGVmYXVsdC5cclxuTWFwLm1lcmdlT3B0aW9ucyh7XHJcblx0em9vbUNvbnRyb2w6IHRydWVcclxufSk7XHJcblxyXG5NYXAuYWRkSW5pdEhvb2soZnVuY3Rpb24gKCkge1xyXG5cdGlmICh0aGlzLm9wdGlvbnMuem9vbUNvbnRyb2wpIHtcclxuXHRcdHRoaXMuem9vbUNvbnRyb2wgPSBuZXcgWm9vbSgpO1xyXG5cdFx0dGhpcy5hZGRDb250cm9sKHRoaXMuem9vbUNvbnRyb2wpO1xyXG5cdH1cclxufSk7XHJcblxyXG4vLyBAbmFtZXNwYWNlIENvbnRyb2wuWm9vbVxyXG4vLyBAZmFjdG9yeSBMLmNvbnRyb2wuem9vbShvcHRpb25zOiBDb250cm9sLlpvb20gb3B0aW9ucylcclxuLy8gQ3JlYXRlcyBhIHpvb20gY29udHJvbFxyXG52YXIgem9vbSA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblx0cmV0dXJuIG5ldyBab29tKG9wdGlvbnMpO1xyXG59O1xuXG4vKlxuICogQGNsYXNzIENvbnRyb2wuU2NhbGVcbiAqIEBha2EgTC5Db250cm9sLlNjYWxlXG4gKiBAaW5oZXJpdHMgQ29udHJvbFxuICpcbiAqIEEgc2ltcGxlIHNjYWxlIGNvbnRyb2wgdGhhdCBzaG93cyB0aGUgc2NhbGUgb2YgdGhlIGN1cnJlbnQgY2VudGVyIG9mIHNjcmVlbiBpbiBtZXRyaWMgKG0va20pIGFuZCBpbXBlcmlhbCAobWkvZnQpIHN5c3RlbXMuIEV4dGVuZHMgYENvbnRyb2xgLlxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBganNcbiAqIEwuY29udHJvbC5zY2FsZSgpLmFkZFRvKG1hcCk7XG4gKiBgYGBcbiAqL1xuXG52YXIgU2NhbGUgPSBDb250cm9sLmV4dGVuZCh7XG5cdC8vIEBzZWN0aW9uXG5cdC8vIEBha2EgQ29udHJvbC5TY2FsZSBvcHRpb25zXG5cdG9wdGlvbnM6IHtcblx0XHRwb3NpdGlvbjogJ2JvdHRvbWxlZnQnLFxuXG5cdFx0Ly8gQG9wdGlvbiBtYXhXaWR0aDogTnVtYmVyID0gMTAwXG5cdFx0Ly8gTWF4aW11bSB3aWR0aCBvZiB0aGUgY29udHJvbCBpbiBwaXhlbHMuIFRoZSB3aWR0aCBpcyBzZXQgZHluYW1pY2FsbHkgdG8gc2hvdyByb3VuZCB2YWx1ZXMgKGUuZy4gMTAwLCAyMDAsIDUwMCkuXG5cdFx0bWF4V2lkdGg6IDEwMCxcblxuXHRcdC8vIEBvcHRpb24gbWV0cmljOiBCb29sZWFuID0gVHJ1ZVxuXHRcdC8vIFdoZXRoZXIgdG8gc2hvdyB0aGUgbWV0cmljIHNjYWxlIGxpbmUgKG0va20pLlxuXHRcdG1ldHJpYzogdHJ1ZSxcblxuXHRcdC8vIEBvcHRpb24gaW1wZXJpYWw6IEJvb2xlYW4gPSBUcnVlXG5cdFx0Ly8gV2hldGhlciB0byBzaG93IHRoZSBpbXBlcmlhbCBzY2FsZSBsaW5lIChtaS9mdCkuXG5cdFx0aW1wZXJpYWw6IHRydWVcblxuXHRcdC8vIEBvcHRpb24gdXBkYXRlV2hlbklkbGU6IEJvb2xlYW4gPSBmYWxzZVxuXHRcdC8vIElmIGB0cnVlYCwgdGhlIGNvbnRyb2wgaXMgdXBkYXRlZCBvbiBbYG1vdmVlbmRgXSgjbWFwLW1vdmVlbmQpLCBvdGhlcndpc2UgaXQncyBhbHdheXMgdXAtdG8tZGF0ZSAodXBkYXRlZCBvbiBbYG1vdmVgXSgjbWFwLW1vdmUpKS5cblx0fSxcblxuXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xuXHRcdHZhciBjbGFzc05hbWUgPSAnbGVhZmxldC1jb250cm9sLXNjYWxlJyxcblx0XHQgICAgY29udGFpbmVyID0gY3JlYXRlJDEoJ2RpdicsIGNsYXNzTmFtZSksXG5cdFx0ICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cblx0XHR0aGlzLl9hZGRTY2FsZXMob3B0aW9ucywgY2xhc3NOYW1lICsgJy1saW5lJywgY29udGFpbmVyKTtcblxuXHRcdG1hcC5vbihvcHRpb25zLnVwZGF0ZVdoZW5JZGxlID8gJ21vdmVlbmQnIDogJ21vdmUnLCB0aGlzLl91cGRhdGUsIHRoaXMpO1xuXHRcdG1hcC53aGVuUmVhZHkodGhpcy5fdXBkYXRlLCB0aGlzKTtcblxuXHRcdHJldHVybiBjb250YWluZXI7XG5cdH0sXG5cblx0b25SZW1vdmU6IGZ1bmN0aW9uIChtYXApIHtcblx0XHRtYXAub2ZmKHRoaXMub3B0aW9ucy51cGRhdGVXaGVuSWRsZSA/ICdtb3ZlZW5kJyA6ICdtb3ZlJywgdGhpcy5fdXBkYXRlLCB0aGlzKTtcblx0fSxcblxuXHRfYWRkU2NhbGVzOiBmdW5jdGlvbiAob3B0aW9ucywgY2xhc3NOYW1lLCBjb250YWluZXIpIHtcblx0XHRpZiAob3B0aW9ucy5tZXRyaWMpIHtcblx0XHRcdHRoaXMuX21TY2FsZSA9IGNyZWF0ZSQxKCdkaXYnLCBjbGFzc05hbWUsIGNvbnRhaW5lcik7XG5cdFx0fVxuXHRcdGlmIChvcHRpb25zLmltcGVyaWFsKSB7XG5cdFx0XHR0aGlzLl9pU2NhbGUgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lLCBjb250YWluZXIpO1xuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcblx0XHQgICAgeSA9IG1hcC5nZXRTaXplKCkueSAvIDI7XG5cblx0XHR2YXIgbWF4TWV0ZXJzID0gbWFwLmRpc3RhbmNlKFxuXHRcdFx0bWFwLmNvbnRhaW5lclBvaW50VG9MYXRMbmcoWzAsIHldKSxcblx0XHRcdG1hcC5jb250YWluZXJQb2ludFRvTGF0TG5nKFt0aGlzLm9wdGlvbnMubWF4V2lkdGgsIHldKSk7XG5cblx0XHR0aGlzLl91cGRhdGVTY2FsZXMobWF4TWV0ZXJzKTtcblx0fSxcblxuXHRfdXBkYXRlU2NhbGVzOiBmdW5jdGlvbiAobWF4TWV0ZXJzKSB7XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5tZXRyaWMgJiYgbWF4TWV0ZXJzKSB7XG5cdFx0XHR0aGlzLl91cGRhdGVNZXRyaWMobWF4TWV0ZXJzKTtcblx0XHR9XG5cdFx0aWYgKHRoaXMub3B0aW9ucy5pbXBlcmlhbCAmJiBtYXhNZXRlcnMpIHtcblx0XHRcdHRoaXMuX3VwZGF0ZUltcGVyaWFsKG1heE1ldGVycyk7XG5cdFx0fVxuXHR9LFxuXG5cdF91cGRhdGVNZXRyaWM6IGZ1bmN0aW9uIChtYXhNZXRlcnMpIHtcblx0XHR2YXIgbWV0ZXJzID0gdGhpcy5fZ2V0Um91bmROdW0obWF4TWV0ZXJzKSxcblx0XHQgICAgbGFiZWwgPSBtZXRlcnMgPCAxMDAwID8gbWV0ZXJzICsgJyBtJyA6IChtZXRlcnMgLyAxMDAwKSArICcga20nO1xuXG5cdFx0dGhpcy5fdXBkYXRlU2NhbGUodGhpcy5fbVNjYWxlLCBsYWJlbCwgbWV0ZXJzIC8gbWF4TWV0ZXJzKTtcblx0fSxcblxuXHRfdXBkYXRlSW1wZXJpYWw6IGZ1bmN0aW9uIChtYXhNZXRlcnMpIHtcblx0XHR2YXIgbWF4RmVldCA9IG1heE1ldGVycyAqIDMuMjgwODM5OSxcblx0XHQgICAgbWF4TWlsZXMsIG1pbGVzLCBmZWV0O1xuXG5cdFx0aWYgKG1heEZlZXQgPiA1MjgwKSB7XG5cdFx0XHRtYXhNaWxlcyA9IG1heEZlZXQgLyA1MjgwO1xuXHRcdFx0bWlsZXMgPSB0aGlzLl9nZXRSb3VuZE51bShtYXhNaWxlcyk7XG5cdFx0XHR0aGlzLl91cGRhdGVTY2FsZSh0aGlzLl9pU2NhbGUsIG1pbGVzICsgJyBtaScsIG1pbGVzIC8gbWF4TWlsZXMpO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGZlZXQgPSB0aGlzLl9nZXRSb3VuZE51bShtYXhGZWV0KTtcblx0XHRcdHRoaXMuX3VwZGF0ZVNjYWxlKHRoaXMuX2lTY2FsZSwgZmVldCArICcgZnQnLCBmZWV0IC8gbWF4RmVldCk7XG5cdFx0fVxuXHR9LFxuXG5cdF91cGRhdGVTY2FsZTogZnVuY3Rpb24gKHNjYWxlLCB0ZXh0LCByYXRpbykge1xuXHRcdHNjYWxlLnN0eWxlLndpZHRoID0gTWF0aC5yb3VuZCh0aGlzLm9wdGlvbnMubWF4V2lkdGggKiByYXRpbykgKyAncHgnO1xuXHRcdHNjYWxlLmlubmVySFRNTCA9IHRleHQ7XG5cdH0sXG5cblx0X2dldFJvdW5kTnVtOiBmdW5jdGlvbiAobnVtKSB7XG5cdFx0dmFyIHBvdzEwID0gTWF0aC5wb3coMTAsIChNYXRoLmZsb29yKG51bSkgKyAnJykubGVuZ3RoIC0gMSksXG5cdFx0ICAgIGQgPSBudW0gLyBwb3cxMDtcblxuXHRcdGQgPSBkID49IDEwID8gMTAgOlxuXHRcdCAgICBkID49IDUgPyA1IDpcblx0XHQgICAgZCA+PSAzID8gMyA6XG5cdFx0ICAgIGQgPj0gMiA/IDIgOiAxO1xuXG5cdFx0cmV0dXJuIHBvdzEwICogZDtcblx0fVxufSk7XG5cblxuLy8gQGZhY3RvcnkgTC5jb250cm9sLnNjYWxlKG9wdGlvbnM/OiBDb250cm9sLlNjYWxlIG9wdGlvbnMpXG4vLyBDcmVhdGVzIGFuIHNjYWxlIGNvbnRyb2wgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy5cbnZhciBzY2FsZSA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XG5cdHJldHVybiBuZXcgU2NhbGUob3B0aW9ucyk7XG59O1xuXG4vKlxyXG4gKiBAY2xhc3MgQ29udHJvbC5BdHRyaWJ1dGlvblxyXG4gKiBAYWthIEwuQ29udHJvbC5BdHRyaWJ1dGlvblxyXG4gKiBAaW5oZXJpdHMgQ29udHJvbFxyXG4gKlxyXG4gKiBUaGUgYXR0cmlidXRpb24gY29udHJvbCBhbGxvd3MgeW91IHRvIGRpc3BsYXkgYXR0cmlidXRpb24gZGF0YSBpbiBhIHNtYWxsIHRleHQgYm94IG9uIGEgbWFwLiBJdCBpcyBwdXQgb24gdGhlIG1hcCBieSBkZWZhdWx0IHVubGVzcyB5b3Ugc2V0IGl0cyBbYGF0dHJpYnV0aW9uQ29udHJvbGAgb3B0aW9uXSgjbWFwLWF0dHJpYnV0aW9uY29udHJvbCkgdG8gYGZhbHNlYCwgYW5kIGl0IGZldGNoZXMgYXR0cmlidXRpb24gdGV4dHMgZnJvbSBsYXllcnMgd2l0aCB0aGUgW2BnZXRBdHRyaWJ1dGlvbmAgbWV0aG9kXSgjbGF5ZXItZ2V0YXR0cmlidXRpb24pIGF1dG9tYXRpY2FsbHkuIEV4dGVuZHMgQ29udHJvbC5cclxuICovXHJcblxyXG52YXIgQXR0cmlidXRpb24gPSBDb250cm9sLmV4dGVuZCh7XHJcblx0Ly8gQHNlY3Rpb25cclxuXHQvLyBAYWthIENvbnRyb2wuQXR0cmlidXRpb24gb3B0aW9uc1xyXG5cdG9wdGlvbnM6IHtcclxuXHRcdHBvc2l0aW9uOiAnYm90dG9tcmlnaHQnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gcHJlZml4OiBTdHJpbmcgPSAnTGVhZmxldCdcclxuXHRcdC8vIFRoZSBIVE1MIHRleHQgc2hvd24gYmVmb3JlIHRoZSBhdHRyaWJ1dGlvbnMuIFBhc3MgYGZhbHNlYCB0byBkaXNhYmxlLlxyXG5cdFx0cHJlZml4OiAnPGEgaHJlZj1cImh0dHA6Ly9sZWFmbGV0anMuY29tXCIgdGl0bGU9XCJBIEpTIGxpYnJhcnkgZm9yIGludGVyYWN0aXZlIG1hcHNcIj5MZWFmbGV0PC9hPidcclxuXHR9LFxyXG5cclxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAob3B0aW9ucykge1xyXG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcblx0XHR0aGlzLl9hdHRyaWJ1dGlvbnMgPSB7fTtcclxuXHR9LFxyXG5cclxuXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0bWFwLmF0dHJpYnV0aW9uQ29udHJvbCA9IHRoaXM7XHJcblx0XHR0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgJ2xlYWZsZXQtY29udHJvbC1hdHRyaWJ1dGlvbicpO1xyXG5cdFx0ZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24odGhpcy5fY29udGFpbmVyKTtcclxuXHJcblx0XHQvLyBUT0RPIHVnbHksIHJlZmFjdG9yXHJcblx0XHRmb3IgKHZhciBpIGluIG1hcC5fbGF5ZXJzKSB7XHJcblx0XHRcdGlmIChtYXAuX2xheWVyc1tpXS5nZXRBdHRyaWJ1dGlvbikge1xyXG5cdFx0XHRcdHRoaXMuYWRkQXR0cmlidXRpb24obWFwLl9sYXllcnNbaV0uZ2V0QXR0cmlidXRpb24oKSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl91cGRhdGUoKTtcclxuXHJcblx0XHRyZXR1cm4gdGhpcy5fY29udGFpbmVyO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0UHJlZml4KHByZWZpeDogU3RyaW5nKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIHRleHQgYmVmb3JlIHRoZSBhdHRyaWJ1dGlvbnMuXHJcblx0c2V0UHJlZml4OiBmdW5jdGlvbiAocHJlZml4KSB7XHJcblx0XHR0aGlzLm9wdGlvbnMucHJlZml4ID0gcHJlZml4O1xyXG5cdFx0dGhpcy5fdXBkYXRlKCk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGFkZEF0dHJpYnV0aW9uKHRleHQ6IFN0cmluZyk6IHRoaXNcclxuXHQvLyBBZGRzIGFuIGF0dHJpYnV0aW9uIHRleHQgKGUuZy4gYCdWZWN0b3IgZGF0YSAmY29weTsgTWFwYm94J2ApLlxyXG5cdGFkZEF0dHJpYnV0aW9uOiBmdW5jdGlvbiAodGV4dCkge1xyXG5cdFx0aWYgKCF0ZXh0KSB7IHJldHVybiB0aGlzOyB9XHJcblxyXG5cdFx0aWYgKCF0aGlzLl9hdHRyaWJ1dGlvbnNbdGV4dF0pIHtcclxuXHRcdFx0dGhpcy5fYXR0cmlidXRpb25zW3RleHRdID0gMDtcclxuXHRcdH1cclxuXHRcdHRoaXMuX2F0dHJpYnV0aW9uc1t0ZXh0XSsrO1xyXG5cclxuXHRcdHRoaXMuX3VwZGF0ZSgpO1xyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgcmVtb3ZlQXR0cmlidXRpb24odGV4dDogU3RyaW5nKTogdGhpc1xyXG5cdC8vIFJlbW92ZXMgYW4gYXR0cmlidXRpb24gdGV4dC5cclxuXHRyZW1vdmVBdHRyaWJ1dGlvbjogZnVuY3Rpb24gKHRleHQpIHtcclxuXHRcdGlmICghdGV4dCkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdGlmICh0aGlzLl9hdHRyaWJ1dGlvbnNbdGV4dF0pIHtcclxuXHRcdFx0dGhpcy5fYXR0cmlidXRpb25zW3RleHRdLS07XHJcblx0XHRcdHRoaXMuX3VwZGF0ZSgpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdF91cGRhdGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICghdGhpcy5fbWFwKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdHZhciBhdHRyaWJzID0gW107XHJcblxyXG5cdFx0Zm9yICh2YXIgaSBpbiB0aGlzLl9hdHRyaWJ1dGlvbnMpIHtcclxuXHRcdFx0aWYgKHRoaXMuX2F0dHJpYnV0aW9uc1tpXSkge1xyXG5cdFx0XHRcdGF0dHJpYnMucHVzaChpKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBwcmVmaXhBbmRBdHRyaWJzID0gW107XHJcblxyXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5wcmVmaXgpIHtcclxuXHRcdFx0cHJlZml4QW5kQXR0cmlicy5wdXNoKHRoaXMub3B0aW9ucy5wcmVmaXgpO1xyXG5cdFx0fVxyXG5cdFx0aWYgKGF0dHJpYnMubGVuZ3RoKSB7XHJcblx0XHRcdHByZWZpeEFuZEF0dHJpYnMucHVzaChhdHRyaWJzLmpvaW4oJywgJykpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2NvbnRhaW5lci5pbm5lckhUTUwgPSBwcmVmaXhBbmRBdHRyaWJzLmpvaW4oJyB8ICcpO1xyXG5cdH1cclxufSk7XHJcblxyXG4vLyBAbmFtZXNwYWNlIE1hcFxyXG4vLyBAc2VjdGlvbiBDb250cm9sIG9wdGlvbnNcclxuLy8gQG9wdGlvbiBhdHRyaWJ1dGlvbkNvbnRyb2w6IEJvb2xlYW4gPSB0cnVlXHJcbi8vIFdoZXRoZXIgYSBbYXR0cmlidXRpb24gY29udHJvbF0oI2NvbnRyb2wtYXR0cmlidXRpb24pIGlzIGFkZGVkIHRvIHRoZSBtYXAgYnkgZGVmYXVsdC5cclxuTWFwLm1lcmdlT3B0aW9ucyh7XHJcblx0YXR0cmlidXRpb25Db250cm9sOiB0cnVlXHJcbn0pO1xyXG5cclxuTWFwLmFkZEluaXRIb29rKGZ1bmN0aW9uICgpIHtcclxuXHRpZiAodGhpcy5vcHRpb25zLmF0dHJpYnV0aW9uQ29udHJvbCkge1xyXG5cdFx0bmV3IEF0dHJpYnV0aW9uKCkuYWRkVG8odGhpcyk7XHJcblx0fVxyXG59KTtcclxuXHJcbi8vIEBuYW1lc3BhY2UgQ29udHJvbC5BdHRyaWJ1dGlvblxyXG4vLyBAZmFjdG9yeSBMLmNvbnRyb2wuYXR0cmlidXRpb24ob3B0aW9uczogQ29udHJvbC5BdHRyaWJ1dGlvbiBvcHRpb25zKVxyXG4vLyBDcmVhdGVzIGFuIGF0dHJpYnV0aW9uIGNvbnRyb2wuXHJcbnZhciBhdHRyaWJ1dGlvbiA9IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblx0cmV0dXJuIG5ldyBBdHRyaWJ1dGlvbihvcHRpb25zKTtcclxufTtcblxuQ29udHJvbC5MYXllcnMgPSBMYXllcnM7XG5Db250cm9sLlpvb20gPSBab29tO1xuQ29udHJvbC5TY2FsZSA9IFNjYWxlO1xuQ29udHJvbC5BdHRyaWJ1dGlvbiA9IEF0dHJpYnV0aW9uO1xuXG5jb250cm9sLmxheWVycyA9IGxheWVycztcbmNvbnRyb2wuem9vbSA9IHpvb207XG5jb250cm9sLnNjYWxlID0gc2NhbGU7XG5jb250cm9sLmF0dHJpYnV0aW9uID0gYXR0cmlidXRpb247XG5cbi8qXG5cdEwuSGFuZGxlciBpcyBhIGJhc2UgY2xhc3MgZm9yIGhhbmRsZXIgY2xhc3NlcyB0aGF0IGFyZSB1c2VkIGludGVybmFsbHkgdG8gaW5qZWN0XG5cdGludGVyYWN0aW9uIGZlYXR1cmVzIGxpa2UgZHJhZ2dpbmcgdG8gY2xhc3NlcyBsaWtlIE1hcCBhbmQgTWFya2VyLlxuKi9cblxuLy8gQGNsYXNzIEhhbmRsZXJcbi8vIEBha2EgTC5IYW5kbGVyXG4vLyBBYnN0cmFjdCBjbGFzcyBmb3IgbWFwIGludGVyYWN0aW9uIGhhbmRsZXJzXG5cbnZhciBIYW5kbGVyID0gQ2xhc3MuZXh0ZW5kKHtcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG1hcCkge1xuXHRcdHRoaXMuX21hcCA9IG1hcDtcblx0fSxcblxuXHQvLyBAbWV0aG9kIGVuYWJsZSgpOiB0aGlzXG5cdC8vIEVuYWJsZXMgdGhlIGhhbmRsZXJcblx0ZW5hYmxlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuIHRoaXM7IH1cblxuXHRcdHRoaXMuX2VuYWJsZWQgPSB0cnVlO1xuXHRcdHRoaXMuYWRkSG9va3MoKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGRpc2FibGUoKTogdGhpc1xuXHQvLyBEaXNhYmxlcyB0aGUgaGFuZGxlclxuXHRkaXNhYmxlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKCF0aGlzLl9lbmFibGVkKSB7IHJldHVybiB0aGlzOyB9XG5cblx0XHR0aGlzLl9lbmFibGVkID0gZmFsc2U7XG5cdFx0dGhpcy5yZW1vdmVIb29rcygpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgZW5hYmxlZCgpOiBCb29sZWFuXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBoYW5kbGVyIGlzIGVuYWJsZWRcblx0ZW5hYmxlZDogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiAhIXRoaXMuX2VuYWJsZWQ7XG5cdH1cblxuXHQvLyBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xuXHQvLyBDbGFzc2VzIGluaGVyaXRpbmcgZnJvbSBgSGFuZGxlcmAgbXVzdCBpbXBsZW1lbnQgdGhlIHR3byBmb2xsb3dpbmcgbWV0aG9kczpcblx0Ly8gQG1ldGhvZCBhZGRIb29rcygpXG5cdC8vIENhbGxlZCB3aGVuIHRoZSBoYW5kbGVyIGlzIGVuYWJsZWQsIHNob3VsZCBhZGQgZXZlbnQgaG9va3MuXG5cdC8vIEBtZXRob2QgcmVtb3ZlSG9va3MoKVxuXHQvLyBDYWxsZWQgd2hlbiB0aGUgaGFuZGxlciBpcyBkaXNhYmxlZCwgc2hvdWxkIHJlbW92ZSB0aGUgZXZlbnQgaG9va3MgYWRkZWQgcHJldmlvdXNseS5cbn0pO1xuXG4vLyBAc2VjdGlvbiBUaGVyZSBpcyBzdGF0aWMgZnVuY3Rpb24gd2hpY2ggY2FuIGJlIGNhbGxlZCB3aXRob3V0IGluc3RhbnRpYXRpbmcgTC5IYW5kbGVyOlxuLy8gQGZ1bmN0aW9uIGFkZFRvKG1hcDogTWFwLCBuYW1lOiBTdHJpbmcpOiB0aGlzXG4vLyBBZGRzIGEgbmV3IEhhbmRsZXIgdG8gdGhlIGdpdmVuIG1hcCB3aXRoIHRoZSBnaXZlbiBuYW1lLlxuSGFuZGxlci5hZGRUbyA9IGZ1bmN0aW9uIChtYXAsIG5hbWUpIHtcblx0bWFwLmFkZEhhbmRsZXIobmFtZSwgdGhpcyk7XG5cdHJldHVybiB0aGlzO1xufTtcblxudmFyIE1peGluID0ge0V2ZW50czogRXZlbnRzfTtcblxuLypcclxuICogQGNsYXNzIERyYWdnYWJsZVxyXG4gKiBAYWthIEwuRHJhZ2dhYmxlXHJcbiAqIEBpbmhlcml0cyBFdmVudGVkXHJcbiAqXHJcbiAqIEEgY2xhc3MgZm9yIG1ha2luZyBET00gZWxlbWVudHMgZHJhZ2dhYmxlIChpbmNsdWRpbmcgdG91Y2ggc3VwcG9ydCkuXHJcbiAqIFVzZWQgaW50ZXJuYWxseSBmb3IgbWFwIGFuZCBtYXJrZXIgZHJhZ2dpbmcuIE9ubHkgd29ya3MgZm9yIGVsZW1lbnRzXHJcbiAqIHRoYXQgd2VyZSBwb3NpdGlvbmVkIHdpdGggW2BMLkRvbVV0aWwuc2V0UG9zaXRpb25gXSgjZG9tdXRpbC1zZXRwb3NpdGlvbikuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBkcmFnZ2FibGUgPSBuZXcgTC5EcmFnZ2FibGUoZWxlbWVudFRvRHJhZyk7XHJcbiAqIGRyYWdnYWJsZS5lbmFibGUoKTtcclxuICogYGBgXHJcbiAqL1xyXG5cclxudmFyIFNUQVJUID0gdG91Y2ggPyAndG91Y2hzdGFydCBtb3VzZWRvd24nIDogJ21vdXNlZG93bic7XHJcbnZhciBFTkQgPSB7XHJcblx0bW91c2Vkb3duOiAnbW91c2V1cCcsXHJcblx0dG91Y2hzdGFydDogJ3RvdWNoZW5kJyxcclxuXHRwb2ludGVyZG93bjogJ3RvdWNoZW5kJyxcclxuXHRNU1BvaW50ZXJEb3duOiAndG91Y2hlbmQnXHJcbn07XHJcbnZhciBNT1ZFID0ge1xyXG5cdG1vdXNlZG93bjogJ21vdXNlbW92ZScsXHJcblx0dG91Y2hzdGFydDogJ3RvdWNobW92ZScsXHJcblx0cG9pbnRlcmRvd246ICd0b3VjaG1vdmUnLFxyXG5cdE1TUG9pbnRlckRvd246ICd0b3VjaG1vdmUnXHJcbn07XHJcblxyXG5cclxudmFyIERyYWdnYWJsZSA9IEV2ZW50ZWQuZXh0ZW5kKHtcclxuXHJcblx0b3B0aW9uczoge1xyXG5cdFx0Ly8gQHNlY3Rpb25cclxuXHRcdC8vIEBha2EgRHJhZ2dhYmxlIG9wdGlvbnNcclxuXHRcdC8vIEBvcHRpb24gY2xpY2tUb2xlcmFuY2U6IE51bWJlciA9IDNcclxuXHRcdC8vIFRoZSBtYXggbnVtYmVyIG9mIHBpeGVscyBhIHVzZXIgY2FuIHNoaWZ0IHRoZSBtb3VzZSBwb2ludGVyIGR1cmluZyBhIGNsaWNrXHJcblx0XHQvLyBmb3IgaXQgdG8gYmUgY29uc2lkZXJlZCBhIHZhbGlkIGNsaWNrIChhcyBvcHBvc2VkIHRvIGEgbW91c2UgZHJhZykuXHJcblx0XHRjbGlja1RvbGVyYW5jZTogM1xyXG5cdH0sXHJcblxyXG5cdC8vIEBjb25zdHJ1Y3RvciBMLkRyYWdnYWJsZShlbDogSFRNTEVsZW1lbnQsIGRyYWdIYW5kbGU/OiBIVE1MRWxlbWVudCwgcHJldmVudE91dGxpbmU/OiBCb29sZWFuLCBvcHRpb25zPzogRHJhZ2dhYmxlIG9wdGlvbnMpXHJcblx0Ly8gQ3JlYXRlcyBhIGBEcmFnZ2FibGVgIG9iamVjdCBmb3IgbW92aW5nIGBlbGAgd2hlbiB5b3Ugc3RhcnQgZHJhZ2dpbmcgdGhlIGBkcmFnSGFuZGxlYCBlbGVtZW50IChlcXVhbHMgYGVsYCBpdHNlbGYgYnkgZGVmYXVsdCkuXHJcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGVsZW1lbnQsIGRyYWdTdGFydFRhcmdldCwgcHJldmVudE91dGxpbmUkJDEsIG9wdGlvbnMpIHtcclxuXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblxyXG5cdFx0dGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XHJcblx0XHR0aGlzLl9kcmFnU3RhcnRUYXJnZXQgPSBkcmFnU3RhcnRUYXJnZXQgfHwgZWxlbWVudDtcclxuXHRcdHRoaXMuX3ByZXZlbnRPdXRsaW5lID0gcHJldmVudE91dGxpbmUkJDE7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBlbmFibGUoKVxyXG5cdC8vIEVuYWJsZXMgdGhlIGRyYWdnaW5nIGFiaWxpdHlcclxuXHRlbmFibGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh0aGlzLl9lbmFibGVkKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdG9uKHRoaXMuX2RyYWdTdGFydFRhcmdldCwgU1RBUlQsIHRoaXMuX29uRG93biwgdGhpcyk7XHJcblxyXG5cdFx0dGhpcy5fZW5hYmxlZCA9IHRydWU7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBkaXNhYmxlKClcclxuXHQvLyBEaXNhYmxlcyB0aGUgZHJhZ2dpbmcgYWJpbGl0eVxyXG5cdGRpc2FibGU6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICghdGhpcy5fZW5hYmxlZCkgeyByZXR1cm47IH1cclxuXHJcblx0XHQvLyBJZiB3ZSdyZSBjdXJyZW50bHkgZHJhZ2dpbmcgdGhpcyBkcmFnZ2FibGUsXHJcblx0XHQvLyBkaXNhYmxpbmcgaXQgY291bnRzIGFzIGZpcnN0IGVuZGluZyB0aGUgZHJhZy5cclxuXHRcdGlmIChEcmFnZ2FibGUuX2RyYWdnaW5nID09PSB0aGlzKSB7XHJcblx0XHRcdHRoaXMuZmluaXNoRHJhZygpO1xyXG5cdFx0fVxyXG5cclxuXHRcdG9mZih0aGlzLl9kcmFnU3RhcnRUYXJnZXQsIFNUQVJULCB0aGlzLl9vbkRvd24sIHRoaXMpO1xyXG5cclxuXHRcdHRoaXMuX2VuYWJsZWQgPSBmYWxzZTtcclxuXHRcdHRoaXMuX21vdmVkID0gZmFsc2U7XHJcblx0fSxcclxuXHJcblx0X29uRG93bjogZnVuY3Rpb24gKGUpIHtcclxuXHRcdC8vIElnbm9yZSBzaW11bGF0ZWQgZXZlbnRzLCBzaW5jZSB3ZSBoYW5kbGUgYm90aCB0b3VjaCBhbmRcclxuXHRcdC8vIG1vdXNlIGV4cGxpY2l0bHk7IG90aGVyd2lzZSB3ZSByaXNrIGdldHRpbmcgZHVwbGljYXRlcyBvZlxyXG5cdFx0Ly8gdG91Y2ggZXZlbnRzLCBzZWUgIzQzMTUuXHJcblx0XHQvLyBBbHNvIGlnbm9yZSB0aGUgZXZlbnQgaWYgZGlzYWJsZWQ7IHRoaXMgaGFwcGVucyBpbiBJRTExXHJcblx0XHQvLyB1bmRlciBzb21lIGNpcmN1bXN0YW5jZXMsIHNlZSAjMzY2Ni5cclxuXHRcdGlmIChlLl9zaW11bGF0ZWQgfHwgIXRoaXMuX2VuYWJsZWQpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0dGhpcy5fbW92ZWQgPSBmYWxzZTtcclxuXHJcblx0XHRpZiAoaGFzQ2xhc3ModGhpcy5fZWxlbWVudCwgJ2xlYWZsZXQtem9vbS1hbmltJykpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0aWYgKERyYWdnYWJsZS5fZHJhZ2dpbmcgfHwgZS5zaGlmdEtleSB8fCAoKGUud2hpY2ggIT09IDEpICYmIChlLmJ1dHRvbiAhPT0gMSkgJiYgIWUudG91Y2hlcykpIHsgcmV0dXJuOyB9XHJcblx0XHREcmFnZ2FibGUuX2RyYWdnaW5nID0gdGhpczsgIC8vIFByZXZlbnQgZHJhZ2dpbmcgbXVsdGlwbGUgb2JqZWN0cyBhdCBvbmNlLlxyXG5cclxuXHRcdGlmICh0aGlzLl9wcmV2ZW50T3V0bGluZSkge1xyXG5cdFx0XHRwcmV2ZW50T3V0bGluZSh0aGlzLl9lbGVtZW50KTtcclxuXHRcdH1cclxuXHJcblx0XHRkaXNhYmxlSW1hZ2VEcmFnKCk7XHJcblx0XHRkaXNhYmxlVGV4dFNlbGVjdGlvbigpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9tb3ZpbmcpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0Ly8gQGV2ZW50IGRvd246IEV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIGEgZHJhZyBpcyBhYm91dCB0byBzdGFydC5cclxuXHRcdHRoaXMuZmlyZSgnZG93bicpO1xyXG5cclxuXHRcdHZhciBmaXJzdCA9IGUudG91Y2hlcyA/IGUudG91Y2hlc1swXSA6IGU7XHJcblxyXG5cdFx0dGhpcy5fc3RhcnRQb2ludCA9IG5ldyBQb2ludChmaXJzdC5jbGllbnRYLCBmaXJzdC5jbGllbnRZKTtcclxuXHJcblx0XHRvbihkb2N1bWVudCwgTU9WRVtlLnR5cGVdLCB0aGlzLl9vbk1vdmUsIHRoaXMpO1xyXG5cdFx0b24oZG9jdW1lbnQsIEVORFtlLnR5cGVdLCB0aGlzLl9vblVwLCB0aGlzKTtcclxuXHR9LFxyXG5cclxuXHRfb25Nb3ZlOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0Ly8gSWdub3JlIHNpbXVsYXRlZCBldmVudHMsIHNpbmNlIHdlIGhhbmRsZSBib3RoIHRvdWNoIGFuZFxyXG5cdFx0Ly8gbW91c2UgZXhwbGljaXRseTsgb3RoZXJ3aXNlIHdlIHJpc2sgZ2V0dGluZyBkdXBsaWNhdGVzIG9mXHJcblx0XHQvLyB0b3VjaCBldmVudHMsIHNlZSAjNDMxNS5cclxuXHRcdC8vIEFsc28gaWdub3JlIHRoZSBldmVudCBpZiBkaXNhYmxlZDsgdGhpcyBoYXBwZW5zIGluIElFMTFcclxuXHRcdC8vIHVuZGVyIHNvbWUgY2lyY3Vtc3RhbmNlcywgc2VlICMzNjY2LlxyXG5cdFx0aWYgKGUuX3NpbXVsYXRlZCB8fCAhdGhpcy5fZW5hYmxlZCkgeyByZXR1cm47IH1cclxuXHJcblx0XHRpZiAoZS50b3VjaGVzICYmIGUudG91Y2hlcy5sZW5ndGggPiAxKSB7XHJcblx0XHRcdHRoaXMuX21vdmVkID0gdHJ1ZTtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBmaXJzdCA9IChlLnRvdWNoZXMgJiYgZS50b3VjaGVzLmxlbmd0aCA9PT0gMSA/IGUudG91Y2hlc1swXSA6IGUpLFxyXG5cdFx0ICAgIG5ld1BvaW50ID0gbmV3IFBvaW50KGZpcnN0LmNsaWVudFgsIGZpcnN0LmNsaWVudFkpLFxyXG5cdFx0ICAgIG9mZnNldCA9IG5ld1BvaW50LnN1YnRyYWN0KHRoaXMuX3N0YXJ0UG9pbnQpO1xyXG5cclxuXHRcdGlmICghb2Zmc2V0LnggJiYgIW9mZnNldC55KSB7IHJldHVybjsgfVxyXG5cdFx0aWYgKE1hdGguYWJzKG9mZnNldC54KSArIE1hdGguYWJzKG9mZnNldC55KSA8IHRoaXMub3B0aW9ucy5jbGlja1RvbGVyYW5jZSkgeyByZXR1cm47IH1cclxuXHJcblx0XHRwcmV2ZW50RGVmYXVsdChlKTtcclxuXHJcblx0XHRpZiAoIXRoaXMuX21vdmVkKSB7XHJcblx0XHRcdC8vIEBldmVudCBkcmFnc3RhcnQ6IEV2ZW50XHJcblx0XHRcdC8vIEZpcmVkIHdoZW4gYSBkcmFnIHN0YXJ0c1xyXG5cdFx0XHR0aGlzLmZpcmUoJ2RyYWdzdGFydCcpO1xyXG5cclxuXHRcdFx0dGhpcy5fbW92ZWQgPSB0cnVlO1xyXG5cdFx0XHR0aGlzLl9zdGFydFBvcyA9IGdldFBvc2l0aW9uKHRoaXMuX2VsZW1lbnQpLnN1YnRyYWN0KG9mZnNldCk7XHJcblxyXG5cdFx0XHRhZGRDbGFzcyhkb2N1bWVudC5ib2R5LCAnbGVhZmxldC1kcmFnZ2luZycpO1xyXG5cclxuXHRcdFx0dGhpcy5fbGFzdFRhcmdldCA9IGUudGFyZ2V0IHx8IGUuc3JjRWxlbWVudDtcclxuXHRcdFx0Ly8gSUUgYW5kIEVkZ2UgZG8gbm90IGdpdmUgdGhlIDx1c2U+IGVsZW1lbnQsIHNvIGZldGNoIGl0XHJcblx0XHRcdC8vIGlmIG5lY2Vzc2FyeVxyXG5cdFx0XHRpZiAoKHdpbmRvdy5TVkdFbGVtZW50SW5zdGFuY2UpICYmICh0aGlzLl9sYXN0VGFyZ2V0IGluc3RhbmNlb2YgU1ZHRWxlbWVudEluc3RhbmNlKSkge1xyXG5cdFx0XHRcdHRoaXMuX2xhc3RUYXJnZXQgPSB0aGlzLl9sYXN0VGFyZ2V0LmNvcnJlc3BvbmRpbmdVc2VFbGVtZW50O1xyXG5cdFx0XHR9XHJcblx0XHRcdGFkZENsYXNzKHRoaXMuX2xhc3RUYXJnZXQsICdsZWFmbGV0LWRyYWctdGFyZ2V0Jyk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fbmV3UG9zID0gdGhpcy5fc3RhcnRQb3MuYWRkKG9mZnNldCk7XHJcblx0XHR0aGlzLl9tb3ZpbmcgPSB0cnVlO1xyXG5cclxuXHRcdGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9hbmltUmVxdWVzdCk7XHJcblx0XHR0aGlzLl9sYXN0RXZlbnQgPSBlO1xyXG5cdFx0dGhpcy5fYW5pbVJlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lKHRoaXMuX3VwZGF0ZVBvc2l0aW9uLCB0aGlzLCB0cnVlKTtcclxuXHR9LFxyXG5cclxuXHRfdXBkYXRlUG9zaXRpb246IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBlID0ge29yaWdpbmFsRXZlbnQ6IHRoaXMuX2xhc3RFdmVudH07XHJcblxyXG5cdFx0Ly8gQGV2ZW50IHByZWRyYWc6IEV2ZW50XHJcblx0XHQvLyBGaXJlZCBjb250aW51b3VzbHkgZHVyaW5nIGRyYWdnaW5nICpiZWZvcmUqIGVhY2ggY29ycmVzcG9uZGluZ1xyXG5cdFx0Ly8gdXBkYXRlIG9mIHRoZSBlbGVtZW50J3MgcG9zaXRpb24uXHJcblx0XHR0aGlzLmZpcmUoJ3ByZWRyYWcnLCBlKTtcclxuXHRcdHNldFBvc2l0aW9uKHRoaXMuX2VsZW1lbnQsIHRoaXMuX25ld1Bvcyk7XHJcblxyXG5cdFx0Ly8gQGV2ZW50IGRyYWc6IEV2ZW50XHJcblx0XHQvLyBGaXJlZCBjb250aW51b3VzbHkgZHVyaW5nIGRyYWdnaW5nLlxyXG5cdFx0dGhpcy5maXJlKCdkcmFnJywgZSk7XHJcblx0fSxcclxuXHJcblx0X29uVXA6IGZ1bmN0aW9uIChlKSB7XHJcblx0XHQvLyBJZ25vcmUgc2ltdWxhdGVkIGV2ZW50cywgc2luY2Ugd2UgaGFuZGxlIGJvdGggdG91Y2ggYW5kXHJcblx0XHQvLyBtb3VzZSBleHBsaWNpdGx5OyBvdGhlcndpc2Ugd2UgcmlzayBnZXR0aW5nIGR1cGxpY2F0ZXMgb2ZcclxuXHRcdC8vIHRvdWNoIGV2ZW50cywgc2VlICM0MzE1LlxyXG5cdFx0Ly8gQWxzbyBpZ25vcmUgdGhlIGV2ZW50IGlmIGRpc2FibGVkOyB0aGlzIGhhcHBlbnMgaW4gSUUxMVxyXG5cdFx0Ly8gdW5kZXIgc29tZSBjaXJjdW1zdGFuY2VzLCBzZWUgIzM2NjYuXHJcblx0XHRpZiAoZS5fc2ltdWxhdGVkIHx8ICF0aGlzLl9lbmFibGVkKSB7IHJldHVybjsgfVxyXG5cdFx0dGhpcy5maW5pc2hEcmFnKCk7XHJcblx0fSxcclxuXHJcblx0ZmluaXNoRHJhZzogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmVtb3ZlQ2xhc3MoZG9jdW1lbnQuYm9keSwgJ2xlYWZsZXQtZHJhZ2dpbmcnKTtcclxuXHJcblx0XHRpZiAodGhpcy5fbGFzdFRhcmdldCkge1xyXG5cdFx0XHRyZW1vdmVDbGFzcyh0aGlzLl9sYXN0VGFyZ2V0LCAnbGVhZmxldC1kcmFnLXRhcmdldCcpO1xyXG5cdFx0XHR0aGlzLl9sYXN0VGFyZ2V0ID0gbnVsbDtcclxuXHRcdH1cclxuXHJcblx0XHRmb3IgKHZhciBpIGluIE1PVkUpIHtcclxuXHRcdFx0b2ZmKGRvY3VtZW50LCBNT1ZFW2ldLCB0aGlzLl9vbk1vdmUsIHRoaXMpO1xyXG5cdFx0XHRvZmYoZG9jdW1lbnQsIEVORFtpXSwgdGhpcy5fb25VcCwgdGhpcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0ZW5hYmxlSW1hZ2VEcmFnKCk7XHJcblx0XHRlbmFibGVUZXh0U2VsZWN0aW9uKCk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX21vdmVkICYmIHRoaXMuX21vdmluZykge1xyXG5cdFx0XHQvLyBlbnN1cmUgZHJhZyBpcyBub3QgZmlyZWQgYWZ0ZXIgZHJhZ2VuZFxyXG5cdFx0XHRjYW5jZWxBbmltRnJhbWUodGhpcy5fYW5pbVJlcXVlc3QpO1xyXG5cclxuXHRcdFx0Ly8gQGV2ZW50IGRyYWdlbmQ6IERyYWdFbmRFdmVudFxyXG5cdFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBkcmFnIGVuZHMuXHJcblx0XHRcdHRoaXMuZmlyZSgnZHJhZ2VuZCcsIHtcclxuXHRcdFx0XHRkaXN0YW5jZTogdGhpcy5fbmV3UG9zLmRpc3RhbmNlVG8odGhpcy5fc3RhcnRQb3MpXHJcblx0XHRcdH0pO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX21vdmluZyA9IGZhbHNlO1xyXG5cdFx0RHJhZ2dhYmxlLl9kcmFnZ2luZyA9IGZhbHNlO1xyXG5cdH1cclxuXHJcbn0pO1xuXG4vKlxyXG4gKiBAbmFtZXNwYWNlIExpbmVVdGlsXHJcbiAqXHJcbiAqIFZhcmlvdXMgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIHBvbHlsaW5lIHBvaW50cyBwcm9jZXNzaW5nLCB1c2VkIGJ5IExlYWZsZXQgaW50ZXJuYWxseSB0byBtYWtlIHBvbHlsaW5lcyBsaWdodG5pbmctZmFzdC5cclxuICovXHJcblxyXG4vLyBTaW1wbGlmeSBwb2x5bGluZSB3aXRoIHZlcnRleCByZWR1Y3Rpb24gYW5kIERvdWdsYXMtUGV1Y2tlciBzaW1wbGlmaWNhdGlvbi5cclxuLy8gSW1wcm92ZXMgcmVuZGVyaW5nIHBlcmZvcm1hbmNlIGRyYW1hdGljYWxseSBieSBsZXNzZW5pbmcgdGhlIG51bWJlciBvZiBwb2ludHMgdG8gZHJhdy5cclxuXHJcbi8vIEBmdW5jdGlvbiBzaW1wbGlmeShwb2ludHM6IFBvaW50W10sIHRvbGVyYW5jZTogTnVtYmVyKTogUG9pbnRbXVxyXG4vLyBEcmFtYXRpY2FsbHkgcmVkdWNlcyB0aGUgbnVtYmVyIG9mIHBvaW50cyBpbiBhIHBvbHlsaW5lIHdoaWxlIHJldGFpbmluZ1xyXG4vLyBpdHMgc2hhcGUgYW5kIHJldHVybnMgYSBuZXcgYXJyYXkgb2Ygc2ltcGxpZmllZCBwb2ludHMsIHVzaW5nIHRoZVxyXG4vLyBbRG91Z2xhcy1QZXVja2VyIGFsZ29yaXRobV0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Eb3VnbGFzLVBldWNrZXJfYWxnb3JpdGhtKS5cclxuLy8gVXNlZCBmb3IgYSBodWdlIHBlcmZvcm1hbmNlIGJvb3N0IHdoZW4gcHJvY2Vzc2luZy9kaXNwbGF5aW5nIExlYWZsZXQgcG9seWxpbmVzIGZvclxyXG4vLyBlYWNoIHpvb20gbGV2ZWwgYW5kIGFsc28gcmVkdWNpbmcgdmlzdWFsIG5vaXNlLiB0b2xlcmFuY2UgYWZmZWN0cyB0aGUgYW1vdW50IG9mXHJcbi8vIHNpbXBsaWZpY2F0aW9uIChsZXNzZXIgdmFsdWUgbWVhbnMgaGlnaGVyIHF1YWxpdHkgYnV0IHNsb3dlciBhbmQgd2l0aCBtb3JlIHBvaW50cykuXHJcbi8vIEFsc28gcmVsZWFzZWQgYXMgYSBzZXBhcmF0ZWQgbWljcm8tbGlicmFyeSBbU2ltcGxpZnkuanNdKGh0dHA6Ly9tb3VybmVyLmdpdGh1Yi5jb20vc2ltcGxpZnktanMvKS5cclxuZnVuY3Rpb24gc2ltcGxpZnkocG9pbnRzLCB0b2xlcmFuY2UpIHtcclxuXHRpZiAoIXRvbGVyYW5jZSB8fCAhcG9pbnRzLmxlbmd0aCkge1xyXG5cdFx0cmV0dXJuIHBvaW50cy5zbGljZSgpO1xyXG5cdH1cclxuXHJcblx0dmFyIHNxVG9sZXJhbmNlID0gdG9sZXJhbmNlICogdG9sZXJhbmNlO1xyXG5cclxuXHQgICAgLy8gc3RhZ2UgMTogdmVydGV4IHJlZHVjdGlvblxyXG5cdCAgICBwb2ludHMgPSBfcmVkdWNlUG9pbnRzKHBvaW50cywgc3FUb2xlcmFuY2UpO1xyXG5cclxuXHQgICAgLy8gc3RhZ2UgMjogRG91Z2xhcy1QZXVja2VyIHNpbXBsaWZpY2F0aW9uXHJcblx0ICAgIHBvaW50cyA9IF9zaW1wbGlmeURQKHBvaW50cywgc3FUb2xlcmFuY2UpO1xyXG5cclxuXHRyZXR1cm4gcG9pbnRzO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gcG9pbnRUb1NlZ21lbnREaXN0YW5jZShwOiBQb2ludCwgcDE6IFBvaW50LCBwMjogUG9pbnQpOiBOdW1iZXJcclxuLy8gUmV0dXJucyB0aGUgZGlzdGFuY2UgYmV0d2VlbiBwb2ludCBgcGAgYW5kIHNlZ21lbnQgYHAxYCB0byBgcDJgLlxyXG5mdW5jdGlvbiBwb2ludFRvU2VnbWVudERpc3RhbmNlKHAsIHAxLCBwMikge1xyXG5cdHJldHVybiBNYXRoLnNxcnQoX3NxQ2xvc2VzdFBvaW50T25TZWdtZW50KHAsIHAxLCBwMiwgdHJ1ZSkpO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gY2xvc2VzdFBvaW50T25TZWdtZW50KHA6IFBvaW50LCBwMTogUG9pbnQsIHAyOiBQb2ludCk6IE51bWJlclxyXG4vLyBSZXR1cm5zIHRoZSBjbG9zZXN0IHBvaW50IGZyb20gYSBwb2ludCBgcGAgb24gYSBzZWdtZW50IGBwMWAgdG8gYHAyYC5cclxuZnVuY3Rpb24gY2xvc2VzdFBvaW50T25TZWdtZW50KHAsIHAxLCBwMikge1xyXG5cdHJldHVybiBfc3FDbG9zZXN0UG9pbnRPblNlZ21lbnQocCwgcDEsIHAyKTtcclxufVxyXG5cclxuLy8gRG91Z2xhcy1QZXVja2VyIHNpbXBsaWZpY2F0aW9uLCBzZWUgaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Eb3VnbGFzLVBldWNrZXJfYWxnb3JpdGhtXHJcbmZ1bmN0aW9uIF9zaW1wbGlmeURQKHBvaW50cywgc3FUb2xlcmFuY2UpIHtcclxuXHJcblx0dmFyIGxlbiA9IHBvaW50cy5sZW5ndGgsXHJcblx0ICAgIEFycmF5Q29uc3RydWN0b3IgPSB0eXBlb2YgVWludDhBcnJheSAhPT0gdW5kZWZpbmVkICsgJycgPyBVaW50OEFycmF5IDogQXJyYXksXHJcblx0ICAgIG1hcmtlcnMgPSBuZXcgQXJyYXlDb25zdHJ1Y3RvcihsZW4pO1xyXG5cclxuXHQgICAgbWFya2Vyc1swXSA9IG1hcmtlcnNbbGVuIC0gMV0gPSAxO1xyXG5cclxuXHRfc2ltcGxpZnlEUFN0ZXAocG9pbnRzLCBtYXJrZXJzLCBzcVRvbGVyYW5jZSwgMCwgbGVuIC0gMSk7XHJcblxyXG5cdHZhciBpLFxyXG5cdCAgICBuZXdQb2ludHMgPSBbXTtcclxuXHJcblx0Zm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRpZiAobWFya2Vyc1tpXSkge1xyXG5cdFx0XHRuZXdQb2ludHMucHVzaChwb2ludHNbaV0pO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0cmV0dXJuIG5ld1BvaW50cztcclxufVxyXG5cclxuZnVuY3Rpb24gX3NpbXBsaWZ5RFBTdGVwKHBvaW50cywgbWFya2Vycywgc3FUb2xlcmFuY2UsIGZpcnN0LCBsYXN0KSB7XHJcblxyXG5cdHZhciBtYXhTcURpc3QgPSAwLFxyXG5cdGluZGV4LCBpLCBzcURpc3Q7XHJcblxyXG5cdGZvciAoaSA9IGZpcnN0ICsgMTsgaSA8PSBsYXN0IC0gMTsgaSsrKSB7XHJcblx0XHRzcURpc3QgPSBfc3FDbG9zZXN0UG9pbnRPblNlZ21lbnQocG9pbnRzW2ldLCBwb2ludHNbZmlyc3RdLCBwb2ludHNbbGFzdF0sIHRydWUpO1xyXG5cclxuXHRcdGlmIChzcURpc3QgPiBtYXhTcURpc3QpIHtcclxuXHRcdFx0aW5kZXggPSBpO1xyXG5cdFx0XHRtYXhTcURpc3QgPSBzcURpc3Q7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRpZiAobWF4U3FEaXN0ID4gc3FUb2xlcmFuY2UpIHtcclxuXHRcdG1hcmtlcnNbaW5kZXhdID0gMTtcclxuXHJcblx0XHRfc2ltcGxpZnlEUFN0ZXAocG9pbnRzLCBtYXJrZXJzLCBzcVRvbGVyYW5jZSwgZmlyc3QsIGluZGV4KTtcclxuXHRcdF9zaW1wbGlmeURQU3RlcChwb2ludHMsIG1hcmtlcnMsIHNxVG9sZXJhbmNlLCBpbmRleCwgbGFzdCk7XHJcblx0fVxyXG59XHJcblxyXG4vLyByZWR1Y2UgcG9pbnRzIHRoYXQgYXJlIHRvbyBjbG9zZSB0byBlYWNoIG90aGVyIHRvIGEgc2luZ2xlIHBvaW50XHJcbmZ1bmN0aW9uIF9yZWR1Y2VQb2ludHMocG9pbnRzLCBzcVRvbGVyYW5jZSkge1xyXG5cdHZhciByZWR1Y2VkUG9pbnRzID0gW3BvaW50c1swXV07XHJcblxyXG5cdGZvciAodmFyIGkgPSAxLCBwcmV2ID0gMCwgbGVuID0gcG9pbnRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRpZiAoX3NxRGlzdChwb2ludHNbaV0sIHBvaW50c1twcmV2XSkgPiBzcVRvbGVyYW5jZSkge1xyXG5cdFx0XHRyZWR1Y2VkUG9pbnRzLnB1c2gocG9pbnRzW2ldKTtcclxuXHRcdFx0cHJldiA9IGk7XHJcblx0XHR9XHJcblx0fVxyXG5cdGlmIChwcmV2IDwgbGVuIC0gMSkge1xyXG5cdFx0cmVkdWNlZFBvaW50cy5wdXNoKHBvaW50c1tsZW4gLSAxXSk7XHJcblx0fVxyXG5cdHJldHVybiByZWR1Y2VkUG9pbnRzO1xyXG59XHJcblxyXG52YXIgX2xhc3RDb2RlO1xyXG5cclxuLy8gQGZ1bmN0aW9uIGNsaXBTZWdtZW50KGE6IFBvaW50LCBiOiBQb2ludCwgYm91bmRzOiBCb3VuZHMsIHVzZUxhc3RDb2RlPzogQm9vbGVhbiwgcm91bmQ/OiBCb29sZWFuKTogUG9pbnRbXXxCb29sZWFuXHJcbi8vIENsaXBzIHRoZSBzZWdtZW50IGEgdG8gYiBieSByZWN0YW5ndWxhciBib3VuZHMgd2l0aCB0aGVcclxuLy8gW0NvaGVuLVN1dGhlcmxhbmQgYWxnb3JpdGhtXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db2hlbiVFMiU4MCU5M1N1dGhlcmxhbmRfYWxnb3JpdGhtKVxyXG4vLyAobW9kaWZ5aW5nIHRoZSBzZWdtZW50IHBvaW50cyBkaXJlY3RseSEpLiBVc2VkIGJ5IExlYWZsZXQgdG8gb25seSBzaG93IHBvbHlsaW5lXHJcbi8vIHBvaW50cyB0aGF0IGFyZSBvbiB0aGUgc2NyZWVuIG9yIG5lYXIsIGluY3JlYXNpbmcgcGVyZm9ybWFuY2UuXHJcbmZ1bmN0aW9uIGNsaXBTZWdtZW50KGEsIGIsIGJvdW5kcywgdXNlTGFzdENvZGUsIHJvdW5kKSB7XHJcblx0dmFyIGNvZGVBID0gdXNlTGFzdENvZGUgPyBfbGFzdENvZGUgOiBfZ2V0Qml0Q29kZShhLCBib3VuZHMpLFxyXG5cdCAgICBjb2RlQiA9IF9nZXRCaXRDb2RlKGIsIGJvdW5kcyksXHJcblxyXG5cdCAgICBjb2RlT3V0LCBwLCBuZXdDb2RlO1xyXG5cclxuXHQgICAgLy8gc2F2ZSAybmQgY29kZSB0byBhdm9pZCBjYWxjdWxhdGluZyBpdCBvbiB0aGUgbmV4dCBzZWdtZW50XHJcblx0ICAgIF9sYXN0Q29kZSA9IGNvZGVCO1xyXG5cclxuXHR3aGlsZSAodHJ1ZSkge1xyXG5cdFx0Ly8gaWYgYSxiIGlzIGluc2lkZSB0aGUgY2xpcCB3aW5kb3cgKHRyaXZpYWwgYWNjZXB0KVxyXG5cdFx0aWYgKCEoY29kZUEgfCBjb2RlQikpIHtcclxuXHRcdFx0cmV0dXJuIFthLCBiXTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBpZiBhLGIgaXMgb3V0c2lkZSB0aGUgY2xpcCB3aW5kb3cgKHRyaXZpYWwgcmVqZWN0KVxyXG5cdFx0aWYgKGNvZGVBICYgY29kZUIpIHtcclxuXHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIG90aGVyIGNhc2VzXHJcblx0XHRjb2RlT3V0ID0gY29kZUEgfHwgY29kZUI7XHJcblx0XHRwID0gX2dldEVkZ2VJbnRlcnNlY3Rpb24oYSwgYiwgY29kZU91dCwgYm91bmRzLCByb3VuZCk7XHJcblx0XHRuZXdDb2RlID0gX2dldEJpdENvZGUocCwgYm91bmRzKTtcclxuXHJcblx0XHRpZiAoY29kZU91dCA9PT0gY29kZUEpIHtcclxuXHRcdFx0YSA9IHA7XHJcblx0XHRcdGNvZGVBID0gbmV3Q29kZTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGIgPSBwO1xyXG5cdFx0XHRjb2RlQiA9IG5ld0NvZGU7XHJcblx0XHR9XHJcblx0fVxyXG59XHJcblxyXG5mdW5jdGlvbiBfZ2V0RWRnZUludGVyc2VjdGlvbihhLCBiLCBjb2RlLCBib3VuZHMsIHJvdW5kKSB7XHJcblx0dmFyIGR4ID0gYi54IC0gYS54LFxyXG5cdCAgICBkeSA9IGIueSAtIGEueSxcclxuXHQgICAgbWluID0gYm91bmRzLm1pbixcclxuXHQgICAgbWF4ID0gYm91bmRzLm1heCxcclxuXHQgICAgeCwgeTtcclxuXHJcblx0aWYgKGNvZGUgJiA4KSB7IC8vIHRvcFxyXG5cdFx0eCA9IGEueCArIGR4ICogKG1heC55IC0gYS55KSAvIGR5O1xyXG5cdFx0eSA9IG1heC55O1xyXG5cclxuXHR9IGVsc2UgaWYgKGNvZGUgJiA0KSB7IC8vIGJvdHRvbVxyXG5cdFx0eCA9IGEueCArIGR4ICogKG1pbi55IC0gYS55KSAvIGR5O1xyXG5cdFx0eSA9IG1pbi55O1xyXG5cclxuXHR9IGVsc2UgaWYgKGNvZGUgJiAyKSB7IC8vIHJpZ2h0XHJcblx0XHR4ID0gbWF4Lng7XHJcblx0XHR5ID0gYS55ICsgZHkgKiAobWF4LnggLSBhLngpIC8gZHg7XHJcblxyXG5cdH0gZWxzZSBpZiAoY29kZSAmIDEpIHsgLy8gbGVmdFxyXG5cdFx0eCA9IG1pbi54O1xyXG5cdFx0eSA9IGEueSArIGR5ICogKG1pbi54IC0gYS54KSAvIGR4O1xyXG5cdH1cclxuXHJcblx0cmV0dXJuIG5ldyBQb2ludCh4LCB5LCByb3VuZCk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIF9nZXRCaXRDb2RlKHAsIGJvdW5kcykge1xyXG5cdHZhciBjb2RlID0gMDtcclxuXHJcblx0aWYgKHAueCA8IGJvdW5kcy5taW4ueCkgeyAvLyBsZWZ0XHJcblx0XHRjb2RlIHw9IDE7XHJcblx0fSBlbHNlIGlmIChwLnggPiBib3VuZHMubWF4LngpIHsgLy8gcmlnaHRcclxuXHRcdGNvZGUgfD0gMjtcclxuXHR9XHJcblxyXG5cdGlmIChwLnkgPCBib3VuZHMubWluLnkpIHsgLy8gYm90dG9tXHJcblx0XHRjb2RlIHw9IDQ7XHJcblx0fSBlbHNlIGlmIChwLnkgPiBib3VuZHMubWF4LnkpIHsgLy8gdG9wXHJcblx0XHRjb2RlIHw9IDg7XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gY29kZTtcclxufVxyXG5cclxuLy8gc3F1YXJlIGRpc3RhbmNlICh0byBhdm9pZCB1bm5lY2Vzc2FyeSBNYXRoLnNxcnQgY2FsbHMpXHJcbmZ1bmN0aW9uIF9zcURpc3QocDEsIHAyKSB7XHJcblx0dmFyIGR4ID0gcDIueCAtIHAxLngsXHJcblx0ICAgIGR5ID0gcDIueSAtIHAxLnk7XHJcblx0cmV0dXJuIGR4ICogZHggKyBkeSAqIGR5O1xyXG59XHJcblxyXG4vLyByZXR1cm4gY2xvc2VzdCBwb2ludCBvbiBzZWdtZW50IG9yIGRpc3RhbmNlIHRvIHRoYXQgcG9pbnRcclxuZnVuY3Rpb24gX3NxQ2xvc2VzdFBvaW50T25TZWdtZW50KHAsIHAxLCBwMiwgc3FEaXN0KSB7XHJcblx0dmFyIHggPSBwMS54LFxyXG5cdCAgICB5ID0gcDEueSxcclxuXHQgICAgZHggPSBwMi54IC0geCxcclxuXHQgICAgZHkgPSBwMi55IC0geSxcclxuXHQgICAgZG90ID0gZHggKiBkeCArIGR5ICogZHksXHJcblx0ICAgIHQ7XHJcblxyXG5cdGlmIChkb3QgPiAwKSB7XHJcblx0XHR0ID0gKChwLnggLSB4KSAqIGR4ICsgKHAueSAtIHkpICogZHkpIC8gZG90O1xyXG5cclxuXHRcdGlmICh0ID4gMSkge1xyXG5cdFx0XHR4ID0gcDIueDtcclxuXHRcdFx0eSA9IHAyLnk7XHJcblx0XHR9IGVsc2UgaWYgKHQgPiAwKSB7XHJcblx0XHRcdHggKz0gZHggKiB0O1xyXG5cdFx0XHR5ICs9IGR5ICogdDtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdGR4ID0gcC54IC0geDtcclxuXHRkeSA9IHAueSAtIHk7XHJcblxyXG5cdHJldHVybiBzcURpc3QgPyBkeCAqIGR4ICsgZHkgKiBkeSA6IG5ldyBQb2ludCh4LCB5KTtcclxufVxyXG5cclxuXHJcbi8vIEBmdW5jdGlvbiBpc0ZsYXQobGF0bG5nczogTGF0TG5nW10pOiBCb29sZWFuXHJcbi8vIFJldHVybnMgdHJ1ZSBpZiBgbGF0bG5nc2AgaXMgYSBmbGF0IGFycmF5LCBmYWxzZSBpcyBuZXN0ZWQuXHJcbmZ1bmN0aW9uIGlzRmxhdChsYXRsbmdzKSB7XHJcblx0cmV0dXJuICFpc0FycmF5KGxhdGxuZ3NbMF0pIHx8ICh0eXBlb2YgbGF0bG5nc1swXVswXSAhPT0gJ29iamVjdCcgJiYgdHlwZW9mIGxhdGxuZ3NbMF1bMF0gIT09ICd1bmRlZmluZWQnKTtcclxufVxyXG5cclxuZnVuY3Rpb24gX2ZsYXQobGF0bG5ncykge1xyXG5cdGNvbnNvbGUud2FybignRGVwcmVjYXRlZCB1c2Ugb2YgX2ZsYXQsIHBsZWFzZSB1c2UgTC5MaW5lVXRpbC5pc0ZsYXQgaW5zdGVhZC4nKTtcclxuXHRyZXR1cm4gaXNGbGF0KGxhdGxuZ3MpO1xyXG59XHJcblxuXG52YXIgTGluZVV0aWwgPSAoT2JqZWN0LmZyZWV6ZSB8fCBPYmplY3QpKHtcblx0c2ltcGxpZnk6IHNpbXBsaWZ5LFxuXHRwb2ludFRvU2VnbWVudERpc3RhbmNlOiBwb2ludFRvU2VnbWVudERpc3RhbmNlLFxuXHRjbG9zZXN0UG9pbnRPblNlZ21lbnQ6IGNsb3Nlc3RQb2ludE9uU2VnbWVudCxcblx0Y2xpcFNlZ21lbnQ6IGNsaXBTZWdtZW50LFxuXHRfZ2V0RWRnZUludGVyc2VjdGlvbjogX2dldEVkZ2VJbnRlcnNlY3Rpb24sXG5cdF9nZXRCaXRDb2RlOiBfZ2V0Qml0Q29kZSxcblx0X3NxQ2xvc2VzdFBvaW50T25TZWdtZW50OiBfc3FDbG9zZXN0UG9pbnRPblNlZ21lbnQsXG5cdGlzRmxhdDogaXNGbGF0LFxuXHRfZmxhdDogX2ZsYXRcbn0pO1xuXG4vKlxyXG4gKiBAbmFtZXNwYWNlIFBvbHlVdGlsXHJcbiAqIFZhcmlvdXMgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIHBvbHlnb24gZ2VvbWV0cmllcy5cclxuICovXHJcblxyXG4vKiBAZnVuY3Rpb24gY2xpcFBvbHlnb24ocG9pbnRzOiBQb2ludFtdLCBib3VuZHM6IEJvdW5kcywgcm91bmQ/OiBCb29sZWFuKTogUG9pbnRbXVxyXG4gKiBDbGlwcyB0aGUgcG9seWdvbiBnZW9tZXRyeSBkZWZpbmVkIGJ5IHRoZSBnaXZlbiBgcG9pbnRzYCBieSB0aGUgZ2l2ZW4gYm91bmRzICh1c2luZyB0aGUgW1N1dGhlcmxhbmQtSG9kZ21hbiBhbGdvcml0aG1dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1N1dGhlcmxhbmQlRTIlODAlOTNIb2RnbWFuX2FsZ29yaXRobSkpLlxyXG4gKiBVc2VkIGJ5IExlYWZsZXQgdG8gb25seSBzaG93IHBvbHlnb24gcG9pbnRzIHRoYXQgYXJlIG9uIHRoZSBzY3JlZW4gb3IgbmVhciwgaW5jcmVhc2luZ1xyXG4gKiBwZXJmb3JtYW5jZS4gTm90ZSB0aGF0IHBvbHlnb24gcG9pbnRzIG5lZWRzIGRpZmZlcmVudCBhbGdvcml0aG0gZm9yIGNsaXBwaW5nXHJcbiAqIHRoYW4gcG9seWxpbmUsIHNvIHRoZXJlJ3MgYSBzZXBhcmF0ZSBtZXRob2QgZm9yIGl0LlxyXG4gKi9cclxuZnVuY3Rpb24gY2xpcFBvbHlnb24ocG9pbnRzLCBib3VuZHMsIHJvdW5kKSB7XHJcblx0dmFyIGNsaXBwZWRQb2ludHMsXHJcblx0ICAgIGVkZ2VzID0gWzEsIDQsIDIsIDhdLFxyXG5cdCAgICBpLCBqLCBrLFxyXG5cdCAgICBhLCBiLFxyXG5cdCAgICBsZW4sIGVkZ2UsIHA7XHJcblxyXG5cdGZvciAoaSA9IDAsIGxlbiA9IHBvaW50cy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xyXG5cdFx0cG9pbnRzW2ldLl9jb2RlID0gX2dldEJpdENvZGUocG9pbnRzW2ldLCBib3VuZHMpO1xyXG5cdH1cclxuXHJcblx0Ly8gZm9yIGVhY2ggZWRnZSAobGVmdCwgYm90dG9tLCByaWdodCwgdG9wKVxyXG5cdGZvciAoayA9IDA7IGsgPCA0OyBrKyspIHtcclxuXHRcdGVkZ2UgPSBlZGdlc1trXTtcclxuXHRcdGNsaXBwZWRQb2ludHMgPSBbXTtcclxuXHJcblx0XHRmb3IgKGkgPSAwLCBsZW4gPSBwb2ludHMubGVuZ3RoLCBqID0gbGVuIC0gMTsgaSA8IGxlbjsgaiA9IGkrKykge1xyXG5cdFx0XHRhID0gcG9pbnRzW2ldO1xyXG5cdFx0XHRiID0gcG9pbnRzW2pdO1xyXG5cclxuXHRcdFx0Ly8gaWYgYSBpcyBpbnNpZGUgdGhlIGNsaXAgd2luZG93XHJcblx0XHRcdGlmICghKGEuX2NvZGUgJiBlZGdlKSkge1xyXG5cdFx0XHRcdC8vIGlmIGIgaXMgb3V0c2lkZSB0aGUgY2xpcCB3aW5kb3cgKGEtPmIgZ29lcyBvdXQgb2Ygc2NyZWVuKVxyXG5cdFx0XHRcdGlmIChiLl9jb2RlICYgZWRnZSkge1xyXG5cdFx0XHRcdFx0cCA9IF9nZXRFZGdlSW50ZXJzZWN0aW9uKGIsIGEsIGVkZ2UsIGJvdW5kcywgcm91bmQpO1xyXG5cdFx0XHRcdFx0cC5fY29kZSA9IF9nZXRCaXRDb2RlKHAsIGJvdW5kcyk7XHJcblx0XHRcdFx0XHRjbGlwcGVkUG9pbnRzLnB1c2gocCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGNsaXBwZWRQb2ludHMucHVzaChhKTtcclxuXHJcblx0XHRcdC8vIGVsc2UgaWYgYiBpcyBpbnNpZGUgdGhlIGNsaXAgd2luZG93IChhLT5iIGVudGVycyB0aGUgc2NyZWVuKVxyXG5cdFx0XHR9IGVsc2UgaWYgKCEoYi5fY29kZSAmIGVkZ2UpKSB7XHJcblx0XHRcdFx0cCA9IF9nZXRFZGdlSW50ZXJzZWN0aW9uKGIsIGEsIGVkZ2UsIGJvdW5kcywgcm91bmQpO1xyXG5cdFx0XHRcdHAuX2NvZGUgPSBfZ2V0Qml0Q29kZShwLCBib3VuZHMpO1xyXG5cdFx0XHRcdGNsaXBwZWRQb2ludHMucHVzaChwKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdFx0cG9pbnRzID0gY2xpcHBlZFBvaW50cztcclxuXHR9XHJcblxyXG5cdHJldHVybiBwb2ludHM7XHJcbn1cclxuXG5cbnZhciBQb2x5VXRpbCA9IChPYmplY3QuZnJlZXplIHx8IE9iamVjdCkoe1xuXHRjbGlwUG9seWdvbjogY2xpcFBvbHlnb25cbn0pO1xuXG4vKlxyXG4gKiBAbmFtZXNwYWNlIFByb2plY3Rpb25cclxuICogQHNlY3Rpb25cclxuICogTGVhZmxldCBjb21lcyB3aXRoIGEgc2V0IG9mIGFscmVhZHkgZGVmaW5lZCBQcm9qZWN0aW9ucyBvdXQgb2YgdGhlIGJveDpcclxuICpcclxuICogQHByb2plY3Rpb24gTC5Qcm9qZWN0aW9uLkxvbkxhdFxyXG4gKlxyXG4gKiBFcXVpcmVjdGFuZ3VsYXIsIG9yIFBsYXRlIENhcnJlZSBwcm9qZWN0aW9uIOKAlCB0aGUgbW9zdCBzaW1wbGUgcHJvamVjdGlvbixcclxuICogbW9zdGx5IHVzZWQgYnkgR0lTIGVudGh1c2lhc3RzLiBEaXJlY3RseSBtYXBzIGB4YCBhcyBsb25naXR1ZGUsIGFuZCBgeWAgYXNcclxuICogbGF0aXR1ZGUuIEFsc28gc3VpdGFibGUgZm9yIGZsYXQgd29ybGRzLCBlLmcuIGdhbWUgbWFwcy4gVXNlZCBieSB0aGVcclxuICogYEVQU0c6NDMyNmAgYW5kIGBTaW1wbGVgIENSUy5cclxuICovXHJcblxyXG52YXIgTG9uTGF0ID0ge1xyXG5cdHByb2plY3Q6IGZ1bmN0aW9uIChsYXRsbmcpIHtcclxuXHRcdHJldHVybiBuZXcgUG9pbnQobGF0bG5nLmxuZywgbGF0bG5nLmxhdCk7XHJcblx0fSxcclxuXHJcblx0dW5wcm9qZWN0OiBmdW5jdGlvbiAocG9pbnQpIHtcclxuXHRcdHJldHVybiBuZXcgTGF0TG5nKHBvaW50LnksIHBvaW50LngpO1xyXG5cdH0sXHJcblxyXG5cdGJvdW5kczogbmV3IEJvdW5kcyhbLTE4MCwgLTkwXSwgWzE4MCwgOTBdKVxyXG59O1xuXG4vKlxyXG4gKiBAbmFtZXNwYWNlIFByb2plY3Rpb25cclxuICogQHByb2plY3Rpb24gTC5Qcm9qZWN0aW9uLk1lcmNhdG9yXHJcbiAqXHJcbiAqIEVsbGlwdGljYWwgTWVyY2F0b3IgcHJvamVjdGlvbiDigJQgbW9yZSBjb21wbGV4IHRoYW4gU3BoZXJpY2FsIE1lcmNhdG9yLiBUYWtlcyBpbnRvIGFjY291bnQgdGhhdCBFYXJ0aCBpcyBhIGdlb2lkLCBub3QgYSBwZXJmZWN0IHNwaGVyZS4gVXNlZCBieSB0aGUgRVBTRzozMzk1IENSUy5cclxuICovXHJcblxyXG52YXIgTWVyY2F0b3IgPSB7XHJcblx0UjogNjM3ODEzNyxcclxuXHRSX01JTk9SOiA2MzU2NzUyLjMxNDI0NTE3OSxcclxuXHJcblx0Ym91bmRzOiBuZXcgQm91bmRzKFstMjAwMzc1MDguMzQyNzksIC0xNTQ5NjU3MC43Mzk3Ml0sIFsyMDAzNzUwOC4zNDI3OSwgMTg3NjQ2NTYuMjMxMzhdKSxcclxuXHJcblx0cHJvamVjdDogZnVuY3Rpb24gKGxhdGxuZykge1xyXG5cdFx0dmFyIGQgPSBNYXRoLlBJIC8gMTgwLFxyXG5cdFx0ICAgIHIgPSB0aGlzLlIsXHJcblx0XHQgICAgeSA9IGxhdGxuZy5sYXQgKiBkLFxyXG5cdFx0ICAgIHRtcCA9IHRoaXMuUl9NSU5PUiAvIHIsXHJcblx0XHQgICAgZSA9IE1hdGguc3FydCgxIC0gdG1wICogdG1wKSxcclxuXHRcdCAgICBjb24gPSBlICogTWF0aC5zaW4oeSk7XHJcblxyXG5cdFx0dmFyIHRzID0gTWF0aC50YW4oTWF0aC5QSSAvIDQgLSB5IC8gMikgLyBNYXRoLnBvdygoMSAtIGNvbikgLyAoMSArIGNvbiksIGUgLyAyKTtcclxuXHRcdHkgPSAtciAqIE1hdGgubG9nKE1hdGgubWF4KHRzLCAxRS0xMCkpO1xyXG5cclxuXHRcdHJldHVybiBuZXcgUG9pbnQobGF0bG5nLmxuZyAqIGQgKiByLCB5KTtcclxuXHR9LFxyXG5cclxuXHR1bnByb2plY3Q6IGZ1bmN0aW9uIChwb2ludCkge1xyXG5cdFx0dmFyIGQgPSAxODAgLyBNYXRoLlBJLFxyXG5cdFx0ICAgIHIgPSB0aGlzLlIsXHJcblx0XHQgICAgdG1wID0gdGhpcy5SX01JTk9SIC8gcixcclxuXHRcdCAgICBlID0gTWF0aC5zcXJ0KDEgLSB0bXAgKiB0bXApLFxyXG5cdFx0ICAgIHRzID0gTWF0aC5leHAoLXBvaW50LnkgLyByKSxcclxuXHRcdCAgICBwaGkgPSBNYXRoLlBJIC8gMiAtIDIgKiBNYXRoLmF0YW4odHMpO1xyXG5cclxuXHRcdGZvciAodmFyIGkgPSAwLCBkcGhpID0gMC4xLCBjb247IGkgPCAxNSAmJiBNYXRoLmFicyhkcGhpKSA+IDFlLTc7IGkrKykge1xyXG5cdFx0XHRjb24gPSBlICogTWF0aC5zaW4ocGhpKTtcclxuXHRcdFx0Y29uID0gTWF0aC5wb3coKDEgLSBjb24pIC8gKDEgKyBjb24pLCBlIC8gMik7XHJcblx0XHRcdGRwaGkgPSBNYXRoLlBJIC8gMiAtIDIgKiBNYXRoLmF0YW4odHMgKiBjb24pIC0gcGhpO1xyXG5cdFx0XHRwaGkgKz0gZHBoaTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gbmV3IExhdExuZyhwaGkgKiBkLCBwb2ludC54ICogZCAvIHIpO1xyXG5cdH1cclxufTtcblxuLypcbiAqIEBjbGFzcyBQcm9qZWN0aW9uXG5cbiAqIEFuIG9iamVjdCB3aXRoIG1ldGhvZHMgZm9yIHByb2plY3RpbmcgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIG9mIHRoZSB3b3JsZCBvbnRvXG4gKiBhIGZsYXQgc3VyZmFjZSAoYW5kIGJhY2spLiBTZWUgW01hcCBwcm9qZWN0aW9uXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL01hcF9wcm9qZWN0aW9uKS5cblxuICogQHByb3BlcnR5IGJvdW5kczogQm91bmRzXG4gKiBUaGUgYm91bmRzIChzcGVjaWZpZWQgaW4gQ1JTIHVuaXRzKSB3aGVyZSB0aGUgcHJvamVjdGlvbiBpcyB2YWxpZFxuXG4gKiBAbWV0aG9kIHByb2plY3QobGF0bG5nOiBMYXRMbmcpOiBQb2ludFxuICogUHJvamVjdHMgZ2VvZ3JhcGhpY2FsIGNvb3JkaW5hdGVzIGludG8gYSAyRCBwb2ludC5cbiAqIE9ubHkgYWNjZXB0cyBhY3R1YWwgYEwuTGF0TG5nYCBpbnN0YW5jZXMsIG5vdCBhcnJheXMuXG5cbiAqIEBtZXRob2QgdW5wcm9qZWN0KHBvaW50OiBQb2ludCk6IExhdExuZ1xuICogVGhlIGludmVyc2Ugb2YgYHByb2plY3RgLiBQcm9qZWN0cyBhIDJEIHBvaW50IGludG8gYSBnZW9ncmFwaGljYWwgbG9jYXRpb24uXG4gKiBPbmx5IGFjY2VwdHMgYWN0dWFsIGBMLlBvaW50YCBpbnN0YW5jZXMsIG5vdCBhcnJheXMuXG5cbiAqIE5vdGUgdGhhdCB0aGUgcHJvamVjdGlvbiBpbnN0YW5jZXMgZG8gbm90IGluaGVyaXQgZnJvbSBMZWFmZXQncyBgQ2xhc3NgIG9iamVjdCxcbiAqIGFuZCBjYW4ndCBiZSBpbnN0YW50aWF0ZWQuIEFsc28sIG5ldyBjbGFzc2VzIGNhbid0IGluaGVyaXQgZnJvbSB0aGVtLFxuICogYW5kIG1ldGhvZHMgY2FuJ3QgYmUgYWRkZWQgdG8gdGhlbSB3aXRoIHRoZSBgaW5jbHVkZWAgZnVuY3Rpb24uXG5cbiAqL1xuXG5cblxuXG52YXIgaW5kZXggPSAoT2JqZWN0LmZyZWV6ZSB8fCBPYmplY3QpKHtcblx0TG9uTGF0OiBMb25MYXQsXG5cdE1lcmNhdG9yOiBNZXJjYXRvcixcblx0U3BoZXJpY2FsTWVyY2F0b3I6IFNwaGVyaWNhbE1lcmNhdG9yXG59KTtcblxuLypcclxuICogQG5hbWVzcGFjZSBDUlNcclxuICogQGNycyBMLkNSUy5FUFNHMzM5NVxyXG4gKlxyXG4gKiBSYXJlbHkgdXNlZCBieSBzb21lIGNvbW1lcmNpYWwgdGlsZSBwcm92aWRlcnMuIFVzZXMgRWxsaXB0aWNhbCBNZXJjYXRvciBwcm9qZWN0aW9uLlxyXG4gKi9cclxudmFyIEVQU0czMzk1ID0gZXh0ZW5kKHt9LCBFYXJ0aCwge1xyXG5cdGNvZGU6ICdFUFNHOjMzOTUnLFxyXG5cdHByb2plY3Rpb246IE1lcmNhdG9yLFxyXG5cclxuXHR0cmFuc2Zvcm1hdGlvbjogKGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBzY2FsZSA9IDAuNSAvIChNYXRoLlBJICogTWVyY2F0b3IuUik7XHJcblx0XHRyZXR1cm4gdG9UcmFuc2Zvcm1hdGlvbihzY2FsZSwgMC41LCAtc2NhbGUsIDAuNSk7XHJcblx0fSgpKVxyXG59KTtcblxuLypcclxuICogQG5hbWVzcGFjZSBDUlNcclxuICogQGNycyBMLkNSUy5FUFNHNDMyNlxyXG4gKlxyXG4gKiBBIGNvbW1vbiBDUlMgYW1vbmcgR0lTIGVudGh1c2lhc3RzLiBVc2VzIHNpbXBsZSBFcXVpcmVjdGFuZ3VsYXIgcHJvamVjdGlvbi5cclxuICpcclxuICogTGVhZmxldCAxLjAueCBjb21wbGllcyB3aXRoIHRoZSBbVE1TIGNvb3JkaW5hdGUgc2NoZW1lIGZvciBFUFNHOjQzMjZdKGh0dHBzOi8vd2lraS5vc2dlby5vcmcvd2lraS9UaWxlX01hcF9TZXJ2aWNlX1NwZWNpZmljYXRpb24jZ2xvYmFsLWdlb2RldGljKSxcclxuICogd2hpY2ggaXMgYSBicmVha2luZyBjaGFuZ2UgZnJvbSAwLjcueCBiZWhhdmlvdXIuICBJZiB5b3UgYXJlIHVzaW5nIGEgYFRpbGVMYXllcmBcclxuICogd2l0aCB0aGlzIENSUywgZW5zdXJlIHRoYXQgdGhlcmUgYXJlIHR3byAyNTZ4MjU2IHBpeGVsIHRpbGVzIGNvdmVyaW5nIHRoZVxyXG4gKiB3aG9sZSBlYXJ0aCBhdCB6b29tIGxldmVsIHplcm8sIGFuZCB0aGF0IHRoZSB0aWxlIGNvb3JkaW5hdGUgb3JpZ2luIGlzICgtMTgwLCs5MCksXHJcbiAqIG9yICgtMTgwLC05MCkgZm9yIGBUaWxlTGF5ZXJgcyB3aXRoIFt0aGUgYHRtc2Agb3B0aW9uXSgjdGlsZWxheWVyLXRtcykgc2V0LlxyXG4gKi9cclxuXHJcbnZhciBFUFNHNDMyNiA9IGV4dGVuZCh7fSwgRWFydGgsIHtcclxuXHRjb2RlOiAnRVBTRzo0MzI2JyxcclxuXHRwcm9qZWN0aW9uOiBMb25MYXQsXHJcblx0dHJhbnNmb3JtYXRpb246IHRvVHJhbnNmb3JtYXRpb24oMSAvIDE4MCwgMSwgLTEgLyAxODAsIDAuNSlcclxufSk7XG5cbi8qXG4gKiBAbmFtZXNwYWNlIENSU1xuICogQGNycyBMLkNSUy5TaW1wbGVcbiAqXG4gKiBBIHNpbXBsZSBDUlMgdGhhdCBtYXBzIGxvbmdpdHVkZSBhbmQgbGF0aXR1ZGUgaW50byBgeGAgYW5kIGB5YCBkaXJlY3RseS5cbiAqIE1heSBiZSB1c2VkIGZvciBtYXBzIG9mIGZsYXQgc3VyZmFjZXMgKGUuZy4gZ2FtZSBtYXBzKS4gTm90ZSB0aGF0IHRoZSBgeWBcbiAqIGF4aXMgc2hvdWxkIHN0aWxsIGJlIGludmVydGVkIChnb2luZyBmcm9tIGJvdHRvbSB0byB0b3ApLiBgZGlzdGFuY2UoKWAgcmV0dXJuc1xuICogc2ltcGxlIGV1Y2xpZGVhbiBkaXN0YW5jZS5cbiAqL1xuXG52YXIgU2ltcGxlID0gZXh0ZW5kKHt9LCBDUlMsIHtcblx0cHJvamVjdGlvbjogTG9uTGF0LFxuXHR0cmFuc2Zvcm1hdGlvbjogdG9UcmFuc2Zvcm1hdGlvbigxLCAwLCAtMSwgMCksXG5cblx0c2NhbGU6IGZ1bmN0aW9uICh6b29tKSB7XG5cdFx0cmV0dXJuIE1hdGgucG93KDIsIHpvb20pO1xuXHR9LFxuXG5cdHpvb206IGZ1bmN0aW9uIChzY2FsZSkge1xuXHRcdHJldHVybiBNYXRoLmxvZyhzY2FsZSkgLyBNYXRoLkxOMjtcblx0fSxcblxuXHRkaXN0YW5jZTogZnVuY3Rpb24gKGxhdGxuZzEsIGxhdGxuZzIpIHtcblx0XHR2YXIgZHggPSBsYXRsbmcyLmxuZyAtIGxhdGxuZzEubG5nLFxuXHRcdCAgICBkeSA9IGxhdGxuZzIubGF0IC0gbGF0bG5nMS5sYXQ7XG5cblx0XHRyZXR1cm4gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcblx0fSxcblxuXHRpbmZpbml0ZTogdHJ1ZVxufSk7XG5cbkNSUy5FYXJ0aCA9IEVhcnRoO1xuQ1JTLkVQU0czMzk1ID0gRVBTRzMzOTU7XG5DUlMuRVBTRzM4NTcgPSBFUFNHMzg1NztcbkNSUy5FUFNHOTAwOTEzID0gRVBTRzkwMDkxMztcbkNSUy5FUFNHNDMyNiA9IEVQU0c0MzI2O1xuQ1JTLlNpbXBsZSA9IFNpbXBsZTtcblxuLypcbiAqIEBjbGFzcyBMYXllclxuICogQGluaGVyaXRzIEV2ZW50ZWRcbiAqIEBha2EgTC5MYXllclxuICogQGFrYSBJTGF5ZXJcbiAqXG4gKiBBIHNldCBvZiBtZXRob2RzIGZyb20gdGhlIExheWVyIGJhc2UgY2xhc3MgdGhhdCBhbGwgTGVhZmxldCBsYXllcnMgdXNlLlxuICogSW5oZXJpdHMgYWxsIG1ldGhvZHMsIG9wdGlvbnMgYW5kIGV2ZW50cyBmcm9tIGBMLkV2ZW50ZWRgLlxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBganNcbiAqIHZhciBsYXllciA9IEwuTWFya2VyKGxhdGxuZykuYWRkVG8obWFwKTtcbiAqIGxheWVyLmFkZFRvKG1hcCk7XG4gKiBsYXllci5yZW1vdmUoKTtcbiAqIGBgYFxuICpcbiAqIEBldmVudCBhZGQ6IEV2ZW50XG4gKiBGaXJlZCBhZnRlciB0aGUgbGF5ZXIgaXMgYWRkZWQgdG8gYSBtYXBcbiAqXG4gKiBAZXZlbnQgcmVtb3ZlOiBFdmVudFxuICogRmlyZWQgYWZ0ZXIgdGhlIGxheWVyIGlzIHJlbW92ZWQgZnJvbSBhIG1hcFxuICovXG5cblxudmFyIExheWVyID0gRXZlbnRlZC5leHRlbmQoe1xuXG5cdC8vIENsYXNzZXMgZXh0ZW5kaW5nIGBMLkxheWVyYCB3aWxsIGluaGVyaXQgdGhlIGZvbGxvd2luZyBvcHRpb25zOlxuXHRvcHRpb25zOiB7XG5cdFx0Ly8gQG9wdGlvbiBwYW5lOiBTdHJpbmcgPSAnb3ZlcmxheVBhbmUnXG5cdFx0Ly8gQnkgZGVmYXVsdCB0aGUgbGF5ZXIgd2lsbCBiZSBhZGRlZCB0byB0aGUgbWFwJ3MgW292ZXJsYXkgcGFuZV0oI21hcC1vdmVybGF5cGFuZSkuIE92ZXJyaWRpbmcgdGhpcyBvcHRpb24gd2lsbCBjYXVzZSB0aGUgbGF5ZXIgdG8gYmUgcGxhY2VkIG9uIGFub3RoZXIgcGFuZSBieSBkZWZhdWx0LlxuXHRcdHBhbmU6ICdvdmVybGF5UGFuZScsXG5cblx0XHQvLyBAb3B0aW9uIGF0dHJpYnV0aW9uOiBTdHJpbmcgPSBudWxsXG5cdFx0Ly8gU3RyaW5nIHRvIGJlIHNob3duIGluIHRoZSBhdHRyaWJ1dGlvbiBjb250cm9sLCBkZXNjcmliZXMgdGhlIGxheWVyIGRhdGEsIGUuZy4gXCLCqSBNYXBib3hcIi5cblx0XHRhdHRyaWJ1dGlvbjogbnVsbCxcblxuXHRcdGJ1YmJsaW5nTW91c2VFdmVudHM6IHRydWVcblx0fSxcblxuXHQvKiBAc2VjdGlvblxuXHQgKiBDbGFzc2VzIGV4dGVuZGluZyBgTC5MYXllcmAgd2lsbCBpbmhlcml0IHRoZSBmb2xsb3dpbmcgbWV0aG9kczpcblx0ICpcblx0ICogQG1ldGhvZCBhZGRUbyhtYXA6IE1hcHxMYXllckdyb3VwKTogdGhpc1xuXHQgKiBBZGRzIHRoZSBsYXllciB0byB0aGUgZ2l2ZW4gbWFwIG9yIGxheWVyIGdyb3VwLlxuXHQgKi9cblx0YWRkVG86IGZ1bmN0aW9uIChtYXApIHtcblx0XHRtYXAuYWRkTGF5ZXIodGhpcyk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCByZW1vdmU6IHRoaXNcblx0Ly8gUmVtb3ZlcyB0aGUgbGF5ZXIgZnJvbSB0aGUgbWFwIGl0IGlzIGN1cnJlbnRseSBhY3RpdmUgb24uXG5cdHJlbW92ZTogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLnJlbW92ZUZyb20odGhpcy5fbWFwIHx8IHRoaXMuX21hcFRvQWRkKTtcblx0fSxcblxuXHQvLyBAbWV0aG9kIHJlbW92ZUZyb20obWFwOiBNYXApOiB0aGlzXG5cdC8vIFJlbW92ZXMgdGhlIGxheWVyIGZyb20gdGhlIGdpdmVuIG1hcFxuXHRyZW1vdmVGcm9tOiBmdW5jdGlvbiAob2JqKSB7XG5cdFx0aWYgKG9iaikge1xuXHRcdFx0b2JqLnJlbW92ZUxheWVyKHRoaXMpO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGdldFBhbmUobmFtZT8gOiBTdHJpbmcpOiBIVE1MRWxlbWVudFxuXHQvLyBSZXR1cm5zIHRoZSBgSFRNTEVsZW1lbnRgIHJlcHJlc2VudGluZyB0aGUgbmFtZWQgcGFuZSBvbiB0aGUgbWFwLiBJZiBgbmFtZWAgaXMgb21pdHRlZCwgcmV0dXJucyB0aGUgcGFuZSBmb3IgdGhpcyBsYXllci5cblx0Z2V0UGFuZTogZnVuY3Rpb24gKG5hbWUpIHtcblx0XHRyZXR1cm4gdGhpcy5fbWFwLmdldFBhbmUobmFtZSA/ICh0aGlzLm9wdGlvbnNbbmFtZV0gfHwgbmFtZSkgOiB0aGlzLm9wdGlvbnMucGFuZSk7XG5cdH0sXG5cblx0YWRkSW50ZXJhY3RpdmVUYXJnZXQ6IGZ1bmN0aW9uICh0YXJnZXRFbCkge1xuXHRcdHRoaXMuX21hcC5fdGFyZ2V0c1tzdGFtcCh0YXJnZXRFbCldID0gdGhpcztcblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRyZW1vdmVJbnRlcmFjdGl2ZVRhcmdldDogZnVuY3Rpb24gKHRhcmdldEVsKSB7XG5cdFx0ZGVsZXRlIHRoaXMuX21hcC5fdGFyZ2V0c1tzdGFtcCh0YXJnZXRFbCldO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgZ2V0QXR0cmlidXRpb246IFN0cmluZ1xuXHQvLyBVc2VkIGJ5IHRoZSBgYXR0cmlidXRpb24gY29udHJvbGAsIHJldHVybnMgdGhlIFthdHRyaWJ1dGlvbiBvcHRpb25dKCNncmlkbGF5ZXItYXR0cmlidXRpb24pLlxuXHRnZXRBdHRyaWJ1dGlvbjogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLm9wdGlvbnMuYXR0cmlidXRpb247XG5cdH0sXG5cblx0X2xheWVyQWRkOiBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBtYXAgPSBlLnRhcmdldDtcblxuXHRcdC8vIGNoZWNrIGluIGNhc2UgbGF5ZXIgZ2V0cyBhZGRlZCBhbmQgdGhlbiByZW1vdmVkIGJlZm9yZSB0aGUgbWFwIGlzIHJlYWR5XG5cdFx0aWYgKCFtYXAuaGFzTGF5ZXIodGhpcykpIHsgcmV0dXJuOyB9XG5cblx0XHR0aGlzLl9tYXAgPSBtYXA7XG5cdFx0dGhpcy5fem9vbUFuaW1hdGVkID0gbWFwLl96b29tQW5pbWF0ZWQ7XG5cblx0XHRpZiAodGhpcy5nZXRFdmVudHMpIHtcblx0XHRcdHZhciBldmVudHMgPSB0aGlzLmdldEV2ZW50cygpO1xuXHRcdFx0bWFwLm9uKGV2ZW50cywgdGhpcyk7XG5cdFx0XHR0aGlzLm9uY2UoJ3JlbW92ZScsIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0bWFwLm9mZihldmVudHMsIHRoaXMpO1xuXHRcdFx0fSwgdGhpcyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5vbkFkZChtYXApO1xuXG5cdFx0aWYgKHRoaXMuZ2V0QXR0cmlidXRpb24gJiYgbWFwLmF0dHJpYnV0aW9uQ29udHJvbCkge1xuXHRcdFx0bWFwLmF0dHJpYnV0aW9uQ29udHJvbC5hZGRBdHRyaWJ1dGlvbih0aGlzLmdldEF0dHJpYnV0aW9uKCkpO1xuXHRcdH1cblxuXHRcdHRoaXMuZmlyZSgnYWRkJyk7XG5cdFx0bWFwLmZpcmUoJ2xheWVyYWRkJywge2xheWVyOiB0aGlzfSk7XG5cdH1cbn0pO1xuXG4vKiBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xuICogQHVuaW5oZXJpdGFibGVcbiAqXG4gKiBFdmVyeSBsYXllciBzaG91bGQgZXh0ZW5kIGZyb20gYEwuTGF5ZXJgIGFuZCAocmUtKWltcGxlbWVudCB0aGUgZm9sbG93aW5nIG1ldGhvZHMuXG4gKlxuICogQG1ldGhvZCBvbkFkZChtYXA6IE1hcCk6IHRoaXNcbiAqIFNob3VsZCBjb250YWluIGNvZGUgdGhhdCBjcmVhdGVzIERPTSBlbGVtZW50cyBmb3IgdGhlIGxheWVyLCBhZGRzIHRoZW0gdG8gYG1hcCBwYW5lc2Agd2hlcmUgdGhleSBzaG91bGQgYmVsb25nIGFuZCBwdXRzIGxpc3RlbmVycyBvbiByZWxldmFudCBtYXAgZXZlbnRzLiBDYWxsZWQgb24gW2BtYXAuYWRkTGF5ZXIobGF5ZXIpYF0oI21hcC1hZGRsYXllcikuXG4gKlxuICogQG1ldGhvZCBvblJlbW92ZShtYXA6IE1hcCk6IHRoaXNcbiAqIFNob3VsZCBjb250YWluIGFsbCBjbGVhbiB1cCBjb2RlIHRoYXQgcmVtb3ZlcyB0aGUgbGF5ZXIncyBlbGVtZW50cyBmcm9tIHRoZSBET00gYW5kIHJlbW92ZXMgbGlzdGVuZXJzIHByZXZpb3VzbHkgYWRkZWQgaW4gW2BvbkFkZGBdKCNsYXllci1vbmFkZCkuIENhbGxlZCBvbiBbYG1hcC5yZW1vdmVMYXllcihsYXllcilgXSgjbWFwLXJlbW92ZWxheWVyKS5cbiAqXG4gKiBAbWV0aG9kIGdldEV2ZW50cygpOiBPYmplY3RcbiAqIFRoaXMgb3B0aW9uYWwgbWV0aG9kIHNob3VsZCByZXR1cm4gYW4gb2JqZWN0IGxpa2UgYHsgdmlld3Jlc2V0OiB0aGlzLl9yZXNldCB9YCBmb3IgW2BhZGRFdmVudExpc3RlbmVyYF0oI2V2ZW50ZWQtYWRkZXZlbnRsaXN0ZW5lcikuIFRoZSBldmVudCBoYW5kbGVycyBpbiB0aGlzIG9iamVjdCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgYWRkZWQgYW5kIHJlbW92ZWQgZnJvbSB0aGUgbWFwIHdpdGggeW91ciBsYXllci5cbiAqXG4gKiBAbWV0aG9kIGdldEF0dHJpYnV0aW9uKCk6IFN0cmluZ1xuICogVGhpcyBvcHRpb25hbCBtZXRob2Qgc2hvdWxkIHJldHVybiBhIHN0cmluZyBjb250YWluaW5nIEhUTUwgdG8gYmUgc2hvd24gb24gdGhlIGBBdHRyaWJ1dGlvbiBjb250cm9sYCB3aGVuZXZlciB0aGUgbGF5ZXIgaXMgdmlzaWJsZS5cbiAqXG4gKiBAbWV0aG9kIGJlZm9yZUFkZChtYXA6IE1hcCk6IHRoaXNcbiAqIE9wdGlvbmFsIG1ldGhvZC4gQ2FsbGVkIG9uIFtgbWFwLmFkZExheWVyKGxheWVyKWBdKCNtYXAtYWRkbGF5ZXIpLCBiZWZvcmUgdGhlIGxheWVyIGlzIGFkZGVkIHRvIHRoZSBtYXAsIGJlZm9yZSBldmVudHMgYXJlIGluaXRpYWxpemVkLCB3aXRob3V0IHdhaXRpbmcgdW50aWwgdGhlIG1hcCBpcyBpbiBhIHVzYWJsZSBzdGF0ZS4gVXNlIGZvciBlYXJseSBpbml0aWFsaXphdGlvbiBvbmx5LlxuICovXG5cblxuLyogQG5hbWVzcGFjZSBNYXBcbiAqIEBzZWN0aW9uIExheWVyIGV2ZW50c1xuICpcbiAqIEBldmVudCBsYXllcmFkZDogTGF5ZXJFdmVudFxuICogRmlyZWQgd2hlbiBhIG5ldyBsYXllciBpcyBhZGRlZCB0byB0aGUgbWFwLlxuICpcbiAqIEBldmVudCBsYXllcnJlbW92ZTogTGF5ZXJFdmVudFxuICogRmlyZWQgd2hlbiBzb21lIGxheWVyIGlzIHJlbW92ZWQgZnJvbSB0aGUgbWFwXG4gKlxuICogQHNlY3Rpb24gTWV0aG9kcyBmb3IgTGF5ZXJzIGFuZCBDb250cm9sc1xuICovXG5NYXAuaW5jbHVkZSh7XG5cdC8vIEBtZXRob2QgYWRkTGF5ZXIobGF5ZXI6IExheWVyKTogdGhpc1xuXHQvLyBBZGRzIHRoZSBnaXZlbiBsYXllciB0byB0aGUgbWFwXG5cdGFkZExheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHRpZiAoIWxheWVyLl9sYXllckFkZCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdUaGUgcHJvdmlkZWQgb2JqZWN0IGlzIG5vdCBhIExheWVyLicpO1xuXHRcdH1cblxuXHRcdHZhciBpZCA9IHN0YW1wKGxheWVyKTtcblx0XHRpZiAodGhpcy5fbGF5ZXJzW2lkXSkgeyByZXR1cm4gdGhpczsgfVxuXHRcdHRoaXMuX2xheWVyc1tpZF0gPSBsYXllcjtcblxuXHRcdGxheWVyLl9tYXBUb0FkZCA9IHRoaXM7XG5cblx0XHRpZiAobGF5ZXIuYmVmb3JlQWRkKSB7XG5cdFx0XHRsYXllci5iZWZvcmVBZGQodGhpcyk7XG5cdFx0fVxuXG5cdFx0dGhpcy53aGVuUmVhZHkobGF5ZXIuX2xheWVyQWRkLCBsYXllcik7XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIHJlbW92ZUxheWVyKGxheWVyOiBMYXllcik6IHRoaXNcblx0Ly8gUmVtb3ZlcyB0aGUgZ2l2ZW4gbGF5ZXIgZnJvbSB0aGUgbWFwLlxuXHRyZW1vdmVMYXllcjogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dmFyIGlkID0gc3RhbXAobGF5ZXIpO1xuXG5cdFx0aWYgKCF0aGlzLl9sYXllcnNbaWRdKSB7IHJldHVybiB0aGlzOyB9XG5cblx0XHRpZiAodGhpcy5fbG9hZGVkKSB7XG5cdFx0XHRsYXllci5vblJlbW92ZSh0aGlzKTtcblx0XHR9XG5cblx0XHRpZiAobGF5ZXIuZ2V0QXR0cmlidXRpb24gJiYgdGhpcy5hdHRyaWJ1dGlvbkNvbnRyb2wpIHtcblx0XHRcdHRoaXMuYXR0cmlidXRpb25Db250cm9sLnJlbW92ZUF0dHJpYnV0aW9uKGxheWVyLmdldEF0dHJpYnV0aW9uKCkpO1xuXHRcdH1cblxuXHRcdGRlbGV0ZSB0aGlzLl9sYXllcnNbaWRdO1xuXG5cdFx0aWYgKHRoaXMuX2xvYWRlZCkge1xuXHRcdFx0dGhpcy5maXJlKCdsYXllcnJlbW92ZScsIHtsYXllcjogbGF5ZXJ9KTtcblx0XHRcdGxheWVyLmZpcmUoJ3JlbW92ZScpO1xuXHRcdH1cblxuXHRcdGxheWVyLl9tYXAgPSBsYXllci5fbWFwVG9BZGQgPSBudWxsO1xuXG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBoYXNMYXllcihsYXllcjogTGF5ZXIpOiBCb29sZWFuXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiBsYXllciBpcyBjdXJyZW50bHkgYWRkZWQgdG8gdGhlIG1hcFxuXHRoYXNMYXllcjogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0cmV0dXJuICEhbGF5ZXIgJiYgKHN0YW1wKGxheWVyKSBpbiB0aGlzLl9sYXllcnMpO1xuXHR9LFxuXG5cdC8qIEBtZXRob2QgZWFjaExheWVyKGZuOiBGdW5jdGlvbiwgY29udGV4dD86IE9iamVjdCk6IHRoaXNcblx0ICogSXRlcmF0ZXMgb3ZlciB0aGUgbGF5ZXJzIG9mIHRoZSBtYXAsIG9wdGlvbmFsbHkgc3BlY2lmeWluZyBjb250ZXh0IG9mIHRoZSBpdGVyYXRvciBmdW5jdGlvbi5cblx0ICogYGBgXG5cdCAqIG1hcC5lYWNoTGF5ZXIoZnVuY3Rpb24obGF5ZXIpe1xuXHQgKiAgICAgbGF5ZXIuYmluZFBvcHVwKCdIZWxsbycpO1xuXHQgKiB9KTtcblx0ICogYGBgXG5cdCAqL1xuXHRlYWNoTGF5ZXI6IGZ1bmN0aW9uIChtZXRob2QsIGNvbnRleHQpIHtcblx0XHRmb3IgKHZhciBpIGluIHRoaXMuX2xheWVycykge1xuXHRcdFx0bWV0aG9kLmNhbGwoY29udGV4dCwgdGhpcy5fbGF5ZXJzW2ldKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0X2FkZExheWVyczogZnVuY3Rpb24gKGxheWVycykge1xuXHRcdGxheWVycyA9IGxheWVycyA/IChpc0FycmF5KGxheWVycykgPyBsYXllcnMgOiBbbGF5ZXJzXSkgOiBbXTtcblxuXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsYXllcnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdHRoaXMuYWRkTGF5ZXIobGF5ZXJzW2ldKTtcblx0XHR9XG5cdH0sXG5cblx0X2FkZFpvb21MaW1pdDogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0aWYgKGlzTmFOKGxheWVyLm9wdGlvbnMubWF4Wm9vbSkgfHwgIWlzTmFOKGxheWVyLm9wdGlvbnMubWluWm9vbSkpIHtcblx0XHRcdHRoaXMuX3pvb21Cb3VuZExheWVyc1tzdGFtcChsYXllcildID0gbGF5ZXI7XG5cdFx0XHR0aGlzLl91cGRhdGVab29tTGV2ZWxzKCk7XG5cdFx0fVxuXHR9LFxuXG5cdF9yZW1vdmVab29tTGltaXQ6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHZhciBpZCA9IHN0YW1wKGxheWVyKTtcblxuXHRcdGlmICh0aGlzLl96b29tQm91bmRMYXllcnNbaWRdKSB7XG5cdFx0XHRkZWxldGUgdGhpcy5fem9vbUJvdW5kTGF5ZXJzW2lkXTtcblx0XHRcdHRoaXMuX3VwZGF0ZVpvb21MZXZlbHMoKTtcblx0XHR9XG5cdH0sXG5cblx0X3VwZGF0ZVpvb21MZXZlbHM6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbWluWm9vbSA9IEluZmluaXR5LFxuXHRcdCAgICBtYXhab29tID0gLUluZmluaXR5LFxuXHRcdCAgICBvbGRab29tU3BhbiA9IHRoaXMuX2dldFpvb21TcGFuKCk7XG5cblx0XHRmb3IgKHZhciBpIGluIHRoaXMuX3pvb21Cb3VuZExheWVycykge1xuXHRcdFx0dmFyIG9wdGlvbnMgPSB0aGlzLl96b29tQm91bmRMYXllcnNbaV0ub3B0aW9ucztcblxuXHRcdFx0bWluWm9vbSA9IG9wdGlvbnMubWluWm9vbSA9PT0gdW5kZWZpbmVkID8gbWluWm9vbSA6IE1hdGgubWluKG1pblpvb20sIG9wdGlvbnMubWluWm9vbSk7XG5cdFx0XHRtYXhab29tID0gb3B0aW9ucy5tYXhab29tID09PSB1bmRlZmluZWQgPyBtYXhab29tIDogTWF0aC5tYXgobWF4Wm9vbSwgb3B0aW9ucy5tYXhab29tKTtcblx0XHR9XG5cblx0XHR0aGlzLl9sYXllcnNNYXhab29tID0gbWF4Wm9vbSA9PT0gLUluZmluaXR5ID8gdW5kZWZpbmVkIDogbWF4Wm9vbTtcblx0XHR0aGlzLl9sYXllcnNNaW5ab29tID0gbWluWm9vbSA9PT0gSW5maW5pdHkgPyB1bmRlZmluZWQgOiBtaW5ab29tO1xuXG5cdFx0Ly8gQHNlY3Rpb24gTWFwIHN0YXRlIGNoYW5nZSBldmVudHNcblx0XHQvLyBAZXZlbnQgem9vbWxldmVsc2NoYW5nZTogRXZlbnRcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSBudW1iZXIgb2Ygem9vbWxldmVscyBvbiB0aGUgbWFwIGlzIGNoYW5nZWQgZHVlXG5cdFx0Ly8gdG8gYWRkaW5nIG9yIHJlbW92aW5nIGEgbGF5ZXIuXG5cdFx0aWYgKG9sZFpvb21TcGFuICE9PSB0aGlzLl9nZXRab29tU3BhbigpKSB7XG5cdFx0XHR0aGlzLmZpcmUoJ3pvb21sZXZlbHNjaGFuZ2UnKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5vcHRpb25zLm1heFpvb20gPT09IHVuZGVmaW5lZCAmJiB0aGlzLl9sYXllcnNNYXhab29tICYmIHRoaXMuZ2V0Wm9vbSgpID4gdGhpcy5fbGF5ZXJzTWF4Wm9vbSkge1xuXHRcdFx0dGhpcy5zZXRab29tKHRoaXMuX2xheWVyc01heFpvb20pO1xuXHRcdH1cblx0XHRpZiAodGhpcy5vcHRpb25zLm1pblpvb20gPT09IHVuZGVmaW5lZCAmJiB0aGlzLl9sYXllcnNNaW5ab29tICYmIHRoaXMuZ2V0Wm9vbSgpIDwgdGhpcy5fbGF5ZXJzTWluWm9vbSkge1xuXHRcdFx0dGhpcy5zZXRab29tKHRoaXMuX2xheWVyc01pblpvb20pO1xuXHRcdH1cblx0fVxufSk7XG5cbi8qXHJcbiAqIEBjbGFzcyBMYXllckdyb3VwXHJcbiAqIEBha2EgTC5MYXllckdyb3VwXHJcbiAqIEBpbmhlcml0cyBMYXllclxyXG4gKlxyXG4gKiBVc2VkIHRvIGdyb3VwIHNldmVyYWwgbGF5ZXJzIGFuZCBoYW5kbGUgdGhlbSBhcyBvbmUuIElmIHlvdSBhZGQgaXQgdG8gdGhlIG1hcCxcclxuICogYW55IGxheWVycyBhZGRlZCBvciByZW1vdmVkIGZyb20gdGhlIGdyb3VwIHdpbGwgYmUgYWRkZWQvcmVtb3ZlZCBvbiB0aGUgbWFwIGFzXHJcbiAqIHdlbGwuIEV4dGVuZHMgYExheWVyYC5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogTC5sYXllckdyb3VwKFttYXJrZXIxLCBtYXJrZXIyXSlcclxuICogXHQuYWRkTGF5ZXIocG9seWxpbmUpXHJcbiAqIFx0LmFkZFRvKG1hcCk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBMYXllckdyb3VwID0gTGF5ZXIuZXh0ZW5kKHtcclxuXHJcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxheWVycywgb3B0aW9ucykge1xyXG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcblx0XHR0aGlzLl9sYXllcnMgPSB7fTtcclxuXHJcblx0XHR2YXIgaSwgbGVuO1xyXG5cclxuXHRcdGlmIChsYXllcnMpIHtcclxuXHRcdFx0Zm9yIChpID0gMCwgbGVuID0gbGF5ZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0dGhpcy5hZGRMYXllcihsYXllcnNbaV0pO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBhZGRMYXllcihsYXllcjogTGF5ZXIpOiB0aGlzXHJcblx0Ly8gQWRkcyB0aGUgZ2l2ZW4gbGF5ZXIgdG8gdGhlIGdyb3VwLlxyXG5cdGFkZExheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHRcdHZhciBpZCA9IHRoaXMuZ2V0TGF5ZXJJZChsYXllcik7XHJcblxyXG5cdFx0dGhpcy5fbGF5ZXJzW2lkXSA9IGxheWVyO1xyXG5cclxuXHRcdGlmICh0aGlzLl9tYXApIHtcclxuXHRcdFx0dGhpcy5fbWFwLmFkZExheWVyKGxheWVyKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHJlbW92ZUxheWVyKGxheWVyOiBMYXllcik6IHRoaXNcclxuXHQvLyBSZW1vdmVzIHRoZSBnaXZlbiBsYXllciBmcm9tIHRoZSBncm91cC5cclxuXHQvLyBAYWx0ZXJuYXRpdmVcclxuXHQvLyBAbWV0aG9kIHJlbW92ZUxheWVyKGlkOiBOdW1iZXIpOiB0aGlzXHJcblx0Ly8gUmVtb3ZlcyB0aGUgbGF5ZXIgd2l0aCB0aGUgZ2l2ZW4gaW50ZXJuYWwgSUQgZnJvbSB0aGUgZ3JvdXAuXHJcblx0cmVtb3ZlTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xyXG5cdFx0dmFyIGlkID0gbGF5ZXIgaW4gdGhpcy5fbGF5ZXJzID8gbGF5ZXIgOiB0aGlzLmdldExheWVySWQobGF5ZXIpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9tYXAgJiYgdGhpcy5fbGF5ZXJzW2lkXSkge1xyXG5cdFx0XHR0aGlzLl9tYXAucmVtb3ZlTGF5ZXIodGhpcy5fbGF5ZXJzW2lkXSk7XHJcblx0XHR9XHJcblxyXG5cdFx0ZGVsZXRlIHRoaXMuX2xheWVyc1tpZF07XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBoYXNMYXllcihsYXllcjogTGF5ZXIpOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGdpdmVuIGxheWVyIGlzIGN1cnJlbnRseSBhZGRlZCB0byB0aGUgZ3JvdXAuXHJcblx0Ly8gQGFsdGVybmF0aXZlXHJcblx0Ly8gQG1ldGhvZCBoYXNMYXllcihpZDogTnVtYmVyKTogQm9vbGVhblxyXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIHRoZSBnaXZlbiBpbnRlcm5hbCBJRCBpcyBjdXJyZW50bHkgYWRkZWQgdG8gdGhlIGdyb3VwLlxyXG5cdGhhc0xheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHRcdHJldHVybiAhIWxheWVyICYmIChsYXllciBpbiB0aGlzLl9sYXllcnMgfHwgdGhpcy5nZXRMYXllcklkKGxheWVyKSBpbiB0aGlzLl9sYXllcnMpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY2xlYXJMYXllcnMoKTogdGhpc1xyXG5cdC8vIFJlbW92ZXMgYWxsIHRoZSBsYXllcnMgZnJvbSB0aGUgZ3JvdXAuXHJcblx0Y2xlYXJMYXllcnM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLmVhY2hMYXllcih0aGlzLnJlbW92ZUxheWVyLCB0aGlzKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGludm9rZShtZXRob2ROYW1lOiBTdHJpbmcsIOKApik6IHRoaXNcclxuXHQvLyBDYWxscyBgbWV0aG9kTmFtZWAgb24gZXZlcnkgbGF5ZXIgY29udGFpbmVkIGluIHRoaXMgZ3JvdXAsIHBhc3NpbmcgYW55XHJcblx0Ly8gYWRkaXRpb25hbCBwYXJhbWV0ZXJzLiBIYXMgbm8gZWZmZWN0IGlmIHRoZSBsYXllcnMgY29udGFpbmVkIGRvIG5vdFxyXG5cdC8vIGltcGxlbWVudCBgbWV0aG9kTmFtZWAuXHJcblx0aW52b2tlOiBmdW5jdGlvbiAobWV0aG9kTmFtZSkge1xyXG5cdFx0dmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxyXG5cdFx0ICAgIGksIGxheWVyO1xyXG5cclxuXHRcdGZvciAoaSBpbiB0aGlzLl9sYXllcnMpIHtcclxuXHRcdFx0bGF5ZXIgPSB0aGlzLl9sYXllcnNbaV07XHJcblxyXG5cdFx0XHRpZiAobGF5ZXJbbWV0aG9kTmFtZV0pIHtcclxuXHRcdFx0XHRsYXllclttZXRob2ROYW1lXS5hcHBseShsYXllciwgYXJncyk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0dGhpcy5lYWNoTGF5ZXIobWFwLmFkZExheWVyLCBtYXApO1xyXG5cdH0sXHJcblxyXG5cdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XHJcblx0XHR0aGlzLmVhY2hMYXllcihtYXAucmVtb3ZlTGF5ZXIsIG1hcCk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBlYWNoTGF5ZXIoZm46IEZ1bmN0aW9uLCBjb250ZXh0PzogT2JqZWN0KTogdGhpc1xyXG5cdC8vIEl0ZXJhdGVzIG92ZXIgdGhlIGxheWVycyBvZiB0aGUgZ3JvdXAsIG9wdGlvbmFsbHkgc3BlY2lmeWluZyBjb250ZXh0IG9mIHRoZSBpdGVyYXRvciBmdW5jdGlvbi5cclxuXHQvLyBgYGBqc1xyXG5cdC8vIGdyb3VwLmVhY2hMYXllcihmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHQvLyBcdGxheWVyLmJpbmRQb3B1cCgnSGVsbG8nKTtcclxuXHQvLyB9KTtcclxuXHQvLyBgYGBcclxuXHRlYWNoTGF5ZXI6IGZ1bmN0aW9uIChtZXRob2QsIGNvbnRleHQpIHtcclxuXHRcdGZvciAodmFyIGkgaW4gdGhpcy5fbGF5ZXJzKSB7XHJcblx0XHRcdG1ldGhvZC5jYWxsKGNvbnRleHQsIHRoaXMuX2xheWVyc1tpXSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldExheWVyKGlkOiBOdW1iZXIpOiBMYXllclxyXG5cdC8vIFJldHVybnMgdGhlIGxheWVyIHdpdGggdGhlIGdpdmVuIGludGVybmFsIElELlxyXG5cdGdldExheWVyOiBmdW5jdGlvbiAoaWQpIHtcclxuXHRcdHJldHVybiB0aGlzLl9sYXllcnNbaWRdO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0TGF5ZXJzKCk6IExheWVyW11cclxuXHQvLyBSZXR1cm5zIGFuIGFycmF5IG9mIGFsbCB0aGUgbGF5ZXJzIGFkZGVkIHRvIHRoZSBncm91cC5cclxuXHRnZXRMYXllcnM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBsYXllcnMgPSBbXTtcclxuXHRcdHRoaXMuZWFjaExheWVyKGxheWVycy5wdXNoLCBsYXllcnMpO1xyXG5cdFx0cmV0dXJuIGxheWVycztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNldFpJbmRleCh6SW5kZXg6IE51bWJlcik6IHRoaXNcclxuXHQvLyBDYWxscyBgc2V0WkluZGV4YCBvbiBldmVyeSBsYXllciBjb250YWluZWQgaW4gdGhpcyBncm91cCwgcGFzc2luZyB0aGUgei1pbmRleC5cclxuXHRzZXRaSW5kZXg6IGZ1bmN0aW9uICh6SW5kZXgpIHtcclxuXHRcdHJldHVybiB0aGlzLmludm9rZSgnc2V0WkluZGV4JywgekluZGV4KTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldExheWVySWQobGF5ZXI6IExheWVyKTogTnVtYmVyXHJcblx0Ly8gUmV0dXJucyB0aGUgaW50ZXJuYWwgSUQgZm9yIGEgbGF5ZXJcclxuXHRnZXRMYXllcklkOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHRcdHJldHVybiBzdGFtcChsYXllcik7XHJcblx0fVxyXG59KTtcclxuXHJcblxyXG4vLyBAZmFjdG9yeSBMLmxheWVyR3JvdXAobGF5ZXJzPzogTGF5ZXJbXSwgb3B0aW9ucz86IE9iamVjdClcclxuLy8gQ3JlYXRlIGEgbGF5ZXIgZ3JvdXAsIG9wdGlvbmFsbHkgZ2l2ZW4gYW4gaW5pdGlhbCBzZXQgb2YgbGF5ZXJzIGFuZCBhbiBgb3B0aW9uc2Agb2JqZWN0LlxyXG52YXIgbGF5ZXJHcm91cCA9IGZ1bmN0aW9uIChsYXllcnMsIG9wdGlvbnMpIHtcclxuXHRyZXR1cm4gbmV3IExheWVyR3JvdXAobGF5ZXJzLCBvcHRpb25zKTtcclxufTtcblxuLypcclxuICogQGNsYXNzIEZlYXR1cmVHcm91cFxyXG4gKiBAYWthIEwuRmVhdHVyZUdyb3VwXHJcbiAqIEBpbmhlcml0cyBMYXllckdyb3VwXHJcbiAqXHJcbiAqIEV4dGVuZGVkIGBMYXllckdyb3VwYCB0aGF0IG1ha2VzIGl0IGVhc2llciB0byBkbyB0aGUgc2FtZSB0aGluZyB0byBhbGwgaXRzIG1lbWJlciBsYXllcnM6XHJcbiAqICAqIFtgYmluZFBvcHVwYF0oI2xheWVyLWJpbmRwb3B1cCkgYmluZHMgYSBwb3B1cCB0byBhbGwgb2YgdGhlIGxheWVycyBhdCBvbmNlIChsaWtld2lzZSB3aXRoIFtgYmluZFRvb2x0aXBgXSgjbGF5ZXItYmluZHRvb2x0aXApKVxyXG4gKiAgKiBFdmVudHMgYXJlIHByb3BhZ2F0ZWQgdG8gdGhlIGBGZWF0dXJlR3JvdXBgLCBzbyBpZiB0aGUgZ3JvdXAgaGFzIGFuIGV2ZW50XHJcbiAqIGhhbmRsZXIsIGl0IHdpbGwgaGFuZGxlIGV2ZW50cyBmcm9tIGFueSBvZiB0aGUgbGF5ZXJzLiBUaGlzIGluY2x1ZGVzIG1vdXNlIGV2ZW50c1xyXG4gKiBhbmQgY3VzdG9tIGV2ZW50cy5cclxuICogICogSGFzIGBsYXllcmFkZGAgYW5kIGBsYXllcnJlbW92ZWAgZXZlbnRzXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIEwuZmVhdHVyZUdyb3VwKFttYXJrZXIxLCBtYXJrZXIyLCBwb2x5bGluZV0pXHJcbiAqIFx0LmJpbmRQb3B1cCgnSGVsbG8gd29ybGQhJylcclxuICogXHQub24oJ2NsaWNrJywgZnVuY3Rpb24oKSB7IGFsZXJ0KCdDbGlja2VkIG9uIGEgbWVtYmVyIG9mIHRoZSBncm91cCEnKTsgfSlcclxuICogXHQuYWRkVG8obWFwKTtcclxuICogYGBgXHJcbiAqL1xyXG5cclxudmFyIEZlYXR1cmVHcm91cCA9IExheWVyR3JvdXAuZXh0ZW5kKHtcclxuXHJcblx0YWRkTGF5ZXI6IGZ1bmN0aW9uIChsYXllcikge1xyXG5cdFx0aWYgKHRoaXMuaGFzTGF5ZXIobGF5ZXIpKSB7XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fVxyXG5cclxuXHRcdGxheWVyLmFkZEV2ZW50UGFyZW50KHRoaXMpO1xyXG5cclxuXHRcdExheWVyR3JvdXAucHJvdG90eXBlLmFkZExheWVyLmNhbGwodGhpcywgbGF5ZXIpO1xyXG5cclxuXHRcdC8vIEBldmVudCBsYXllcmFkZDogTGF5ZXJFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiBhIGxheWVyIGlzIGFkZGVkIHRvIHRoaXMgYEZlYXR1cmVHcm91cGBcclxuXHRcdHJldHVybiB0aGlzLmZpcmUoJ2xheWVyYWRkJywge2xheWVyOiBsYXllcn0pO1xyXG5cdH0sXHJcblxyXG5cdHJlbW92ZUxheWVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHRcdGlmICghdGhpcy5oYXNMYXllcihsYXllcikpIHtcclxuXHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHR9XHJcblx0XHRpZiAobGF5ZXIgaW4gdGhpcy5fbGF5ZXJzKSB7XHJcblx0XHRcdGxheWVyID0gdGhpcy5fbGF5ZXJzW2xheWVyXTtcclxuXHRcdH1cclxuXHJcblx0XHRsYXllci5yZW1vdmVFdmVudFBhcmVudCh0aGlzKTtcclxuXHJcblx0XHRMYXllckdyb3VwLnByb3RvdHlwZS5yZW1vdmVMYXllci5jYWxsKHRoaXMsIGxheWVyKTtcclxuXHJcblx0XHQvLyBAZXZlbnQgbGF5ZXJyZW1vdmU6IExheWVyRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gYSBsYXllciBpcyByZW1vdmVkIGZyb20gdGhpcyBgRmVhdHVyZUdyb3VwYFxyXG5cdFx0cmV0dXJuIHRoaXMuZmlyZSgnbGF5ZXJyZW1vdmUnLCB7bGF5ZXI6IGxheWVyfSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRTdHlsZShzdHlsZTogUGF0aCBvcHRpb25zKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIGdpdmVuIHBhdGggb3B0aW9ucyB0byBlYWNoIGxheWVyIG9mIHRoZSBncm91cCB0aGF0IGhhcyBhIGBzZXRTdHlsZWAgbWV0aG9kLlxyXG5cdHNldFN0eWxlOiBmdW5jdGlvbiAoc3R5bGUpIHtcclxuXHRcdHJldHVybiB0aGlzLmludm9rZSgnc2V0U3R5bGUnLCBzdHlsZSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBicmluZ1RvRnJvbnQoKTogdGhpc1xyXG5cdC8vIEJyaW5ncyB0aGUgbGF5ZXIgZ3JvdXAgdG8gdGhlIHRvcCBvZiBhbGwgb3RoZXIgbGF5ZXJzXHJcblx0YnJpbmdUb0Zyb250OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5pbnZva2UoJ2JyaW5nVG9Gcm9udCcpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgYnJpbmdUb0JhY2soKTogdGhpc1xyXG5cdC8vIEJyaW5ncyB0aGUgbGF5ZXIgZ3JvdXAgdG8gdGhlIGJhY2sgb2YgYWxsIG90aGVyIGxheWVyc1xyXG5cdGJyaW5nVG9CYWNrOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5pbnZva2UoJ2JyaW5nVG9CYWNrJyk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRCb3VuZHMoKTogTGF0TG5nQm91bmRzXHJcblx0Ly8gUmV0dXJucyB0aGUgTGF0TG5nQm91bmRzIG9mIHRoZSBGZWF0dXJlIEdyb3VwIChjcmVhdGVkIGZyb20gYm91bmRzIGFuZCBjb29yZGluYXRlcyBvZiBpdHMgY2hpbGRyZW4pLlxyXG5cdGdldEJvdW5kczogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGJvdW5kcyA9IG5ldyBMYXRMbmdCb3VuZHMoKTtcclxuXHJcblx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9sYXllcnMpIHtcclxuXHRcdFx0dmFyIGxheWVyID0gdGhpcy5fbGF5ZXJzW2lkXTtcclxuXHRcdFx0Ym91bmRzLmV4dGVuZChsYXllci5nZXRCb3VuZHMgPyBsYXllci5nZXRCb3VuZHMoKSA6IGxheWVyLmdldExhdExuZygpKTtcclxuXHRcdH1cclxuXHRcdHJldHVybiBib3VuZHM7XHJcblx0fVxyXG59KTtcclxuXHJcbi8vIEBmYWN0b3J5IEwuZmVhdHVyZUdyb3VwKGxheWVyczogTGF5ZXJbXSlcclxuLy8gQ3JlYXRlIGEgZmVhdHVyZSBncm91cCwgb3B0aW9uYWxseSBnaXZlbiBhbiBpbml0aWFsIHNldCBvZiBsYXllcnMuXHJcbnZhciBmZWF0dXJlR3JvdXAgPSBmdW5jdGlvbiAobGF5ZXJzKSB7XHJcblx0cmV0dXJuIG5ldyBGZWF0dXJlR3JvdXAobGF5ZXJzKTtcclxufTtcblxuLypcclxuICogQGNsYXNzIEljb25cclxuICogQGFrYSBMLkljb25cclxuICpcclxuICogUmVwcmVzZW50cyBhbiBpY29uIHRvIHByb3ZpZGUgd2hlbiBjcmVhdGluZyBhIG1hcmtlci5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogdmFyIG15SWNvbiA9IEwuaWNvbih7XHJcbiAqICAgICBpY29uVXJsOiAnbXktaWNvbi5wbmcnLFxyXG4gKiAgICAgaWNvblJldGluYVVybDogJ215LWljb25AMngucG5nJyxcclxuICogICAgIGljb25TaXplOiBbMzgsIDk1XSxcclxuICogICAgIGljb25BbmNob3I6IFsyMiwgOTRdLFxyXG4gKiAgICAgcG9wdXBBbmNob3I6IFstMywgLTc2XSxcclxuICogICAgIHNoYWRvd1VybDogJ215LWljb24tc2hhZG93LnBuZycsXHJcbiAqICAgICBzaGFkb3dSZXRpbmFVcmw6ICdteS1pY29uLXNoYWRvd0AyeC5wbmcnLFxyXG4gKiAgICAgc2hhZG93U2l6ZTogWzY4LCA5NV0sXHJcbiAqICAgICBzaGFkb3dBbmNob3I6IFsyMiwgOTRdXHJcbiAqIH0pO1xyXG4gKlxyXG4gKiBMLm1hcmtlcihbNTAuNTA1LCAzMC41N10sIHtpY29uOiBteUljb259KS5hZGRUbyhtYXApO1xyXG4gKiBgYGBcclxuICpcclxuICogYEwuSWNvbi5EZWZhdWx0YCBleHRlbmRzIGBMLkljb25gIGFuZCBpcyB0aGUgYmx1ZSBpY29uIExlYWZsZXQgdXNlcyBmb3IgbWFya2VycyBieSBkZWZhdWx0LlxyXG4gKlxyXG4gKi9cclxuXHJcbnZhciBJY29uID0gQ2xhc3MuZXh0ZW5kKHtcclxuXHJcblx0LyogQHNlY3Rpb25cclxuXHQgKiBAYWthIEljb24gb3B0aW9uc1xyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBpY29uVXJsOiBTdHJpbmcgPSBudWxsXHJcblx0ICogKioocmVxdWlyZWQpKiogVGhlIFVSTCB0byB0aGUgaWNvbiBpbWFnZSAoYWJzb2x1dGUgb3IgcmVsYXRpdmUgdG8geW91ciBzY3JpcHQgcGF0aCkuXHJcblx0ICpcclxuXHQgKiBAb3B0aW9uIGljb25SZXRpbmFVcmw6IFN0cmluZyA9IG51bGxcclxuXHQgKiBUaGUgVVJMIHRvIGEgcmV0aW5hIHNpemVkIHZlcnNpb24gb2YgdGhlIGljb24gaW1hZ2UgKGFic29sdXRlIG9yIHJlbGF0aXZlIHRvIHlvdXJcclxuXHQgKiBzY3JpcHQgcGF0aCkuIFVzZWQgZm9yIFJldGluYSBzY3JlZW4gZGV2aWNlcy5cclxuXHQgKlxyXG5cdCAqIEBvcHRpb24gaWNvblNpemU6IFBvaW50ID0gbnVsbFxyXG5cdCAqIFNpemUgb2YgdGhlIGljb24gaW1hZ2UgaW4gcGl4ZWxzLlxyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBpY29uQW5jaG9yOiBQb2ludCA9IG51bGxcclxuXHQgKiBUaGUgY29vcmRpbmF0ZXMgb2YgdGhlIFwidGlwXCIgb2YgdGhlIGljb24gKHJlbGF0aXZlIHRvIGl0cyB0b3AgbGVmdCBjb3JuZXIpLiBUaGUgaWNvblxyXG5cdCAqIHdpbGwgYmUgYWxpZ25lZCBzbyB0aGF0IHRoaXMgcG9pbnQgaXMgYXQgdGhlIG1hcmtlcidzIGdlb2dyYXBoaWNhbCBsb2NhdGlvbi4gQ2VudGVyZWRcclxuXHQgKiBieSBkZWZhdWx0IGlmIHNpemUgaXMgc3BlY2lmaWVkLCBhbHNvIGNhbiBiZSBzZXQgaW4gQ1NTIHdpdGggbmVnYXRpdmUgbWFyZ2lucy5cclxuXHQgKlxyXG5cdCAqIEBvcHRpb24gcG9wdXBBbmNob3I6IFBvaW50ID0gWzAsIDBdXHJcblx0ICogVGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBwb2ludCBmcm9tIHdoaWNoIHBvcHVwcyB3aWxsIFwib3BlblwiLCByZWxhdGl2ZSB0byB0aGUgaWNvbiBhbmNob3IuXHJcblx0ICpcclxuXHQgKiBAb3B0aW9uIHRvb2x0aXBBbmNob3I6IFBvaW50ID0gWzAsIDBdXHJcblx0ICogVGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBwb2ludCBmcm9tIHdoaWNoIHRvb2x0aXBzIHdpbGwgXCJvcGVuXCIsIHJlbGF0aXZlIHRvIHRoZSBpY29uIGFuY2hvci5cclxuXHQgKlxyXG5cdCAqIEBvcHRpb24gc2hhZG93VXJsOiBTdHJpbmcgPSBudWxsXHJcblx0ICogVGhlIFVSTCB0byB0aGUgaWNvbiBzaGFkb3cgaW1hZ2UuIElmIG5vdCBzcGVjaWZpZWQsIG5vIHNoYWRvdyBpbWFnZSB3aWxsIGJlIGNyZWF0ZWQuXHJcblx0ICpcclxuXHQgKiBAb3B0aW9uIHNoYWRvd1JldGluYVVybDogU3RyaW5nID0gbnVsbFxyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBzaGFkb3dTaXplOiBQb2ludCA9IG51bGxcclxuXHQgKiBTaXplIG9mIHRoZSBzaGFkb3cgaW1hZ2UgaW4gcGl4ZWxzLlxyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBzaGFkb3dBbmNob3I6IFBvaW50ID0gbnVsbFxyXG5cdCAqIFRoZSBjb29yZGluYXRlcyBvZiB0aGUgXCJ0aXBcIiBvZiB0aGUgc2hhZG93IChyZWxhdGl2ZSB0byBpdHMgdG9wIGxlZnQgY29ybmVyKSAodGhlIHNhbWVcclxuXHQgKiBhcyBpY29uQW5jaG9yIGlmIG5vdCBzcGVjaWZpZWQpLlxyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9ICcnXHJcblx0ICogQSBjdXN0b20gY2xhc3MgbmFtZSB0byBhc3NpZ24gdG8gYm90aCBpY29uIGFuZCBzaGFkb3cgaW1hZ2VzLiBFbXB0eSBieSBkZWZhdWx0LlxyXG5cdCAqL1xyXG5cclxuXHRvcHRpb25zOiB7XHJcblx0XHRwb3B1cEFuY2hvcjogWzAsIDBdLFxyXG5cdFx0dG9vbHRpcEFuY2hvcjogWzAsIDBdLFxyXG5cdH0sXHJcblxyXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XHJcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY3JlYXRlSWNvbihvbGRJY29uPzogSFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudFxyXG5cdC8vIENhbGxlZCBpbnRlcm5hbGx5IHdoZW4gdGhlIGljb24gaGFzIHRvIGJlIHNob3duLCByZXR1cm5zIGEgYDxpbWc+YCBIVE1MIGVsZW1lbnRcclxuXHQvLyBzdHlsZWQgYWNjb3JkaW5nIHRvIHRoZSBvcHRpb25zLlxyXG5cdGNyZWF0ZUljb246IGZ1bmN0aW9uIChvbGRJY29uKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fY3JlYXRlSWNvbignaWNvbicsIG9sZEljb24pO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY3JlYXRlU2hhZG93KG9sZEljb24/OiBIVE1MRWxlbWVudCk6IEhUTUxFbGVtZW50XHJcblx0Ly8gQXMgYGNyZWF0ZUljb25gLCBidXQgZm9yIHRoZSBzaGFkb3cgYmVuZWF0aCBpdC5cclxuXHRjcmVhdGVTaGFkb3c6IGZ1bmN0aW9uIChvbGRJY29uKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fY3JlYXRlSWNvbignc2hhZG93Jywgb2xkSWNvbik7XHJcblx0fSxcclxuXHJcblx0X2NyZWF0ZUljb246IGZ1bmN0aW9uIChuYW1lLCBvbGRJY29uKSB7XHJcblx0XHR2YXIgc3JjID0gdGhpcy5fZ2V0SWNvblVybChuYW1lKTtcclxuXHJcblx0XHRpZiAoIXNyYykge1xyXG5cdFx0XHRpZiAobmFtZSA9PT0gJ2ljb24nKSB7XHJcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCdpY29uVXJsIG5vdCBzZXQgaW4gSWNvbiBvcHRpb25zIChzZWUgdGhlIGRvY3MpLicpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiBudWxsO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBpbWcgPSB0aGlzLl9jcmVhdGVJbWcoc3JjLCBvbGRJY29uICYmIG9sZEljb24udGFnTmFtZSA9PT0gJ0lNRycgPyBvbGRJY29uIDogbnVsbCk7XHJcblx0XHR0aGlzLl9zZXRJY29uU3R5bGVzKGltZywgbmFtZSk7XHJcblxyXG5cdFx0cmV0dXJuIGltZztcclxuXHR9LFxyXG5cclxuXHRfc2V0SWNvblN0eWxlczogZnVuY3Rpb24gKGltZywgbmFtZSkge1xyXG5cdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XHJcblx0XHR2YXIgc2l6ZU9wdGlvbiA9IG9wdGlvbnNbbmFtZSArICdTaXplJ107XHJcblxyXG5cdFx0aWYgKHR5cGVvZiBzaXplT3B0aW9uID09PSAnbnVtYmVyJykge1xyXG5cdFx0XHRzaXplT3B0aW9uID0gW3NpemVPcHRpb24sIHNpemVPcHRpb25dO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBzaXplID0gdG9Qb2ludChzaXplT3B0aW9uKSxcclxuXHRcdCAgICBhbmNob3IgPSB0b1BvaW50KG5hbWUgPT09ICdzaGFkb3cnICYmIG9wdGlvbnMuc2hhZG93QW5jaG9yIHx8IG9wdGlvbnMuaWNvbkFuY2hvciB8fFxyXG5cdFx0ICAgICAgICAgICAgc2l6ZSAmJiBzaXplLmRpdmlkZUJ5KDIsIHRydWUpKTtcclxuXHJcblx0XHRpbWcuY2xhc3NOYW1lID0gJ2xlYWZsZXQtbWFya2VyLScgKyBuYW1lICsgJyAnICsgKG9wdGlvbnMuY2xhc3NOYW1lIHx8ICcnKTtcclxuXHJcblx0XHRpZiAoYW5jaG9yKSB7XHJcblx0XHRcdGltZy5zdHlsZS5tYXJnaW5MZWZ0ID0gKC1hbmNob3IueCkgKyAncHgnO1xyXG5cdFx0XHRpbWcuc3R5bGUubWFyZ2luVG9wICA9ICgtYW5jaG9yLnkpICsgJ3B4JztcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoc2l6ZSkge1xyXG5cdFx0XHRpbWcuc3R5bGUud2lkdGggID0gc2l6ZS54ICsgJ3B4JztcclxuXHRcdFx0aW1nLnN0eWxlLmhlaWdodCA9IHNpemUueSArICdweCc7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X2NyZWF0ZUltZzogZnVuY3Rpb24gKHNyYywgZWwpIHtcclxuXHRcdGVsID0gZWwgfHwgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyk7XHJcblx0XHRlbC5zcmMgPSBzcmM7XHJcblx0XHRyZXR1cm4gZWw7XHJcblx0fSxcclxuXHJcblx0X2dldEljb25Vcmw6IGZ1bmN0aW9uIChuYW1lKSB7XHJcblx0XHRyZXR1cm4gcmV0aW5hICYmIHRoaXMub3B0aW9uc1tuYW1lICsgJ1JldGluYVVybCddIHx8IHRoaXMub3B0aW9uc1tuYW1lICsgJ1VybCddO1xyXG5cdH1cclxufSk7XHJcblxyXG5cclxuLy8gQGZhY3RvcnkgTC5pY29uKG9wdGlvbnM6IEljb24gb3B0aW9ucylcclxuLy8gQ3JlYXRlcyBhbiBpY29uIGluc3RhbmNlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXHJcbmZ1bmN0aW9uIGljb24ob3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgSWNvbihvcHRpb25zKTtcclxufVxuXG4vKlxuICogQG1pbmljbGFzcyBJY29uLkRlZmF1bHQgKEljb24pXG4gKiBAYWthIEwuSWNvbi5EZWZhdWx0XG4gKiBAc2VjdGlvblxuICpcbiAqIEEgdHJpdmlhbCBzdWJjbGFzcyBvZiBgSWNvbmAsIHJlcHJlc2VudHMgdGhlIGljb24gdG8gdXNlIGluIGBNYXJrZXJgcyB3aGVuXG4gKiBubyBpY29uIGlzIHNwZWNpZmllZC4gUG9pbnRzIHRvIHRoZSBibHVlIG1hcmtlciBpbWFnZSBkaXN0cmlidXRlZCB3aXRoIExlYWZsZXRcbiAqIHJlbGVhc2VzLlxuICpcbiAqIEluIG9yZGVyIHRvIGN1c3RvbWl6ZSB0aGUgZGVmYXVsdCBpY29uLCBqdXN0IGNoYW5nZSB0aGUgcHJvcGVydGllcyBvZiBgTC5JY29uLkRlZmF1bHQucHJvdG90eXBlLm9wdGlvbnNgXG4gKiAod2hpY2ggaXMgYSBzZXQgb2YgYEljb24gb3B0aW9uc2ApLlxuICpcbiAqIElmIHlvdSB3YW50IHRvIF9jb21wbGV0ZWx5XyByZXBsYWNlIHRoZSBkZWZhdWx0IGljb24sIG92ZXJyaWRlIHRoZVxuICogYEwuTWFya2VyLnByb3RvdHlwZS5vcHRpb25zLmljb25gIHdpdGggeW91ciBvd24gaWNvbiBpbnN0ZWFkLlxuICovXG5cbnZhciBJY29uRGVmYXVsdCA9IEljb24uZXh0ZW5kKHtcblxuXHRvcHRpb25zOiB7XG5cdFx0aWNvblVybDogICAgICAgJ21hcmtlci1pY29uLnBuZycsXG5cdFx0aWNvblJldGluYVVybDogJ21hcmtlci1pY29uLTJ4LnBuZycsXG5cdFx0c2hhZG93VXJsOiAgICAgJ21hcmtlci1zaGFkb3cucG5nJyxcblx0XHRpY29uU2l6ZTogICAgWzI1LCA0MV0sXG5cdFx0aWNvbkFuY2hvcjogIFsxMiwgNDFdLFxuXHRcdHBvcHVwQW5jaG9yOiBbMSwgLTM0XSxcblx0XHR0b29sdGlwQW5jaG9yOiBbMTYsIC0yOF0sXG5cdFx0c2hhZG93U2l6ZTogIFs0MSwgNDFdXG5cdH0sXG5cblx0X2dldEljb25Vcmw6IGZ1bmN0aW9uIChuYW1lKSB7XG5cdFx0aWYgKCFJY29uRGVmYXVsdC5pbWFnZVBhdGgpIHtcdC8vIERlcHJlY2F0ZWQsIGJhY2t3YXJkcy1jb21wYXRpYmlsaXR5IG9ubHlcblx0XHRcdEljb25EZWZhdWx0LmltYWdlUGF0aCA9IHRoaXMuX2RldGVjdEljb25QYXRoKCk7XG5cdFx0fVxuXG5cdFx0Ly8gQG9wdGlvbiBpbWFnZVBhdGg6IFN0cmluZ1xuXHRcdC8vIGBJY29uLkRlZmF1bHRgIHdpbGwgdHJ5IHRvIGF1dG8tZGV0ZWN0IHRoZSBsb2NhdGlvbiBvZiB0aGVcblx0XHQvLyBibHVlIGljb24gaW1hZ2VzLiBJZiB5b3UgYXJlIHBsYWNpbmcgdGhlc2UgaW1hZ2VzIGluIGEgbm9uLXN0YW5kYXJkXG5cdFx0Ly8gd2F5LCBzZXQgdGhpcyBvcHRpb24gdG8gcG9pbnQgdG8gdGhlIHJpZ2h0IHBhdGguXG5cdFx0cmV0dXJuICh0aGlzLm9wdGlvbnMuaW1hZ2VQYXRoIHx8IEljb25EZWZhdWx0LmltYWdlUGF0aCkgKyBJY29uLnByb3RvdHlwZS5fZ2V0SWNvblVybC5jYWxsKHRoaXMsIG5hbWUpO1xuXHR9LFxuXG5cdF9kZXRlY3RJY29uUGF0aDogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBlbCA9IGNyZWF0ZSQxKCdkaXYnLCAgJ2xlYWZsZXQtZGVmYXVsdC1pY29uLXBhdGgnLCBkb2N1bWVudC5ib2R5KTtcblx0XHR2YXIgcGF0aCA9IGdldFN0eWxlKGVsLCAnYmFja2dyb3VuZC1pbWFnZScpIHx8XG5cdFx0ICAgICAgICAgICBnZXRTdHlsZShlbCwgJ2JhY2tncm91bmRJbWFnZScpO1x0Ly8gSUU4XG5cblx0XHRkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGVsKTtcblxuXHRcdGlmIChwYXRoID09PSBudWxsIHx8IHBhdGguaW5kZXhPZigndXJsJykgIT09IDApIHtcblx0XHRcdHBhdGggPSAnJztcblx0XHR9IGVsc2Uge1xuXHRcdFx0cGF0aCA9IHBhdGgucmVwbGFjZSgvXnVybFxcKFtcIiddPy8sICcnKS5yZXBsYWNlKC9tYXJrZXItaWNvblxcLnBuZ1tcIiddP1xcKSQvLCAnJyk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHBhdGg7XG5cdH1cbn0pO1xuXG4vKlxuICogTC5IYW5kbGVyLk1hcmtlckRyYWcgaXMgdXNlZCBpbnRlcm5hbGx5IGJ5IEwuTWFya2VyIHRvIG1ha2UgdGhlIG1hcmtlcnMgZHJhZ2dhYmxlLlxuICovXG5cblxuLyogQG5hbWVzcGFjZSBNYXJrZXJcbiAqIEBzZWN0aW9uIEludGVyYWN0aW9uIGhhbmRsZXJzXG4gKlxuICogSW50ZXJhY3Rpb24gaGFuZGxlcnMgYXJlIHByb3BlcnRpZXMgb2YgYSBtYXJrZXIgaW5zdGFuY2UgdGhhdCBhbGxvdyB5b3UgdG8gY29udHJvbCBpbnRlcmFjdGlvbiBiZWhhdmlvciBpbiBydW50aW1lLCBlbmFibGluZyBvciBkaXNhYmxpbmcgY2VydGFpbiBmZWF0dXJlcyBzdWNoIGFzIGRyYWdnaW5nIChzZWUgYEhhbmRsZXJgIG1ldGhvZHMpLiBFeGFtcGxlOlxuICpcbiAqIGBgYGpzXG4gKiBtYXJrZXIuZHJhZ2dpbmcuZGlzYWJsZSgpO1xuICogYGBgXG4gKlxuICogQHByb3BlcnR5IGRyYWdnaW5nOiBIYW5kbGVyXG4gKiBNYXJrZXIgZHJhZ2dpbmcgaGFuZGxlciAoYnkgYm90aCBtb3VzZSBhbmQgdG91Y2gpLiBPbmx5IHZhbGlkIHdoZW4gdGhlIG1hcmtlciBpcyBvbiB0aGUgbWFwIChPdGhlcndpc2Ugc2V0IFtgbWFya2VyLm9wdGlvbnMuZHJhZ2dhYmxlYF0oI21hcmtlci1kcmFnZ2FibGUpKS5cbiAqL1xuXG52YXIgTWFya2VyRHJhZyA9IEhhbmRsZXIuZXh0ZW5kKHtcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG1hcmtlcikge1xuXHRcdHRoaXMuX21hcmtlciA9IG1hcmtlcjtcblx0fSxcblxuXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBpY29uID0gdGhpcy5fbWFya2VyLl9pY29uO1xuXG5cdFx0aWYgKCF0aGlzLl9kcmFnZ2FibGUpIHtcblx0XHRcdHRoaXMuX2RyYWdnYWJsZSA9IG5ldyBEcmFnZ2FibGUoaWNvbiwgaWNvbiwgdHJ1ZSk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fZHJhZ2dhYmxlLm9uKHtcblx0XHRcdGRyYWdzdGFydDogdGhpcy5fb25EcmFnU3RhcnQsXG5cdFx0XHRwcmVkcmFnOiB0aGlzLl9vblByZURyYWcsXG5cdFx0XHRkcmFnOiB0aGlzLl9vbkRyYWcsXG5cdFx0XHRkcmFnZW5kOiB0aGlzLl9vbkRyYWdFbmRcblx0XHR9LCB0aGlzKS5lbmFibGUoKTtcblxuXHRcdGFkZENsYXNzKGljb24sICdsZWFmbGV0LW1hcmtlci1kcmFnZ2FibGUnKTtcblx0fSxcblxuXHRyZW1vdmVIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX2RyYWdnYWJsZS5vZmYoe1xuXHRcdFx0ZHJhZ3N0YXJ0OiB0aGlzLl9vbkRyYWdTdGFydCxcblx0XHRcdHByZWRyYWc6IHRoaXMuX29uUHJlRHJhZyxcblx0XHRcdGRyYWc6IHRoaXMuX29uRHJhZyxcblx0XHRcdGRyYWdlbmQ6IHRoaXMuX29uRHJhZ0VuZFxuXHRcdH0sIHRoaXMpLmRpc2FibGUoKTtcblxuXHRcdGlmICh0aGlzLl9tYXJrZXIuX2ljb24pIHtcblx0XHRcdHJlbW92ZUNsYXNzKHRoaXMuX21hcmtlci5faWNvbiwgJ2xlYWZsZXQtbWFya2VyLWRyYWdnYWJsZScpO1xuXHRcdH1cblx0fSxcblxuXHRtb3ZlZDogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLl9kcmFnZ2FibGUgJiYgdGhpcy5fZHJhZ2dhYmxlLl9tb3ZlZDtcblx0fSxcblxuXHRfYWRqdXN0UGFuOiBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBtYXJrZXIgPSB0aGlzLl9tYXJrZXIsXG5cdFx0ICAgIG1hcCA9IG1hcmtlci5fbWFwLFxuXHRcdCAgICBzcGVlZCA9IHRoaXMuX21hcmtlci5vcHRpb25zLmF1dG9QYW5TcGVlZCxcblx0XHQgICAgcGFkZGluZyA9IHRoaXMuX21hcmtlci5vcHRpb25zLmF1dG9QYW5QYWRkaW5nLFxuXHRcdCAgICBpY29uUG9zID0gTC5Eb21VdGlsLmdldFBvc2l0aW9uKG1hcmtlci5faWNvbiksXG5cdFx0ICAgIGJvdW5kcyA9IG1hcC5nZXRQaXhlbEJvdW5kcygpLFxuXHRcdCAgICBvcmlnaW4gPSBtYXAuZ2V0UGl4ZWxPcmlnaW4oKTtcblxuXHRcdHZhciBwYW5Cb3VuZHMgPSB0b0JvdW5kcyhcblx0XHRcdGJvdW5kcy5taW4uX3N1YnRyYWN0KG9yaWdpbikuYWRkKHBhZGRpbmcpLFxuXHRcdFx0Ym91bmRzLm1heC5fc3VidHJhY3Qob3JpZ2luKS5zdWJ0cmFjdChwYWRkaW5nKVxuXHRcdCk7XG5cblx0XHRpZiAoIXBhbkJvdW5kcy5jb250YWlucyhpY29uUG9zKSkge1xuXHRcdFx0Ly8gQ29tcHV0ZSBpbmNyZW1lbnRhbCBtb3ZlbWVudFxuXHRcdFx0dmFyIG1vdmVtZW50ID0gdG9Qb2ludChcblx0XHRcdFx0KE1hdGgubWF4KHBhbkJvdW5kcy5tYXgueCwgaWNvblBvcy54KSAtIHBhbkJvdW5kcy5tYXgueCkgLyAoYm91bmRzLm1heC54IC0gcGFuQm91bmRzLm1heC54KSAtXG5cdFx0XHRcdChNYXRoLm1pbihwYW5Cb3VuZHMubWluLngsIGljb25Qb3MueCkgLSBwYW5Cb3VuZHMubWluLngpIC8gKGJvdW5kcy5taW4ueCAtIHBhbkJvdW5kcy5taW4ueCksXG5cblx0XHRcdFx0KE1hdGgubWF4KHBhbkJvdW5kcy5tYXgueSwgaWNvblBvcy55KSAtIHBhbkJvdW5kcy5tYXgueSkgLyAoYm91bmRzLm1heC55IC0gcGFuQm91bmRzLm1heC55KSAtXG5cdFx0XHRcdChNYXRoLm1pbihwYW5Cb3VuZHMubWluLnksIGljb25Qb3MueSkgLSBwYW5Cb3VuZHMubWluLnkpIC8gKGJvdW5kcy5taW4ueSAtIHBhbkJvdW5kcy5taW4ueSlcblx0XHRcdCkubXVsdGlwbHlCeShzcGVlZCk7XG5cblx0XHRcdG1hcC5wYW5CeShtb3ZlbWVudCwge2FuaW1hdGU6IGZhbHNlfSk7XG5cblx0XHRcdHRoaXMuX2RyYWdnYWJsZS5fbmV3UG9zLl9hZGQobW92ZW1lbnQpO1xuXHRcdFx0dGhpcy5fZHJhZ2dhYmxlLl9zdGFydFBvcy5fYWRkKG1vdmVtZW50KTtcblxuXHRcdFx0TC5Eb21VdGlsLnNldFBvc2l0aW9uKG1hcmtlci5faWNvbiwgdGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3MpO1xuXHRcdFx0dGhpcy5fb25EcmFnKGUpO1xuXG5cdFx0XHR0aGlzLl9wYW5SZXF1ZXN0ID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl9hZGp1c3RQYW4uYmluZCh0aGlzLCBlKSk7XG5cdFx0fVxuXHR9LFxuXG5cdF9vbkRyYWdTdGFydDogZnVuY3Rpb24gKCkge1xuXHRcdC8vIEBzZWN0aW9uIERyYWdnaW5nIGV2ZW50c1xuXHRcdC8vIEBldmVudCBkcmFnc3RhcnQ6IEV2ZW50XG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdXNlciBzdGFydHMgZHJhZ2dpbmcgdGhlIG1hcmtlci5cblxuXHRcdC8vIEBldmVudCBtb3Zlc3RhcnQ6IEV2ZW50XG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFya2VyIHN0YXJ0cyBtb3ZpbmcgKGJlY2F1c2Ugb2YgZHJhZ2dpbmcpLlxuXG5cdFx0dGhpcy5fb2xkTGF0TG5nID0gdGhpcy5fbWFya2VyLmdldExhdExuZygpO1xuXHRcdHRoaXMuX21hcmtlclxuXHRcdCAgICAuY2xvc2VQb3B1cCgpXG5cdFx0ICAgIC5maXJlKCdtb3Zlc3RhcnQnKVxuXHRcdCAgICAuZmlyZSgnZHJhZ3N0YXJ0Jyk7XG5cdH0sXG5cblx0X29uUHJlRHJhZzogZnVuY3Rpb24gKGUpIHtcblx0XHRpZiAodGhpcy5fbWFya2VyLm9wdGlvbnMuYXV0b1Bhbikge1xuXHRcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX3BhblJlcXVlc3QpO1xuXHRcdFx0dGhpcy5fcGFuUmVxdWVzdCA9IHJlcXVlc3RBbmltRnJhbWUodGhpcy5fYWRqdXN0UGFuLmJpbmQodGhpcywgZSkpO1xuXHRcdH1cblx0fSxcblxuXHRfb25EcmFnOiBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBtYXJrZXIgPSB0aGlzLl9tYXJrZXIsXG5cdFx0ICAgIHNoYWRvdyA9IG1hcmtlci5fc2hhZG93LFxuXHRcdGljb25Qb3MgPSBnZXRQb3NpdGlvbihtYXJrZXIuX2ljb24pLFxuXHRcdCAgICBsYXRsbmcgPSBtYXJrZXIuX21hcC5sYXllclBvaW50VG9MYXRMbmcoaWNvblBvcyk7XG5cblx0XHQvLyB1cGRhdGUgc2hhZG93IHBvc2l0aW9uXG5cdFx0aWYgKHNoYWRvdykge1xuXHRcdFx0c2V0UG9zaXRpb24oc2hhZG93LCBpY29uUG9zKTtcblx0XHR9XG5cblx0XHRtYXJrZXIuX2xhdGxuZyA9IGxhdGxuZztcblx0XHRlLmxhdGxuZyA9IGxhdGxuZztcblx0XHRlLm9sZExhdExuZyA9IHRoaXMuX29sZExhdExuZztcblxuXHRcdC8vIEBldmVudCBkcmFnOiBFdmVudFxuXHRcdC8vIEZpcmVkIHJlcGVhdGVkbHkgd2hpbGUgdGhlIHVzZXIgZHJhZ3MgdGhlIG1hcmtlci5cblx0XHRtYXJrZXJcblx0XHQgICAgLmZpcmUoJ21vdmUnLCBlKVxuXHRcdCAgICAuZmlyZSgnZHJhZycsIGUpO1xuXHR9LFxuXG5cdF9vbkRyYWdFbmQ6IGZ1bmN0aW9uIChlKSB7XG5cdFx0Ly8gQGV2ZW50IGRyYWdlbmQ6IERyYWdFbmRFdmVudFxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIHVzZXIgc3RvcHMgZHJhZ2dpbmcgdGhlIG1hcmtlci5cblxuXHRcdCBjYW5jZWxBbmltRnJhbWUodGhpcy5fcGFuUmVxdWVzdCk7XG5cblx0XHQvLyBAZXZlbnQgbW92ZWVuZDogRXZlbnRcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSBtYXJrZXIgc3RvcHMgbW92aW5nIChiZWNhdXNlIG9mIGRyYWdnaW5nKS5cblx0XHRkZWxldGUgdGhpcy5fb2xkTGF0TG5nO1xuXHRcdHRoaXMuX21hcmtlclxuXHRcdCAgICAuZmlyZSgnbW92ZWVuZCcpXG5cdFx0ICAgIC5maXJlKCdkcmFnZW5kJywgZSk7XG5cdH1cbn0pO1xuXG4vKlxyXG4gKiBAY2xhc3MgTWFya2VyXHJcbiAqIEBpbmhlcml0cyBJbnRlcmFjdGl2ZSBsYXllclxyXG4gKiBAYWthIEwuTWFya2VyXHJcbiAqIEwuTWFya2VyIGlzIHVzZWQgdG8gZGlzcGxheSBjbGlja2FibGUvZHJhZ2dhYmxlIGljb25zIG9uIHRoZSBtYXAuIEV4dGVuZHMgYExheWVyYC5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogTC5tYXJrZXIoWzUwLjUsIDMwLjVdKS5hZGRUbyhtYXApO1xyXG4gKiBgYGBcclxuICovXHJcblxyXG52YXIgTWFya2VyID0gTGF5ZXIuZXh0ZW5kKHtcclxuXHJcblx0Ly8gQHNlY3Rpb25cclxuXHQvLyBAYWthIE1hcmtlciBvcHRpb25zXHJcblx0b3B0aW9uczoge1xyXG5cdFx0Ly8gQG9wdGlvbiBpY29uOiBJY29uID0gKlxyXG5cdFx0Ly8gSWNvbiBpbnN0YW5jZSB0byB1c2UgZm9yIHJlbmRlcmluZyB0aGUgbWFya2VyLlxyXG5cdFx0Ly8gU2VlIFtJY29uIGRvY3VtZW50YXRpb25dKCNMLkljb24pIGZvciBkZXRhaWxzIG9uIGhvdyB0byBjdXN0b21pemUgdGhlIG1hcmtlciBpY29uLlxyXG5cdFx0Ly8gSWYgbm90IHNwZWNpZmllZCwgYSBjb21tb24gaW5zdGFuY2Ugb2YgYEwuSWNvbi5EZWZhdWx0YCBpcyB1c2VkLlxyXG5cdFx0aWNvbjogbmV3IEljb25EZWZhdWx0KCksXHJcblxyXG5cdFx0Ly8gT3B0aW9uIGluaGVyaXRlZCBmcm9tIFwiSW50ZXJhY3RpdmUgbGF5ZXJcIiBhYnN0cmFjdCBjbGFzc1xyXG5cdFx0aW50ZXJhY3RpdmU6IHRydWUsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBkcmFnZ2FibGU6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gV2hldGhlciB0aGUgbWFya2VyIGlzIGRyYWdnYWJsZSB3aXRoIG1vdXNlL3RvdWNoIG9yIG5vdC5cclxuXHRcdGRyYWdnYWJsZTogZmFsc2UsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBhdXRvUGFuOiBCb29sZWFuID0gZmFsc2VcclxuXHRcdC8vIFNldCBpdCB0byBgdHJ1ZWAgaWYgeW91IHdhbnQgdGhlIG1hcCB0byBkbyBwYW5uaW5nIGFuaW1hdGlvbiB3aGVuIG1hcmtlciBoaXRzIHRoZSBlZGdlcy5cclxuXHRcdGF1dG9QYW46IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gYXV0b1BhblBhZGRpbmc6IFBvaW50ID0gUG9pbnQoNTAsIDUwKVxyXG5cdFx0Ly8gRXF1aXZhbGVudCBvZiBzZXR0aW5nIGJvdGggdG9wIGxlZnQgYW5kIGJvdHRvbSByaWdodCBhdXRvcGFuIHBhZGRpbmcgdG8gdGhlIHNhbWUgdmFsdWUuXHJcblx0XHRhdXRvUGFuUGFkZGluZzogWzUwLCA1MF0sXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBhdXRvUGFuU3BlZWQ6IE51bWJlciA9IDEwXHJcblx0XHQvLyBOdW1iZXIgb2YgcGl4ZWxzIHRoZSBtYXAgc2hvdWxkIG1vdmUgYnkuXHJcblx0XHRhdXRvUGFuU3BlZWQ6IDEwLFxyXG5cclxuXHRcdC8vIEBvcHRpb24ga2V5Ym9hcmQ6IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBXaGV0aGVyIHRoZSBtYXJrZXIgY2FuIGJlIHRhYmJlZCB0byB3aXRoIGEga2V5Ym9hcmQgYW5kIGNsaWNrZWQgYnkgcHJlc3NpbmcgZW50ZXIuXHJcblx0XHRrZXlib2FyZDogdHJ1ZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHRpdGxlOiBTdHJpbmcgPSAnJ1xyXG5cdFx0Ly8gVGV4dCBmb3IgdGhlIGJyb3dzZXIgdG9vbHRpcCB0aGF0IGFwcGVhciBvbiBtYXJrZXIgaG92ZXIgKG5vIHRvb2x0aXAgYnkgZGVmYXVsdCkuXHJcblx0XHR0aXRsZTogJycsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBhbHQ6IFN0cmluZyA9ICcnXHJcblx0XHQvLyBUZXh0IGZvciB0aGUgYGFsdGAgYXR0cmlidXRlIG9mIHRoZSBpY29uIGltYWdlICh1c2VmdWwgZm9yIGFjY2Vzc2liaWxpdHkpLlxyXG5cdFx0YWx0OiAnJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHpJbmRleE9mZnNldDogTnVtYmVyID0gMFxyXG5cdFx0Ly8gQnkgZGVmYXVsdCwgbWFya2VyIGltYWdlcyB6SW5kZXggaXMgc2V0IGF1dG9tYXRpY2FsbHkgYmFzZWQgb24gaXRzIGxhdGl0dWRlLiBVc2UgdGhpcyBvcHRpb24gaWYgeW91IHdhbnQgdG8gcHV0IHRoZSBtYXJrZXIgb24gdG9wIG9mIGFsbCBvdGhlcnMgKG9yIGJlbG93KSwgc3BlY2lmeWluZyBhIGhpZ2ggdmFsdWUgbGlrZSBgMTAwMGAgKG9yIGhpZ2ggbmVnYXRpdmUgdmFsdWUsIHJlc3BlY3RpdmVseSkuXHJcblx0XHR6SW5kZXhPZmZzZXQ6IDAsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBvcGFjaXR5OiBOdW1iZXIgPSAxLjBcclxuXHRcdC8vIFRoZSBvcGFjaXR5IG9mIHRoZSBtYXJrZXIuXHJcblx0XHRvcGFjaXR5OiAxLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gcmlzZU9uSG92ZXI6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gSWYgYHRydWVgLCB0aGUgbWFya2VyIHdpbGwgZ2V0IG9uIHRvcCBvZiBvdGhlcnMgd2hlbiB5b3UgaG92ZXIgdGhlIG1vdXNlIG92ZXIgaXQuXHJcblx0XHRyaXNlT25Ib3ZlcjogZmFsc2UsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiByaXNlT2Zmc2V0OiBOdW1iZXIgPSAyNTBcclxuXHRcdC8vIFRoZSB6LWluZGV4IG9mZnNldCB1c2VkIGZvciB0aGUgYHJpc2VPbkhvdmVyYCBmZWF0dXJlLlxyXG5cdFx0cmlzZU9mZnNldDogMjUwLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gcGFuZTogU3RyaW5nID0gJ21hcmtlclBhbmUnXHJcblx0XHQvLyBgTWFwIHBhbmVgIHdoZXJlIHRoZSBtYXJrZXJzIGljb24gd2lsbCBiZSBhZGRlZC5cclxuXHRcdHBhbmU6ICdtYXJrZXJQYW5lJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGJ1YmJsaW5nTW91c2VFdmVudHM6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gV2hlbiBgdHJ1ZWAsIGEgbW91c2UgZXZlbnQgb24gdGhpcyBtYXJrZXIgd2lsbCB0cmlnZ2VyIHRoZSBzYW1lIGV2ZW50IG9uIHRoZSBtYXBcclxuXHRcdC8vICh1bmxlc3MgW2BMLkRvbUV2ZW50LnN0b3BQcm9wYWdhdGlvbmBdKCNkb21ldmVudC1zdG9wcHJvcGFnYXRpb24pIGlzIHVzZWQpLlxyXG5cdFx0YnViYmxpbmdNb3VzZUV2ZW50czogZmFsc2VcclxuXHR9LFxyXG5cclxuXHQvKiBAc2VjdGlvblxyXG5cdCAqXHJcblx0ICogSW4gYWRkaXRpb24gdG8gW3NoYXJlZCBsYXllciBtZXRob2RzXSgjTGF5ZXIpIGxpa2UgYGFkZFRvKClgIGFuZCBgcmVtb3ZlKClgIGFuZCBbcG9wdXAgbWV0aG9kc10oI1BvcHVwKSBsaWtlIGJpbmRQb3B1cCgpIHlvdSBjYW4gYWxzbyB1c2UgdGhlIGZvbGxvd2luZyBtZXRob2RzOlxyXG5cdCAqL1xyXG5cclxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAobGF0bG5nLCBvcHRpb25zKSB7XHJcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcclxuXHR9LFxyXG5cclxuXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0dGhpcy5fem9vbUFuaW1hdGVkID0gdGhpcy5fem9vbUFuaW1hdGVkICYmIG1hcC5vcHRpb25zLm1hcmtlclpvb21BbmltYXRpb247XHJcblxyXG5cdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xyXG5cdFx0XHRtYXAub24oJ3pvb21hbmltJywgdGhpcy5fYW5pbWF0ZVpvb20sIHRoaXMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2luaXRJY29uKCk7XHJcblx0XHR0aGlzLnVwZGF0ZSgpO1xyXG5cdH0sXHJcblxyXG5cdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XHJcblx0XHRpZiAodGhpcy5kcmFnZ2luZyAmJiB0aGlzLmRyYWdnaW5nLmVuYWJsZWQoKSkge1xyXG5cdFx0XHR0aGlzLm9wdGlvbnMuZHJhZ2dhYmxlID0gdHJ1ZTtcclxuXHRcdFx0dGhpcy5kcmFnZ2luZy5yZW1vdmVIb29rcygpO1xyXG5cdFx0fVxyXG5cdFx0ZGVsZXRlIHRoaXMuZHJhZ2dpbmc7XHJcblxyXG5cdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xyXG5cdFx0XHRtYXAub2ZmKCd6b29tYW5pbScsIHRoaXMuX2FuaW1hdGVab29tLCB0aGlzKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9yZW1vdmVJY29uKCk7XHJcblx0XHR0aGlzLl9yZW1vdmVTaGFkb3coKTtcclxuXHR9LFxyXG5cclxuXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB7XHJcblx0XHRcdHpvb206IHRoaXMudXBkYXRlLFxyXG5cdFx0XHR2aWV3cmVzZXQ6IHRoaXMudXBkYXRlXHJcblx0XHR9O1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0TGF0TG5nOiBMYXRMbmdcclxuXHQvLyBSZXR1cm5zIHRoZSBjdXJyZW50IGdlb2dyYXBoaWNhbCBwb3NpdGlvbiBvZiB0aGUgbWFya2VyLlxyXG5cdGdldExhdExuZzogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuX2xhdGxuZztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNldExhdExuZyhsYXRsbmc6IExhdExuZyk6IHRoaXNcclxuXHQvLyBDaGFuZ2VzIHRoZSBtYXJrZXIgcG9zaXRpb24gdG8gdGhlIGdpdmVuIHBvaW50LlxyXG5cdHNldExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xyXG5cdFx0dmFyIG9sZExhdExuZyA9IHRoaXMuX2xhdGxuZztcclxuXHRcdHRoaXMuX2xhdGxuZyA9IHRvTGF0TG5nKGxhdGxuZyk7XHJcblx0XHR0aGlzLnVwZGF0ZSgpO1xyXG5cclxuXHRcdC8vIEBldmVudCBtb3ZlOiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFya2VyIGlzIG1vdmVkIHZpYSBbYHNldExhdExuZ2BdKCNtYXJrZXItc2V0bGF0bG5nKSBvciBieSBbZHJhZ2dpbmddKCNtYXJrZXItZHJhZ2dpbmcpLiBPbGQgYW5kIG5ldyBjb29yZGluYXRlcyBhcmUgaW5jbHVkZWQgaW4gZXZlbnQgYXJndW1lbnRzIGFzIGBvbGRMYXRMbmdgLCBgbGF0bG5nYC5cclxuXHRcdHJldHVybiB0aGlzLmZpcmUoJ21vdmUnLCB7b2xkTGF0TG5nOiBvbGRMYXRMbmcsIGxhdGxuZzogdGhpcy5fbGF0bG5nfSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRaSW5kZXhPZmZzZXQob2Zmc2V0OiBOdW1iZXIpOiB0aGlzXHJcblx0Ly8gQ2hhbmdlcyB0aGUgW3pJbmRleCBvZmZzZXRdKCNtYXJrZXItemluZGV4b2Zmc2V0KSBvZiB0aGUgbWFya2VyLlxyXG5cdHNldFpJbmRleE9mZnNldDogZnVuY3Rpb24gKG9mZnNldCkge1xyXG5cdFx0dGhpcy5vcHRpb25zLnpJbmRleE9mZnNldCA9IG9mZnNldDtcclxuXHRcdHJldHVybiB0aGlzLnVwZGF0ZSgpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0SWNvbihpY29uOiBJY29uKTogdGhpc1xyXG5cdC8vIENoYW5nZXMgdGhlIG1hcmtlciBpY29uLlxyXG5cdHNldEljb246IGZ1bmN0aW9uIChpY29uKSB7XHJcblxyXG5cdFx0dGhpcy5vcHRpb25zLmljb24gPSBpY29uO1xyXG5cclxuXHRcdGlmICh0aGlzLl9tYXApIHtcclxuXHRcdFx0dGhpcy5faW5pdEljb24oKTtcclxuXHRcdFx0dGhpcy51cGRhdGUoKTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAodGhpcy5fcG9wdXApIHtcclxuXHRcdFx0dGhpcy5iaW5kUG9wdXAodGhpcy5fcG9wdXAsIHRoaXMuX3BvcHVwLm9wdGlvbnMpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdGdldEVsZW1lbnQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9pY29uO1xyXG5cdH0sXHJcblxyXG5cdHVwZGF0ZTogZnVuY3Rpb24gKCkge1xyXG5cclxuXHRcdGlmICh0aGlzLl9pY29uICYmIHRoaXMuX21hcCkge1xyXG5cdFx0XHR2YXIgcG9zID0gdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcpLnJvdW5kKCk7XHJcblx0XHRcdHRoaXMuX3NldFBvcyhwb3MpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdF9pbml0SWNvbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXHJcblx0XHQgICAgY2xhc3NUb0FkZCA9ICdsZWFmbGV0LXpvb20tJyArICh0aGlzLl96b29tQW5pbWF0ZWQgPyAnYW5pbWF0ZWQnIDogJ2hpZGUnKTtcclxuXHJcblx0XHR2YXIgaWNvbiA9IG9wdGlvbnMuaWNvbi5jcmVhdGVJY29uKHRoaXMuX2ljb24pLFxyXG5cdFx0ICAgIGFkZEljb24gPSBmYWxzZTtcclxuXHJcblx0XHQvLyBpZiB3ZSdyZSBub3QgcmV1c2luZyB0aGUgaWNvbiwgcmVtb3ZlIHRoZSBvbGQgb25lIGFuZCBpbml0IG5ldyBvbmVcclxuXHRcdGlmIChpY29uICE9PSB0aGlzLl9pY29uKSB7XHJcblx0XHRcdGlmICh0aGlzLl9pY29uKSB7XHJcblx0XHRcdFx0dGhpcy5fcmVtb3ZlSWNvbigpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGFkZEljb24gPSB0cnVlO1xyXG5cclxuXHRcdFx0aWYgKG9wdGlvbnMudGl0bGUpIHtcclxuXHRcdFx0XHRpY29uLnRpdGxlID0gb3B0aW9ucy50aXRsZTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKGljb24udGFnTmFtZSA9PT0gJ0lNRycpIHtcclxuXHRcdFx0XHRpY29uLmFsdCA9IG9wdGlvbnMuYWx0IHx8ICcnO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0YWRkQ2xhc3MoaWNvbiwgY2xhc3NUb0FkZCk7XHJcblxyXG5cdFx0aWYgKG9wdGlvbnMua2V5Ym9hcmQpIHtcclxuXHRcdFx0aWNvbi50YWJJbmRleCA9ICcwJztcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9pY29uID0gaWNvbjtcclxuXHJcblx0XHRpZiAob3B0aW9ucy5yaXNlT25Ib3Zlcikge1xyXG5cdFx0XHR0aGlzLm9uKHtcclxuXHRcdFx0XHRtb3VzZW92ZXI6IHRoaXMuX2JyaW5nVG9Gcm9udCxcclxuXHRcdFx0XHRtb3VzZW91dDogdGhpcy5fcmVzZXRaSW5kZXhcclxuXHRcdFx0fSk7XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIG5ld1NoYWRvdyA9IG9wdGlvbnMuaWNvbi5jcmVhdGVTaGFkb3codGhpcy5fc2hhZG93KSxcclxuXHRcdCAgICBhZGRTaGFkb3cgPSBmYWxzZTtcclxuXHJcblx0XHRpZiAobmV3U2hhZG93ICE9PSB0aGlzLl9zaGFkb3cpIHtcclxuXHRcdFx0dGhpcy5fcmVtb3ZlU2hhZG93KCk7XHJcblx0XHRcdGFkZFNoYWRvdyA9IHRydWU7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKG5ld1NoYWRvdykge1xyXG5cdFx0XHRhZGRDbGFzcyhuZXdTaGFkb3csIGNsYXNzVG9BZGQpO1xyXG5cdFx0XHRuZXdTaGFkb3cuYWx0ID0gJyc7XHJcblx0XHR9XHJcblx0XHR0aGlzLl9zaGFkb3cgPSBuZXdTaGFkb3c7XHJcblxyXG5cclxuXHRcdGlmIChvcHRpb25zLm9wYWNpdHkgPCAxKSB7XHJcblx0XHRcdHRoaXMuX3VwZGF0ZU9wYWNpdHkoKTtcclxuXHRcdH1cclxuXHJcblxyXG5cdFx0aWYgKGFkZEljb24pIHtcclxuXHRcdFx0dGhpcy5nZXRQYW5lKCkuYXBwZW5kQ2hpbGQodGhpcy5faWNvbik7XHJcblx0XHR9XHJcblx0XHR0aGlzLl9pbml0SW50ZXJhY3Rpb24oKTtcclxuXHRcdGlmIChuZXdTaGFkb3cgJiYgYWRkU2hhZG93KSB7XHJcblx0XHRcdHRoaXMuZ2V0UGFuZSgnc2hhZG93UGFuZScpLmFwcGVuZENoaWxkKHRoaXMuX3NoYWRvdyk7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X3JlbW92ZUljb246IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh0aGlzLm9wdGlvbnMucmlzZU9uSG92ZXIpIHtcclxuXHRcdFx0dGhpcy5vZmYoe1xyXG5cdFx0XHRcdG1vdXNlb3ZlcjogdGhpcy5fYnJpbmdUb0Zyb250LFxyXG5cdFx0XHRcdG1vdXNlb3V0OiB0aGlzLl9yZXNldFpJbmRleFxyXG5cdFx0XHR9KTtcclxuXHRcdH1cclxuXHJcblx0XHRyZW1vdmUodGhpcy5faWNvbik7XHJcblx0XHR0aGlzLnJlbW92ZUludGVyYWN0aXZlVGFyZ2V0KHRoaXMuX2ljb24pO1xyXG5cclxuXHRcdHRoaXMuX2ljb24gPSBudWxsO1xyXG5cdH0sXHJcblxyXG5cdF9yZW1vdmVTaGFkb3c6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh0aGlzLl9zaGFkb3cpIHtcclxuXHRcdFx0cmVtb3ZlKHRoaXMuX3NoYWRvdyk7XHJcblx0XHR9XHJcblx0XHR0aGlzLl9zaGFkb3cgPSBudWxsO1xyXG5cdH0sXHJcblxyXG5cdF9zZXRQb3M6IGZ1bmN0aW9uIChwb3MpIHtcclxuXHRcdHNldFBvc2l0aW9uKHRoaXMuX2ljb24sIHBvcyk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX3NoYWRvdykge1xyXG5cdFx0XHRzZXRQb3NpdGlvbih0aGlzLl9zaGFkb3csIHBvcyk7XHJcblx0XHR9XHJcblxyXG5cdFx0dGhpcy5fekluZGV4ID0gcG9zLnkgKyB0aGlzLm9wdGlvbnMuekluZGV4T2Zmc2V0O1xyXG5cclxuXHRcdHRoaXMuX3Jlc2V0WkluZGV4KCk7XHJcblx0fSxcclxuXHJcblx0X3VwZGF0ZVpJbmRleDogZnVuY3Rpb24gKG9mZnNldCkge1xyXG5cdFx0dGhpcy5faWNvbi5zdHlsZS56SW5kZXggPSB0aGlzLl96SW5kZXggKyBvZmZzZXQ7XHJcblx0fSxcclxuXHJcblx0X2FuaW1hdGVab29tOiBmdW5jdGlvbiAob3B0KSB7XHJcblx0XHR2YXIgcG9zID0gdGhpcy5fbWFwLl9sYXRMbmdUb05ld0xheWVyUG9pbnQodGhpcy5fbGF0bG5nLCBvcHQuem9vbSwgb3B0LmNlbnRlcikucm91bmQoKTtcclxuXHJcblx0XHR0aGlzLl9zZXRQb3MocG9zKTtcclxuXHR9LFxyXG5cclxuXHRfaW5pdEludGVyYWN0aW9uOiBmdW5jdGlvbiAoKSB7XHJcblxyXG5cdFx0aWYgKCF0aGlzLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0YWRkQ2xhc3ModGhpcy5faWNvbiwgJ2xlYWZsZXQtaW50ZXJhY3RpdmUnKTtcclxuXHJcblx0XHR0aGlzLmFkZEludGVyYWN0aXZlVGFyZ2V0KHRoaXMuX2ljb24pO1xyXG5cclxuXHRcdGlmIChNYXJrZXJEcmFnKSB7XHJcblx0XHRcdHZhciBkcmFnZ2FibGUgPSB0aGlzLm9wdGlvbnMuZHJhZ2dhYmxlO1xyXG5cdFx0XHRpZiAodGhpcy5kcmFnZ2luZykge1xyXG5cdFx0XHRcdGRyYWdnYWJsZSA9IHRoaXMuZHJhZ2dpbmcuZW5hYmxlZCgpO1xyXG5cdFx0XHRcdHRoaXMuZHJhZ2dpbmcuZGlzYWJsZSgpO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR0aGlzLmRyYWdnaW5nID0gbmV3IE1hcmtlckRyYWcodGhpcyk7XHJcblxyXG5cdFx0XHRpZiAoZHJhZ2dhYmxlKSB7XHJcblx0XHRcdFx0dGhpcy5kcmFnZ2luZy5lbmFibGUoKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0T3BhY2l0eShvcGFjaXR5OiBOdW1iZXIpOiB0aGlzXHJcblx0Ly8gQ2hhbmdlcyB0aGUgb3BhY2l0eSBvZiB0aGUgbWFya2VyLlxyXG5cdHNldE9wYWNpdHk6IGZ1bmN0aW9uIChvcGFjaXR5KSB7XHJcblx0XHR0aGlzLm9wdGlvbnMub3BhY2l0eSA9IG9wYWNpdHk7XHJcblx0XHRpZiAodGhpcy5fbWFwKSB7XHJcblx0XHRcdHRoaXMuX3VwZGF0ZU9wYWNpdHkoKTtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRfdXBkYXRlT3BhY2l0eTogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIG9wYWNpdHkgPSB0aGlzLm9wdGlvbnMub3BhY2l0eTtcclxuXHJcblx0XHRzZXRPcGFjaXR5KHRoaXMuX2ljb24sIG9wYWNpdHkpO1xyXG5cclxuXHRcdGlmICh0aGlzLl9zaGFkb3cpIHtcclxuXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9zaGFkb3csIG9wYWNpdHkpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9icmluZ1RvRnJvbnQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX3VwZGF0ZVpJbmRleCh0aGlzLm9wdGlvbnMucmlzZU9mZnNldCk7XHJcblx0fSxcclxuXHJcblx0X3Jlc2V0WkluZGV4OiBmdW5jdGlvbiAoKSB7XHJcblx0XHR0aGlzLl91cGRhdGVaSW5kZXgoMCk7XHJcblx0fSxcclxuXHJcblx0X2dldFBvcHVwQW5jaG9yOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5vcHRpb25zLmljb24ub3B0aW9ucy5wb3B1cEFuY2hvcjtcclxuXHR9LFxyXG5cclxuXHRfZ2V0VG9vbHRpcEFuY2hvcjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5pY29uLm9wdGlvbnMudG9vbHRpcEFuY2hvcjtcclxuXHR9XHJcbn0pO1xyXG5cclxuXHJcbi8vIGZhY3RvcnkgTC5tYXJrZXIobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/IDogTWFya2VyIG9wdGlvbnMpXHJcblxyXG4vLyBAZmFjdG9yeSBMLm1hcmtlcihsYXRsbmc6IExhdExuZywgb3B0aW9ucz8gOiBNYXJrZXIgb3B0aW9ucylcclxuLy8gSW5zdGFudGlhdGVzIGEgTWFya2VyIG9iamVjdCBnaXZlbiBhIGdlb2dyYXBoaWNhbCBwb2ludCBhbmQgb3B0aW9uYWxseSBhbiBvcHRpb25zIG9iamVjdC5cclxuZnVuY3Rpb24gbWFya2VyKGxhdGxuZywgb3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgTWFya2VyKGxhdGxuZywgb3B0aW9ucyk7XHJcbn1cblxuLypcbiAqIEBjbGFzcyBQYXRoXG4gKiBAYWthIEwuUGF0aFxuICogQGluaGVyaXRzIEludGVyYWN0aXZlIGxheWVyXG4gKlxuICogQW4gYWJzdHJhY3QgY2xhc3MgdGhhdCBjb250YWlucyBvcHRpb25zIGFuZCBjb25zdGFudHMgc2hhcmVkIGJldHdlZW4gdmVjdG9yXG4gKiBvdmVybGF5cyAoUG9seWdvbiwgUG9seWxpbmUsIENpcmNsZSkuIERvIG5vdCB1c2UgaXQgZGlyZWN0bHkuIEV4dGVuZHMgYExheWVyYC5cbiAqL1xuXG52YXIgUGF0aCA9IExheWVyLmV4dGVuZCh7XG5cblx0Ly8gQHNlY3Rpb25cblx0Ly8gQGFrYSBQYXRoIG9wdGlvbnNcblx0b3B0aW9uczoge1xuXHRcdC8vIEBvcHRpb24gc3Ryb2tlOiBCb29sZWFuID0gdHJ1ZVxuXHRcdC8vIFdoZXRoZXIgdG8gZHJhdyBzdHJva2UgYWxvbmcgdGhlIHBhdGguIFNldCBpdCB0byBgZmFsc2VgIHRvIGRpc2FibGUgYm9yZGVycyBvbiBwb2x5Z29ucyBvciBjaXJjbGVzLlxuXHRcdHN0cm9rZTogdHJ1ZSxcblxuXHRcdC8vIEBvcHRpb24gY29sb3I6IFN0cmluZyA9ICcjMzM4OGZmJ1xuXHRcdC8vIFN0cm9rZSBjb2xvclxuXHRcdGNvbG9yOiAnIzMzODhmZicsXG5cblx0XHQvLyBAb3B0aW9uIHdlaWdodDogTnVtYmVyID0gM1xuXHRcdC8vIFN0cm9rZSB3aWR0aCBpbiBwaXhlbHNcblx0XHR3ZWlnaHQ6IDMsXG5cblx0XHQvLyBAb3B0aW9uIG9wYWNpdHk6IE51bWJlciA9IDEuMFxuXHRcdC8vIFN0cm9rZSBvcGFjaXR5XG5cdFx0b3BhY2l0eTogMSxcblxuXHRcdC8vIEBvcHRpb24gbGluZUNhcDogU3RyaW5nPSAncm91bmQnXG5cdFx0Ly8gQSBzdHJpbmcgdGhhdCBkZWZpbmVzIFtzaGFwZSB0byBiZSB1c2VkIGF0IHRoZSBlbmRdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL1NWRy9BdHRyaWJ1dGUvc3Ryb2tlLWxpbmVjYXApIG9mIHRoZSBzdHJva2UuXG5cdFx0bGluZUNhcDogJ3JvdW5kJyxcblxuXHRcdC8vIEBvcHRpb24gbGluZUpvaW46IFN0cmluZyA9ICdyb3VuZCdcblx0XHQvLyBBIHN0cmluZyB0aGF0IGRlZmluZXMgW3NoYXBlIHRvIGJlIHVzZWQgYXQgdGhlIGNvcm5lcnNdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL1NWRy9BdHRyaWJ1dGUvc3Ryb2tlLWxpbmVqb2luKSBvZiB0aGUgc3Ryb2tlLlxuXHRcdGxpbmVKb2luOiAncm91bmQnLFxuXG5cdFx0Ly8gQG9wdGlvbiBkYXNoQXJyYXk6IFN0cmluZyA9IG51bGxcblx0XHQvLyBBIHN0cmluZyB0aGF0IGRlZmluZXMgdGhlIHN0cm9rZSBbZGFzaCBwYXR0ZXJuXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlL3N0cm9rZS1kYXNoYXJyYXkpLiBEb2Vzbid0IHdvcmsgb24gYENhbnZhc2AtcG93ZXJlZCBsYXllcnMgaW4gW3NvbWUgb2xkIGJyb3dzZXJzXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvQ2FudmFzUmVuZGVyaW5nQ29udGV4dDJEL3NldExpbmVEYXNoI0Jyb3dzZXJfY29tcGF0aWJpbGl0eSkuXG5cdFx0ZGFzaEFycmF5OiBudWxsLFxuXG5cdFx0Ly8gQG9wdGlvbiBkYXNoT2Zmc2V0OiBTdHJpbmcgPSBudWxsXG5cdFx0Ly8gQSBzdHJpbmcgdGhhdCBkZWZpbmVzIHRoZSBbZGlzdGFuY2UgaW50byB0aGUgZGFzaCBwYXR0ZXJuIHRvIHN0YXJ0IHRoZSBkYXNoXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcvQXR0cmlidXRlL3N0cm9rZS1kYXNob2Zmc2V0KS4gRG9lc24ndCB3b3JrIG9uIGBDYW52YXNgLXBvd2VyZWQgbGF5ZXJzIGluIFtzb21lIG9sZCBicm93c2Vyc10oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvQVBJL0NhbnZhc1JlbmRlcmluZ0NvbnRleHQyRC9zZXRMaW5lRGFzaCNCcm93c2VyX2NvbXBhdGliaWxpdHkpLlxuXHRcdGRhc2hPZmZzZXQ6IG51bGwsXG5cblx0XHQvLyBAb3B0aW9uIGZpbGw6IEJvb2xlYW4gPSBkZXBlbmRzXG5cdFx0Ly8gV2hldGhlciB0byBmaWxsIHRoZSBwYXRoIHdpdGggY29sb3IuIFNldCBpdCB0byBgZmFsc2VgIHRvIGRpc2FibGUgZmlsbGluZyBvbiBwb2x5Z29ucyBvciBjaXJjbGVzLlxuXHRcdGZpbGw6IGZhbHNlLFxuXG5cdFx0Ly8gQG9wdGlvbiBmaWxsQ29sb3I6IFN0cmluZyA9ICpcblx0XHQvLyBGaWxsIGNvbG9yLiBEZWZhdWx0cyB0byB0aGUgdmFsdWUgb2YgdGhlIFtgY29sb3JgXSgjcGF0aC1jb2xvcikgb3B0aW9uXG5cdFx0ZmlsbENvbG9yOiBudWxsLFxuXG5cdFx0Ly8gQG9wdGlvbiBmaWxsT3BhY2l0eTogTnVtYmVyID0gMC4yXG5cdFx0Ly8gRmlsbCBvcGFjaXR5LlxuXHRcdGZpbGxPcGFjaXR5OiAwLjIsXG5cblx0XHQvLyBAb3B0aW9uIGZpbGxSdWxlOiBTdHJpbmcgPSAnZXZlbm9kZCdcblx0XHQvLyBBIHN0cmluZyB0aGF0IGRlZmluZXMgW2hvdyB0aGUgaW5zaWRlIG9mIGEgc2hhcGVdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL1NWRy9BdHRyaWJ1dGUvZmlsbC1ydWxlKSBpcyBkZXRlcm1pbmVkLlxuXHRcdGZpbGxSdWxlOiAnZXZlbm9kZCcsXG5cblx0XHQvLyBjbGFzc05hbWU6ICcnLFxuXG5cdFx0Ly8gT3B0aW9uIGluaGVyaXRlZCBmcm9tIFwiSW50ZXJhY3RpdmUgbGF5ZXJcIiBhYnN0cmFjdCBjbGFzc1xuXHRcdGludGVyYWN0aXZlOiB0cnVlLFxuXG5cdFx0Ly8gQG9wdGlvbiBidWJibGluZ01vdXNlRXZlbnRzOiBCb29sZWFuID0gdHJ1ZVxuXHRcdC8vIFdoZW4gYHRydWVgLCBhIG1vdXNlIGV2ZW50IG9uIHRoaXMgcGF0aCB3aWxsIHRyaWdnZXIgdGhlIHNhbWUgZXZlbnQgb24gdGhlIG1hcFxuXHRcdC8vICh1bmxlc3MgW2BMLkRvbUV2ZW50LnN0b3BQcm9wYWdhdGlvbmBdKCNkb21ldmVudC1zdG9wcHJvcGFnYXRpb24pIGlzIHVzZWQpLlxuXHRcdGJ1YmJsaW5nTW91c2VFdmVudHM6IHRydWVcblx0fSxcblxuXHRiZWZvcmVBZGQ6IGZ1bmN0aW9uIChtYXApIHtcblx0XHQvLyBSZW5kZXJlciBpcyBzZXQgaGVyZSBiZWNhdXNlIHdlIG5lZWQgdG8gY2FsbCByZW5kZXJlci5nZXRFdmVudHNcblx0XHQvLyBiZWZvcmUgdGhpcy5nZXRFdmVudHMuXG5cdFx0dGhpcy5fcmVuZGVyZXIgPSBtYXAuZ2V0UmVuZGVyZXIodGhpcyk7XG5cdH0sXG5cblx0b25BZGQ6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9yZW5kZXJlci5faW5pdFBhdGgodGhpcyk7XG5cdFx0dGhpcy5fcmVzZXQoKTtcblx0XHR0aGlzLl9yZW5kZXJlci5fYWRkUGF0aCh0aGlzKTtcblx0fSxcblxuXHRvblJlbW92ZTogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3JlbmRlcmVyLl9yZW1vdmVQYXRoKHRoaXMpO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgcmVkcmF3KCk6IHRoaXNcblx0Ly8gUmVkcmF3cyB0aGUgbGF5ZXIuIFNvbWV0aW1lcyB1c2VmdWwgYWZ0ZXIgeW91IGNoYW5nZWQgdGhlIGNvb3JkaW5hdGVzIHRoYXQgdGhlIHBhdGggdXNlcy5cblx0cmVkcmF3OiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcCkge1xuXHRcdFx0dGhpcy5fcmVuZGVyZXIuX3VwZGF0ZVBhdGgodGhpcyk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2Qgc2V0U3R5bGUoc3R5bGU6IFBhdGggb3B0aW9ucyk6IHRoaXNcblx0Ly8gQ2hhbmdlcyB0aGUgYXBwZWFyYW5jZSBvZiBhIFBhdGggYmFzZWQgb24gdGhlIG9wdGlvbnMgaW4gdGhlIGBQYXRoIG9wdGlvbnNgIG9iamVjdC5cblx0c2V0U3R5bGU6IGZ1bmN0aW9uIChzdHlsZSkge1xuXHRcdHNldE9wdGlvbnModGhpcywgc3R5bGUpO1xuXHRcdGlmICh0aGlzLl9yZW5kZXJlcikge1xuXHRcdFx0dGhpcy5fcmVuZGVyZXIuX3VwZGF0ZVN0eWxlKHRoaXMpO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udCgpOiB0aGlzXG5cdC8vIEJyaW5ncyB0aGUgbGF5ZXIgdG8gdGhlIHRvcCBvZiBhbGwgcGF0aCBsYXllcnMuXG5cdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9yZW5kZXJlcikge1xuXHRcdFx0dGhpcy5fcmVuZGVyZXIuX2JyaW5nVG9Gcm9udCh0aGlzKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBicmluZ1RvQmFjaygpOiB0aGlzXG5cdC8vIEJyaW5ncyB0aGUgbGF5ZXIgdG8gdGhlIGJvdHRvbSBvZiBhbGwgcGF0aCBsYXllcnMuXG5cdGJyaW5nVG9CYWNrOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX3JlbmRlcmVyKSB7XG5cdFx0XHR0aGlzLl9yZW5kZXJlci5fYnJpbmdUb0JhY2sodGhpcyk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdGdldEVsZW1lbnQ6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fcGF0aDtcblx0fSxcblxuXHRfcmVzZXQ6IGZ1bmN0aW9uICgpIHtcblx0XHQvLyBkZWZpbmVkIGluIGNoaWxkIGNsYXNzZXNcblx0XHR0aGlzLl9wcm9qZWN0KCk7XG5cdFx0dGhpcy5fdXBkYXRlKCk7XG5cdH0sXG5cblx0X2NsaWNrVG9sZXJhbmNlOiBmdW5jdGlvbiAoKSB7XG5cdFx0Ly8gdXNlZCB3aGVuIGRvaW5nIGhpdCBkZXRlY3Rpb24gZm9yIENhbnZhcyBsYXllcnNcblx0XHRyZXR1cm4gKHRoaXMub3B0aW9ucy5zdHJva2UgPyB0aGlzLm9wdGlvbnMud2VpZ2h0IC8gMiA6IDApICsgdGhpcy5fcmVuZGVyZXIub3B0aW9ucy50b2xlcmFuY2U7XG5cdH1cbn0pO1xuXG4vKlxuICogQGNsYXNzIENpcmNsZU1hcmtlclxuICogQGFrYSBMLkNpcmNsZU1hcmtlclxuICogQGluaGVyaXRzIFBhdGhcbiAqXG4gKiBBIGNpcmNsZSBvZiBhIGZpeGVkIHNpemUgd2l0aCByYWRpdXMgc3BlY2lmaWVkIGluIHBpeGVscy4gRXh0ZW5kcyBgUGF0aGAuXG4gKi9cblxudmFyIENpcmNsZU1hcmtlciA9IFBhdGguZXh0ZW5kKHtcblxuXHQvLyBAc2VjdGlvblxuXHQvLyBAYWthIENpcmNsZU1hcmtlciBvcHRpb25zXG5cdG9wdGlvbnM6IHtcblx0XHRmaWxsOiB0cnVlLFxuXG5cdFx0Ly8gQG9wdGlvbiByYWRpdXM6IE51bWJlciA9IDEwXG5cdFx0Ly8gUmFkaXVzIG9mIHRoZSBjaXJjbGUgbWFya2VyLCBpbiBwaXhlbHNcblx0XHRyYWRpdXM6IDEwXG5cdH0sXG5cblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxhdGxuZywgb3B0aW9ucykge1xuXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XG5cdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcblx0XHR0aGlzLl9yYWRpdXMgPSB0aGlzLm9wdGlvbnMucmFkaXVzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2Qgc2V0TGF0TG5nKGxhdExuZzogTGF0TG5nKTogdGhpc1xuXHQvLyBTZXRzIHRoZSBwb3NpdGlvbiBvZiBhIGNpcmNsZSBtYXJrZXIgdG8gYSBuZXcgbG9jYXRpb24uXG5cdHNldExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xuXHRcdHRoaXMuX2xhdGxuZyA9IHRvTGF0TG5nKGxhdGxuZyk7XG5cdFx0dGhpcy5yZWRyYXcoKTtcblx0XHRyZXR1cm4gdGhpcy5maXJlKCdtb3ZlJywge2xhdGxuZzogdGhpcy5fbGF0bG5nfSk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBnZXRMYXRMbmcoKTogTGF0TG5nXG5cdC8vIFJldHVybnMgdGhlIGN1cnJlbnQgZ2VvZ3JhcGhpY2FsIHBvc2l0aW9uIG9mIHRoZSBjaXJjbGUgbWFya2VyXG5cdGdldExhdExuZzogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLl9sYXRsbmc7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBzZXRSYWRpdXMocmFkaXVzOiBOdW1iZXIpOiB0aGlzXG5cdC8vIFNldHMgdGhlIHJhZGl1cyBvZiBhIGNpcmNsZSBtYXJrZXIuIFVuaXRzIGFyZSBpbiBwaXhlbHMuXG5cdHNldFJhZGl1czogZnVuY3Rpb24gKHJhZGl1cykge1xuXHRcdHRoaXMub3B0aW9ucy5yYWRpdXMgPSB0aGlzLl9yYWRpdXMgPSByYWRpdXM7XG5cdFx0cmV0dXJuIHRoaXMucmVkcmF3KCk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBnZXRSYWRpdXMoKTogTnVtYmVyXG5cdC8vIFJldHVybnMgdGhlIGN1cnJlbnQgcmFkaXVzIG9mIHRoZSBjaXJjbGVcblx0Z2V0UmFkaXVzOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3JhZGl1cztcblx0fSxcblxuXHRzZXRTdHlsZSA6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG5cdFx0dmFyIHJhZGl1cyA9IG9wdGlvbnMgJiYgb3B0aW9ucy5yYWRpdXMgfHwgdGhpcy5fcmFkaXVzO1xuXHRcdFBhdGgucHJvdG90eXBlLnNldFN0eWxlLmNhbGwodGhpcywgb3B0aW9ucyk7XG5cdFx0dGhpcy5zZXRSYWRpdXMocmFkaXVzKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRfcHJvamVjdDogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3BvaW50ID0gdGhpcy5fbWFwLmxhdExuZ1RvTGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcpO1xuXHRcdHRoaXMuX3VwZGF0ZUJvdW5kcygpO1xuXHR9LFxuXG5cdF91cGRhdGVCb3VuZHM6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgciA9IHRoaXMuX3JhZGl1cyxcblx0XHQgICAgcjIgPSB0aGlzLl9yYWRpdXNZIHx8IHIsXG5cdFx0ICAgIHcgPSB0aGlzLl9jbGlja1RvbGVyYW5jZSgpLFxuXHRcdCAgICBwID0gW3IgKyB3LCByMiArIHddO1xuXHRcdHRoaXMuX3B4Qm91bmRzID0gbmV3IEJvdW5kcyh0aGlzLl9wb2ludC5zdWJ0cmFjdChwKSwgdGhpcy5fcG9pbnQuYWRkKHApKTtcblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcCkge1xuXHRcdFx0dGhpcy5fdXBkYXRlUGF0aCgpO1xuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlUGF0aDogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3JlbmRlcmVyLl91cGRhdGVDaXJjbGUodGhpcyk7XG5cdH0sXG5cblx0X2VtcHR5OiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3JhZGl1cyAmJiAhdGhpcy5fcmVuZGVyZXIuX2JvdW5kcy5pbnRlcnNlY3RzKHRoaXMuX3B4Qm91bmRzKTtcblx0fSxcblxuXHQvLyBOZWVkZWQgYnkgdGhlIGBDYW52YXNgIHJlbmRlcmVyIGZvciBpbnRlcmFjdGl2aXR5XG5cdF9jb250YWluc1BvaW50OiBmdW5jdGlvbiAocCkge1xuXHRcdHJldHVybiBwLmRpc3RhbmNlVG8odGhpcy5fcG9pbnQpIDw9IHRoaXMuX3JhZGl1cyArIHRoaXMuX2NsaWNrVG9sZXJhbmNlKCk7XG5cdH1cbn0pO1xuXG5cbi8vIEBmYWN0b3J5IEwuY2lyY2xlTWFya2VyKGxhdGxuZzogTGF0TG5nLCBvcHRpb25zPzogQ2lyY2xlTWFya2VyIG9wdGlvbnMpXG4vLyBJbnN0YW50aWF0ZXMgYSBjaXJjbGUgbWFya2VyIG9iamVjdCBnaXZlbiBhIGdlb2dyYXBoaWNhbCBwb2ludCwgYW5kIGFuIG9wdGlvbmFsIG9wdGlvbnMgb2JqZWN0LlxuZnVuY3Rpb24gY2lyY2xlTWFya2VyKGxhdGxuZywgb3B0aW9ucykge1xuXHRyZXR1cm4gbmV3IENpcmNsZU1hcmtlcihsYXRsbmcsIG9wdGlvbnMpO1xufVxuXG4vKlxuICogQGNsYXNzIENpcmNsZVxuICogQGFrYSBMLkNpcmNsZVxuICogQGluaGVyaXRzIENpcmNsZU1hcmtlclxuICpcbiAqIEEgY2xhc3MgZm9yIGRyYXdpbmcgY2lyY2xlIG92ZXJsYXlzIG9uIGEgbWFwLiBFeHRlbmRzIGBDaXJjbGVNYXJrZXJgLlxuICpcbiAqIEl0J3MgYW4gYXBwcm94aW1hdGlvbiBhbmQgc3RhcnRzIHRvIGRpdmVyZ2UgZnJvbSBhIHJlYWwgY2lyY2xlIGNsb3NlciB0byBwb2xlcyAoZHVlIHRvIHByb2plY3Rpb24gZGlzdG9ydGlvbikuXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGBqc1xuICogTC5jaXJjbGUoWzUwLjUsIDMwLjVdLCB7cmFkaXVzOiAyMDB9KS5hZGRUbyhtYXApO1xuICogYGBgXG4gKi9cblxudmFyIENpcmNsZSA9IENpcmNsZU1hcmtlci5leHRlbmQoe1xuXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChsYXRsbmcsIG9wdGlvbnMsIGxlZ2FjeU9wdGlvbnMpIHtcblx0XHRpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdudW1iZXInKSB7XG5cdFx0XHQvLyBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eSB3aXRoIDAuNy54IGZhY3RvcnkgKGxhdGxuZywgcmFkaXVzLCBvcHRpb25zPylcblx0XHRcdG9wdGlvbnMgPSBleHRlbmQoe30sIGxlZ2FjeU9wdGlvbnMsIHtyYWRpdXM6IG9wdGlvbnN9KTtcblx0XHR9XG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcblx0XHR0aGlzLl9sYXRsbmcgPSB0b0xhdExuZyhsYXRsbmcpO1xuXG5cdFx0aWYgKGlzTmFOKHRoaXMub3B0aW9ucy5yYWRpdXMpKSB7IHRocm93IG5ldyBFcnJvcignQ2lyY2xlIHJhZGl1cyBjYW5ub3QgYmUgTmFOJyk7IH1cblxuXHRcdC8vIEBzZWN0aW9uXG5cdFx0Ly8gQGFrYSBDaXJjbGUgb3B0aW9uc1xuXHRcdC8vIEBvcHRpb24gcmFkaXVzOiBOdW1iZXI7IFJhZGl1cyBvZiB0aGUgY2lyY2xlLCBpbiBtZXRlcnMuXG5cdFx0dGhpcy5fbVJhZGl1cyA9IHRoaXMub3B0aW9ucy5yYWRpdXM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBzZXRSYWRpdXMocmFkaXVzOiBOdW1iZXIpOiB0aGlzXG5cdC8vIFNldHMgdGhlIHJhZGl1cyBvZiBhIGNpcmNsZS4gVW5pdHMgYXJlIGluIG1ldGVycy5cblx0c2V0UmFkaXVzOiBmdW5jdGlvbiAocmFkaXVzKSB7XG5cdFx0dGhpcy5fbVJhZGl1cyA9IHJhZGl1cztcblx0XHRyZXR1cm4gdGhpcy5yZWRyYXcoKTtcblx0fSxcblxuXHQvLyBAbWV0aG9kIGdldFJhZGl1cygpOiBOdW1iZXJcblx0Ly8gUmV0dXJucyB0aGUgY3VycmVudCByYWRpdXMgb2YgYSBjaXJjbGUuIFVuaXRzIGFyZSBpbiBtZXRlcnMuXG5cdGdldFJhZGl1czogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLl9tUmFkaXVzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgZ2V0Qm91bmRzKCk6IExhdExuZ0JvdW5kc1xuXHQvLyBSZXR1cm5zIHRoZSBgTGF0TG5nQm91bmRzYCBvZiB0aGUgcGF0aC5cblx0Z2V0Qm91bmRzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGhhbGYgPSBbdGhpcy5fcmFkaXVzLCB0aGlzLl9yYWRpdXNZIHx8IHRoaXMuX3JhZGl1c107XG5cblx0XHRyZXR1cm4gbmV3IExhdExuZ0JvdW5kcyhcblx0XHRcdHRoaXMuX21hcC5sYXllclBvaW50VG9MYXRMbmcodGhpcy5fcG9pbnQuc3VidHJhY3QoaGFsZikpLFxuXHRcdFx0dGhpcy5fbWFwLmxheWVyUG9pbnRUb0xhdExuZyh0aGlzLl9wb2ludC5hZGQoaGFsZikpKTtcblx0fSxcblxuXHRzZXRTdHlsZTogUGF0aC5wcm90b3R5cGUuc2V0U3R5bGUsXG5cblx0X3Byb2plY3Q6IGZ1bmN0aW9uICgpIHtcblxuXHRcdHZhciBsbmcgPSB0aGlzLl9sYXRsbmcubG5nLFxuXHRcdCAgICBsYXQgPSB0aGlzLl9sYXRsbmcubGF0LFxuXHRcdCAgICBtYXAgPSB0aGlzLl9tYXAsXG5cdFx0ICAgIGNycyA9IG1hcC5vcHRpb25zLmNycztcblxuXHRcdGlmIChjcnMuZGlzdGFuY2UgPT09IEVhcnRoLmRpc3RhbmNlKSB7XG5cdFx0XHR2YXIgZCA9IE1hdGguUEkgLyAxODAsXG5cdFx0XHQgICAgbGF0UiA9ICh0aGlzLl9tUmFkaXVzIC8gRWFydGguUikgLyBkLFxuXHRcdFx0ICAgIHRvcCA9IG1hcC5wcm9qZWN0KFtsYXQgKyBsYXRSLCBsbmddKSxcblx0XHRcdCAgICBib3R0b20gPSBtYXAucHJvamVjdChbbGF0IC0gbGF0UiwgbG5nXSksXG5cdFx0XHQgICAgcCA9IHRvcC5hZGQoYm90dG9tKS5kaXZpZGVCeSgyKSxcblx0XHRcdCAgICBsYXQyID0gbWFwLnVucHJvamVjdChwKS5sYXQsXG5cdFx0XHQgICAgbG5nUiA9IE1hdGguYWNvcygoTWF0aC5jb3MobGF0UiAqIGQpIC0gTWF0aC5zaW4obGF0ICogZCkgKiBNYXRoLnNpbihsYXQyICogZCkpIC9cblx0XHRcdCAgICAgICAgICAgIChNYXRoLmNvcyhsYXQgKiBkKSAqIE1hdGguY29zKGxhdDIgKiBkKSkpIC8gZDtcblxuXHRcdFx0aWYgKGlzTmFOKGxuZ1IpIHx8IGxuZ1IgPT09IDApIHtcblx0XHRcdFx0bG5nUiA9IGxhdFIgLyBNYXRoLmNvcyhNYXRoLlBJIC8gMTgwICogbGF0KTsgLy8gRmFsbGJhY2sgZm9yIGVkZ2UgY2FzZSwgIzI0MjVcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5fcG9pbnQgPSBwLnN1YnRyYWN0KG1hcC5nZXRQaXhlbE9yaWdpbigpKTtcblx0XHRcdHRoaXMuX3JhZGl1cyA9IGlzTmFOKGxuZ1IpID8gMCA6IHAueCAtIG1hcC5wcm9qZWN0KFtsYXQyLCBsbmcgLSBsbmdSXSkueDtcblx0XHRcdHRoaXMuX3JhZGl1c1kgPSBwLnkgLSB0b3AueTtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgbGF0bG5nMiA9IGNycy51bnByb2plY3QoY3JzLnByb2plY3QodGhpcy5fbGF0bG5nKS5zdWJ0cmFjdChbdGhpcy5fbVJhZGl1cywgMF0pKTtcblxuXHRcdFx0dGhpcy5fcG9pbnQgPSBtYXAubGF0TG5nVG9MYXllclBvaW50KHRoaXMuX2xhdGxuZyk7XG5cdFx0XHR0aGlzLl9yYWRpdXMgPSB0aGlzLl9wb2ludC54IC0gbWFwLmxhdExuZ1RvTGF5ZXJQb2ludChsYXRsbmcyKS54O1xuXHRcdH1cblxuXHRcdHRoaXMuX3VwZGF0ZUJvdW5kcygpO1xuXHR9XG59KTtcblxuLy8gQGZhY3RvcnkgTC5jaXJjbGUobGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBDaXJjbGUgb3B0aW9ucylcbi8vIEluc3RhbnRpYXRlcyBhIGNpcmNsZSBvYmplY3QgZ2l2ZW4gYSBnZW9ncmFwaGljYWwgcG9pbnQsIGFuZCBhbiBvcHRpb25zIG9iamVjdFxuLy8gd2hpY2ggY29udGFpbnMgdGhlIGNpcmNsZSByYWRpdXMuXG4vLyBAYWx0ZXJuYXRpdmVcbi8vIEBmYWN0b3J5IEwuY2lyY2xlKGxhdGxuZzogTGF0TG5nLCByYWRpdXM6IE51bWJlciwgb3B0aW9ucz86IENpcmNsZSBvcHRpb25zKVxuLy8gT2Jzb2xldGUgd2F5IG9mIGluc3RhbnRpYXRpbmcgYSBjaXJjbGUsIGZvciBjb21wYXRpYmlsaXR5IHdpdGggMC43LnggY29kZS5cbi8vIERvIG5vdCB1c2UgaW4gbmV3IGFwcGxpY2F0aW9ucyBvciBwbHVnaW5zLlxuZnVuY3Rpb24gY2lyY2xlKGxhdGxuZywgb3B0aW9ucywgbGVnYWN5T3B0aW9ucykge1xuXHRyZXR1cm4gbmV3IENpcmNsZShsYXRsbmcsIG9wdGlvbnMsIGxlZ2FjeU9wdGlvbnMpO1xufVxuXG4vKlxuICogQGNsYXNzIFBvbHlsaW5lXG4gKiBAYWthIEwuUG9seWxpbmVcbiAqIEBpbmhlcml0cyBQYXRoXG4gKlxuICogQSBjbGFzcyBmb3IgZHJhd2luZyBwb2x5bGluZSBvdmVybGF5cyBvbiBhIG1hcC4gRXh0ZW5kcyBgUGF0aGAuXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGBqc1xuICogLy8gY3JlYXRlIGEgcmVkIHBvbHlsaW5lIGZyb20gYW4gYXJyYXkgb2YgTGF0TG5nIHBvaW50c1xuICogdmFyIGxhdGxuZ3MgPSBbXG4gKiBcdFs0NS41MSwgLTEyMi42OF0sXG4gKiBcdFszNy43NywgLTEyMi40M10sXG4gKiBcdFszNC4wNCwgLTExOC4yXVxuICogXTtcbiAqXG4gKiB2YXIgcG9seWxpbmUgPSBMLnBvbHlsaW5lKGxhdGxuZ3MsIHtjb2xvcjogJ3JlZCd9KS5hZGRUbyhtYXApO1xuICpcbiAqIC8vIHpvb20gdGhlIG1hcCB0byB0aGUgcG9seWxpbmVcbiAqIG1hcC5maXRCb3VuZHMocG9seWxpbmUuZ2V0Qm91bmRzKCkpO1xuICogYGBgXG4gKlxuICogWW91IGNhbiBhbHNvIHBhc3MgYSBtdWx0aS1kaW1lbnNpb25hbCBhcnJheSB0byByZXByZXNlbnQgYSBgTXVsdGlQb2x5bGluZWAgc2hhcGU6XG4gKlxuICogYGBganNcbiAqIC8vIGNyZWF0ZSBhIHJlZCBwb2x5bGluZSBmcm9tIGFuIGFycmF5IG9mIGFycmF5cyBvZiBMYXRMbmcgcG9pbnRzXG4gKiB2YXIgbGF0bG5ncyA9IFtcbiAqIFx0W1s0NS41MSwgLTEyMi42OF0sXG4gKiBcdCBbMzcuNzcsIC0xMjIuNDNdLFxuICogXHQgWzM0LjA0LCAtMTE4LjJdXSxcbiAqIFx0W1s0MC43OCwgLTczLjkxXSxcbiAqIFx0IFs0MS44MywgLTg3LjYyXSxcbiAqIFx0IFszMi43NiwgLTk2LjcyXV1cbiAqIF07XG4gKiBgYGBcbiAqL1xuXG5cbnZhciBQb2x5bGluZSA9IFBhdGguZXh0ZW5kKHtcblxuXHQvLyBAc2VjdGlvblxuXHQvLyBAYWthIFBvbHlsaW5lIG9wdGlvbnNcblx0b3B0aW9uczoge1xuXHRcdC8vIEBvcHRpb24gc21vb3RoRmFjdG9yOiBOdW1iZXIgPSAxLjBcblx0XHQvLyBIb3cgbXVjaCB0byBzaW1wbGlmeSB0aGUgcG9seWxpbmUgb24gZWFjaCB6b29tIGxldmVsLiBNb3JlIG1lYW5zXG5cdFx0Ly8gYmV0dGVyIHBlcmZvcm1hbmNlIGFuZCBzbW9vdGhlciBsb29rLCBhbmQgbGVzcyBtZWFucyBtb3JlIGFjY3VyYXRlIHJlcHJlc2VudGF0aW9uLlxuXHRcdHNtb290aEZhY3RvcjogMS4wLFxuXG5cdFx0Ly8gQG9wdGlvbiBub0NsaXA6IEJvb2xlYW4gPSBmYWxzZVxuXHRcdC8vIERpc2FibGUgcG9seWxpbmUgY2xpcHBpbmcuXG5cdFx0bm9DbGlwOiBmYWxzZVxuXHR9LFxuXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChsYXRsbmdzLCBvcHRpb25zKSB7XG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcblx0XHR0aGlzLl9zZXRMYXRMbmdzKGxhdGxuZ3MpO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgZ2V0TGF0TG5ncygpOiBMYXRMbmdbXVxuXHQvLyBSZXR1cm5zIGFuIGFycmF5IG9mIHRoZSBwb2ludHMgaW4gdGhlIHBhdGgsIG9yIG5lc3RlZCBhcnJheXMgb2YgcG9pbnRzIGluIGNhc2Ugb2YgbXVsdGktcG9seWxpbmUuXG5cdGdldExhdExuZ3M6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fbGF0bG5ncztcblx0fSxcblxuXHQvLyBAbWV0aG9kIHNldExhdExuZ3MobGF0bG5nczogTGF0TG5nW10pOiB0aGlzXG5cdC8vIFJlcGxhY2VzIGFsbCB0aGUgcG9pbnRzIGluIHRoZSBwb2x5bGluZSB3aXRoIHRoZSBnaXZlbiBhcnJheSBvZiBnZW9ncmFwaGljYWwgcG9pbnRzLlxuXHRzZXRMYXRMbmdzOiBmdW5jdGlvbiAobGF0bG5ncykge1xuXHRcdHRoaXMuX3NldExhdExuZ3MobGF0bG5ncyk7XG5cdFx0cmV0dXJuIHRoaXMucmVkcmF3KCk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBpc0VtcHR5KCk6IEJvb2xlYW5cblx0Ly8gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIFBvbHlsaW5lIGhhcyBubyBMYXRMbmdzLlxuXHRpc0VtcHR5OiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuICF0aGlzLl9sYXRsbmdzLmxlbmd0aDtcblx0fSxcblxuXHQvLyBAbWV0aG9kIGNsb3Nlc3RMYXllclBvaW50OiBQb2ludFxuXHQvLyBSZXR1cm5zIHRoZSBwb2ludCBjbG9zZXN0IHRvIGBwYCBvbiB0aGUgUG9seWxpbmUuXG5cdGNsb3Nlc3RMYXllclBvaW50OiBmdW5jdGlvbiAocCkge1xuXHRcdHZhciBtaW5EaXN0YW5jZSA9IEluZmluaXR5LFxuXHRcdCAgICBtaW5Qb2ludCA9IG51bGwsXG5cdFx0ICAgIGNsb3Nlc3QgPSBfc3FDbG9zZXN0UG9pbnRPblNlZ21lbnQsXG5cdFx0ICAgIHAxLCBwMjtcblxuXHRcdGZvciAodmFyIGogPSAwLCBqTGVuID0gdGhpcy5fcGFydHMubGVuZ3RoOyBqIDwgakxlbjsgaisrKSB7XG5cdFx0XHR2YXIgcG9pbnRzID0gdGhpcy5fcGFydHNbal07XG5cblx0XHRcdGZvciAodmFyIGkgPSAxLCBsZW4gPSBwb2ludHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdFx0cDEgPSBwb2ludHNbaSAtIDFdO1xuXHRcdFx0XHRwMiA9IHBvaW50c1tpXTtcblxuXHRcdFx0XHR2YXIgc3FEaXN0ID0gY2xvc2VzdChwLCBwMSwgcDIsIHRydWUpO1xuXG5cdFx0XHRcdGlmIChzcURpc3QgPCBtaW5EaXN0YW5jZSkge1xuXHRcdFx0XHRcdG1pbkRpc3RhbmNlID0gc3FEaXN0O1xuXHRcdFx0XHRcdG1pblBvaW50ID0gY2xvc2VzdChwLCBwMSwgcDIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmIChtaW5Qb2ludCkge1xuXHRcdFx0bWluUG9pbnQuZGlzdGFuY2UgPSBNYXRoLnNxcnQobWluRGlzdGFuY2UpO1xuXHRcdH1cblx0XHRyZXR1cm4gbWluUG9pbnQ7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBnZXRDZW50ZXIoKTogTGF0TG5nXG5cdC8vIFJldHVybnMgdGhlIGNlbnRlciAoW2NlbnRyb2lkXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NlbnRyb2lkKSkgb2YgdGhlIHBvbHlsaW5lLlxuXHRnZXRDZW50ZXI6IGZ1bmN0aW9uICgpIHtcblx0XHQvLyB0aHJvd3MgZXJyb3Igd2hlbiBub3QgeWV0IGFkZGVkIHRvIG1hcCBhcyB0aGlzIGNlbnRlciBjYWxjdWxhdGlvbiByZXF1aXJlcyBwcm9qZWN0ZWQgY29vcmRpbmF0ZXNcblx0XHRpZiAoIXRoaXMuX21hcCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdNdXN0IGFkZCBsYXllciB0byBtYXAgYmVmb3JlIHVzaW5nIGdldENlbnRlcigpJyk7XG5cdFx0fVxuXG5cdFx0dmFyIGksIGhhbGZEaXN0LCBzZWdEaXN0LCBkaXN0LCBwMSwgcDIsIHJhdGlvLFxuXHRcdCAgICBwb2ludHMgPSB0aGlzLl9yaW5nc1swXSxcblx0XHQgICAgbGVuID0gcG9pbnRzLmxlbmd0aDtcblxuXHRcdGlmICghbGVuKSB7IHJldHVybiBudWxsOyB9XG5cblx0XHQvLyBwb2x5bGluZSBjZW50cm9pZCBhbGdvcml0aG07IG9ubHkgdXNlcyB0aGUgZmlyc3QgcmluZyBpZiB0aGVyZSBhcmUgbXVsdGlwbGVcblxuXHRcdGZvciAoaSA9IDAsIGhhbGZEaXN0ID0gMDsgaSA8IGxlbiAtIDE7IGkrKykge1xuXHRcdFx0aGFsZkRpc3QgKz0gcG9pbnRzW2ldLmRpc3RhbmNlVG8ocG9pbnRzW2kgKyAxXSkgLyAyO1xuXHRcdH1cblxuXHRcdC8vIFRoZSBsaW5lIGlzIHNvIHNtYWxsIGluIHRoZSBjdXJyZW50IHZpZXcgdGhhdCBhbGwgcG9pbnRzIGFyZSBvbiB0aGUgc2FtZSBwaXhlbC5cblx0XHRpZiAoaGFsZkRpc3QgPT09IDApIHtcblx0XHRcdHJldHVybiB0aGlzLl9tYXAubGF5ZXJQb2ludFRvTGF0TG5nKHBvaW50c1swXSk7XG5cdFx0fVxuXG5cdFx0Zm9yIChpID0gMCwgZGlzdCA9IDA7IGkgPCBsZW4gLSAxOyBpKyspIHtcblx0XHRcdHAxID0gcG9pbnRzW2ldO1xuXHRcdFx0cDIgPSBwb2ludHNbaSArIDFdO1xuXHRcdFx0c2VnRGlzdCA9IHAxLmRpc3RhbmNlVG8ocDIpO1xuXHRcdFx0ZGlzdCArPSBzZWdEaXN0O1xuXG5cdFx0XHRpZiAoZGlzdCA+IGhhbGZEaXN0KSB7XG5cdFx0XHRcdHJhdGlvID0gKGRpc3QgLSBoYWxmRGlzdCkgLyBzZWdEaXN0O1xuXHRcdFx0XHRyZXR1cm4gdGhpcy5fbWFwLmxheWVyUG9pbnRUb0xhdExuZyhbXG5cdFx0XHRcdFx0cDIueCAtIHJhdGlvICogKHAyLnggLSBwMS54KSxcblx0XHRcdFx0XHRwMi55IC0gcmF0aW8gKiAocDIueSAtIHAxLnkpXG5cdFx0XHRcdF0pO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHQvLyBAbWV0aG9kIGdldEJvdW5kcygpOiBMYXRMbmdCb3VuZHNcblx0Ly8gUmV0dXJucyB0aGUgYExhdExuZ0JvdW5kc2Agb2YgdGhlIHBhdGguXG5cdGdldEJvdW5kczogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLl9ib3VuZHM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBhZGRMYXRMbmcobGF0bG5nOiBMYXRMbmcsIGxhdGxuZ3M/IExhdExuZ1tdKTogdGhpc1xuXHQvLyBBZGRzIGEgZ2l2ZW4gcG9pbnQgdG8gdGhlIHBvbHlsaW5lLiBCeSBkZWZhdWx0LCBhZGRzIHRvIHRoZSBmaXJzdCByaW5nIG9mXG5cdC8vIHRoZSBwb2x5bGluZSBpbiBjYXNlIG9mIGEgbXVsdGktcG9seWxpbmUsIGJ1dCBjYW4gYmUgb3ZlcnJpZGRlbiBieSBwYXNzaW5nXG5cdC8vIGEgc3BlY2lmaWMgcmluZyBhcyBhIExhdExuZyBhcnJheSAodGhhdCB5b3UgY2FuIGVhcmxpZXIgYWNjZXNzIHdpdGggW2BnZXRMYXRMbmdzYF0oI3BvbHlsaW5lLWdldGxhdGxuZ3MpKS5cblx0YWRkTGF0TG5nOiBmdW5jdGlvbiAobGF0bG5nLCBsYXRsbmdzKSB7XG5cdFx0bGF0bG5ncyA9IGxhdGxuZ3MgfHwgdGhpcy5fZGVmYXVsdFNoYXBlKCk7XG5cdFx0bGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcblx0XHRsYXRsbmdzLnB1c2gobGF0bG5nKTtcblx0XHR0aGlzLl9ib3VuZHMuZXh0ZW5kKGxhdGxuZyk7XG5cdFx0cmV0dXJuIHRoaXMucmVkcmF3KCk7XG5cdH0sXG5cblx0X3NldExhdExuZ3M6IGZ1bmN0aW9uIChsYXRsbmdzKSB7XG5cdFx0dGhpcy5fYm91bmRzID0gbmV3IExhdExuZ0JvdW5kcygpO1xuXHRcdHRoaXMuX2xhdGxuZ3MgPSB0aGlzLl9jb252ZXJ0TGF0TG5ncyhsYXRsbmdzKTtcblx0fSxcblxuXHRfZGVmYXVsdFNoYXBlOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIGlzRmxhdCh0aGlzLl9sYXRsbmdzKSA/IHRoaXMuX2xhdGxuZ3MgOiB0aGlzLl9sYXRsbmdzWzBdO1xuXHR9LFxuXG5cdC8vIHJlY3Vyc2l2ZWx5IGNvbnZlcnQgbGF0bG5ncyBpbnB1dCBpbnRvIGFjdHVhbCBMYXRMbmcgaW5zdGFuY2VzOyBjYWxjdWxhdGUgYm91bmRzIGFsb25nIHRoZSB3YXlcblx0X2NvbnZlcnRMYXRMbmdzOiBmdW5jdGlvbiAobGF0bG5ncykge1xuXHRcdHZhciByZXN1bHQgPSBbXSxcblx0XHQgICAgZmxhdCA9IGlzRmxhdChsYXRsbmdzKTtcblxuXHRcdGZvciAodmFyIGkgPSAwLCBsZW4gPSBsYXRsbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRpZiAoZmxhdCkge1xuXHRcdFx0XHRyZXN1bHRbaV0gPSB0b0xhdExuZyhsYXRsbmdzW2ldKTtcblx0XHRcdFx0dGhpcy5fYm91bmRzLmV4dGVuZChyZXN1bHRbaV0pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmVzdWx0W2ldID0gdGhpcy5fY29udmVydExhdExuZ3MobGF0bG5nc1tpXSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fSxcblxuXHRfcHJvamVjdDogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBweEJvdW5kcyA9IG5ldyBCb3VuZHMoKTtcblx0XHR0aGlzLl9yaW5ncyA9IFtdO1xuXHRcdHRoaXMuX3Byb2plY3RMYXRsbmdzKHRoaXMuX2xhdGxuZ3MsIHRoaXMuX3JpbmdzLCBweEJvdW5kcyk7XG5cblx0XHR2YXIgdyA9IHRoaXMuX2NsaWNrVG9sZXJhbmNlKCksXG5cdFx0ICAgIHAgPSBuZXcgUG9pbnQodywgdyk7XG5cblx0XHRpZiAodGhpcy5fYm91bmRzLmlzVmFsaWQoKSAmJiBweEJvdW5kcy5pc1ZhbGlkKCkpIHtcblx0XHRcdHB4Qm91bmRzLm1pbi5fc3VidHJhY3QocCk7XG5cdFx0XHRweEJvdW5kcy5tYXguX2FkZChwKTtcblx0XHRcdHRoaXMuX3B4Qm91bmRzID0gcHhCb3VuZHM7XG5cdFx0fVxuXHR9LFxuXG5cdC8vIHJlY3Vyc2l2ZWx5IHR1cm5zIGxhdGxuZ3MgaW50byBhIHNldCBvZiByaW5ncyB3aXRoIHByb2plY3RlZCBjb29yZGluYXRlc1xuXHRfcHJvamVjdExhdGxuZ3M6IGZ1bmN0aW9uIChsYXRsbmdzLCByZXN1bHQsIHByb2plY3RlZEJvdW5kcykge1xuXHRcdHZhciBmbGF0ID0gbGF0bG5nc1swXSBpbnN0YW5jZW9mIExhdExuZyxcblx0XHQgICAgbGVuID0gbGF0bG5ncy5sZW5ndGgsXG5cdFx0ICAgIGksIHJpbmc7XG5cblx0XHRpZiAoZmxhdCkge1xuXHRcdFx0cmluZyA9IFtdO1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRcdHJpbmdbaV0gPSB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KGxhdGxuZ3NbaV0pO1xuXHRcdFx0XHRwcm9qZWN0ZWRCb3VuZHMuZXh0ZW5kKHJpbmdbaV0pO1xuXHRcdFx0fVxuXHRcdFx0cmVzdWx0LnB1c2gocmluZyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0XHR0aGlzLl9wcm9qZWN0TGF0bG5ncyhsYXRsbmdzW2ldLCByZXN1bHQsIHByb2plY3RlZEJvdW5kcyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdC8vIGNsaXAgcG9seWxpbmUgYnkgcmVuZGVyZXIgYm91bmRzIHNvIHRoYXQgd2UgaGF2ZSBsZXNzIHRvIHJlbmRlciBmb3IgcGVyZm9ybWFuY2Vcblx0X2NsaXBQb2ludHM6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgYm91bmRzID0gdGhpcy5fcmVuZGVyZXIuX2JvdW5kcztcblxuXHRcdHRoaXMuX3BhcnRzID0gW107XG5cdFx0aWYgKCF0aGlzLl9weEJvdW5kcyB8fCAhdGhpcy5fcHhCb3VuZHMuaW50ZXJzZWN0cyhib3VuZHMpKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5ub0NsaXApIHtcblx0XHRcdHRoaXMuX3BhcnRzID0gdGhpcy5fcmluZ3M7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHBhcnRzID0gdGhpcy5fcGFydHMsXG5cdFx0ICAgIGksIGosIGssIGxlbiwgbGVuMiwgc2VnbWVudCwgcG9pbnRzO1xuXG5cdFx0Zm9yIChpID0gMCwgayA9IDAsIGxlbiA9IHRoaXMuX3JpbmdzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRwb2ludHMgPSB0aGlzLl9yaW5nc1tpXTtcblxuXHRcdFx0Zm9yIChqID0gMCwgbGVuMiA9IHBvaW50cy5sZW5ndGg7IGogPCBsZW4yIC0gMTsgaisrKSB7XG5cdFx0XHRcdHNlZ21lbnQgPSBjbGlwU2VnbWVudChwb2ludHNbal0sIHBvaW50c1tqICsgMV0sIGJvdW5kcywgaiwgdHJ1ZSk7XG5cblx0XHRcdFx0aWYgKCFzZWdtZW50KSB7IGNvbnRpbnVlOyB9XG5cblx0XHRcdFx0cGFydHNba10gPSBwYXJ0c1trXSB8fCBbXTtcblx0XHRcdFx0cGFydHNba10ucHVzaChzZWdtZW50WzBdKTtcblxuXHRcdFx0XHQvLyBpZiBzZWdtZW50IGdvZXMgb3V0IG9mIHNjcmVlbiwgb3IgaXQncyB0aGUgbGFzdCBvbmUsIGl0J3MgdGhlIGVuZCBvZiB0aGUgbGluZSBwYXJ0XG5cdFx0XHRcdGlmICgoc2VnbWVudFsxXSAhPT0gcG9pbnRzW2ogKyAxXSkgfHwgKGogPT09IGxlbjIgLSAyKSkge1xuXHRcdFx0XHRcdHBhcnRzW2tdLnB1c2goc2VnbWVudFsxXSk7XG5cdFx0XHRcdFx0aysrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdC8vIHNpbXBsaWZ5IGVhY2ggY2xpcHBlZCBwYXJ0IG9mIHRoZSBwb2x5bGluZSBmb3IgcGVyZm9ybWFuY2Vcblx0X3NpbXBsaWZ5UG9pbnRzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHBhcnRzID0gdGhpcy5fcGFydHMsXG5cdFx0ICAgIHRvbGVyYW5jZSA9IHRoaXMub3B0aW9ucy5zbW9vdGhGYWN0b3I7XG5cblx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gcGFydHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdHBhcnRzW2ldID0gc2ltcGxpZnkocGFydHNbaV0sIHRvbGVyYW5jZSk7XG5cdFx0fVxuXHR9LFxuXG5cdF91cGRhdGU6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoIXRoaXMuX21hcCkgeyByZXR1cm47IH1cblxuXHRcdHRoaXMuX2NsaXBQb2ludHMoKTtcblx0XHR0aGlzLl9zaW1wbGlmeVBvaW50cygpO1xuXHRcdHRoaXMuX3VwZGF0ZVBhdGgoKTtcblx0fSxcblxuXHRfdXBkYXRlUGF0aDogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3JlbmRlcmVyLl91cGRhdGVQb2x5KHRoaXMpO1xuXHR9LFxuXG5cdC8vIE5lZWRlZCBieSB0aGUgYENhbnZhc2AgcmVuZGVyZXIgZm9yIGludGVyYWN0aXZpdHlcblx0X2NvbnRhaW5zUG9pbnQ6IGZ1bmN0aW9uIChwLCBjbG9zZWQpIHtcblx0XHR2YXIgaSwgaiwgaywgbGVuLCBsZW4yLCBwYXJ0LFxuXHRcdCAgICB3ID0gdGhpcy5fY2xpY2tUb2xlcmFuY2UoKTtcblxuXHRcdGlmICghdGhpcy5fcHhCb3VuZHMgfHwgIXRoaXMuX3B4Qm91bmRzLmNvbnRhaW5zKHApKSB7IHJldHVybiBmYWxzZTsgfVxuXG5cdFx0Ly8gaGl0IGRldGVjdGlvbiBmb3IgcG9seWxpbmVzXG5cdFx0Zm9yIChpID0gMCwgbGVuID0gdGhpcy5fcGFydHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdHBhcnQgPSB0aGlzLl9wYXJ0c1tpXTtcblxuXHRcdFx0Zm9yIChqID0gMCwgbGVuMiA9IHBhcnQubGVuZ3RoLCBrID0gbGVuMiAtIDE7IGogPCBsZW4yOyBrID0gaisrKSB7XG5cdFx0XHRcdGlmICghY2xvc2VkICYmIChqID09PSAwKSkgeyBjb250aW51ZTsgfVxuXG5cdFx0XHRcdGlmIChwb2ludFRvU2VnbWVudERpc3RhbmNlKHAsIHBhcnRba10sIHBhcnRbal0pIDw9IHcpIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn0pO1xuXG4vLyBAZmFjdG9yeSBMLnBvbHlsaW5lKGxhdGxuZ3M6IExhdExuZ1tdLCBvcHRpb25zPzogUG9seWxpbmUgb3B0aW9ucylcbi8vIEluc3RhbnRpYXRlcyBhIHBvbHlsaW5lIG9iamVjdCBnaXZlbiBhbiBhcnJheSBvZiBnZW9ncmFwaGljYWwgcG9pbnRzIGFuZFxuLy8gb3B0aW9uYWxseSBhbiBvcHRpb25zIG9iamVjdC4gWW91IGNhbiBjcmVhdGUgYSBgUG9seWxpbmVgIG9iamVjdCB3aXRoXG4vLyBtdWx0aXBsZSBzZXBhcmF0ZSBsaW5lcyAoYE11bHRpUG9seWxpbmVgKSBieSBwYXNzaW5nIGFuIGFycmF5IG9mIGFycmF5c1xuLy8gb2YgZ2VvZ3JhcGhpYyBwb2ludHMuXG5mdW5jdGlvbiBwb2x5bGluZShsYXRsbmdzLCBvcHRpb25zKSB7XG5cdHJldHVybiBuZXcgUG9seWxpbmUobGF0bG5ncywgb3B0aW9ucyk7XG59XG5cbi8vIFJldHJvY29tcGF0LiBBbGxvdyBwbHVnaW5zIHRvIHN1cHBvcnQgTGVhZmxldCB2ZXJzaW9ucyBiZWZvcmUgYW5kIGFmdGVyIDEuMS5cblBvbHlsaW5lLl9mbGF0ID0gX2ZsYXQ7XG5cbi8qXG4gKiBAY2xhc3MgUG9seWdvblxuICogQGFrYSBMLlBvbHlnb25cbiAqIEBpbmhlcml0cyBQb2x5bGluZVxuICpcbiAqIEEgY2xhc3MgZm9yIGRyYXdpbmcgcG9seWdvbiBvdmVybGF5cyBvbiBhIG1hcC4gRXh0ZW5kcyBgUG9seWxpbmVgLlxuICpcbiAqIE5vdGUgdGhhdCBwb2ludHMgeW91IHBhc3Mgd2hlbiBjcmVhdGluZyBhIHBvbHlnb24gc2hvdWxkbid0IGhhdmUgYW4gYWRkaXRpb25hbCBsYXN0IHBvaW50IGVxdWFsIHRvIHRoZSBmaXJzdCBvbmUg4oCUIGl0J3MgYmV0dGVyIHRvIGZpbHRlciBvdXQgc3VjaCBwb2ludHMuXG4gKlxuICpcbiAqIEBleGFtcGxlXG4gKlxuICogYGBganNcbiAqIC8vIGNyZWF0ZSBhIHJlZCBwb2x5Z29uIGZyb20gYW4gYXJyYXkgb2YgTGF0TG5nIHBvaW50c1xuICogdmFyIGxhdGxuZ3MgPSBbWzM3LCAtMTA5LjA1XSxbNDEsIC0xMDkuMDNdLFs0MSwgLTEwMi4wNV0sWzM3LCAtMTAyLjA0XV07XG4gKlxuICogdmFyIHBvbHlnb24gPSBMLnBvbHlnb24obGF0bG5ncywge2NvbG9yOiAncmVkJ30pLmFkZFRvKG1hcCk7XG4gKlxuICogLy8gem9vbSB0aGUgbWFwIHRvIHRoZSBwb2x5Z29uXG4gKiBtYXAuZml0Qm91bmRzKHBvbHlnb24uZ2V0Qm91bmRzKCkpO1xuICogYGBgXG4gKlxuICogWW91IGNhbiBhbHNvIHBhc3MgYW4gYXJyYXkgb2YgYXJyYXlzIG9mIGxhdGxuZ3MsIHdpdGggdGhlIGZpcnN0IGFycmF5IHJlcHJlc2VudGluZyB0aGUgb3V0ZXIgc2hhcGUgYW5kIHRoZSBvdGhlciBhcnJheXMgcmVwcmVzZW50aW5nIGhvbGVzIGluIHRoZSBvdXRlciBzaGFwZTpcbiAqXG4gKiBgYGBqc1xuICogdmFyIGxhdGxuZ3MgPSBbXG4gKiAgIFtbMzcsIC0xMDkuMDVdLFs0MSwgLTEwOS4wM10sWzQxLCAtMTAyLjA1XSxbMzcsIC0xMDIuMDRdXSwgLy8gb3V0ZXIgcmluZ1xuICogICBbWzM3LjI5LCAtMTA4LjU4XSxbNDAuNzEsIC0xMDguNThdLFs0MC43MSwgLTEwMi41MF0sWzM3LjI5LCAtMTAyLjUwXV0gLy8gaG9sZVxuICogXTtcbiAqIGBgYFxuICpcbiAqIEFkZGl0aW9uYWxseSwgeW91IGNhbiBwYXNzIGEgbXVsdGktZGltZW5zaW9uYWwgYXJyYXkgdG8gcmVwcmVzZW50IGEgTXVsdGlQb2x5Z29uIHNoYXBlLlxuICpcbiAqIGBgYGpzXG4gKiB2YXIgbGF0bG5ncyA9IFtcbiAqICAgWyAvLyBmaXJzdCBwb2x5Z29uXG4gKiAgICAgW1szNywgLTEwOS4wNV0sWzQxLCAtMTA5LjAzXSxbNDEsIC0xMDIuMDVdLFszNywgLTEwMi4wNF1dLCAvLyBvdXRlciByaW5nXG4gKiAgICAgW1szNy4yOSwgLTEwOC41OF0sWzQwLjcxLCAtMTA4LjU4XSxbNDAuNzEsIC0xMDIuNTBdLFszNy4yOSwgLTEwMi41MF1dIC8vIGhvbGVcbiAqICAgXSxcbiAqICAgWyAvLyBzZWNvbmQgcG9seWdvblxuICogICAgIFtbNDEsIC0xMTEuMDNdLFs0NSwgLTExMS4wNF0sWzQ1LCAtMTA0LjA1XSxbNDEsIC0xMDQuMDVdXVxuICogICBdXG4gKiBdO1xuICogYGBgXG4gKi9cblxudmFyIFBvbHlnb24gPSBQb2x5bGluZS5leHRlbmQoe1xuXG5cdG9wdGlvbnM6IHtcblx0XHRmaWxsOiB0cnVlXG5cdH0sXG5cblx0aXNFbXB0eTogZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiAhdGhpcy5fbGF0bG5ncy5sZW5ndGggfHwgIXRoaXMuX2xhdGxuZ3NbMF0ubGVuZ3RoO1xuXHR9LFxuXG5cdGdldENlbnRlcjogZnVuY3Rpb24gKCkge1xuXHRcdC8vIHRocm93cyBlcnJvciB3aGVuIG5vdCB5ZXQgYWRkZWQgdG8gbWFwIGFzIHRoaXMgY2VudGVyIGNhbGN1bGF0aW9uIHJlcXVpcmVzIHByb2plY3RlZCBjb29yZGluYXRlc1xuXHRcdGlmICghdGhpcy5fbWFwKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ011c3QgYWRkIGxheWVyIHRvIG1hcCBiZWZvcmUgdXNpbmcgZ2V0Q2VudGVyKCknKTtcblx0XHR9XG5cblx0XHR2YXIgaSwgaiwgcDEsIHAyLCBmLCBhcmVhLCB4LCB5LCBjZW50ZXIsXG5cdFx0ICAgIHBvaW50cyA9IHRoaXMuX3JpbmdzWzBdLFxuXHRcdCAgICBsZW4gPSBwb2ludHMubGVuZ3RoO1xuXG5cdFx0aWYgKCFsZW4pIHsgcmV0dXJuIG51bGw7IH1cblxuXHRcdC8vIHBvbHlnb24gY2VudHJvaWQgYWxnb3JpdGhtOyBvbmx5IHVzZXMgdGhlIGZpcnN0IHJpbmcgaWYgdGhlcmUgYXJlIG11bHRpcGxlXG5cblx0XHRhcmVhID0geCA9IHkgPSAwO1xuXG5cdFx0Zm9yIChpID0gMCwgaiA9IGxlbiAtIDE7IGkgPCBsZW47IGogPSBpKyspIHtcblx0XHRcdHAxID0gcG9pbnRzW2ldO1xuXHRcdFx0cDIgPSBwb2ludHNbal07XG5cblx0XHRcdGYgPSBwMS55ICogcDIueCAtIHAyLnkgKiBwMS54O1xuXHRcdFx0eCArPSAocDEueCArIHAyLngpICogZjtcblx0XHRcdHkgKz0gKHAxLnkgKyBwMi55KSAqIGY7XG5cdFx0XHRhcmVhICs9IGYgKiAzO1xuXHRcdH1cblxuXHRcdGlmIChhcmVhID09PSAwKSB7XG5cdFx0XHQvLyBQb2x5Z29uIGlzIHNvIHNtYWxsIHRoYXQgYWxsIHBvaW50cyBhcmUgb24gc2FtZSBwaXhlbC5cblx0XHRcdGNlbnRlciA9IHBvaW50c1swXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y2VudGVyID0gW3ggLyBhcmVhLCB5IC8gYXJlYV07XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLl9tYXAubGF5ZXJQb2ludFRvTGF0TG5nKGNlbnRlcik7XG5cdH0sXG5cblx0X2NvbnZlcnRMYXRMbmdzOiBmdW5jdGlvbiAobGF0bG5ncykge1xuXHRcdHZhciByZXN1bHQgPSBQb2x5bGluZS5wcm90b3R5cGUuX2NvbnZlcnRMYXRMbmdzLmNhbGwodGhpcywgbGF0bG5ncyksXG5cdFx0ICAgIGxlbiA9IHJlc3VsdC5sZW5ndGg7XG5cblx0XHQvLyByZW1vdmUgbGFzdCBwb2ludCBpZiBpdCBlcXVhbHMgZmlyc3Qgb25lXG5cdFx0aWYgKGxlbiA+PSAyICYmIHJlc3VsdFswXSBpbnN0YW5jZW9mIExhdExuZyAmJiByZXN1bHRbMF0uZXF1YWxzKHJlc3VsdFtsZW4gLSAxXSkpIHtcblx0XHRcdHJlc3VsdC5wb3AoKTtcblx0XHR9XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fSxcblxuXHRfc2V0TGF0TG5nczogZnVuY3Rpb24gKGxhdGxuZ3MpIHtcblx0XHRQb2x5bGluZS5wcm90b3R5cGUuX3NldExhdExuZ3MuY2FsbCh0aGlzLCBsYXRsbmdzKTtcblx0XHRpZiAoaXNGbGF0KHRoaXMuX2xhdGxuZ3MpKSB7XG5cdFx0XHR0aGlzLl9sYXRsbmdzID0gW3RoaXMuX2xhdGxuZ3NdO1xuXHRcdH1cblx0fSxcblxuXHRfZGVmYXVsdFNoYXBlOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIGlzRmxhdCh0aGlzLl9sYXRsbmdzWzBdKSA/IHRoaXMuX2xhdGxuZ3NbMF0gOiB0aGlzLl9sYXRsbmdzWzBdWzBdO1xuXHR9LFxuXG5cdF9jbGlwUG9pbnRzOiBmdW5jdGlvbiAoKSB7XG5cdFx0Ly8gcG9seWdvbnMgbmVlZCBhIGRpZmZlcmVudCBjbGlwcGluZyBhbGdvcml0aG0gc28gd2UgcmVkZWZpbmUgdGhhdFxuXG5cdFx0dmFyIGJvdW5kcyA9IHRoaXMuX3JlbmRlcmVyLl9ib3VuZHMsXG5cdFx0ICAgIHcgPSB0aGlzLm9wdGlvbnMud2VpZ2h0LFxuXHRcdCAgICBwID0gbmV3IFBvaW50KHcsIHcpO1xuXG5cdFx0Ly8gaW5jcmVhc2UgY2xpcCBwYWRkaW5nIGJ5IHN0cm9rZSB3aWR0aCB0byBhdm9pZCBzdHJva2Ugb24gY2xpcCBlZGdlc1xuXHRcdGJvdW5kcyA9IG5ldyBCb3VuZHMoYm91bmRzLm1pbi5zdWJ0cmFjdChwKSwgYm91bmRzLm1heC5hZGQocCkpO1xuXG5cdFx0dGhpcy5fcGFydHMgPSBbXTtcblx0XHRpZiAoIXRoaXMuX3B4Qm91bmRzIHx8ICF0aGlzLl9weEJvdW5kcy5pbnRlcnNlY3RzKGJvdW5kcykpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5vcHRpb25zLm5vQ2xpcCkge1xuXHRcdFx0dGhpcy5fcGFydHMgPSB0aGlzLl9yaW5ncztcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRmb3IgKHZhciBpID0gMCwgbGVuID0gdGhpcy5fcmluZ3MubGVuZ3RoLCBjbGlwcGVkOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdGNsaXBwZWQgPSBjbGlwUG9seWdvbih0aGlzLl9yaW5nc1tpXSwgYm91bmRzLCB0cnVlKTtcblx0XHRcdGlmIChjbGlwcGVkLmxlbmd0aCkge1xuXHRcdFx0XHR0aGlzLl9wYXJ0cy5wdXNoKGNsaXBwZWQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlUGF0aDogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3JlbmRlcmVyLl91cGRhdGVQb2x5KHRoaXMsIHRydWUpO1xuXHR9LFxuXG5cdC8vIE5lZWRlZCBieSB0aGUgYENhbnZhc2AgcmVuZGVyZXIgZm9yIGludGVyYWN0aXZpdHlcblx0X2NvbnRhaW5zUG9pbnQ6IGZ1bmN0aW9uIChwKSB7XG5cdFx0dmFyIGluc2lkZSA9IGZhbHNlLFxuXHRcdCAgICBwYXJ0LCBwMSwgcDIsIGksIGosIGssIGxlbiwgbGVuMjtcblxuXHRcdGlmICghdGhpcy5fcHhCb3VuZHMuY29udGFpbnMocCkpIHsgcmV0dXJuIGZhbHNlOyB9XG5cblx0XHQvLyByYXkgY2FzdGluZyBhbGdvcml0aG0gZm9yIGRldGVjdGluZyBpZiBwb2ludCBpcyBpbiBwb2x5Z29uXG5cdFx0Zm9yIChpID0gMCwgbGVuID0gdGhpcy5fcGFydHMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdHBhcnQgPSB0aGlzLl9wYXJ0c1tpXTtcblxuXHRcdFx0Zm9yIChqID0gMCwgbGVuMiA9IHBhcnQubGVuZ3RoLCBrID0gbGVuMiAtIDE7IGogPCBsZW4yOyBrID0gaisrKSB7XG5cdFx0XHRcdHAxID0gcGFydFtqXTtcblx0XHRcdFx0cDIgPSBwYXJ0W2tdO1xuXG5cdFx0XHRcdGlmICgoKHAxLnkgPiBwLnkpICE9PSAocDIueSA+IHAueSkpICYmIChwLnggPCAocDIueCAtIHAxLngpICogKHAueSAtIHAxLnkpIC8gKHAyLnkgLSBwMS55KSArIHAxLngpKSB7XG5cdFx0XHRcdFx0aW5zaWRlID0gIWluc2lkZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIGFsc28gY2hlY2sgaWYgaXQncyBvbiBwb2x5Z29uIHN0cm9rZVxuXHRcdHJldHVybiBpbnNpZGUgfHwgUG9seWxpbmUucHJvdG90eXBlLl9jb250YWluc1BvaW50LmNhbGwodGhpcywgcCwgdHJ1ZSk7XG5cdH1cblxufSk7XG5cblxuLy8gQGZhY3RvcnkgTC5wb2x5Z29uKGxhdGxuZ3M6IExhdExuZ1tdLCBvcHRpb25zPzogUG9seWxpbmUgb3B0aW9ucylcbmZ1bmN0aW9uIHBvbHlnb24obGF0bG5ncywgb3B0aW9ucykge1xuXHRyZXR1cm4gbmV3IFBvbHlnb24obGF0bG5ncywgb3B0aW9ucyk7XG59XG5cbi8qXHJcbiAqIEBjbGFzcyBHZW9KU09OXHJcbiAqIEBha2EgTC5HZW9KU09OXHJcbiAqIEBpbmhlcml0cyBGZWF0dXJlR3JvdXBcclxuICpcclxuICogUmVwcmVzZW50cyBhIEdlb0pTT04gb2JqZWN0IG9yIGFuIGFycmF5IG9mIEdlb0pTT04gb2JqZWN0cy4gQWxsb3dzIHlvdSB0byBwYXJzZVxyXG4gKiBHZW9KU09OIGRhdGEgYW5kIGRpc3BsYXkgaXQgb24gdGhlIG1hcC4gRXh0ZW5kcyBgRmVhdHVyZUdyb3VwYC5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogTC5nZW9KU09OKGRhdGEsIHtcclxuICogXHRzdHlsZTogZnVuY3Rpb24gKGZlYXR1cmUpIHtcclxuICogXHRcdHJldHVybiB7Y29sb3I6IGZlYXR1cmUucHJvcGVydGllcy5jb2xvcn07XHJcbiAqIFx0fVxyXG4gKiB9KS5iaW5kUG9wdXAoZnVuY3Rpb24gKGxheWVyKSB7XHJcbiAqIFx0cmV0dXJuIGxheWVyLmZlYXR1cmUucHJvcGVydGllcy5kZXNjcmlwdGlvbjtcclxuICogfSkuYWRkVG8obWFwKTtcclxuICogYGBgXHJcbiAqL1xyXG5cclxudmFyIEdlb0pTT04gPSBGZWF0dXJlR3JvdXAuZXh0ZW5kKHtcclxuXHJcblx0LyogQHNlY3Rpb25cclxuXHQgKiBAYWthIEdlb0pTT04gb3B0aW9uc1xyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBwb2ludFRvTGF5ZXI6IEZ1bmN0aW9uID0gKlxyXG5cdCAqIEEgYEZ1bmN0aW9uYCBkZWZpbmluZyBob3cgR2VvSlNPTiBwb2ludHMgc3Bhd24gTGVhZmxldCBsYXllcnMuIEl0IGlzIGludGVybmFsbHlcclxuXHQgKiBjYWxsZWQgd2hlbiBkYXRhIGlzIGFkZGVkLCBwYXNzaW5nIHRoZSBHZW9KU09OIHBvaW50IGZlYXR1cmUgYW5kIGl0cyBgTGF0TG5nYC5cclxuXHQgKiBUaGUgZGVmYXVsdCBpcyB0byBzcGF3biBhIGRlZmF1bHQgYE1hcmtlcmA6XHJcblx0ICogYGBganNcclxuXHQgKiBmdW5jdGlvbihnZW9Kc29uUG9pbnQsIGxhdGxuZykge1xyXG5cdCAqIFx0cmV0dXJuIEwubWFya2VyKGxhdGxuZyk7XHJcblx0ICogfVxyXG5cdCAqIGBgYFxyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBzdHlsZTogRnVuY3Rpb24gPSAqXHJcblx0ICogQSBgRnVuY3Rpb25gIGRlZmluaW5nIHRoZSBgUGF0aCBvcHRpb25zYCBmb3Igc3R5bGluZyBHZW9KU09OIGxpbmVzIGFuZCBwb2x5Z29ucyxcclxuXHQgKiBjYWxsZWQgaW50ZXJuYWxseSB3aGVuIGRhdGEgaXMgYWRkZWQuXHJcblx0ICogVGhlIGRlZmF1bHQgdmFsdWUgaXMgdG8gbm90IG92ZXJyaWRlIGFueSBkZWZhdWx0czpcclxuXHQgKiBgYGBqc1xyXG5cdCAqIGZ1bmN0aW9uIChnZW9Kc29uRmVhdHVyZSkge1xyXG5cdCAqIFx0cmV0dXJuIHt9XHJcblx0ICogfVxyXG5cdCAqIGBgYFxyXG5cdCAqXHJcblx0ICogQG9wdGlvbiBvbkVhY2hGZWF0dXJlOiBGdW5jdGlvbiA9ICpcclxuXHQgKiBBIGBGdW5jdGlvbmAgdGhhdCB3aWxsIGJlIGNhbGxlZCBvbmNlIGZvciBlYWNoIGNyZWF0ZWQgYEZlYXR1cmVgLCBhZnRlciBpdCBoYXNcclxuXHQgKiBiZWVuIGNyZWF0ZWQgYW5kIHN0eWxlZC4gVXNlZnVsIGZvciBhdHRhY2hpbmcgZXZlbnRzIGFuZCBwb3B1cHMgdG8gZmVhdHVyZXMuXHJcblx0ICogVGhlIGRlZmF1bHQgaXMgdG8gZG8gbm90aGluZyB3aXRoIHRoZSBuZXdseSBjcmVhdGVkIGxheWVyczpcclxuXHQgKiBgYGBqc1xyXG5cdCAqIGZ1bmN0aW9uIChmZWF0dXJlLCBsYXllcikge31cclxuXHQgKiBgYGBcclxuXHQgKlxyXG5cdCAqIEBvcHRpb24gZmlsdGVyOiBGdW5jdGlvbiA9ICpcclxuXHQgKiBBIGBGdW5jdGlvbmAgdGhhdCB3aWxsIGJlIHVzZWQgdG8gZGVjaWRlIHdoZXRoZXIgdG8gaW5jbHVkZSBhIGZlYXR1cmUgb3Igbm90LlxyXG5cdCAqIFRoZSBkZWZhdWx0IGlzIHRvIGluY2x1ZGUgYWxsIGZlYXR1cmVzOlxyXG5cdCAqIGBgYGpzXHJcblx0ICogZnVuY3Rpb24gKGdlb0pzb25GZWF0dXJlKSB7XHJcblx0ICogXHRyZXR1cm4gdHJ1ZTtcclxuXHQgKiB9XHJcblx0ICogYGBgXHJcblx0ICogTm90ZTogZHluYW1pY2FsbHkgY2hhbmdpbmcgdGhlIGBmaWx0ZXJgIG9wdGlvbiB3aWxsIGhhdmUgZWZmZWN0IG9ubHkgb24gbmV3bHlcclxuXHQgKiBhZGRlZCBkYXRhLiBJdCB3aWxsIF9ub3RfIHJlLWV2YWx1YXRlIGFscmVhZHkgaW5jbHVkZWQgZmVhdHVyZXMuXHJcblx0ICpcclxuXHQgKiBAb3B0aW9uIGNvb3Jkc1RvTGF0TG5nOiBGdW5jdGlvbiA9ICpcclxuXHQgKiBBIGBGdW5jdGlvbmAgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIGNvbnZlcnRpbmcgR2VvSlNPTiBjb29yZGluYXRlcyB0byBgTGF0TG5nYHMuXHJcblx0ICogVGhlIGRlZmF1bHQgaXMgdGhlIGBjb29yZHNUb0xhdExuZ2Agc3RhdGljIG1ldGhvZC5cclxuXHQgKi9cclxuXHJcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGdlb2pzb24sIG9wdGlvbnMpIHtcclxuXHRcdHNldE9wdGlvbnModGhpcywgb3B0aW9ucyk7XHJcblxyXG5cdFx0dGhpcy5fbGF5ZXJzID0ge307XHJcblxyXG5cdFx0aWYgKGdlb2pzb24pIHtcclxuXHRcdFx0dGhpcy5hZGREYXRhKGdlb2pzb24pO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgYWRkRGF0YSggPEdlb0pTT04+IGRhdGEgKTogdGhpc1xyXG5cdC8vIEFkZHMgYSBHZW9KU09OIG9iamVjdCB0byB0aGUgbGF5ZXIuXHJcblx0YWRkRGF0YTogZnVuY3Rpb24gKGdlb2pzb24pIHtcclxuXHRcdHZhciBmZWF0dXJlcyA9IGlzQXJyYXkoZ2VvanNvbikgPyBnZW9qc29uIDogZ2VvanNvbi5mZWF0dXJlcyxcclxuXHRcdCAgICBpLCBsZW4sIGZlYXR1cmU7XHJcblxyXG5cdFx0aWYgKGZlYXR1cmVzKSB7XHJcblx0XHRcdGZvciAoaSA9IDAsIGxlbiA9IGZlYXR1cmVzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdFx0Ly8gb25seSBhZGQgdGhpcyBpZiBnZW9tZXRyeSBvciBnZW9tZXRyaWVzIGFyZSBzZXQgYW5kIG5vdCBudWxsXHJcblx0XHRcdFx0ZmVhdHVyZSA9IGZlYXR1cmVzW2ldO1xyXG5cdFx0XHRcdGlmIChmZWF0dXJlLmdlb21ldHJpZXMgfHwgZmVhdHVyZS5nZW9tZXRyeSB8fCBmZWF0dXJlLmZlYXR1cmVzIHx8IGZlYXR1cmUuY29vcmRpbmF0ZXMpIHtcclxuXHRcdFx0XHRcdHRoaXMuYWRkRGF0YShmZWF0dXJlKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XHJcblxyXG5cdFx0aWYgKG9wdGlvbnMuZmlsdGVyICYmICFvcHRpb25zLmZpbHRlcihnZW9qc29uKSkgeyByZXR1cm4gdGhpczsgfVxyXG5cclxuXHRcdHZhciBsYXllciA9IGdlb21ldHJ5VG9MYXllcihnZW9qc29uLCBvcHRpb25zKTtcclxuXHRcdGlmICghbGF5ZXIpIHtcclxuXHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHR9XHJcblx0XHRsYXllci5mZWF0dXJlID0gYXNGZWF0dXJlKGdlb2pzb24pO1xyXG5cclxuXHRcdGxheWVyLmRlZmF1bHRPcHRpb25zID0gbGF5ZXIub3B0aW9ucztcclxuXHRcdHRoaXMucmVzZXRTdHlsZShsYXllcik7XHJcblxyXG5cdFx0aWYgKG9wdGlvbnMub25FYWNoRmVhdHVyZSkge1xyXG5cdFx0XHRvcHRpb25zLm9uRWFjaEZlYXR1cmUoZ2VvanNvbiwgbGF5ZXIpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0aGlzLmFkZExheWVyKGxheWVyKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHJlc2V0U3R5bGUoIDxQYXRoPiBsYXllciApOiB0aGlzXHJcblx0Ly8gUmVzZXRzIHRoZSBnaXZlbiB2ZWN0b3IgbGF5ZXIncyBzdHlsZSB0byB0aGUgb3JpZ2luYWwgR2VvSlNPTiBzdHlsZSwgdXNlZnVsIGZvciByZXNldHRpbmcgc3R5bGUgYWZ0ZXIgaG92ZXIgZXZlbnRzLlxyXG5cdHJlc2V0U3R5bGU6IGZ1bmN0aW9uIChsYXllcikge1xyXG5cdFx0Ly8gcmVzZXQgYW55IGN1c3RvbSBzdHlsZXNcclxuXHRcdGxheWVyLm9wdGlvbnMgPSBleHRlbmQoe30sIGxheWVyLmRlZmF1bHRPcHRpb25zKTtcclxuXHRcdHRoaXMuX3NldExheWVyU3R5bGUobGF5ZXIsIHRoaXMub3B0aW9ucy5zdHlsZSk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNldFN0eWxlKCA8RnVuY3Rpb24+IHN0eWxlICk6IHRoaXNcclxuXHQvLyBDaGFuZ2VzIHN0eWxlcyBvZiBHZW9KU09OIHZlY3RvciBsYXllcnMgd2l0aCB0aGUgZ2l2ZW4gc3R5bGUgZnVuY3Rpb24uXHJcblx0c2V0U3R5bGU6IGZ1bmN0aW9uIChzdHlsZSkge1xyXG5cdFx0cmV0dXJuIHRoaXMuZWFjaExheWVyKGZ1bmN0aW9uIChsYXllcikge1xyXG5cdFx0XHR0aGlzLl9zZXRMYXllclN0eWxlKGxheWVyLCBzdHlsZSk7XHJcblx0XHR9LCB0aGlzKTtcclxuXHR9LFxyXG5cclxuXHRfc2V0TGF5ZXJTdHlsZTogZnVuY3Rpb24gKGxheWVyLCBzdHlsZSkge1xyXG5cdFx0aWYgKHR5cGVvZiBzdHlsZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG5cdFx0XHRzdHlsZSA9IHN0eWxlKGxheWVyLmZlYXR1cmUpO1xyXG5cdFx0fVxyXG5cdFx0aWYgKGxheWVyLnNldFN0eWxlKSB7XHJcblx0XHRcdGxheWVyLnNldFN0eWxlKHN0eWxlKTtcclxuXHRcdH1cclxuXHR9XHJcbn0pO1xyXG5cclxuLy8gQHNlY3Rpb25cclxuLy8gVGhlcmUgYXJlIHNldmVyYWwgc3RhdGljIGZ1bmN0aW9ucyB3aGljaCBjYW4gYmUgY2FsbGVkIHdpdGhvdXQgaW5zdGFudGlhdGluZyBMLkdlb0pTT046XHJcblxyXG4vLyBAZnVuY3Rpb24gZ2VvbWV0cnlUb0xheWVyKGZlYXR1cmVEYXRhOiBPYmplY3QsIG9wdGlvbnM/OiBHZW9KU09OIG9wdGlvbnMpOiBMYXllclxyXG4vLyBDcmVhdGVzIGEgYExheWVyYCBmcm9tIGEgZ2l2ZW4gR2VvSlNPTiBmZWF0dXJlLiBDYW4gdXNlIGEgY3VzdG9tXHJcbi8vIFtgcG9pbnRUb0xheWVyYF0oI2dlb2pzb24tcG9pbnR0b2xheWVyKSBhbmQvb3IgW2Bjb29yZHNUb0xhdExuZ2BdKCNnZW9qc29uLWNvb3Jkc3RvbGF0bG5nKVxyXG4vLyBmdW5jdGlvbnMgaWYgcHJvdmlkZWQgYXMgb3B0aW9ucy5cclxuZnVuY3Rpb24gZ2VvbWV0cnlUb0xheWVyKGdlb2pzb24sIG9wdGlvbnMpIHtcclxuXHJcblx0dmFyIGdlb21ldHJ5ID0gZ2VvanNvbi50eXBlID09PSAnRmVhdHVyZScgPyBnZW9qc29uLmdlb21ldHJ5IDogZ2VvanNvbixcclxuXHQgICAgY29vcmRzID0gZ2VvbWV0cnkgPyBnZW9tZXRyeS5jb29yZGluYXRlcyA6IG51bGwsXHJcblx0ICAgIGxheWVycyA9IFtdLFxyXG5cdCAgICBwb2ludFRvTGF5ZXIgPSBvcHRpb25zICYmIG9wdGlvbnMucG9pbnRUb0xheWVyLFxyXG5cdCAgICBfY29vcmRzVG9MYXRMbmcgPSBvcHRpb25zICYmIG9wdGlvbnMuY29vcmRzVG9MYXRMbmcgfHwgY29vcmRzVG9MYXRMbmcsXHJcblx0ICAgIGxhdGxuZywgbGF0bG5ncywgaSwgbGVuO1xyXG5cclxuXHRpZiAoIWNvb3JkcyAmJiAhZ2VvbWV0cnkpIHtcclxuXHRcdHJldHVybiBudWxsO1xyXG5cdH1cclxuXHJcblx0c3dpdGNoIChnZW9tZXRyeS50eXBlKSB7XHJcblx0Y2FzZSAnUG9pbnQnOlxyXG5cdFx0bGF0bG5nID0gX2Nvb3Jkc1RvTGF0TG5nKGNvb3Jkcyk7XHJcblx0XHRyZXR1cm4gcG9pbnRUb0xheWVyID8gcG9pbnRUb0xheWVyKGdlb2pzb24sIGxhdGxuZykgOiBuZXcgTWFya2VyKGxhdGxuZyk7XHJcblxyXG5cdGNhc2UgJ011bHRpUG9pbnQnOlxyXG5cdFx0Zm9yIChpID0gMCwgbGVuID0gY29vcmRzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XHJcblx0XHRcdGxhdGxuZyA9IF9jb29yZHNUb0xhdExuZyhjb29yZHNbaV0pO1xyXG5cdFx0XHRsYXllcnMucHVzaChwb2ludFRvTGF5ZXIgPyBwb2ludFRvTGF5ZXIoZ2VvanNvbiwgbGF0bG5nKSA6IG5ldyBNYXJrZXIobGF0bG5nKSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gbmV3IEZlYXR1cmVHcm91cChsYXllcnMpO1xyXG5cclxuXHRjYXNlICdMaW5lU3RyaW5nJzpcclxuXHRjYXNlICdNdWx0aUxpbmVTdHJpbmcnOlxyXG5cdFx0bGF0bG5ncyA9IGNvb3Jkc1RvTGF0TG5ncyhjb29yZHMsIGdlb21ldHJ5LnR5cGUgPT09ICdMaW5lU3RyaW5nJyA/IDAgOiAxLCBfY29vcmRzVG9MYXRMbmcpO1xyXG5cdFx0cmV0dXJuIG5ldyBQb2x5bGluZShsYXRsbmdzLCBvcHRpb25zKTtcclxuXHJcblx0Y2FzZSAnUG9seWdvbic6XHJcblx0Y2FzZSAnTXVsdGlQb2x5Z29uJzpcclxuXHRcdGxhdGxuZ3MgPSBjb29yZHNUb0xhdExuZ3MoY29vcmRzLCBnZW9tZXRyeS50eXBlID09PSAnUG9seWdvbicgPyAxIDogMiwgX2Nvb3Jkc1RvTGF0TG5nKTtcclxuXHRcdHJldHVybiBuZXcgUG9seWdvbihsYXRsbmdzLCBvcHRpb25zKTtcclxuXHJcblx0Y2FzZSAnR2VvbWV0cnlDb2xsZWN0aW9uJzpcclxuXHRcdGZvciAoaSA9IDAsIGxlbiA9IGdlb21ldHJ5Lmdlb21ldHJpZXMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdFx0dmFyIGxheWVyID0gZ2VvbWV0cnlUb0xheWVyKHtcclxuXHRcdFx0XHRnZW9tZXRyeTogZ2VvbWV0cnkuZ2VvbWV0cmllc1tpXSxcclxuXHRcdFx0XHR0eXBlOiAnRmVhdHVyZScsXHJcblx0XHRcdFx0cHJvcGVydGllczogZ2VvanNvbi5wcm9wZXJ0aWVzXHJcblx0XHRcdH0sIG9wdGlvbnMpO1xyXG5cclxuXHRcdFx0aWYgKGxheWVyKSB7XHJcblx0XHRcdFx0bGF5ZXJzLnB1c2gobGF5ZXIpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gbmV3IEZlYXR1cmVHcm91cChsYXllcnMpO1xyXG5cclxuXHRkZWZhdWx0OlxyXG5cdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIEdlb0pTT04gb2JqZWN0LicpO1xyXG5cdH1cclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGNvb3Jkc1RvTGF0TG5nKGNvb3JkczogQXJyYXkpOiBMYXRMbmdcclxuLy8gQ3JlYXRlcyBhIGBMYXRMbmdgIG9iamVjdCBmcm9tIGFuIGFycmF5IG9mIDIgbnVtYmVycyAobG9uZ2l0dWRlLCBsYXRpdHVkZSlcclxuLy8gb3IgMyBudW1iZXJzIChsb25naXR1ZGUsIGxhdGl0dWRlLCBhbHRpdHVkZSkgdXNlZCBpbiBHZW9KU09OIGZvciBwb2ludHMuXHJcbmZ1bmN0aW9uIGNvb3Jkc1RvTGF0TG5nKGNvb3Jkcykge1xyXG5cdHJldHVybiBuZXcgTGF0TG5nKGNvb3Jkc1sxXSwgY29vcmRzWzBdLCBjb29yZHNbMl0pO1xyXG59XHJcblxyXG4vLyBAZnVuY3Rpb24gY29vcmRzVG9MYXRMbmdzKGNvb3JkczogQXJyYXksIGxldmVsc0RlZXA/OiBOdW1iZXIsIGNvb3Jkc1RvTGF0TG5nPzogRnVuY3Rpb24pOiBBcnJheVxyXG4vLyBDcmVhdGVzIGEgbXVsdGlkaW1lbnNpb25hbCBhcnJheSBvZiBgTGF0TG5nYHMgZnJvbSBhIEdlb0pTT04gY29vcmRpbmF0ZXMgYXJyYXkuXHJcbi8vIGBsZXZlbHNEZWVwYCBzcGVjaWZpZXMgdGhlIG5lc3RpbmcgbGV2ZWwgKDAgaXMgZm9yIGFuIGFycmF5IG9mIHBvaW50cywgMSBmb3IgYW4gYXJyYXkgb2YgYXJyYXlzIG9mIHBvaW50cywgZXRjLiwgMCBieSBkZWZhdWx0KS5cclxuLy8gQ2FuIHVzZSBhIGN1c3RvbSBbYGNvb3Jkc1RvTGF0TG5nYF0oI2dlb2pzb24tY29vcmRzdG9sYXRsbmcpIGZ1bmN0aW9uLlxyXG5mdW5jdGlvbiBjb29yZHNUb0xhdExuZ3MoY29vcmRzLCBsZXZlbHNEZWVwLCBfY29vcmRzVG9MYXRMbmcpIHtcclxuXHR2YXIgbGF0bG5ncyA9IFtdO1xyXG5cclxuXHRmb3IgKHZhciBpID0gMCwgbGVuID0gY29vcmRzLmxlbmd0aCwgbGF0bG5nOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdGxhdGxuZyA9IGxldmVsc0RlZXAgP1xyXG5cdFx0XHRjb29yZHNUb0xhdExuZ3MoY29vcmRzW2ldLCBsZXZlbHNEZWVwIC0gMSwgX2Nvb3Jkc1RvTGF0TG5nKSA6XHJcblx0XHRcdChfY29vcmRzVG9MYXRMbmcgfHwgY29vcmRzVG9MYXRMbmcpKGNvb3Jkc1tpXSk7XHJcblxyXG5cdFx0bGF0bG5ncy5wdXNoKGxhdGxuZyk7XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gbGF0bG5ncztcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGxhdExuZ1RvQ29vcmRzKGxhdGxuZzogTGF0TG5nLCBwcmVjaXNpb24/OiBOdW1iZXIpOiBBcnJheVxyXG4vLyBSZXZlcnNlIG9mIFtgY29vcmRzVG9MYXRMbmdgXSgjZ2VvanNvbi1jb29yZHN0b2xhdGxuZylcclxuZnVuY3Rpb24gbGF0TG5nVG9Db29yZHMobGF0bG5nLCBwcmVjaXNpb24pIHtcclxuXHRwcmVjaXNpb24gPSB0eXBlb2YgcHJlY2lzaW9uID09PSAnbnVtYmVyJyA/IHByZWNpc2lvbiA6IDY7XHJcblx0cmV0dXJuIGxhdGxuZy5hbHQgIT09IHVuZGVmaW5lZCA/XHJcblx0XHRbZm9ybWF0TnVtKGxhdGxuZy5sbmcsIHByZWNpc2lvbiksIGZvcm1hdE51bShsYXRsbmcubGF0LCBwcmVjaXNpb24pLCBmb3JtYXROdW0obGF0bG5nLmFsdCwgcHJlY2lzaW9uKV0gOlxyXG5cdFx0W2Zvcm1hdE51bShsYXRsbmcubG5nLCBwcmVjaXNpb24pLCBmb3JtYXROdW0obGF0bG5nLmxhdCwgcHJlY2lzaW9uKV07XHJcbn1cclxuXHJcbi8vIEBmdW5jdGlvbiBsYXRMbmdzVG9Db29yZHMobGF0bG5nczogQXJyYXksIGxldmVsc0RlZXA/OiBOdW1iZXIsIGNsb3NlZD86IEJvb2xlYW4pOiBBcnJheVxyXG4vLyBSZXZlcnNlIG9mIFtgY29vcmRzVG9MYXRMbmdzYF0oI2dlb2pzb24tY29vcmRzdG9sYXRsbmdzKVxyXG4vLyBgY2xvc2VkYCBkZXRlcm1pbmVzIHdoZXRoZXIgdGhlIGZpcnN0IHBvaW50IHNob3VsZCBiZSBhcHBlbmRlZCB0byB0aGUgZW5kIG9mIHRoZSBhcnJheSB0byBjbG9zZSB0aGUgZmVhdHVyZSwgb25seSB1c2VkIHdoZW4gYGxldmVsc0RlZXBgIGlzIDAuIEZhbHNlIGJ5IGRlZmF1bHQuXHJcbmZ1bmN0aW9uIGxhdExuZ3NUb0Nvb3JkcyhsYXRsbmdzLCBsZXZlbHNEZWVwLCBjbG9zZWQsIHByZWNpc2lvbikge1xyXG5cdHZhciBjb29yZHMgPSBbXTtcclxuXHJcblx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGxhdGxuZ3MubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcclxuXHRcdGNvb3Jkcy5wdXNoKGxldmVsc0RlZXAgP1xyXG5cdFx0XHRsYXRMbmdzVG9Db29yZHMobGF0bG5nc1tpXSwgbGV2ZWxzRGVlcCAtIDEsIGNsb3NlZCwgcHJlY2lzaW9uKSA6XHJcblx0XHRcdGxhdExuZ1RvQ29vcmRzKGxhdGxuZ3NbaV0sIHByZWNpc2lvbikpO1xyXG5cdH1cclxuXHJcblx0aWYgKCFsZXZlbHNEZWVwICYmIGNsb3NlZCkge1xyXG5cdFx0Y29vcmRzLnB1c2goY29vcmRzWzBdKTtcclxuXHR9XHJcblxyXG5cdHJldHVybiBjb29yZHM7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldEZlYXR1cmUobGF5ZXIsIG5ld0dlb21ldHJ5KSB7XHJcblx0cmV0dXJuIGxheWVyLmZlYXR1cmUgP1xyXG5cdFx0ZXh0ZW5kKHt9LCBsYXllci5mZWF0dXJlLCB7Z2VvbWV0cnk6IG5ld0dlb21ldHJ5fSkgOlxyXG5cdFx0YXNGZWF0dXJlKG5ld0dlb21ldHJ5KTtcclxufVxyXG5cclxuLy8gQGZ1bmN0aW9uIGFzRmVhdHVyZShnZW9qc29uOiBPYmplY3QpOiBPYmplY3RcclxuLy8gTm9ybWFsaXplIEdlb0pTT04gZ2VvbWV0cmllcy9mZWF0dXJlcyBpbnRvIEdlb0pTT04gZmVhdHVyZXMuXHJcbmZ1bmN0aW9uIGFzRmVhdHVyZShnZW9qc29uKSB7XHJcblx0aWYgKGdlb2pzb24udHlwZSA9PT0gJ0ZlYXR1cmUnIHx8IGdlb2pzb24udHlwZSA9PT0gJ0ZlYXR1cmVDb2xsZWN0aW9uJykge1xyXG5cdFx0cmV0dXJuIGdlb2pzb247XHJcblx0fVxyXG5cclxuXHRyZXR1cm4ge1xyXG5cdFx0dHlwZTogJ0ZlYXR1cmUnLFxyXG5cdFx0cHJvcGVydGllczoge30sXHJcblx0XHRnZW9tZXRyeTogZ2VvanNvblxyXG5cdH07XHJcbn1cclxuXHJcbnZhciBQb2ludFRvR2VvSlNPTiA9IHtcclxuXHR0b0dlb0pTT046IGZ1bmN0aW9uIChwcmVjaXNpb24pIHtcclxuXHRcdHJldHVybiBnZXRGZWF0dXJlKHRoaXMsIHtcclxuXHRcdFx0dHlwZTogJ1BvaW50JyxcclxuXHRcdFx0Y29vcmRpbmF0ZXM6IGxhdExuZ1RvQ29vcmRzKHRoaXMuZ2V0TGF0TG5nKCksIHByZWNpc2lvbilcclxuXHRcdH0pO1xyXG5cdH1cclxufTtcclxuXHJcbi8vIEBuYW1lc3BhY2UgTWFya2VyXHJcbi8vIEBtZXRob2QgdG9HZW9KU09OKCk6IE9iamVjdFxyXG4vLyBSZXR1cm5zIGEgW2BHZW9KU09OYF0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HZW9KU09OKSByZXByZXNlbnRhdGlvbiBvZiB0aGUgbWFya2VyIChhcyBhIEdlb0pTT04gYFBvaW50YCBGZWF0dXJlKS5cclxuTWFya2VyLmluY2x1ZGUoUG9pbnRUb0dlb0pTT04pO1xyXG5cclxuLy8gQG5hbWVzcGFjZSBDaXJjbGVNYXJrZXJcclxuLy8gQG1ldGhvZCB0b0dlb0pTT04oKTogT2JqZWN0XHJcbi8vIFJldHVybnMgYSBbYEdlb0pTT05gXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dlb0pTT04pIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBjaXJjbGUgbWFya2VyIChhcyBhIEdlb0pTT04gYFBvaW50YCBGZWF0dXJlKS5cclxuQ2lyY2xlLmluY2x1ZGUoUG9pbnRUb0dlb0pTT04pO1xyXG5DaXJjbGVNYXJrZXIuaW5jbHVkZShQb2ludFRvR2VvSlNPTik7XHJcblxyXG5cclxuLy8gQG5hbWVzcGFjZSBQb2x5bGluZVxyXG4vLyBAbWV0aG9kIHRvR2VvSlNPTigpOiBPYmplY3RcclxuLy8gUmV0dXJucyBhIFtgR2VvSlNPTmBdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvR2VvSlNPTikgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBvbHlsaW5lIChhcyBhIEdlb0pTT04gYExpbmVTdHJpbmdgIG9yIGBNdWx0aUxpbmVTdHJpbmdgIEZlYXR1cmUpLlxyXG5Qb2x5bGluZS5pbmNsdWRlKHtcclxuXHR0b0dlb0pTT046IGZ1bmN0aW9uIChwcmVjaXNpb24pIHtcclxuXHRcdHZhciBtdWx0aSA9ICFpc0ZsYXQodGhpcy5fbGF0bG5ncyk7XHJcblxyXG5cdFx0dmFyIGNvb3JkcyA9IGxhdExuZ3NUb0Nvb3Jkcyh0aGlzLl9sYXRsbmdzLCBtdWx0aSA/IDEgOiAwLCBmYWxzZSwgcHJlY2lzaW9uKTtcclxuXHJcblx0XHRyZXR1cm4gZ2V0RmVhdHVyZSh0aGlzLCB7XHJcblx0XHRcdHR5cGU6IChtdWx0aSA/ICdNdWx0aScgOiAnJykgKyAnTGluZVN0cmluZycsXHJcblx0XHRcdGNvb3JkaW5hdGVzOiBjb29yZHNcclxuXHRcdH0pO1xyXG5cdH1cclxufSk7XHJcblxyXG4vLyBAbmFtZXNwYWNlIFBvbHlnb25cclxuLy8gQG1ldGhvZCB0b0dlb0pTT04oKTogT2JqZWN0XHJcbi8vIFJldHVybnMgYSBbYEdlb0pTT05gXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dlb0pTT04pIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwb2x5Z29uIChhcyBhIEdlb0pTT04gYFBvbHlnb25gIG9yIGBNdWx0aVBvbHlnb25gIEZlYXR1cmUpLlxyXG5Qb2x5Z29uLmluY2x1ZGUoe1xyXG5cdHRvR2VvSlNPTjogZnVuY3Rpb24gKHByZWNpc2lvbikge1xyXG5cdFx0dmFyIGhvbGVzID0gIWlzRmxhdCh0aGlzLl9sYXRsbmdzKSxcclxuXHRcdCAgICBtdWx0aSA9IGhvbGVzICYmICFpc0ZsYXQodGhpcy5fbGF0bG5nc1swXSk7XHJcblxyXG5cdFx0dmFyIGNvb3JkcyA9IGxhdExuZ3NUb0Nvb3Jkcyh0aGlzLl9sYXRsbmdzLCBtdWx0aSA/IDIgOiBob2xlcyA/IDEgOiAwLCB0cnVlLCBwcmVjaXNpb24pO1xyXG5cclxuXHRcdGlmICghaG9sZXMpIHtcclxuXHRcdFx0Y29vcmRzID0gW2Nvb3Jkc107XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIGdldEZlYXR1cmUodGhpcywge1xyXG5cdFx0XHR0eXBlOiAobXVsdGkgPyAnTXVsdGknIDogJycpICsgJ1BvbHlnb24nLFxyXG5cdFx0XHRjb29yZGluYXRlczogY29vcmRzXHJcblx0XHR9KTtcclxuXHR9XHJcbn0pO1xyXG5cclxuXHJcbi8vIEBuYW1lc3BhY2UgTGF5ZXJHcm91cFxyXG5MYXllckdyb3VwLmluY2x1ZGUoe1xyXG5cdHRvTXVsdGlQb2ludDogZnVuY3Rpb24gKHByZWNpc2lvbikge1xyXG5cdFx0dmFyIGNvb3JkcyA9IFtdO1xyXG5cclxuXHRcdHRoaXMuZWFjaExheWVyKGZ1bmN0aW9uIChsYXllcikge1xyXG5cdFx0XHRjb29yZHMucHVzaChsYXllci50b0dlb0pTT04ocHJlY2lzaW9uKS5nZW9tZXRyeS5jb29yZGluYXRlcyk7XHJcblx0XHR9KTtcclxuXHJcblx0XHRyZXR1cm4gZ2V0RmVhdHVyZSh0aGlzLCB7XHJcblx0XHRcdHR5cGU6ICdNdWx0aVBvaW50JyxcclxuXHRcdFx0Y29vcmRpbmF0ZXM6IGNvb3Jkc1xyXG5cdFx0fSk7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB0b0dlb0pTT04oKTogT2JqZWN0XHJcblx0Ly8gUmV0dXJucyBhIFtgR2VvSlNPTmBdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvR2VvSlNPTikgcmVwcmVzZW50YXRpb24gb2YgdGhlIGxheWVyIGdyb3VwIChhcyBhIEdlb0pTT04gYEZlYXR1cmVDb2xsZWN0aW9uYCwgYEdlb21ldHJ5Q29sbGVjdGlvbmAsIG9yIGBNdWx0aVBvaW50YCkuXHJcblx0dG9HZW9KU09OOiBmdW5jdGlvbiAocHJlY2lzaW9uKSB7XHJcblxyXG5cdFx0dmFyIHR5cGUgPSB0aGlzLmZlYXR1cmUgJiYgdGhpcy5mZWF0dXJlLmdlb21ldHJ5ICYmIHRoaXMuZmVhdHVyZS5nZW9tZXRyeS50eXBlO1xyXG5cclxuXHRcdGlmICh0eXBlID09PSAnTXVsdGlQb2ludCcpIHtcclxuXHRcdFx0cmV0dXJuIHRoaXMudG9NdWx0aVBvaW50KHByZWNpc2lvbik7XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIGlzR2VvbWV0cnlDb2xsZWN0aW9uID0gdHlwZSA9PT0gJ0dlb21ldHJ5Q29sbGVjdGlvbicsXHJcblx0XHQgICAganNvbnMgPSBbXTtcclxuXHJcblx0XHR0aGlzLmVhY2hMYXllcihmdW5jdGlvbiAobGF5ZXIpIHtcclxuXHRcdFx0aWYgKGxheWVyLnRvR2VvSlNPTikge1xyXG5cdFx0XHRcdHZhciBqc29uID0gbGF5ZXIudG9HZW9KU09OKHByZWNpc2lvbik7XHJcblx0XHRcdFx0aWYgKGlzR2VvbWV0cnlDb2xsZWN0aW9uKSB7XHJcblx0XHRcdFx0XHRqc29ucy5wdXNoKGpzb24uZ2VvbWV0cnkpO1xyXG5cdFx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0XHR2YXIgZmVhdHVyZSA9IGFzRmVhdHVyZShqc29uKTtcclxuXHRcdFx0XHRcdC8vIFNxdWFzaCBuZXN0ZWQgZmVhdHVyZSBjb2xsZWN0aW9uc1xyXG5cdFx0XHRcdFx0aWYgKGZlYXR1cmUudHlwZSA9PT0gJ0ZlYXR1cmVDb2xsZWN0aW9uJykge1xyXG5cdFx0XHRcdFx0XHRqc29ucy5wdXNoLmFwcGx5KGpzb25zLCBmZWF0dXJlLmZlYXR1cmVzKTtcclxuXHRcdFx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0XHRcdGpzb25zLnB1c2goZmVhdHVyZSk7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9KTtcclxuXHJcblx0XHRpZiAoaXNHZW9tZXRyeUNvbGxlY3Rpb24pIHtcclxuXHRcdFx0cmV0dXJuIGdldEZlYXR1cmUodGhpcywge1xyXG5cdFx0XHRcdGdlb21ldHJpZXM6IGpzb25zLFxyXG5cdFx0XHRcdHR5cGU6ICdHZW9tZXRyeUNvbGxlY3Rpb24nXHJcblx0XHRcdH0pO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB7XHJcblx0XHRcdHR5cGU6ICdGZWF0dXJlQ29sbGVjdGlvbicsXHJcblx0XHRcdGZlYXR1cmVzOiBqc29uc1xyXG5cdFx0fTtcclxuXHR9XHJcbn0pO1xyXG5cclxuLy8gQG5hbWVzcGFjZSBHZW9KU09OXHJcbi8vIEBmYWN0b3J5IEwuZ2VvSlNPTihnZW9qc29uPzogT2JqZWN0LCBvcHRpb25zPzogR2VvSlNPTiBvcHRpb25zKVxyXG4vLyBDcmVhdGVzIGEgR2VvSlNPTiBsYXllci4gT3B0aW9uYWxseSBhY2NlcHRzIGFuIG9iamVjdCBpblxyXG4vLyBbR2VvSlNPTiBmb3JtYXRdKGh0dHA6Ly9nZW9qc29uLm9yZy9nZW9qc29uLXNwZWMuaHRtbCkgdG8gZGlzcGxheSBvbiB0aGUgbWFwXHJcbi8vICh5b3UgY2FuIGFsdGVybmF0aXZlbHkgYWRkIGl0IGxhdGVyIHdpdGggYGFkZERhdGFgIG1ldGhvZCkgYW5kIGFuIGBvcHRpb25zYCBvYmplY3QuXHJcbmZ1bmN0aW9uIGdlb0pTT04oZ2VvanNvbiwgb3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgR2VvSlNPTihnZW9qc29uLCBvcHRpb25zKTtcclxufVxyXG5cclxuLy8gQmFja3dhcmQgY29tcGF0aWJpbGl0eS5cclxudmFyIGdlb0pzb24gPSBnZW9KU09OO1xuXG4vKlxyXG4gKiBAY2xhc3MgSW1hZ2VPdmVybGF5XHJcbiAqIEBha2EgTC5JbWFnZU92ZXJsYXlcclxuICogQGluaGVyaXRzIEludGVyYWN0aXZlIGxheWVyXHJcbiAqXHJcbiAqIFVzZWQgdG8gbG9hZCBhbmQgZGlzcGxheSBhIHNpbmdsZSBpbWFnZSBvdmVyIHNwZWNpZmljIGJvdW5kcyBvZiB0aGUgbWFwLiBFeHRlbmRzIGBMYXllcmAuXHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBpbWFnZVVybCA9ICdodHRwOi8vd3d3LmxpYi51dGV4YXMuZWR1L21hcHMvaGlzdG9yaWNhbC9uZXdhcmtfbmpfMTkyMi5qcGcnLFxyXG4gKiBcdGltYWdlQm91bmRzID0gW1s0MC43MTIyMTYsIC03NC4yMjY1NV0sIFs0MC43NzM5NDEsIC03NC4xMjU0NF1dO1xyXG4gKiBMLmltYWdlT3ZlcmxheShpbWFnZVVybCwgaW1hZ2VCb3VuZHMpLmFkZFRvKG1hcCk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBJbWFnZU92ZXJsYXkgPSBMYXllci5leHRlbmQoe1xyXG5cclxuXHQvLyBAc2VjdGlvblxyXG5cdC8vIEBha2EgSW1hZ2VPdmVybGF5IG9wdGlvbnNcclxuXHRvcHRpb25zOiB7XHJcblx0XHQvLyBAb3B0aW9uIG9wYWNpdHk6IE51bWJlciA9IDEuMFxyXG5cdFx0Ly8gVGhlIG9wYWNpdHkgb2YgdGhlIGltYWdlIG92ZXJsYXkuXHJcblx0XHRvcGFjaXR5OiAxLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gYWx0OiBTdHJpbmcgPSAnJ1xyXG5cdFx0Ly8gVGV4dCBmb3IgdGhlIGBhbHRgIGF0dHJpYnV0ZSBvZiB0aGUgaW1hZ2UgKHVzZWZ1bCBmb3IgYWNjZXNzaWJpbGl0eSkuXHJcblx0XHRhbHQ6ICcnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gaW50ZXJhY3RpdmU6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gSWYgYHRydWVgLCB0aGUgaW1hZ2Ugb3ZlcmxheSB3aWxsIGVtaXQgW21vdXNlIGV2ZW50c10oI2ludGVyYWN0aXZlLWxheWVyKSB3aGVuIGNsaWNrZWQgb3IgaG92ZXJlZC5cclxuXHRcdGludGVyYWN0aXZlOiBmYWxzZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGNyb3NzT3JpZ2luOiBCb29sZWFuID0gZmFsc2VcclxuXHRcdC8vIElmIHRydWUsIHRoZSBpbWFnZSB3aWxsIGhhdmUgaXRzIGNyb3NzT3JpZ2luIGF0dHJpYnV0ZSBzZXQgdG8gJycuIFRoaXMgaXMgbmVlZGVkIGlmIHlvdSB3YW50IHRvIGFjY2VzcyBpbWFnZSBwaXhlbCBkYXRhLlxyXG5cdFx0Y3Jvc3NPcmlnaW46IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gZXJyb3JPdmVybGF5VXJsOiBTdHJpbmcgPSAnJ1xyXG5cdFx0Ly8gVVJMIHRvIHRoZSBvdmVybGF5IGltYWdlIHRvIHNob3cgaW4gcGxhY2Ugb2YgdGhlIG92ZXJsYXkgdGhhdCBmYWlsZWQgdG8gbG9hZC5cclxuXHRcdGVycm9yT3ZlcmxheVVybDogJycsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiB6SW5kZXg6IE51bWJlciA9IDFcclxuXHRcdC8vIFRoZSBleHBsaWNpdCBbekluZGV4XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9DU1MvQ1NTX1Bvc2l0aW9uaW5nL1VuZGVyc3RhbmRpbmdfel9pbmRleCkgb2YgdGhlIHRpbGUgbGF5ZXIuXHJcblx0XHR6SW5kZXg6IDEsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9ICcnXHJcblx0XHQvLyBBIGN1c3RvbSBjbGFzcyBuYW1lIHRvIGFzc2lnbiB0byB0aGUgaW1hZ2UuIEVtcHR5IGJ5IGRlZmF1bHQuXHJcblx0XHRjbGFzc05hbWU6ICcnLFxyXG5cdH0sXHJcblxyXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uICh1cmwsIGJvdW5kcywgb3B0aW9ucykgeyAvLyAoU3RyaW5nLCBMYXRMbmdCb3VuZHMsIE9iamVjdClcclxuXHRcdHRoaXMuX3VybCA9IHVybDtcclxuXHRcdHRoaXMuX2JvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHR9LFxyXG5cclxuXHRvbkFkZDogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKCF0aGlzLl9pbWFnZSkge1xyXG5cdFx0XHR0aGlzLl9pbml0SW1hZ2UoKTtcclxuXHJcblx0XHRcdGlmICh0aGlzLm9wdGlvbnMub3BhY2l0eSA8IDEpIHtcclxuXHRcdFx0XHR0aGlzLl91cGRhdGVPcGFjaXR5KCk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRpZiAodGhpcy5vcHRpb25zLmludGVyYWN0aXZlKSB7XHJcblx0XHRcdGFkZENsYXNzKHRoaXMuX2ltYWdlLCAnbGVhZmxldC1pbnRlcmFjdGl2ZScpO1xyXG5cdFx0XHR0aGlzLmFkZEludGVyYWN0aXZlVGFyZ2V0KHRoaXMuX2ltYWdlKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLmdldFBhbmUoKS5hcHBlbmRDaGlsZCh0aGlzLl9pbWFnZSk7XHJcblx0XHR0aGlzLl9yZXNldCgpO1xyXG5cdH0sXHJcblxyXG5cdG9uUmVtb3ZlOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZW1vdmUodGhpcy5faW1hZ2UpO1xyXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xyXG5cdFx0XHR0aGlzLnJlbW92ZUludGVyYWN0aXZlVGFyZ2V0KHRoaXMuX2ltYWdlKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHNldE9wYWNpdHkob3BhY2l0eTogTnVtYmVyKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIG9wYWNpdHkgb2YgdGhlIG92ZXJsYXkuXHJcblx0c2V0T3BhY2l0eTogZnVuY3Rpb24gKG9wYWNpdHkpIHtcclxuXHRcdHRoaXMub3B0aW9ucy5vcGFjaXR5ID0gb3BhY2l0eTtcclxuXHJcblx0XHRpZiAodGhpcy5faW1hZ2UpIHtcclxuXHRcdFx0dGhpcy5fdXBkYXRlT3BhY2l0eSgpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0c2V0U3R5bGU6IGZ1bmN0aW9uIChzdHlsZU9wdHMpIHtcclxuXHRcdGlmIChzdHlsZU9wdHMub3BhY2l0eSkge1xyXG5cdFx0XHR0aGlzLnNldE9wYWNpdHkoc3R5bGVPcHRzLm9wYWNpdHkpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBicmluZ1RvRnJvbnQoKTogdGhpc1xyXG5cdC8vIEJyaW5ncyB0aGUgbGF5ZXIgdG8gdGhlIHRvcCBvZiBhbGwgb3ZlcmxheXMuXHJcblx0YnJpbmdUb0Zyb250OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAodGhpcy5fbWFwKSB7XHJcblx0XHRcdHRvRnJvbnQodGhpcy5faW1hZ2UpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBicmluZ1RvQmFjaygpOiB0aGlzXHJcblx0Ly8gQnJpbmdzIHRoZSBsYXllciB0byB0aGUgYm90dG9tIG9mIGFsbCBvdmVybGF5cy5cclxuXHRicmluZ1RvQmFjazogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKHRoaXMuX21hcCkge1xyXG5cdFx0XHR0b0JhY2sodGhpcy5faW1hZ2UpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRVcmwodXJsOiBTdHJpbmcpOiB0aGlzXHJcblx0Ly8gQ2hhbmdlcyB0aGUgVVJMIG9mIHRoZSBpbWFnZS5cclxuXHRzZXRVcmw6IGZ1bmN0aW9uICh1cmwpIHtcclxuXHRcdHRoaXMuX3VybCA9IHVybDtcclxuXHJcblx0XHRpZiAodGhpcy5faW1hZ2UpIHtcclxuXHRcdFx0dGhpcy5faW1hZ2Uuc3JjID0gdXJsO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRCb3VuZHMoYm91bmRzOiBMYXRMbmdCb3VuZHMpOiB0aGlzXHJcblx0Ly8gVXBkYXRlIHRoZSBib3VuZHMgdGhhdCB0aGlzIEltYWdlT3ZlcmxheSBjb3ZlcnNcclxuXHRzZXRCb3VuZHM6IGZ1bmN0aW9uIChib3VuZHMpIHtcclxuXHRcdHRoaXMuX2JvdW5kcyA9IHRvTGF0TG5nQm91bmRzKGJvdW5kcyk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX21hcCkge1xyXG5cdFx0XHR0aGlzLl9yZXNldCgpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgZXZlbnRzID0ge1xyXG5cdFx0XHR6b29tOiB0aGlzLl9yZXNldCxcclxuXHRcdFx0dmlld3Jlc2V0OiB0aGlzLl9yZXNldFxyXG5cdFx0fTtcclxuXHJcblx0XHRpZiAodGhpcy5fem9vbUFuaW1hdGVkKSB7XHJcblx0XHRcdGV2ZW50cy56b29tYW5pbSA9IHRoaXMuX2FuaW1hdGVab29tO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiBldmVudHM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZDogc2V0WkluZGV4KHZhbHVlOiBOdW1iZXIpIDogdGhpc1xyXG5cdC8vIENoYW5nZXMgdGhlIFt6SW5kZXhdKCNpbWFnZW92ZXJsYXktemluZGV4KSBvZiB0aGUgaW1hZ2Ugb3ZlcmxheS5cclxuXHRzZXRaSW5kZXg6IGZ1bmN0aW9uICh2YWx1ZSkge1xyXG5cdFx0dGhpcy5vcHRpb25zLnpJbmRleCA9IHZhbHVlO1xyXG5cdFx0dGhpcy5fdXBkYXRlWkluZGV4KCk7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldEJvdW5kcygpOiBMYXRMbmdCb3VuZHNcclxuXHQvLyBHZXQgdGhlIGJvdW5kcyB0aGF0IHRoaXMgSW1hZ2VPdmVybGF5IGNvdmVyc1xyXG5cdGdldEJvdW5kczogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuX2JvdW5kcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldEVsZW1lbnQoKTogSFRNTEVsZW1lbnRcclxuXHQvLyBSZXR1cm5zIHRoZSBpbnN0YW5jZSBvZiBbYEhUTUxJbWFnZUVsZW1lbnRgXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9BUEkvSFRNTEltYWdlRWxlbWVudClcclxuXHQvLyB1c2VkIGJ5IHRoaXMgb3ZlcmxheS5cclxuXHRnZXRFbGVtZW50OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5faW1hZ2U7XHJcblx0fSxcclxuXHJcblx0X2luaXRJbWFnZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIHdhc0VsZW1lbnRTdXBwbGllZCA9IHRoaXMuX3VybC50YWdOYW1lID09PSAnSU1HJztcclxuXHRcdHZhciBpbWcgPSB0aGlzLl9pbWFnZSA9IHdhc0VsZW1lbnRTdXBwbGllZCA/IHRoaXMuX3VybCA6IGNyZWF0ZSQxKCdpbWcnKTtcclxuXHJcblx0XHRhZGRDbGFzcyhpbWcsICdsZWFmbGV0LWltYWdlLWxheWVyJyk7XHJcblx0XHRpZiAodGhpcy5fem9vbUFuaW1hdGVkKSB7IGFkZENsYXNzKGltZywgJ2xlYWZsZXQtem9vbS1hbmltYXRlZCcpOyB9XHJcblx0XHRpZiAodGhpcy5vcHRpb25zLmNsYXNzTmFtZSkgeyBhZGRDbGFzcyhpbWcsIHRoaXMub3B0aW9ucy5jbGFzc05hbWUpOyB9XHJcblxyXG5cdFx0aW1nLm9uc2VsZWN0c3RhcnQgPSBmYWxzZUZuO1xyXG5cdFx0aW1nLm9ubW91c2Vtb3ZlID0gZmFsc2VGbjtcclxuXHJcblx0XHQvLyBAZXZlbnQgbG9hZDogRXZlbnRcclxuXHRcdC8vIEZpcmVkIHdoZW4gdGhlIEltYWdlT3ZlcmxheSBsYXllciBoYXMgbG9hZGVkIGl0cyBpbWFnZVxyXG5cdFx0aW1nLm9ubG9hZCA9IGJpbmQodGhpcy5maXJlLCB0aGlzLCAnbG9hZCcpO1xyXG5cdFx0aW1nLm9uZXJyb3IgPSBiaW5kKHRoaXMuX292ZXJsYXlPbkVycm9yLCB0aGlzLCAnZXJyb3InKTtcclxuXHJcblx0XHRpZiAodGhpcy5vcHRpb25zLmNyb3NzT3JpZ2luKSB7XHJcblx0XHRcdGltZy5jcm9zc09yaWdpbiA9ICcnO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuekluZGV4KSB7XHJcblx0XHRcdHRoaXMuX3VwZGF0ZVpJbmRleCgpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh3YXNFbGVtZW50U3VwcGxpZWQpIHtcclxuXHRcdFx0dGhpcy5fdXJsID0gaW1nLnNyYztcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdGltZy5zcmMgPSB0aGlzLl91cmw7XHJcblx0XHRpbWcuYWx0ID0gdGhpcy5vcHRpb25zLmFsdDtcclxuXHR9LFxyXG5cclxuXHRfYW5pbWF0ZVpvb206IGZ1bmN0aW9uIChlKSB7XHJcblx0XHR2YXIgc2NhbGUgPSB0aGlzLl9tYXAuZ2V0Wm9vbVNjYWxlKGUuem9vbSksXHJcblx0XHQgICAgb2Zmc2V0ID0gdGhpcy5fbWFwLl9sYXRMbmdCb3VuZHNUb05ld0xheWVyQm91bmRzKHRoaXMuX2JvdW5kcywgZS56b29tLCBlLmNlbnRlcikubWluO1xyXG5cclxuXHRcdHNldFRyYW5zZm9ybSh0aGlzLl9pbWFnZSwgb2Zmc2V0LCBzY2FsZSk7XHJcblx0fSxcclxuXHJcblx0X3Jlc2V0OiBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgaW1hZ2UgPSB0aGlzLl9pbWFnZSxcclxuXHRcdCAgICBib3VuZHMgPSBuZXcgQm91bmRzKFxyXG5cdFx0ICAgICAgICB0aGlzLl9tYXAubGF0TG5nVG9MYXllclBvaW50KHRoaXMuX2JvdW5kcy5nZXROb3J0aFdlc3QoKSksXHJcblx0XHQgICAgICAgIHRoaXMuX21hcC5sYXRMbmdUb0xheWVyUG9pbnQodGhpcy5fYm91bmRzLmdldFNvdXRoRWFzdCgpKSksXHJcblx0XHQgICAgc2l6ZSA9IGJvdW5kcy5nZXRTaXplKCk7XHJcblxyXG5cdFx0c2V0UG9zaXRpb24oaW1hZ2UsIGJvdW5kcy5taW4pO1xyXG5cclxuXHRcdGltYWdlLnN0eWxlLndpZHRoICA9IHNpemUueCArICdweCc7XHJcblx0XHRpbWFnZS5zdHlsZS5oZWlnaHQgPSBzaXplLnkgKyAncHgnO1xyXG5cdH0sXHJcblxyXG5cdF91cGRhdGVPcGFjaXR5OiBmdW5jdGlvbiAoKSB7XHJcblx0XHRzZXRPcGFjaXR5KHRoaXMuX2ltYWdlLCB0aGlzLm9wdGlvbnMub3BhY2l0eSk7XHJcblx0fSxcclxuXHJcblx0X3VwZGF0ZVpJbmRleDogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKHRoaXMuX2ltYWdlICYmIHRoaXMub3B0aW9ucy56SW5kZXggIT09IHVuZGVmaW5lZCAmJiB0aGlzLm9wdGlvbnMuekluZGV4ICE9PSBudWxsKSB7XHJcblx0XHRcdHRoaXMuX2ltYWdlLnN0eWxlLnpJbmRleCA9IHRoaXMub3B0aW9ucy56SW5kZXg7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X292ZXJsYXlPbkVycm9yOiBmdW5jdGlvbiAoKSB7XHJcblx0XHQvLyBAZXZlbnQgZXJyb3I6IEV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIHRoZSBJbWFnZU92ZXJsYXkgbGF5ZXIgaGFzIGxvYWRlZCBpdHMgaW1hZ2VcclxuXHRcdHRoaXMuZmlyZSgnZXJyb3InKTtcclxuXHJcblx0XHR2YXIgZXJyb3JVcmwgPSB0aGlzLm9wdGlvbnMuZXJyb3JPdmVybGF5VXJsO1xyXG5cdFx0aWYgKGVycm9yVXJsICYmIHRoaXMuX3VybCAhPT0gZXJyb3JVcmwpIHtcclxuXHRcdFx0dGhpcy5fdXJsID0gZXJyb3JVcmw7XHJcblx0XHRcdHRoaXMuX2ltYWdlLnNyYyA9IGVycm9yVXJsO1xyXG5cdFx0fVxyXG5cdH1cclxufSk7XHJcblxyXG4vLyBAZmFjdG9yeSBMLmltYWdlT3ZlcmxheShpbWFnZVVybDogU3RyaW5nLCBib3VuZHM6IExhdExuZ0JvdW5kcywgb3B0aW9ucz86IEltYWdlT3ZlcmxheSBvcHRpb25zKVxyXG4vLyBJbnN0YW50aWF0ZXMgYW4gaW1hZ2Ugb3ZlcmxheSBvYmplY3QgZ2l2ZW4gdGhlIFVSTCBvZiB0aGUgaW1hZ2UgYW5kIHRoZVxyXG4vLyBnZW9ncmFwaGljYWwgYm91bmRzIGl0IGlzIHRpZWQgdG8uXHJcbnZhciBpbWFnZU92ZXJsYXkgPSBmdW5jdGlvbiAodXJsLCBib3VuZHMsIG9wdGlvbnMpIHtcclxuXHRyZXR1cm4gbmV3IEltYWdlT3ZlcmxheSh1cmwsIGJvdW5kcywgb3B0aW9ucyk7XHJcbn07XG5cbi8qXHJcbiAqIEBjbGFzcyBWaWRlb092ZXJsYXlcclxuICogQGFrYSBMLlZpZGVvT3ZlcmxheVxyXG4gKiBAaW5oZXJpdHMgSW1hZ2VPdmVybGF5XHJcbiAqXHJcbiAqIFVzZWQgdG8gbG9hZCBhbmQgZGlzcGxheSBhIHZpZGVvIHBsYXllciBvdmVyIHNwZWNpZmljIGJvdW5kcyBvZiB0aGUgbWFwLiBFeHRlbmRzIGBJbWFnZU92ZXJsYXlgLlxyXG4gKlxyXG4gKiBBIHZpZGVvIG92ZXJsYXkgdXNlcyB0aGUgW2A8dmlkZW8+YF0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvSFRNTC9FbGVtZW50L3ZpZGVvKVxyXG4gKiBIVE1MNSBlbGVtZW50LlxyXG4gKlxyXG4gKiBAZXhhbXBsZVxyXG4gKlxyXG4gKiBgYGBqc1xyXG4gKiB2YXIgdmlkZW9VcmwgPSAnaHR0cHM6Ly93d3cubWFwYm94LmNvbS9iaXRlcy8wMDE4OC9wYXRyaWNpYV9uYXNhLndlYm0nLFxyXG4gKiBcdHZpZGVvQm91bmRzID0gW1sgMzIsIC0xMzBdLCBbIDEzLCAtMTAwXV07XHJcbiAqIEwuVmlkZW9PdmVybGF5KHZpZGVvVXJsLCB2aWRlb0JvdW5kcyApLmFkZFRvKG1hcCk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBWaWRlb092ZXJsYXkgPSBJbWFnZU92ZXJsYXkuZXh0ZW5kKHtcclxuXHJcblx0Ly8gQHNlY3Rpb25cclxuXHQvLyBAYWthIFZpZGVvT3ZlcmxheSBvcHRpb25zXHJcblx0b3B0aW9uczoge1xyXG5cdFx0Ly8gQG9wdGlvbiBhdXRvcGxheTogQm9vbGVhbiA9IHRydWVcclxuXHRcdC8vIFdoZXRoZXIgdGhlIHZpZGVvIHN0YXJ0cyBwbGF5aW5nIGF1dG9tYXRpY2FsbHkgd2hlbiBsb2FkZWQuXHJcblx0XHRhdXRvcGxheTogdHJ1ZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGxvb3A6IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBXaGV0aGVyIHRoZSB2aWRlbyB3aWxsIGxvb3AgYmFjayB0byB0aGUgYmVnaW5uaW5nIHdoZW4gcGxheWVkLlxyXG5cdFx0bG9vcDogdHJ1ZVxyXG5cdH0sXHJcblxyXG5cdF9pbml0SW1hZ2U6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciB3YXNFbGVtZW50U3VwcGxpZWQgPSB0aGlzLl91cmwudGFnTmFtZSA9PT0gJ1ZJREVPJztcclxuXHRcdHZhciB2aWQgPSB0aGlzLl9pbWFnZSA9IHdhc0VsZW1lbnRTdXBwbGllZCA/IHRoaXMuX3VybCA6IGNyZWF0ZSQxKCd2aWRlbycpO1xyXG5cclxuXHRcdGFkZENsYXNzKHZpZCwgJ2xlYWZsZXQtaW1hZ2UtbGF5ZXInKTtcclxuXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHsgYWRkQ2xhc3ModmlkLCAnbGVhZmxldC16b29tLWFuaW1hdGVkJyk7IH1cclxuXHJcblx0XHR2aWQub25zZWxlY3RzdGFydCA9IGZhbHNlRm47XHJcblx0XHR2aWQub25tb3VzZW1vdmUgPSBmYWxzZUZuO1xyXG5cclxuXHRcdC8vIEBldmVudCBsb2FkOiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgdmlkZW8gaGFzIGZpbmlzaGVkIGxvYWRpbmcgdGhlIGZpcnN0IGZyYW1lXHJcblx0XHR2aWQub25sb2FkZWRkYXRhID0gYmluZCh0aGlzLmZpcmUsIHRoaXMsICdsb2FkJyk7XHJcblxyXG5cdFx0aWYgKHdhc0VsZW1lbnRTdXBwbGllZCkge1xyXG5cdFx0XHR2YXIgc291cmNlRWxlbWVudHMgPSB2aWQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3NvdXJjZScpO1xyXG5cdFx0XHR2YXIgc291cmNlcyA9IFtdO1xyXG5cdFx0XHRmb3IgKHZhciBqID0gMDsgaiA8IHNvdXJjZUVsZW1lbnRzLmxlbmd0aDsgaisrKSB7XHJcblx0XHRcdFx0c291cmNlcy5wdXNoKHNvdXJjZUVsZW1lbnRzW2pdLnNyYyk7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHRoaXMuX3VybCA9IChzb3VyY2VFbGVtZW50cy5sZW5ndGggPiAwKSA/IHNvdXJjZXMgOiBbdmlkLnNyY107XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIWlzQXJyYXkodGhpcy5fdXJsKSkgeyB0aGlzLl91cmwgPSBbdGhpcy5fdXJsXTsgfVxyXG5cclxuXHRcdHZpZC5hdXRvcGxheSA9ICEhdGhpcy5vcHRpb25zLmF1dG9wbGF5O1xyXG5cdFx0dmlkLmxvb3AgPSAhIXRoaXMub3B0aW9ucy5sb29wO1xyXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLl91cmwubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0dmFyIHNvdXJjZSA9IGNyZWF0ZSQxKCdzb3VyY2UnKTtcclxuXHRcdFx0c291cmNlLnNyYyA9IHRoaXMuX3VybFtpXTtcclxuXHRcdFx0dmlkLmFwcGVuZENoaWxkKHNvdXJjZSk7XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvLyBAbWV0aG9kIGdldEVsZW1lbnQoKTogSFRNTFZpZGVvRWxlbWVudFxyXG5cdC8vIFJldHVybnMgdGhlIGluc3RhbmNlIG9mIFtgSFRNTFZpZGVvRWxlbWVudGBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9IVE1MVmlkZW9FbGVtZW50KVxyXG5cdC8vIHVzZWQgYnkgdGhpcyBvdmVybGF5LlxyXG59KTtcclxuXHJcblxyXG4vLyBAZmFjdG9yeSBMLnZpZGVvT3ZlcmxheSh2aWRlbzogU3RyaW5nfEFycmF5fEhUTUxWaWRlb0VsZW1lbnQsIGJvdW5kczogTGF0TG5nQm91bmRzLCBvcHRpb25zPzogVmlkZW9PdmVybGF5IG9wdGlvbnMpXHJcbi8vIEluc3RhbnRpYXRlcyBhbiBpbWFnZSBvdmVybGF5IG9iamVjdCBnaXZlbiB0aGUgVVJMIG9mIHRoZSB2aWRlbyAob3IgYXJyYXkgb2YgVVJMcywgb3IgZXZlbiBhIHZpZGVvIGVsZW1lbnQpIGFuZCB0aGVcclxuLy8gZ2VvZ3JhcGhpY2FsIGJvdW5kcyBpdCBpcyB0aWVkIHRvLlxyXG5cclxuZnVuY3Rpb24gdmlkZW9PdmVybGF5KHZpZGVvLCBib3VuZHMsIG9wdGlvbnMpIHtcclxuXHRyZXR1cm4gbmV3IFZpZGVvT3ZlcmxheSh2aWRlbywgYm91bmRzLCBvcHRpb25zKTtcclxufVxuXG4vKlxyXG4gKiBAY2xhc3MgRGl2T3ZlcmxheVxyXG4gKiBAaW5oZXJpdHMgTGF5ZXJcclxuICogQGFrYSBMLkRpdk92ZXJsYXlcclxuICogQmFzZSBtb2RlbCBmb3IgTC5Qb3B1cCBhbmQgTC5Ub29sdGlwLiBJbmhlcml0IGZyb20gaXQgZm9yIGN1c3RvbSBwb3B1cCBsaWtlIHBsdWdpbnMuXHJcbiAqL1xyXG5cclxuLy8gQG5hbWVzcGFjZSBEaXZPdmVybGF5XHJcbnZhciBEaXZPdmVybGF5ID0gTGF5ZXIuZXh0ZW5kKHtcclxuXHJcblx0Ly8gQHNlY3Rpb25cclxuXHQvLyBAYWthIERpdk92ZXJsYXkgb3B0aW9uc1xyXG5cdG9wdGlvbnM6IHtcclxuXHRcdC8vIEBvcHRpb24gb2Zmc2V0OiBQb2ludCA9IFBvaW50KDAsIDcpXHJcblx0XHQvLyBUaGUgb2Zmc2V0IG9mIHRoZSBwb3B1cCBwb3NpdGlvbi4gVXNlZnVsIHRvIGNvbnRyb2wgdGhlIGFuY2hvclxyXG5cdFx0Ly8gb2YgdGhlIHBvcHVwIHdoZW4gb3BlbmluZyBpdCBvbiBzb21lIG92ZXJsYXlzLlxyXG5cdFx0b2Zmc2V0OiBbMCwgN10sXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBjbGFzc05hbWU6IFN0cmluZyA9ICcnXHJcblx0XHQvLyBBIGN1c3RvbSBDU1MgY2xhc3MgbmFtZSB0byBhc3NpZ24gdG8gdGhlIHBvcHVwLlxyXG5cdFx0Y2xhc3NOYW1lOiAnJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHBhbmU6IFN0cmluZyA9ICdwb3B1cFBhbmUnXHJcblx0XHQvLyBgTWFwIHBhbmVgIHdoZXJlIHRoZSBwb3B1cCB3aWxsIGJlIGFkZGVkLlxyXG5cdFx0cGFuZTogJ3BvcHVwUGFuZSdcclxuXHR9LFxyXG5cclxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAob3B0aW9ucywgc291cmNlKSB7XHJcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuXHRcdHRoaXMuX3NvdXJjZSA9IHNvdXJjZTtcclxuXHR9LFxyXG5cclxuXHRvbkFkZDogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0dGhpcy5fem9vbUFuaW1hdGVkID0gbWFwLl96b29tQW5pbWF0ZWQ7XHJcblxyXG5cdFx0aWYgKCF0aGlzLl9jb250YWluZXIpIHtcclxuXHRcdFx0dGhpcy5faW5pdExheW91dCgpO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChtYXAuX2ZhZGVBbmltYXRlZCkge1xyXG5cdFx0XHRzZXRPcGFjaXR5KHRoaXMuX2NvbnRhaW5lciwgMCk7XHJcblx0XHR9XHJcblxyXG5cdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3JlbW92ZVRpbWVvdXQpO1xyXG5cdFx0dGhpcy5nZXRQYW5lKCkuYXBwZW5kQ2hpbGQodGhpcy5fY29udGFpbmVyKTtcclxuXHRcdHRoaXMudXBkYXRlKCk7XHJcblxyXG5cdFx0aWYgKG1hcC5fZmFkZUFuaW1hdGVkKSB7XHJcblx0XHRcdHNldE9wYWNpdHkodGhpcy5fY29udGFpbmVyLCAxKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLmJyaW5nVG9Gcm9udCgpO1xyXG5cdH0sXHJcblxyXG5cdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XHJcblx0XHRpZiAobWFwLl9mYWRlQW5pbWF0ZWQpIHtcclxuXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9jb250YWluZXIsIDApO1xyXG5cdFx0XHR0aGlzLl9yZW1vdmVUaW1lb3V0ID0gc2V0VGltZW91dChiaW5kKHJlbW92ZSwgdW5kZWZpbmVkLCB0aGlzLl9jb250YWluZXIpLCAyMDApO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0Ly8gQG5hbWVzcGFjZSBQb3B1cFxyXG5cdC8vIEBtZXRob2QgZ2V0TGF0TG5nOiBMYXRMbmdcclxuXHQvLyBSZXR1cm5zIHRoZSBnZW9ncmFwaGljYWwgcG9pbnQgb2YgcG9wdXAuXHJcblx0Z2V0TGF0TG5nOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gdGhpcy5fbGF0bG5nO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0TGF0TG5nKGxhdGxuZzogTGF0TG5nKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIGdlb2dyYXBoaWNhbCBwb2ludCB3aGVyZSB0aGUgcG9wdXAgd2lsbCBvcGVuLlxyXG5cdHNldExhdExuZzogZnVuY3Rpb24gKGxhdGxuZykge1xyXG5cdFx0dGhpcy5fbGF0bG5nID0gdG9MYXRMbmcobGF0bG5nKTtcclxuXHRcdGlmICh0aGlzLl9tYXApIHtcclxuXHRcdFx0dGhpcy5fdXBkYXRlUG9zaXRpb24oKTtcclxuXHRcdFx0dGhpcy5fYWRqdXN0UGFuKCk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGdldENvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudFxyXG5cdC8vIFJldHVybnMgdGhlIGNvbnRlbnQgb2YgdGhlIHBvcHVwLlxyXG5cdGdldENvbnRlbnQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9jb250ZW50O1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0Q29udGVudChodG1sQ29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fEZ1bmN0aW9uKTogdGhpc1xyXG5cdC8vIFNldHMgdGhlIEhUTUwgY29udGVudCBvZiB0aGUgcG9wdXAuIElmIGEgZnVuY3Rpb24gaXMgcGFzc2VkIHRoZSBzb3VyY2UgbGF5ZXIgd2lsbCBiZSBwYXNzZWQgdG8gdGhlIGZ1bmN0aW9uLiBUaGUgZnVuY3Rpb24gc2hvdWxkIHJldHVybiBhIGBTdHJpbmdgIG9yIGBIVE1MRWxlbWVudGAgdG8gYmUgdXNlZCBpbiB0aGUgcG9wdXAuXHJcblx0c2V0Q29udGVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcclxuXHRcdHRoaXMuX2NvbnRlbnQgPSBjb250ZW50O1xyXG5cdFx0dGhpcy51cGRhdGUoKTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgZ2V0RWxlbWVudDogU3RyaW5nfEhUTUxFbGVtZW50XHJcblx0Ly8gQWxpYXMgZm9yIFtnZXRDb250ZW50KCldKCNwb3B1cC1nZXRjb250ZW50KVxyXG5cdGdldEVsZW1lbnQ6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9jb250YWluZXI7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB1cGRhdGU6IG51bGxcclxuXHQvLyBVcGRhdGVzIHRoZSBwb3B1cCBjb250ZW50LCBsYXlvdXQgYW5kIHBvc2l0aW9uLiBVc2VmdWwgZm9yIHVwZGF0aW5nIHRoZSBwb3B1cCBhZnRlciBzb21ldGhpbmcgaW5zaWRlIGNoYW5nZWQsIGUuZy4gaW1hZ2UgbG9hZGVkLlxyXG5cdHVwZGF0ZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0dGhpcy5fY29udGFpbmVyLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcclxuXHJcblx0XHR0aGlzLl91cGRhdGVDb250ZW50KCk7XHJcblx0XHR0aGlzLl91cGRhdGVMYXlvdXQoKTtcclxuXHRcdHRoaXMuX3VwZGF0ZVBvc2l0aW9uKCk7XHJcblxyXG5cdFx0dGhpcy5fY29udGFpbmVyLnN0eWxlLnZpc2liaWxpdHkgPSAnJztcclxuXHJcblx0XHR0aGlzLl9hZGp1c3RQYW4oKTtcclxuXHR9LFxyXG5cclxuXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBldmVudHMgPSB7XHJcblx0XHRcdHpvb206IHRoaXMuX3VwZGF0ZVBvc2l0aW9uLFxyXG5cdFx0XHR2aWV3cmVzZXQ6IHRoaXMuX3VwZGF0ZVBvc2l0aW9uXHJcblx0XHR9O1xyXG5cclxuXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuXHRcdFx0ZXZlbnRzLnpvb21hbmltID0gdGhpcy5fYW5pbWF0ZVpvb207XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gZXZlbnRzO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgaXNPcGVuOiBCb29sZWFuXHJcblx0Ly8gUmV0dXJucyBgdHJ1ZWAgd2hlbiB0aGUgcG9wdXAgaXMgdmlzaWJsZSBvbiB0aGUgbWFwLlxyXG5cdGlzT3BlbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuICEhdGhpcy5fbWFwICYmIHRoaXMuX21hcC5oYXNMYXllcih0aGlzKTtcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udDogdGhpc1xyXG5cdC8vIEJyaW5ncyB0aGlzIHBvcHVwIGluIGZyb250IG9mIG90aGVyIHBvcHVwcyAoaW4gdGhlIHNhbWUgbWFwIHBhbmUpLlxyXG5cdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKHRoaXMuX21hcCkge1xyXG5cdFx0XHR0b0Zyb250KHRoaXMuX2NvbnRhaW5lcik7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGJyaW5nVG9CYWNrOiB0aGlzXHJcblx0Ly8gQnJpbmdzIHRoaXMgcG9wdXAgdG8gdGhlIGJhY2sgb2Ygb3RoZXIgcG9wdXBzIChpbiB0aGUgc2FtZSBtYXAgcGFuZSkuXHJcblx0YnJpbmdUb0JhY2s6IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICh0aGlzLl9tYXApIHtcclxuXHRcdFx0dG9CYWNrKHRoaXMuX2NvbnRhaW5lcik7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHRfdXBkYXRlQ29udGVudDogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKCF0aGlzLl9jb250ZW50KSB7IHJldHVybjsgfVxyXG5cclxuXHRcdHZhciBub2RlID0gdGhpcy5fY29udGVudE5vZGU7XHJcblx0XHR2YXIgY29udGVudCA9ICh0eXBlb2YgdGhpcy5fY29udGVudCA9PT0gJ2Z1bmN0aW9uJykgPyB0aGlzLl9jb250ZW50KHRoaXMuX3NvdXJjZSB8fCB0aGlzKSA6IHRoaXMuX2NvbnRlbnQ7XHJcblxyXG5cdFx0aWYgKHR5cGVvZiBjb250ZW50ID09PSAnc3RyaW5nJykge1xyXG5cdFx0XHRub2RlLmlubmVySFRNTCA9IGNvbnRlbnQ7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHR3aGlsZSAobm9kZS5oYXNDaGlsZE5vZGVzKCkpIHtcclxuXHRcdFx0XHRub2RlLnJlbW92ZUNoaWxkKG5vZGUuZmlyc3RDaGlsZCk7XHJcblx0XHRcdH1cclxuXHRcdFx0bm9kZS5hcHBlbmRDaGlsZChjb250ZW50KTtcclxuXHRcdH1cclxuXHRcdHRoaXMuZmlyZSgnY29udGVudHVwZGF0ZScpO1xyXG5cdH0sXHJcblxyXG5cdF91cGRhdGVQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XHJcblxyXG5cdFx0dmFyIHBvcyA9IHRoaXMuX21hcC5sYXRMbmdUb0xheWVyUG9pbnQodGhpcy5fbGF0bG5nKSxcclxuXHRcdCAgICBvZmZzZXQgPSB0b1BvaW50KHRoaXMub3B0aW9ucy5vZmZzZXQpLFxyXG5cdFx0ICAgIGFuY2hvciA9IHRoaXMuX2dldEFuY2hvcigpO1xyXG5cclxuXHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcclxuXHRcdFx0c2V0UG9zaXRpb24odGhpcy5fY29udGFpbmVyLCBwb3MuYWRkKGFuY2hvcikpO1xyXG5cdFx0fSBlbHNlIHtcclxuXHRcdFx0b2Zmc2V0ID0gb2Zmc2V0LmFkZChwb3MpLmFkZChhbmNob3IpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBib3R0b20gPSB0aGlzLl9jb250YWluZXJCb3R0b20gPSAtb2Zmc2V0LnksXHJcblx0XHQgICAgbGVmdCA9IHRoaXMuX2NvbnRhaW5lckxlZnQgPSAtTWF0aC5yb3VuZCh0aGlzLl9jb250YWluZXJXaWR0aCAvIDIpICsgb2Zmc2V0Lng7XHJcblxyXG5cdFx0Ly8gYm90dG9tIHBvc2l0aW9uIHRoZSBwb3B1cCBpbiBjYXNlIHRoZSBoZWlnaHQgb2YgdGhlIHBvcHVwIGNoYW5nZXMgKGltYWdlcyBsb2FkaW5nIGV0YylcclxuXHRcdHRoaXMuX2NvbnRhaW5lci5zdHlsZS5ib3R0b20gPSBib3R0b20gKyAncHgnO1xyXG5cdFx0dGhpcy5fY29udGFpbmVyLnN0eWxlLmxlZnQgPSBsZWZ0ICsgJ3B4JztcclxuXHR9LFxyXG5cclxuXHRfZ2V0QW5jaG9yOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRyZXR1cm4gWzAsIDBdO1xyXG5cdH1cclxuXHJcbn0pO1xuXG4vKlxyXG4gKiBAY2xhc3MgUG9wdXBcclxuICogQGluaGVyaXRzIERpdk92ZXJsYXlcclxuICogQGFrYSBMLlBvcHVwXHJcbiAqIFVzZWQgdG8gb3BlbiBwb3B1cHMgaW4gY2VydGFpbiBwbGFjZXMgb2YgdGhlIG1hcC4gVXNlIFtNYXAub3BlblBvcHVwXSgjbWFwLW9wZW5wb3B1cCkgdG9cclxuICogb3BlbiBwb3B1cHMgd2hpbGUgbWFraW5nIHN1cmUgdGhhdCBvbmx5IG9uZSBwb3B1cCBpcyBvcGVuIGF0IG9uZSB0aW1lXHJcbiAqIChyZWNvbW1lbmRlZCBmb3IgdXNhYmlsaXR5KSwgb3IgdXNlIFtNYXAuYWRkTGF5ZXJdKCNtYXAtYWRkbGF5ZXIpIHRvIG9wZW4gYXMgbWFueSBhcyB5b3Ugd2FudC5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogSWYgeW91IHdhbnQgdG8ganVzdCBiaW5kIGEgcG9wdXAgdG8gbWFya2VyIGNsaWNrIGFuZCB0aGVuIG9wZW4gaXQsIGl0J3MgcmVhbGx5IGVhc3k6XHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIG1hcmtlci5iaW5kUG9wdXAocG9wdXBDb250ZW50KS5vcGVuUG9wdXAoKTtcclxuICogYGBgXHJcbiAqIFBhdGggb3ZlcmxheXMgbGlrZSBwb2x5bGluZXMgYWxzbyBoYXZlIGEgYGJpbmRQb3B1cGAgbWV0aG9kLlxyXG4gKiBIZXJlJ3MgYSBtb3JlIGNvbXBsaWNhdGVkIHdheSB0byBvcGVuIGEgcG9wdXAgb24gYSBtYXA6XHJcbiAqXHJcbiAqIGBgYGpzXHJcbiAqIHZhciBwb3B1cCA9IEwucG9wdXAoKVxyXG4gKiBcdC5zZXRMYXRMbmcobGF0bG5nKVxyXG4gKiBcdC5zZXRDb250ZW50KCc8cD5IZWxsbyB3b3JsZCE8YnIgLz5UaGlzIGlzIGEgbmljZSBwb3B1cC48L3A+JylcclxuICogXHQub3Blbk9uKG1hcCk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcblxyXG4vLyBAbmFtZXNwYWNlIFBvcHVwXHJcbnZhciBQb3B1cCA9IERpdk92ZXJsYXkuZXh0ZW5kKHtcclxuXHJcblx0Ly8gQHNlY3Rpb25cclxuXHQvLyBAYWthIFBvcHVwIG9wdGlvbnNcclxuXHRvcHRpb25zOiB7XHJcblx0XHQvLyBAb3B0aW9uIG1heFdpZHRoOiBOdW1iZXIgPSAzMDBcclxuXHRcdC8vIE1heCB3aWR0aCBvZiB0aGUgcG9wdXAsIGluIHBpeGVscy5cclxuXHRcdG1heFdpZHRoOiAzMDAsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBtaW5XaWR0aDogTnVtYmVyID0gNTBcclxuXHRcdC8vIE1pbiB3aWR0aCBvZiB0aGUgcG9wdXAsIGluIHBpeGVscy5cclxuXHRcdG1pbldpZHRoOiA1MCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIG1heEhlaWdodDogTnVtYmVyID0gbnVsbFxyXG5cdFx0Ly8gSWYgc2V0LCBjcmVhdGVzIGEgc2Nyb2xsYWJsZSBjb250YWluZXIgb2YgdGhlIGdpdmVuIGhlaWdodFxyXG5cdFx0Ly8gaW5zaWRlIGEgcG9wdXAgaWYgaXRzIGNvbnRlbnQgZXhjZWVkcyBpdC5cclxuXHRcdG1heEhlaWdodDogbnVsbCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGF1dG9QYW46IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBTZXQgaXQgdG8gYGZhbHNlYCBpZiB5b3UgZG9uJ3Qgd2FudCB0aGUgbWFwIHRvIGRvIHBhbm5pbmcgYW5pbWF0aW9uXHJcblx0XHQvLyB0byBmaXQgdGhlIG9wZW5lZCBwb3B1cC5cclxuXHRcdGF1dG9QYW46IHRydWUsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBhdXRvUGFuUGFkZGluZ1RvcExlZnQ6IFBvaW50ID0gbnVsbFxyXG5cdFx0Ly8gVGhlIG1hcmdpbiBiZXR3ZWVuIHRoZSBwb3B1cCBhbmQgdGhlIHRvcCBsZWZ0IGNvcm5lciBvZiB0aGUgbWFwXHJcblx0XHQvLyB2aWV3IGFmdGVyIGF1dG9wYW5uaW5nIHdhcyBwZXJmb3JtZWQuXHJcblx0XHRhdXRvUGFuUGFkZGluZ1RvcExlZnQ6IG51bGwsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBhdXRvUGFuUGFkZGluZ0JvdHRvbVJpZ2h0OiBQb2ludCA9IG51bGxcclxuXHRcdC8vIFRoZSBtYXJnaW4gYmV0d2VlbiB0aGUgcG9wdXAgYW5kIHRoZSBib3R0b20gcmlnaHQgY29ybmVyIG9mIHRoZSBtYXBcclxuXHRcdC8vIHZpZXcgYWZ0ZXIgYXV0b3Bhbm5pbmcgd2FzIHBlcmZvcm1lZC5cclxuXHRcdGF1dG9QYW5QYWRkaW5nQm90dG9tUmlnaHQ6IG51bGwsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBhdXRvUGFuUGFkZGluZzogUG9pbnQgPSBQb2ludCg1LCA1KVxyXG5cdFx0Ly8gRXF1aXZhbGVudCBvZiBzZXR0aW5nIGJvdGggdG9wIGxlZnQgYW5kIGJvdHRvbSByaWdodCBhdXRvcGFuIHBhZGRpbmcgdG8gdGhlIHNhbWUgdmFsdWUuXHJcblx0XHRhdXRvUGFuUGFkZGluZzogWzUsIDVdLFxyXG5cclxuXHRcdC8vIEBvcHRpb24ga2VlcEluVmlldzogQm9vbGVhbiA9IGZhbHNlXHJcblx0XHQvLyBTZXQgaXQgdG8gYHRydWVgIGlmIHlvdSB3YW50IHRvIHByZXZlbnQgdXNlcnMgZnJvbSBwYW5uaW5nIHRoZSBwb3B1cFxyXG5cdFx0Ly8gb2ZmIG9mIHRoZSBzY3JlZW4gd2hpbGUgaXQgaXMgb3Blbi5cclxuXHRcdGtlZXBJblZpZXc6IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gY2xvc2VCdXR0b246IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBDb250cm9scyB0aGUgcHJlc2VuY2Ugb2YgYSBjbG9zZSBidXR0b24gaW4gdGhlIHBvcHVwLlxyXG5cdFx0Y2xvc2VCdXR0b246IHRydWUsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBhdXRvQ2xvc2U6IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBTZXQgaXQgdG8gYGZhbHNlYCBpZiB5b3Ugd2FudCB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZlxyXG5cdFx0Ly8gdGhlIHBvcHVwIGNsb3Npbmcgd2hlbiBhbm90aGVyIHBvcHVwIGlzIG9wZW5lZC5cclxuXHRcdGF1dG9DbG9zZTogdHJ1ZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGNsb3NlT25Fc2NhcGVLZXk6IEJvb2xlYW4gPSB0cnVlXHJcblx0XHQvLyBTZXQgaXQgdG8gYGZhbHNlYCBpZiB5b3Ugd2FudCB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZlxyXG5cdFx0Ly8gdGhlIEVTQyBrZXkgZm9yIGNsb3Npbmcgb2YgdGhlIHBvcHVwLlxyXG5cdFx0Y2xvc2VPbkVzY2FwZUtleTogdHJ1ZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGNsb3NlT25DbGljazogQm9vbGVhbiA9ICpcclxuXHRcdC8vIFNldCBpdCBpZiB5b3Ugd2FudCB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiB0aGUgcG9wdXAgY2xvc2luZyB3aGVuIHVzZXIgY2xpY2tzXHJcblx0XHQvLyBvbiB0aGUgbWFwLiBEZWZhdWx0cyB0byB0aGUgbWFwJ3MgW2BjbG9zZVBvcHVwT25DbGlja2BdKCNtYXAtY2xvc2Vwb3B1cG9uY2xpY2spIG9wdGlvbi5cclxuXHJcblx0XHQvLyBAb3B0aW9uIGNsYXNzTmFtZTogU3RyaW5nID0gJydcclxuXHRcdC8vIEEgY3VzdG9tIENTUyBjbGFzcyBuYW1lIHRvIGFzc2lnbiB0byB0aGUgcG9wdXAuXHJcblx0XHRjbGFzc05hbWU6ICcnXHJcblx0fSxcclxuXHJcblx0Ly8gQG5hbWVzcGFjZSBQb3B1cFxyXG5cdC8vIEBtZXRob2Qgb3Blbk9uKG1hcDogTWFwKTogdGhpc1xyXG5cdC8vIEFkZHMgdGhlIHBvcHVwIHRvIHRoZSBtYXAgYW5kIGNsb3NlcyB0aGUgcHJldmlvdXMgb25lLiBUaGUgc2FtZSBhcyBgbWFwLm9wZW5Qb3B1cChwb3B1cClgLlxyXG5cdG9wZW5PbjogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0bWFwLm9wZW5Qb3B1cCh0aGlzKTtcclxuXHRcdHJldHVybiB0aGlzO1xyXG5cdH0sXHJcblxyXG5cdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XHJcblx0XHREaXZPdmVybGF5LnByb3RvdHlwZS5vbkFkZC5jYWxsKHRoaXMsIG1hcCk7XHJcblxyXG5cdFx0Ly8gQG5hbWVzcGFjZSBNYXBcclxuXHRcdC8vIEBzZWN0aW9uIFBvcHVwIGV2ZW50c1xyXG5cdFx0Ly8gQGV2ZW50IHBvcHVwb3BlbjogUG9wdXBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiBhIHBvcHVwIGlzIG9wZW5lZCBpbiB0aGUgbWFwXHJcblx0XHRtYXAuZmlyZSgncG9wdXBvcGVuJywge3BvcHVwOiB0aGlzfSk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX3NvdXJjZSkge1xyXG5cdFx0XHQvLyBAbmFtZXNwYWNlIExheWVyXHJcblx0XHRcdC8vIEBzZWN0aW9uIFBvcHVwIGV2ZW50c1xyXG5cdFx0XHQvLyBAZXZlbnQgcG9wdXBvcGVuOiBQb3B1cEV2ZW50XHJcblx0XHRcdC8vIEZpcmVkIHdoZW4gYSBwb3B1cCBib3VuZCB0byB0aGlzIGxheWVyIGlzIG9wZW5lZFxyXG5cdFx0XHR0aGlzLl9zb3VyY2UuZmlyZSgncG9wdXBvcGVuJywge3BvcHVwOiB0aGlzfSwgdHJ1ZSk7XHJcblx0XHRcdC8vIEZvciBub24tcGF0aCBsYXllcnMsIHdlIHRvZ2dsZSB0aGUgcG9wdXAgd2hlbiBjbGlja2luZ1xyXG5cdFx0XHQvLyBhZ2FpbiB0aGUgbGF5ZXIsIHNvIHByZXZlbnQgdGhlIG1hcCB0byByZW9wZW4gaXQuXHJcblx0XHRcdGlmICghKHRoaXMuX3NvdXJjZSBpbnN0YW5jZW9mIFBhdGgpKSB7XHJcblx0XHRcdFx0dGhpcy5fc291cmNlLm9uKCdwcmVjbGljaycsIHN0b3BQcm9wYWdhdGlvbik7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xyXG5cdFx0RGl2T3ZlcmxheS5wcm90b3R5cGUub25SZW1vdmUuY2FsbCh0aGlzLCBtYXApO1xyXG5cclxuXHRcdC8vIEBuYW1lc3BhY2UgTWFwXHJcblx0XHQvLyBAc2VjdGlvbiBQb3B1cCBldmVudHNcclxuXHRcdC8vIEBldmVudCBwb3B1cGNsb3NlOiBQb3B1cEV2ZW50XHJcblx0XHQvLyBGaXJlZCB3aGVuIGEgcG9wdXAgaW4gdGhlIG1hcCBpcyBjbG9zZWRcclxuXHRcdG1hcC5maXJlKCdwb3B1cGNsb3NlJywge3BvcHVwOiB0aGlzfSk7XHJcblxyXG5cdFx0aWYgKHRoaXMuX3NvdXJjZSkge1xyXG5cdFx0XHQvLyBAbmFtZXNwYWNlIExheWVyXHJcblx0XHRcdC8vIEBzZWN0aW9uIFBvcHVwIGV2ZW50c1xyXG5cdFx0XHQvLyBAZXZlbnQgcG9wdXBjbG9zZTogUG9wdXBFdmVudFxyXG5cdFx0XHQvLyBGaXJlZCB3aGVuIGEgcG9wdXAgYm91bmQgdG8gdGhpcyBsYXllciBpcyBjbG9zZWRcclxuXHRcdFx0dGhpcy5fc291cmNlLmZpcmUoJ3BvcHVwY2xvc2UnLCB7cG9wdXA6IHRoaXN9LCB0cnVlKTtcclxuXHRcdFx0aWYgKCEodGhpcy5fc291cmNlIGluc3RhbmNlb2YgUGF0aCkpIHtcclxuXHRcdFx0XHR0aGlzLl9zb3VyY2Uub2ZmKCdwcmVjbGljaycsIHN0b3BQcm9wYWdhdGlvbik7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBldmVudHMgPSBEaXZPdmVybGF5LnByb3RvdHlwZS5nZXRFdmVudHMuY2FsbCh0aGlzKTtcclxuXHJcblx0XHRpZiAodGhpcy5vcHRpb25zLmNsb3NlT25DbGljayAhPT0gdW5kZWZpbmVkID8gdGhpcy5vcHRpb25zLmNsb3NlT25DbGljayA6IHRoaXMuX21hcC5vcHRpb25zLmNsb3NlUG9wdXBPbkNsaWNrKSB7XHJcblx0XHRcdGV2ZW50cy5wcmVjbGljayA9IHRoaXMuX2Nsb3NlO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMua2VlcEluVmlldykge1xyXG5cdFx0XHRldmVudHMubW92ZWVuZCA9IHRoaXMuX2FkanVzdFBhbjtcclxuXHRcdH1cclxuXHJcblx0XHRyZXR1cm4gZXZlbnRzO1xyXG5cdH0sXHJcblxyXG5cdF9jbG9zZTogZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKHRoaXMuX21hcCkge1xyXG5cdFx0XHR0aGlzLl9tYXAuY2xvc2VQb3B1cCh0aGlzKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfaW5pdExheW91dDogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIHByZWZpeCA9ICdsZWFmbGV0LXBvcHVwJyxcclxuXHRcdCAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JyxcclxuXHRcdFx0cHJlZml4ICsgJyAnICsgKHRoaXMub3B0aW9ucy5jbGFzc05hbWUgfHwgJycpICtcclxuXHRcdFx0JyBsZWFmbGV0LXpvb20tYW5pbWF0ZWQnKTtcclxuXHJcblx0XHR2YXIgd3JhcHBlciA9IHRoaXMuX3dyYXBwZXIgPSBjcmVhdGUkMSgnZGl2JywgcHJlZml4ICsgJy1jb250ZW50LXdyYXBwZXInLCBjb250YWluZXIpO1xyXG5cdFx0dGhpcy5fY29udGVudE5vZGUgPSBjcmVhdGUkMSgnZGl2JywgcHJlZml4ICsgJy1jb250ZW50Jywgd3JhcHBlcik7XHJcblxyXG5cdFx0ZGlzYWJsZUNsaWNrUHJvcGFnYXRpb24od3JhcHBlcik7XHJcblx0XHRkaXNhYmxlU2Nyb2xsUHJvcGFnYXRpb24odGhpcy5fY29udGVudE5vZGUpO1xyXG5cdFx0b24od3JhcHBlciwgJ2NvbnRleHRtZW51Jywgc3RvcFByb3BhZ2F0aW9uKTtcclxuXHJcblx0XHR0aGlzLl90aXBDb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgcHJlZml4ICsgJy10aXAtY29udGFpbmVyJywgY29udGFpbmVyKTtcclxuXHRcdHRoaXMuX3RpcCA9IGNyZWF0ZSQxKCdkaXYnLCBwcmVmaXggKyAnLXRpcCcsIHRoaXMuX3RpcENvbnRhaW5lcik7XHJcblxyXG5cdFx0aWYgKHRoaXMub3B0aW9ucy5jbG9zZUJ1dHRvbikge1xyXG5cdFx0XHR2YXIgY2xvc2VCdXR0b24gPSB0aGlzLl9jbG9zZUJ1dHRvbiA9IGNyZWF0ZSQxKCdhJywgcHJlZml4ICsgJy1jbG9zZS1idXR0b24nLCBjb250YWluZXIpO1xyXG5cdFx0XHRjbG9zZUJ1dHRvbi5ocmVmID0gJyNjbG9zZSc7XHJcblx0XHRcdGNsb3NlQnV0dG9uLmlubmVySFRNTCA9ICcmIzIxNTsnO1xyXG5cclxuXHRcdFx0b24oY2xvc2VCdXR0b24sICdjbGljaycsIHRoaXMuX29uQ2xvc2VCdXR0b25DbGljaywgdGhpcyk7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X3VwZGF0ZUxheW91dDogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIGNvbnRhaW5lciA9IHRoaXMuX2NvbnRlbnROb2RlLFxyXG5cdFx0ICAgIHN0eWxlID0gY29udGFpbmVyLnN0eWxlO1xyXG5cclxuXHRcdHN0eWxlLndpZHRoID0gJyc7XHJcblx0XHRzdHlsZS53aGl0ZVNwYWNlID0gJ25vd3JhcCc7XHJcblxyXG5cdFx0dmFyIHdpZHRoID0gY29udGFpbmVyLm9mZnNldFdpZHRoO1xyXG5cdFx0d2lkdGggPSBNYXRoLm1pbih3aWR0aCwgdGhpcy5vcHRpb25zLm1heFdpZHRoKTtcclxuXHRcdHdpZHRoID0gTWF0aC5tYXgod2lkdGgsIHRoaXMub3B0aW9ucy5taW5XaWR0aCk7XHJcblxyXG5cdFx0c3R5bGUud2lkdGggPSAod2lkdGggKyAxKSArICdweCc7XHJcblx0XHRzdHlsZS53aGl0ZVNwYWNlID0gJyc7XHJcblxyXG5cdFx0c3R5bGUuaGVpZ2h0ID0gJyc7XHJcblxyXG5cdFx0dmFyIGhlaWdodCA9IGNvbnRhaW5lci5vZmZzZXRIZWlnaHQsXHJcblx0XHQgICAgbWF4SGVpZ2h0ID0gdGhpcy5vcHRpb25zLm1heEhlaWdodCxcclxuXHRcdCAgICBzY3JvbGxlZENsYXNzID0gJ2xlYWZsZXQtcG9wdXAtc2Nyb2xsZWQnO1xyXG5cclxuXHRcdGlmIChtYXhIZWlnaHQgJiYgaGVpZ2h0ID4gbWF4SGVpZ2h0KSB7XHJcblx0XHRcdHN0eWxlLmhlaWdodCA9IG1heEhlaWdodCArICdweCc7XHJcblx0XHRcdGFkZENsYXNzKGNvbnRhaW5lciwgc2Nyb2xsZWRDbGFzcyk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRyZW1vdmVDbGFzcyhjb250YWluZXIsIHNjcm9sbGVkQ2xhc3MpO1xyXG5cdFx0fVxyXG5cclxuXHRcdHRoaXMuX2NvbnRhaW5lcldpZHRoID0gdGhpcy5fY29udGFpbmVyLm9mZnNldFdpZHRoO1xyXG5cdH0sXHJcblxyXG5cdF9hbmltYXRlWm9vbTogZnVuY3Rpb24gKGUpIHtcclxuXHRcdHZhciBwb3MgPSB0aGlzLl9tYXAuX2xhdExuZ1RvTmV3TGF5ZXJQb2ludCh0aGlzLl9sYXRsbmcsIGUuem9vbSwgZS5jZW50ZXIpLFxyXG5cdFx0ICAgIGFuY2hvciA9IHRoaXMuX2dldEFuY2hvcigpO1xyXG5cdFx0c2V0UG9zaXRpb24odGhpcy5fY29udGFpbmVyLCBwb3MuYWRkKGFuY2hvcikpO1xyXG5cdH0sXHJcblxyXG5cdF9hZGp1c3RQYW46IGZ1bmN0aW9uICgpIHtcclxuXHRcdGlmICghdGhpcy5vcHRpb25zLmF1dG9QYW4gfHwgKHRoaXMuX21hcC5fcGFuQW5pbSAmJiB0aGlzLl9tYXAuX3BhbkFuaW0uX2luUHJvZ3Jlc3MpKSB7IHJldHVybjsgfVxyXG5cclxuXHRcdHZhciBtYXAgPSB0aGlzLl9tYXAsXHJcblx0XHQgICAgbWFyZ2luQm90dG9tID0gcGFyc2VJbnQoZ2V0U3R5bGUodGhpcy5fY29udGFpbmVyLCAnbWFyZ2luQm90dG9tJyksIDEwKSB8fCAwLFxyXG5cdFx0ICAgIGNvbnRhaW5lckhlaWdodCA9IHRoaXMuX2NvbnRhaW5lci5vZmZzZXRIZWlnaHQgKyBtYXJnaW5Cb3R0b20sXHJcblx0XHQgICAgY29udGFpbmVyV2lkdGggPSB0aGlzLl9jb250YWluZXJXaWR0aCxcclxuXHRcdCAgICBsYXllclBvcyA9IG5ldyBQb2ludCh0aGlzLl9jb250YWluZXJMZWZ0LCAtY29udGFpbmVySGVpZ2h0IC0gdGhpcy5fY29udGFpbmVyQm90dG9tKTtcclxuXHJcblx0XHRsYXllclBvcy5fYWRkKGdldFBvc2l0aW9uKHRoaXMuX2NvbnRhaW5lcikpO1xyXG5cclxuXHRcdHZhciBjb250YWluZXJQb3MgPSBtYXAubGF5ZXJQb2ludFRvQ29udGFpbmVyUG9pbnQobGF5ZXJQb3MpLFxyXG5cdFx0ICAgIHBhZGRpbmcgPSB0b1BvaW50KHRoaXMub3B0aW9ucy5hdXRvUGFuUGFkZGluZyksXHJcblx0XHQgICAgcGFkZGluZ1RMID0gdG9Qb2ludCh0aGlzLm9wdGlvbnMuYXV0b1BhblBhZGRpbmdUb3BMZWZ0IHx8IHBhZGRpbmcpLFxyXG5cdFx0ICAgIHBhZGRpbmdCUiA9IHRvUG9pbnQodGhpcy5vcHRpb25zLmF1dG9QYW5QYWRkaW5nQm90dG9tUmlnaHQgfHwgcGFkZGluZyksXHJcblx0XHQgICAgc2l6ZSA9IG1hcC5nZXRTaXplKCksXHJcblx0XHQgICAgZHggPSAwLFxyXG5cdFx0ICAgIGR5ID0gMDtcclxuXHJcblx0XHRpZiAoY29udGFpbmVyUG9zLnggKyBjb250YWluZXJXaWR0aCArIHBhZGRpbmdCUi54ID4gc2l6ZS54KSB7IC8vIHJpZ2h0XHJcblx0XHRcdGR4ID0gY29udGFpbmVyUG9zLnggKyBjb250YWluZXJXaWR0aCAtIHNpemUueCArIHBhZGRpbmdCUi54O1xyXG5cdFx0fVxyXG5cdFx0aWYgKGNvbnRhaW5lclBvcy54IC0gZHggLSBwYWRkaW5nVEwueCA8IDApIHsgLy8gbGVmdFxyXG5cdFx0XHRkeCA9IGNvbnRhaW5lclBvcy54IC0gcGFkZGluZ1RMLng7XHJcblx0XHR9XHJcblx0XHRpZiAoY29udGFpbmVyUG9zLnkgKyBjb250YWluZXJIZWlnaHQgKyBwYWRkaW5nQlIueSA+IHNpemUueSkgeyAvLyBib3R0b21cclxuXHRcdFx0ZHkgPSBjb250YWluZXJQb3MueSArIGNvbnRhaW5lckhlaWdodCAtIHNpemUueSArIHBhZGRpbmdCUi55O1xyXG5cdFx0fVxyXG5cdFx0aWYgKGNvbnRhaW5lclBvcy55IC0gZHkgLSBwYWRkaW5nVEwueSA8IDApIHsgLy8gdG9wXHJcblx0XHRcdGR5ID0gY29udGFpbmVyUG9zLnkgLSBwYWRkaW5nVEwueTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBAbmFtZXNwYWNlIE1hcFxyXG5cdFx0Ly8gQHNlY3Rpb24gUG9wdXAgZXZlbnRzXHJcblx0XHQvLyBAZXZlbnQgYXV0b3BhbnN0YXJ0OiBFdmVudFxyXG5cdFx0Ly8gRmlyZWQgd2hlbiB0aGUgbWFwIHN0YXJ0cyBhdXRvcGFubmluZyB3aGVuIG9wZW5pbmcgYSBwb3B1cC5cclxuXHRcdGlmIChkeCB8fCBkeSkge1xyXG5cdFx0XHRtYXBcclxuXHRcdFx0ICAgIC5maXJlKCdhdXRvcGFuc3RhcnQnKVxyXG5cdFx0XHQgICAgLnBhbkJ5KFtkeCwgZHldKTtcclxuXHRcdH1cclxuXHR9LFxyXG5cclxuXHRfb25DbG9zZUJ1dHRvbkNsaWNrOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0dGhpcy5fY2xvc2UoKTtcclxuXHRcdHN0b3AoZSk7XHJcblx0fSxcclxuXHJcblx0X2dldEFuY2hvcjogZnVuY3Rpb24gKCkge1xyXG5cdFx0Ly8gV2hlcmUgc2hvdWxkIHdlIGFuY2hvciB0aGUgcG9wdXAgb24gdGhlIHNvdXJjZSBsYXllcj9cclxuXHRcdHJldHVybiB0b1BvaW50KHRoaXMuX3NvdXJjZSAmJiB0aGlzLl9zb3VyY2UuX2dldFBvcHVwQW5jaG9yID8gdGhpcy5fc291cmNlLl9nZXRQb3B1cEFuY2hvcigpIDogWzAsIDBdKTtcclxuXHR9XHJcblxyXG59KTtcclxuXHJcbi8vIEBuYW1lc3BhY2UgUG9wdXBcclxuLy8gQGZhY3RvcnkgTC5wb3B1cChvcHRpb25zPzogUG9wdXAgb3B0aW9ucywgc291cmNlPzogTGF5ZXIpXHJcbi8vIEluc3RhbnRpYXRlcyBhIGBQb3B1cGAgb2JqZWN0IGdpdmVuIGFuIG9wdGlvbmFsIGBvcHRpb25zYCBvYmplY3QgdGhhdCBkZXNjcmliZXMgaXRzIGFwcGVhcmFuY2UgYW5kIGxvY2F0aW9uIGFuZCBhbiBvcHRpb25hbCBgc291cmNlYCBvYmplY3QgdGhhdCBpcyB1c2VkIHRvIHRhZyB0aGUgcG9wdXAgd2l0aCBhIHJlZmVyZW5jZSB0byB0aGUgTGF5ZXIgdG8gd2hpY2ggaXQgcmVmZXJzLlxyXG52YXIgcG9wdXAgPSBmdW5jdGlvbiAob3B0aW9ucywgc291cmNlKSB7XHJcblx0cmV0dXJuIG5ldyBQb3B1cChvcHRpb25zLCBzb3VyY2UpO1xyXG59O1xyXG5cclxuXHJcbi8qIEBuYW1lc3BhY2UgTWFwXHJcbiAqIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcclxuICogQG9wdGlvbiBjbG9zZVBvcHVwT25DbGljazogQm9vbGVhbiA9IHRydWVcclxuICogU2V0IGl0IHRvIGBmYWxzZWAgaWYgeW91IGRvbid0IHdhbnQgcG9wdXBzIHRvIGNsb3NlIHdoZW4gdXNlciBjbGlja3MgdGhlIG1hcC5cclxuICovXHJcbk1hcC5tZXJnZU9wdGlvbnMoe1xyXG5cdGNsb3NlUG9wdXBPbkNsaWNrOiB0cnVlXHJcbn0pO1xyXG5cclxuXHJcbi8vIEBuYW1lc3BhY2UgTWFwXHJcbi8vIEBzZWN0aW9uIE1ldGhvZHMgZm9yIExheWVycyBhbmQgQ29udHJvbHNcclxuTWFwLmluY2x1ZGUoe1xyXG5cdC8vIEBtZXRob2Qgb3BlblBvcHVwKHBvcHVwOiBQb3B1cCk6IHRoaXNcclxuXHQvLyBPcGVucyB0aGUgc3BlY2lmaWVkIHBvcHVwIHdoaWxlIGNsb3NpbmcgdGhlIHByZXZpb3VzbHkgb3BlbmVkICh0byBtYWtlIHN1cmUgb25seSBvbmUgaXMgb3BlbmVkIGF0IG9uZSB0aW1lIGZvciB1c2FiaWxpdHkpLlxyXG5cdC8vIEBhbHRlcm5hdGl2ZVxyXG5cdC8vIEBtZXRob2Qgb3BlblBvcHVwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudCwgbGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBQb3B1cCBvcHRpb25zKTogdGhpc1xyXG5cdC8vIENyZWF0ZXMgYSBwb3B1cCB3aXRoIHRoZSBzcGVjaWZpZWQgY29udGVudCBhbmQgb3B0aW9ucyBhbmQgb3BlbnMgaXQgaW4gdGhlIGdpdmVuIHBvaW50IG9uIGEgbWFwLlxyXG5cdG9wZW5Qb3B1cDogZnVuY3Rpb24gKHBvcHVwLCBsYXRsbmcsIG9wdGlvbnMpIHtcclxuXHRcdGlmICghKHBvcHVwIGluc3RhbmNlb2YgUG9wdXApKSB7XHJcblx0XHRcdHBvcHVwID0gbmV3IFBvcHVwKG9wdGlvbnMpLnNldENvbnRlbnQocG9wdXApO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmIChsYXRsbmcpIHtcclxuXHRcdFx0cG9wdXAuc2V0TGF0TG5nKGxhdGxuZyk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKHRoaXMuaGFzTGF5ZXIocG9wdXApKSB7XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fVxyXG5cclxuXHRcdGlmICh0aGlzLl9wb3B1cCAmJiB0aGlzLl9wb3B1cC5vcHRpb25zLmF1dG9DbG9zZSkge1xyXG5cdFx0XHR0aGlzLmNsb3NlUG9wdXAoKTtcclxuXHRcdH1cclxuXHJcblx0XHR0aGlzLl9wb3B1cCA9IHBvcHVwO1xyXG5cdFx0cmV0dXJuIHRoaXMuYWRkTGF5ZXIocG9wdXApO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2QgY2xvc2VQb3B1cChwb3B1cD86IFBvcHVwKTogdGhpc1xyXG5cdC8vIENsb3NlcyB0aGUgcG9wdXAgcHJldmlvdXNseSBvcGVuZWQgd2l0aCBbb3BlblBvcHVwXSgjbWFwLW9wZW5wb3B1cCkgKG9yIHRoZSBnaXZlbiBvbmUpLlxyXG5cdGNsb3NlUG9wdXA6IGZ1bmN0aW9uIChwb3B1cCkge1xyXG5cdFx0aWYgKCFwb3B1cCB8fCBwb3B1cCA9PT0gdGhpcy5fcG9wdXApIHtcclxuXHRcdFx0cG9wdXAgPSB0aGlzLl9wb3B1cDtcclxuXHRcdFx0dGhpcy5fcG9wdXAgPSBudWxsO1xyXG5cdFx0fVxyXG5cdFx0aWYgKHBvcHVwKSB7XHJcblx0XHRcdHRoaXMucmVtb3ZlTGF5ZXIocG9wdXApO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fVxyXG59KTtcclxuXHJcbi8qXHJcbiAqIEBuYW1lc3BhY2UgTGF5ZXJcclxuICogQHNlY3Rpb24gUG9wdXAgbWV0aG9kcyBleGFtcGxlXHJcbiAqXHJcbiAqIEFsbCBsYXllcnMgc2hhcmUgYSBzZXQgb2YgbWV0aG9kcyBjb252ZW5pZW50IGZvciBiaW5kaW5nIHBvcHVwcyB0byBpdC5cclxuICpcclxuICogYGBganNcclxuICogdmFyIGxheWVyID0gTC5Qb2x5Z29uKGxhdGxuZ3MpLmJpbmRQb3B1cCgnSGkgVGhlcmUhJykuYWRkVG8obWFwKTtcclxuICogbGF5ZXIub3BlblBvcHVwKCk7XHJcbiAqIGxheWVyLmNsb3NlUG9wdXAoKTtcclxuICogYGBgXHJcbiAqXHJcbiAqIFBvcHVwcyB3aWxsIGFsc28gYmUgYXV0b21hdGljYWxseSBvcGVuZWQgd2hlbiB0aGUgbGF5ZXIgaXMgY2xpY2tlZCBvbiBhbmQgY2xvc2VkIHdoZW4gdGhlIGxheWVyIGlzIHJlbW92ZWQgZnJvbSB0aGUgbWFwIG9yIGFub3RoZXIgcG9wdXAgaXMgb3BlbmVkLlxyXG4gKi9cclxuXHJcbi8vIEBzZWN0aW9uIFBvcHVwIG1ldGhvZHNcclxuTGF5ZXIuaW5jbHVkZSh7XHJcblxyXG5cdC8vIEBtZXRob2QgYmluZFBvcHVwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudHxGdW5jdGlvbnxQb3B1cCwgb3B0aW9ucz86IFBvcHVwIG9wdGlvbnMpOiB0aGlzXHJcblx0Ly8gQmluZHMgYSBwb3B1cCB0byB0aGUgbGF5ZXIgd2l0aCB0aGUgcGFzc2VkIGBjb250ZW50YCBhbmQgc2V0cyB1cCB0aGVcclxuXHQvLyBuZWNlc3NhcnkgZXZlbnQgbGlzdGVuZXJzLiBJZiBhIGBGdW5jdGlvbmAgaXMgcGFzc2VkIGl0IHdpbGwgcmVjZWl2ZVxyXG5cdC8vIHRoZSBsYXllciBhcyB0aGUgZmlyc3QgYXJndW1lbnQgYW5kIHNob3VsZCByZXR1cm4gYSBgU3RyaW5nYCBvciBgSFRNTEVsZW1lbnRgLlxyXG5cdGJpbmRQb3B1cDogZnVuY3Rpb24gKGNvbnRlbnQsIG9wdGlvbnMpIHtcclxuXHJcblx0XHRpZiAoY29udGVudCBpbnN0YW5jZW9mIFBvcHVwKSB7XHJcblx0XHRcdHNldE9wdGlvbnMoY29udGVudCwgb3B0aW9ucyk7XHJcblx0XHRcdHRoaXMuX3BvcHVwID0gY29udGVudDtcclxuXHRcdFx0Y29udGVudC5fc291cmNlID0gdGhpcztcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGlmICghdGhpcy5fcG9wdXAgfHwgb3B0aW9ucykge1xyXG5cdFx0XHRcdHRoaXMuX3BvcHVwID0gbmV3IFBvcHVwKG9wdGlvbnMsIHRoaXMpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXMuX3BvcHVwLnNldENvbnRlbnQoY29udGVudCk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCF0aGlzLl9wb3B1cEhhbmRsZXJzQWRkZWQpIHtcclxuXHRcdFx0dGhpcy5vbih7XHJcblx0XHRcdFx0Y2xpY2s6IHRoaXMuX29wZW5Qb3B1cCxcclxuXHRcdFx0XHRrZXlwcmVzczogdGhpcy5fb25LZXlQcmVzcyxcclxuXHRcdFx0XHRyZW1vdmU6IHRoaXMuY2xvc2VQb3B1cCxcclxuXHRcdFx0XHRtb3ZlOiB0aGlzLl9tb3ZlUG9wdXBcclxuXHRcdFx0fSk7XHJcblx0XHRcdHRoaXMuX3BvcHVwSGFuZGxlcnNBZGRlZCA9IHRydWU7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCB1bmJpbmRQb3B1cCgpOiB0aGlzXHJcblx0Ly8gUmVtb3ZlcyB0aGUgcG9wdXAgcHJldmlvdXNseSBib3VuZCB3aXRoIGBiaW5kUG9wdXBgLlxyXG5cdHVuYmluZFBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAodGhpcy5fcG9wdXApIHtcclxuXHRcdFx0dGhpcy5vZmYoe1xyXG5cdFx0XHRcdGNsaWNrOiB0aGlzLl9vcGVuUG9wdXAsXHJcblx0XHRcdFx0a2V5cHJlc3M6IHRoaXMuX29uS2V5UHJlc3MsXHJcblx0XHRcdFx0cmVtb3ZlOiB0aGlzLmNsb3NlUG9wdXAsXHJcblx0XHRcdFx0bW92ZTogdGhpcy5fbW92ZVBvcHVwXHJcblx0XHRcdH0pO1xyXG5cdFx0XHR0aGlzLl9wb3B1cEhhbmRsZXJzQWRkZWQgPSBmYWxzZTtcclxuXHRcdFx0dGhpcy5fcG9wdXAgPSBudWxsO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBvcGVuUG9wdXAobGF0bG5nPzogTGF0TG5nKTogdGhpc1xyXG5cdC8vIE9wZW5zIHRoZSBib3VuZCBwb3B1cCBhdCB0aGUgc3BlY2lmaWVkIGBsYXRsbmdgIG9yIGF0IHRoZSBkZWZhdWx0IHBvcHVwIGFuY2hvciBpZiBubyBgbGF0bG5nYCBpcyBwYXNzZWQuXHJcblx0b3BlblBvcHVwOiBmdW5jdGlvbiAobGF5ZXIsIGxhdGxuZykge1xyXG5cdFx0aWYgKCEobGF5ZXIgaW5zdGFuY2VvZiBMYXllcikpIHtcclxuXHRcdFx0bGF0bG5nID0gbGF5ZXI7XHJcblx0XHRcdGxheWVyID0gdGhpcztcclxuXHRcdH1cclxuXHJcblx0XHRpZiAobGF5ZXIgaW5zdGFuY2VvZiBGZWF0dXJlR3JvdXApIHtcclxuXHRcdFx0Zm9yICh2YXIgaWQgaW4gdGhpcy5fbGF5ZXJzKSB7XHJcblx0XHRcdFx0bGF5ZXIgPSB0aGlzLl9sYXllcnNbaWRdO1xyXG5cdFx0XHRcdGJyZWFrO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKCFsYXRsbmcpIHtcclxuXHRcdFx0bGF0bG5nID0gbGF5ZXIuZ2V0Q2VudGVyID8gbGF5ZXIuZ2V0Q2VudGVyKCkgOiBsYXllci5nZXRMYXRMbmcoKTtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAodGhpcy5fcG9wdXAgJiYgdGhpcy5fbWFwKSB7XHJcblx0XHRcdC8vIHNldCBwb3B1cCBzb3VyY2UgdG8gdGhpcyBsYXllclxyXG5cdFx0XHR0aGlzLl9wb3B1cC5fc291cmNlID0gbGF5ZXI7XHJcblxyXG5cdFx0XHQvLyB1cGRhdGUgdGhlIHBvcHVwIChjb250ZW50LCBsYXlvdXQsIGVjdC4uLilcclxuXHRcdFx0dGhpcy5fcG9wdXAudXBkYXRlKCk7XHJcblxyXG5cdFx0XHQvLyBvcGVuIHRoZSBwb3B1cCBvbiB0aGUgbWFwXHJcblx0XHRcdHRoaXMuX21hcC5vcGVuUG9wdXAodGhpcy5fcG9wdXAsIGxhdGxuZyk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBjbG9zZVBvcHVwKCk6IHRoaXNcclxuXHQvLyBDbG9zZXMgdGhlIHBvcHVwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgaWYgaXQgaXMgb3Blbi5cclxuXHRjbG9zZVBvcHVwOiBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAodGhpcy5fcG9wdXApIHtcclxuXHRcdFx0dGhpcy5fcG9wdXAuX2Nsb3NlKCk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIHRvZ2dsZVBvcHVwKCk6IHRoaXNcclxuXHQvLyBPcGVucyBvciBjbG9zZXMgdGhlIHBvcHVwIGJvdW5kIHRvIHRoaXMgbGF5ZXIgZGVwZW5kaW5nIG9uIGl0cyBjdXJyZW50IHN0YXRlLlxyXG5cdHRvZ2dsZVBvcHVwOiBmdW5jdGlvbiAodGFyZ2V0KSB7XHJcblx0XHRpZiAodGhpcy5fcG9wdXApIHtcclxuXHRcdFx0aWYgKHRoaXMuX3BvcHVwLl9tYXApIHtcclxuXHRcdFx0XHR0aGlzLmNsb3NlUG9wdXAoKTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHR0aGlzLm9wZW5Qb3B1cCh0YXJnZXQpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGlzUG9wdXBPcGVuKCk6IGJvb2xlYW5cclxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgcG9wdXAgYm91bmQgdG8gdGhpcyBsYXllciBpcyBjdXJyZW50bHkgb3Blbi5cclxuXHRpc1BvcHVwT3BlbjogZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuICh0aGlzLl9wb3B1cCA/IHRoaXMuX3BvcHVwLmlzT3BlbigpIDogZmFsc2UpO1xyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0UG9wdXBDb250ZW50KGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudHxQb3B1cCk6IHRoaXNcclxuXHQvLyBTZXRzIHRoZSBjb250ZW50IG9mIHRoZSBwb3B1cCBib3VuZCB0byB0aGlzIGxheWVyLlxyXG5cdHNldFBvcHVwQ29udGVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcclxuXHRcdGlmICh0aGlzLl9wb3B1cCkge1xyXG5cdFx0XHR0aGlzLl9wb3B1cC5zZXRDb250ZW50KGNvbnRlbnQpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBnZXRQb3B1cCgpOiBQb3B1cFxyXG5cdC8vIFJldHVybnMgdGhlIHBvcHVwIGJvdW5kIHRvIHRoaXMgbGF5ZXIuXHJcblx0Z2V0UG9wdXA6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHJldHVybiB0aGlzLl9wb3B1cDtcclxuXHR9LFxyXG5cclxuXHRfb3BlblBvcHVwOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0dmFyIGxheWVyID0gZS5sYXllciB8fCBlLnRhcmdldDtcclxuXHJcblx0XHRpZiAoIXRoaXMuX3BvcHVwKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRpZiAoIXRoaXMuX21hcCkge1xyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gcHJldmVudCBtYXAgY2xpY2tcclxuXHRcdHN0b3AoZSk7XHJcblxyXG5cdFx0Ly8gaWYgdGhpcyBpbmhlcml0cyBmcm9tIFBhdGggaXRzIGEgdmVjdG9yIGFuZCB3ZSBjYW4ganVzdFxyXG5cdFx0Ly8gb3BlbiB0aGUgcG9wdXAgYXQgdGhlIG5ldyBsb2NhdGlvblxyXG5cdFx0aWYgKGxheWVyIGluc3RhbmNlb2YgUGF0aCkge1xyXG5cdFx0XHR0aGlzLm9wZW5Qb3B1cChlLmxheWVyIHx8IGUudGFyZ2V0LCBlLmxhdGxuZyk7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBvdGhlcndpc2UgdHJlYXQgaXQgbGlrZSBhIG1hcmtlciBhbmQgZmlndXJlIG91dFxyXG5cdFx0Ly8gaWYgd2Ugc2hvdWxkIHRvZ2dsZSBpdCBvcGVuL2Nsb3NlZFxyXG5cdFx0aWYgKHRoaXMuX21hcC5oYXNMYXllcih0aGlzLl9wb3B1cCkgJiYgdGhpcy5fcG9wdXAuX3NvdXJjZSA9PT0gbGF5ZXIpIHtcclxuXHRcdFx0dGhpcy5jbG9zZVBvcHVwKCk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHR0aGlzLm9wZW5Qb3B1cChsYXllciwgZS5sYXRsbmcpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdF9tb3ZlUG9wdXA6IGZ1bmN0aW9uIChlKSB7XHJcblx0XHR0aGlzLl9wb3B1cC5zZXRMYXRMbmcoZS5sYXRsbmcpO1xyXG5cdH0sXHJcblxyXG5cdF9vbktleVByZXNzOiBmdW5jdGlvbiAoZSkge1xyXG5cdFx0aWYgKGUub3JpZ2luYWxFdmVudC5rZXlDb2RlID09PSAxMykge1xyXG5cdFx0XHR0aGlzLl9vcGVuUG9wdXAoZSk7XHJcblx0XHR9XHJcblx0fVxyXG59KTtcblxuLypcbiAqIEBjbGFzcyBUb29sdGlwXG4gKiBAaW5oZXJpdHMgRGl2T3ZlcmxheVxuICogQGFrYSBMLlRvb2x0aXBcbiAqIFVzZWQgdG8gZGlzcGxheSBzbWFsbCB0ZXh0cyBvbiB0b3Agb2YgbWFwIGxheWVycy5cbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIGBgYGpzXG4gKiBtYXJrZXIuYmluZFRvb2x0aXAoXCJteSB0b29sdGlwIHRleHRcIikub3BlblRvb2x0aXAoKTtcbiAqIGBgYFxuICogTm90ZSBhYm91dCB0b29sdGlwIG9mZnNldC4gTGVhZmxldCB0YWtlcyB0d28gb3B0aW9ucyBpbiBjb25zaWRlcmF0aW9uXG4gKiBmb3IgY29tcHV0aW5nIHRvb2x0aXAgb2Zmc2V0dGluZzpcbiAqIC0gdGhlIGBvZmZzZXRgIFRvb2x0aXAgb3B0aW9uOiBpdCBkZWZhdWx0cyB0byBbMCwgMF0sIGFuZCBpdCdzIHNwZWNpZmljIHRvIG9uZSB0b29sdGlwLlxuICogICBBZGQgYSBwb3NpdGl2ZSB4IG9mZnNldCB0byBtb3ZlIHRoZSB0b29sdGlwIHRvIHRoZSByaWdodCwgYW5kIGEgcG9zaXRpdmUgeSBvZmZzZXQgdG9cbiAqICAgbW92ZSBpdCB0byB0aGUgYm90dG9tLiBOZWdhdGl2ZXMgd2lsbCBtb3ZlIHRvIHRoZSBsZWZ0IGFuZCB0b3AuXG4gKiAtIHRoZSBgdG9vbHRpcEFuY2hvcmAgSWNvbiBvcHRpb246IHRoaXMgd2lsbCBvbmx5IGJlIGNvbnNpZGVyZWQgZm9yIE1hcmtlci4gWW91XG4gKiAgIHNob3VsZCBhZGFwdCB0aGlzIHZhbHVlIGlmIHlvdSB1c2UgYSBjdXN0b20gaWNvbi5cbiAqL1xuXG5cbi8vIEBuYW1lc3BhY2UgVG9vbHRpcFxudmFyIFRvb2x0aXAgPSBEaXZPdmVybGF5LmV4dGVuZCh7XG5cblx0Ly8gQHNlY3Rpb25cblx0Ly8gQGFrYSBUb29sdGlwIG9wdGlvbnNcblx0b3B0aW9uczoge1xuXHRcdC8vIEBvcHRpb24gcGFuZTogU3RyaW5nID0gJ3Rvb2x0aXBQYW5lJ1xuXHRcdC8vIGBNYXAgcGFuZWAgd2hlcmUgdGhlIHRvb2x0aXAgd2lsbCBiZSBhZGRlZC5cblx0XHRwYW5lOiAndG9vbHRpcFBhbmUnLFxuXG5cdFx0Ly8gQG9wdGlvbiBvZmZzZXQ6IFBvaW50ID0gUG9pbnQoMCwgMClcblx0XHQvLyBPcHRpb25hbCBvZmZzZXQgb2YgdGhlIHRvb2x0aXAgcG9zaXRpb24uXG5cdFx0b2Zmc2V0OiBbMCwgMF0sXG5cblx0XHQvLyBAb3B0aW9uIGRpcmVjdGlvbjogU3RyaW5nID0gJ2F1dG8nXG5cdFx0Ly8gRGlyZWN0aW9uIHdoZXJlIHRvIG9wZW4gdGhlIHRvb2x0aXAuIFBvc3NpYmxlIHZhbHVlcyBhcmU6IGByaWdodGAsIGBsZWZ0YCxcblx0XHQvLyBgdG9wYCwgYGJvdHRvbWAsIGBjZW50ZXJgLCBgYXV0b2AuXG5cdFx0Ly8gYGF1dG9gIHdpbGwgZHluYW1pY2FsbHkgc3dpdGNoIGJldHdlZW4gYHJpZ2h0YCBhbmQgYGxlZnRgIGFjY29yZGluZyB0byB0aGUgdG9vbHRpcFxuXHRcdC8vIHBvc2l0aW9uIG9uIHRoZSBtYXAuXG5cdFx0ZGlyZWN0aW9uOiAnYXV0bycsXG5cblx0XHQvLyBAb3B0aW9uIHBlcm1hbmVudDogQm9vbGVhbiA9IGZhbHNlXG5cdFx0Ly8gV2hldGhlciB0byBvcGVuIHRoZSB0b29sdGlwIHBlcm1hbmVudGx5IG9yIG9ubHkgb24gbW91c2VvdmVyLlxuXHRcdHBlcm1hbmVudDogZmFsc2UsXG5cblx0XHQvLyBAb3B0aW9uIHN0aWNreTogQm9vbGVhbiA9IGZhbHNlXG5cdFx0Ly8gSWYgdHJ1ZSwgdGhlIHRvb2x0aXAgd2lsbCBmb2xsb3cgdGhlIG1vdXNlIGluc3RlYWQgb2YgYmVpbmcgZml4ZWQgYXQgdGhlIGZlYXR1cmUgY2VudGVyLlxuXHRcdHN0aWNreTogZmFsc2UsXG5cblx0XHQvLyBAb3B0aW9uIGludGVyYWN0aXZlOiBCb29sZWFuID0gZmFsc2Vcblx0XHQvLyBJZiB0cnVlLCB0aGUgdG9vbHRpcCB3aWxsIGxpc3RlbiB0byB0aGUgZmVhdHVyZSBldmVudHMuXG5cdFx0aW50ZXJhY3RpdmU6IGZhbHNlLFxuXG5cdFx0Ly8gQG9wdGlvbiBvcGFjaXR5OiBOdW1iZXIgPSAwLjlcblx0XHQvLyBUb29sdGlwIGNvbnRhaW5lciBvcGFjaXR5LlxuXHRcdG9wYWNpdHk6IDAuOVxuXHR9LFxuXG5cdG9uQWRkOiBmdW5jdGlvbiAobWFwKSB7XG5cdFx0RGl2T3ZlcmxheS5wcm90b3R5cGUub25BZGQuY2FsbCh0aGlzLCBtYXApO1xuXHRcdHRoaXMuc2V0T3BhY2l0eSh0aGlzLm9wdGlvbnMub3BhY2l0eSk7XG5cblx0XHQvLyBAbmFtZXNwYWNlIE1hcFxuXHRcdC8vIEBzZWN0aW9uIFRvb2x0aXAgZXZlbnRzXG5cdFx0Ly8gQGV2ZW50IHRvb2x0aXBvcGVuOiBUb29sdGlwRXZlbnRcblx0XHQvLyBGaXJlZCB3aGVuIGEgdG9vbHRpcCBpcyBvcGVuZWQgaW4gdGhlIG1hcC5cblx0XHRtYXAuZmlyZSgndG9vbHRpcG9wZW4nLCB7dG9vbHRpcDogdGhpc30pO1xuXG5cdFx0aWYgKHRoaXMuX3NvdXJjZSkge1xuXHRcdFx0Ly8gQG5hbWVzcGFjZSBMYXllclxuXHRcdFx0Ly8gQHNlY3Rpb24gVG9vbHRpcCBldmVudHNcblx0XHRcdC8vIEBldmVudCB0b29sdGlwb3BlbjogVG9vbHRpcEV2ZW50XG5cdFx0XHQvLyBGaXJlZCB3aGVuIGEgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGlzIG9wZW5lZC5cblx0XHRcdHRoaXMuX3NvdXJjZS5maXJlKCd0b29sdGlwb3BlbicsIHt0b29sdGlwOiB0aGlzfSwgdHJ1ZSk7XG5cdFx0fVxuXHR9LFxuXG5cdG9uUmVtb3ZlOiBmdW5jdGlvbiAobWFwKSB7XG5cdFx0RGl2T3ZlcmxheS5wcm90b3R5cGUub25SZW1vdmUuY2FsbCh0aGlzLCBtYXApO1xuXG5cdFx0Ly8gQG5hbWVzcGFjZSBNYXBcblx0XHQvLyBAc2VjdGlvbiBUb29sdGlwIGV2ZW50c1xuXHRcdC8vIEBldmVudCB0b29sdGlwY2xvc2U6IFRvb2x0aXBFdmVudFxuXHRcdC8vIEZpcmVkIHdoZW4gYSB0b29sdGlwIGluIHRoZSBtYXAgaXMgY2xvc2VkLlxuXHRcdG1hcC5maXJlKCd0b29sdGlwY2xvc2UnLCB7dG9vbHRpcDogdGhpc30pO1xuXG5cdFx0aWYgKHRoaXMuX3NvdXJjZSkge1xuXHRcdFx0Ly8gQG5hbWVzcGFjZSBMYXllclxuXHRcdFx0Ly8gQHNlY3Rpb24gVG9vbHRpcCBldmVudHNcblx0XHRcdC8vIEBldmVudCB0b29sdGlwY2xvc2U6IFRvb2x0aXBFdmVudFxuXHRcdFx0Ly8gRmlyZWQgd2hlbiBhIHRvb2x0aXAgYm91bmQgdG8gdGhpcyBsYXllciBpcyBjbG9zZWQuXG5cdFx0XHR0aGlzLl9zb3VyY2UuZmlyZSgndG9vbHRpcGNsb3NlJywge3Rvb2x0aXA6IHRoaXN9LCB0cnVlKTtcblx0XHR9XG5cdH0sXG5cblx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGV2ZW50cyA9IERpdk92ZXJsYXkucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xuXG5cdFx0aWYgKHRvdWNoICYmICF0aGlzLm9wdGlvbnMucGVybWFuZW50KSB7XG5cdFx0XHRldmVudHMucHJlY2xpY2sgPSB0aGlzLl9jbG9zZTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZXZlbnRzO1xuXHR9LFxuXG5cdF9jbG9zZTogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9tYXApIHtcblx0XHRcdHRoaXMuX21hcC5jbG9zZVRvb2x0aXAodGhpcyk7XG5cdFx0fVxuXHR9LFxuXG5cdF9pbml0TGF5b3V0OiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHByZWZpeCA9ICdsZWFmbGV0LXRvb2x0aXAnLFxuXHRcdCAgICBjbGFzc05hbWUgPSBwcmVmaXggKyAnICcgKyAodGhpcy5vcHRpb25zLmNsYXNzTmFtZSB8fCAnJykgKyAnIGxlYWZsZXQtem9vbS0nICsgKHRoaXMuX3pvb21BbmltYXRlZCA/ICdhbmltYXRlZCcgOiAnaGlkZScpO1xuXG5cdFx0dGhpcy5fY29udGVudE5vZGUgPSB0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgY2xhc3NOYW1lKTtcblx0fSxcblxuXHRfdXBkYXRlTGF5b3V0OiBmdW5jdGlvbiAoKSB7fSxcblxuXHRfYWRqdXN0UGFuOiBmdW5jdGlvbiAoKSB7fSxcblxuXHRfc2V0UG9zaXRpb246IGZ1bmN0aW9uIChwb3MpIHtcblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuXHRcdCAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIsXG5cdFx0ICAgIGNlbnRlclBvaW50ID0gbWFwLmxhdExuZ1RvQ29udGFpbmVyUG9pbnQobWFwLmdldENlbnRlcigpKSxcblx0XHQgICAgdG9vbHRpcFBvaW50ID0gbWFwLmxheWVyUG9pbnRUb0NvbnRhaW5lclBvaW50KHBvcyksXG5cdFx0ICAgIGRpcmVjdGlvbiA9IHRoaXMub3B0aW9ucy5kaXJlY3Rpb24sXG5cdFx0ICAgIHRvb2x0aXBXaWR0aCA9IGNvbnRhaW5lci5vZmZzZXRXaWR0aCxcblx0XHQgICAgdG9vbHRpcEhlaWdodCA9IGNvbnRhaW5lci5vZmZzZXRIZWlnaHQsXG5cdFx0ICAgIG9mZnNldCA9IHRvUG9pbnQodGhpcy5vcHRpb25zLm9mZnNldCksXG5cdFx0ICAgIGFuY2hvciA9IHRoaXMuX2dldEFuY2hvcigpO1xuXG5cdFx0aWYgKGRpcmVjdGlvbiA9PT0gJ3RvcCcpIHtcblx0XHRcdHBvcyA9IHBvcy5hZGQodG9Qb2ludCgtdG9vbHRpcFdpZHRoIC8gMiArIG9mZnNldC54LCAtdG9vbHRpcEhlaWdodCArIG9mZnNldC55ICsgYW5jaG9yLnksIHRydWUpKTtcblx0XHR9IGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gJ2JvdHRvbScpIHtcblx0XHRcdHBvcyA9IHBvcy5zdWJ0cmFjdCh0b1BvaW50KHRvb2x0aXBXaWR0aCAvIDIgLSBvZmZzZXQueCwgLW9mZnNldC55LCB0cnVlKSk7XG5cdFx0fSBlbHNlIGlmIChkaXJlY3Rpb24gPT09ICdjZW50ZXInKSB7XG5cdFx0XHRwb3MgPSBwb3Muc3VidHJhY3QodG9Qb2ludCh0b29sdGlwV2lkdGggLyAyICsgb2Zmc2V0LngsIHRvb2x0aXBIZWlnaHQgLyAyIC0gYW5jaG9yLnkgKyBvZmZzZXQueSwgdHJ1ZSkpO1xuXHRcdH0gZWxzZSBpZiAoZGlyZWN0aW9uID09PSAncmlnaHQnIHx8IGRpcmVjdGlvbiA9PT0gJ2F1dG8nICYmIHRvb2x0aXBQb2ludC54IDwgY2VudGVyUG9pbnQueCkge1xuXHRcdFx0ZGlyZWN0aW9uID0gJ3JpZ2h0Jztcblx0XHRcdHBvcyA9IHBvcy5hZGQodG9Qb2ludChvZmZzZXQueCArIGFuY2hvci54LCBhbmNob3IueSAtIHRvb2x0aXBIZWlnaHQgLyAyICsgb2Zmc2V0LnksIHRydWUpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZGlyZWN0aW9uID0gJ2xlZnQnO1xuXHRcdFx0cG9zID0gcG9zLnN1YnRyYWN0KHRvUG9pbnQodG9vbHRpcFdpZHRoICsgYW5jaG9yLnggLSBvZmZzZXQueCwgdG9vbHRpcEhlaWdodCAvIDIgLSBhbmNob3IueSAtIG9mZnNldC55LCB0cnVlKSk7XG5cdFx0fVxuXG5cdFx0cmVtb3ZlQ2xhc3MoY29udGFpbmVyLCAnbGVhZmxldC10b29sdGlwLXJpZ2h0Jyk7XG5cdFx0cmVtb3ZlQ2xhc3MoY29udGFpbmVyLCAnbGVhZmxldC10b29sdGlwLWxlZnQnKTtcblx0XHRyZW1vdmVDbGFzcyhjb250YWluZXIsICdsZWFmbGV0LXRvb2x0aXAtdG9wJyk7XG5cdFx0cmVtb3ZlQ2xhc3MoY29udGFpbmVyLCAnbGVhZmxldC10b29sdGlwLWJvdHRvbScpO1xuXHRcdGFkZENsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdG9vbHRpcC0nICsgZGlyZWN0aW9uKTtcblx0XHRzZXRQb3NpdGlvbihjb250YWluZXIsIHBvcyk7XG5cdH0sXG5cblx0X3VwZGF0ZVBvc2l0aW9uOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHBvcyA9IHRoaXMuX21hcC5sYXRMbmdUb0xheWVyUG9pbnQodGhpcy5fbGF0bG5nKTtcblx0XHR0aGlzLl9zZXRQb3NpdGlvbihwb3MpO1xuXHR9LFxuXG5cdHNldE9wYWNpdHk6IGZ1bmN0aW9uIChvcGFjaXR5KSB7XG5cdFx0dGhpcy5vcHRpb25zLm9wYWNpdHkgPSBvcGFjaXR5O1xuXG5cdFx0aWYgKHRoaXMuX2NvbnRhaW5lcikge1xuXHRcdFx0c2V0T3BhY2l0eSh0aGlzLl9jb250YWluZXIsIG9wYWNpdHkpO1xuXHRcdH1cblx0fSxcblxuXHRfYW5pbWF0ZVpvb206IGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIHBvcyA9IHRoaXMuX21hcC5fbGF0TG5nVG9OZXdMYXllclBvaW50KHRoaXMuX2xhdGxuZywgZS56b29tLCBlLmNlbnRlcik7XG5cdFx0dGhpcy5fc2V0UG9zaXRpb24ocG9zKTtcblx0fSxcblxuXHRfZ2V0QW5jaG9yOiBmdW5jdGlvbiAoKSB7XG5cdFx0Ly8gV2hlcmUgc2hvdWxkIHdlIGFuY2hvciB0aGUgdG9vbHRpcCBvbiB0aGUgc291cmNlIGxheWVyP1xuXHRcdHJldHVybiB0b1BvaW50KHRoaXMuX3NvdXJjZSAmJiB0aGlzLl9zb3VyY2UuX2dldFRvb2x0aXBBbmNob3IgJiYgIXRoaXMub3B0aW9ucy5zdGlja3kgPyB0aGlzLl9zb3VyY2UuX2dldFRvb2x0aXBBbmNob3IoKSA6IFswLCAwXSk7XG5cdH1cblxufSk7XG5cbi8vIEBuYW1lc3BhY2UgVG9vbHRpcFxuLy8gQGZhY3RvcnkgTC50b29sdGlwKG9wdGlvbnM/OiBUb29sdGlwIG9wdGlvbnMsIHNvdXJjZT86IExheWVyKVxuLy8gSW5zdGFudGlhdGVzIGEgVG9vbHRpcCBvYmplY3QgZ2l2ZW4gYW4gb3B0aW9uYWwgYG9wdGlvbnNgIG9iamVjdCB0aGF0IGRlc2NyaWJlcyBpdHMgYXBwZWFyYW5jZSBhbmQgbG9jYXRpb24gYW5kIGFuIG9wdGlvbmFsIGBzb3VyY2VgIG9iamVjdCB0aGF0IGlzIHVzZWQgdG8gdGFnIHRoZSB0b29sdGlwIHdpdGggYSByZWZlcmVuY2UgdG8gdGhlIExheWVyIHRvIHdoaWNoIGl0IHJlZmVycy5cbnZhciB0b29sdGlwID0gZnVuY3Rpb24gKG9wdGlvbnMsIHNvdXJjZSkge1xuXHRyZXR1cm4gbmV3IFRvb2x0aXAob3B0aW9ucywgc291cmNlKTtcbn07XG5cbi8vIEBuYW1lc3BhY2UgTWFwXG4vLyBAc2VjdGlvbiBNZXRob2RzIGZvciBMYXllcnMgYW5kIENvbnRyb2xzXG5NYXAuaW5jbHVkZSh7XG5cblx0Ly8gQG1ldGhvZCBvcGVuVG9vbHRpcCh0b29sdGlwOiBUb29sdGlwKTogdGhpc1xuXHQvLyBPcGVucyB0aGUgc3BlY2lmaWVkIHRvb2x0aXAuXG5cdC8vIEBhbHRlcm5hdGl2ZVxuXHQvLyBAbWV0aG9kIG9wZW5Ub29sdGlwKGNvbnRlbnQ6IFN0cmluZ3xIVE1MRWxlbWVudCwgbGF0bG5nOiBMYXRMbmcsIG9wdGlvbnM/OiBUb29sdGlwIG9wdGlvbnMpOiB0aGlzXG5cdC8vIENyZWF0ZXMgYSB0b29sdGlwIHdpdGggdGhlIHNwZWNpZmllZCBjb250ZW50IGFuZCBvcHRpb25zIGFuZCBvcGVuIGl0LlxuXHRvcGVuVG9vbHRpcDogZnVuY3Rpb24gKHRvb2x0aXAsIGxhdGxuZywgb3B0aW9ucykge1xuXHRcdGlmICghKHRvb2x0aXAgaW5zdGFuY2VvZiBUb29sdGlwKSkge1xuXHRcdFx0dG9vbHRpcCA9IG5ldyBUb29sdGlwKG9wdGlvbnMpLnNldENvbnRlbnQodG9vbHRpcCk7XG5cdFx0fVxuXG5cdFx0aWYgKGxhdGxuZykge1xuXHRcdFx0dG9vbHRpcC5zZXRMYXRMbmcobGF0bG5nKTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5oYXNMYXllcih0b29sdGlwKSkge1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuYWRkTGF5ZXIodG9vbHRpcCk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBjbG9zZVRvb2x0aXAodG9vbHRpcD86IFRvb2x0aXApOiB0aGlzXG5cdC8vIENsb3NlcyB0aGUgdG9vbHRpcCBnaXZlbiBhcyBwYXJhbWV0ZXIuXG5cdGNsb3NlVG9vbHRpcDogZnVuY3Rpb24gKHRvb2x0aXApIHtcblx0XHRpZiAodG9vbHRpcCkge1xuXHRcdFx0dGhpcy5yZW1vdmVMYXllcih0b29sdGlwKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cblxufSk7XG5cbi8qXG4gKiBAbmFtZXNwYWNlIExheWVyXG4gKiBAc2VjdGlvbiBUb29sdGlwIG1ldGhvZHMgZXhhbXBsZVxuICpcbiAqIEFsbCBsYXllcnMgc2hhcmUgYSBzZXQgb2YgbWV0aG9kcyBjb252ZW5pZW50IGZvciBiaW5kaW5nIHRvb2x0aXBzIHRvIGl0LlxuICpcbiAqIGBgYGpzXG4gKiB2YXIgbGF5ZXIgPSBMLlBvbHlnb24obGF0bG5ncykuYmluZFRvb2x0aXAoJ0hpIFRoZXJlIScpLmFkZFRvKG1hcCk7XG4gKiBsYXllci5vcGVuVG9vbHRpcCgpO1xuICogbGF5ZXIuY2xvc2VUb29sdGlwKCk7XG4gKiBgYGBcbiAqL1xuXG4vLyBAc2VjdGlvbiBUb29sdGlwIG1ldGhvZHNcbkxheWVyLmluY2x1ZGUoe1xuXG5cdC8vIEBtZXRob2QgYmluZFRvb2x0aXAoY29udGVudDogU3RyaW5nfEhUTUxFbGVtZW50fEZ1bmN0aW9ufFRvb2x0aXAsIG9wdGlvbnM/OiBUb29sdGlwIG9wdGlvbnMpOiB0aGlzXG5cdC8vIEJpbmRzIGEgdG9vbHRpcCB0byB0aGUgbGF5ZXIgd2l0aCB0aGUgcGFzc2VkIGBjb250ZW50YCBhbmQgc2V0cyB1cCB0aGVcblx0Ly8gbmVjZXNzYXJ5IGV2ZW50IGxpc3RlbmVycy4gSWYgYSBgRnVuY3Rpb25gIGlzIHBhc3NlZCBpdCB3aWxsIHJlY2VpdmVcblx0Ly8gdGhlIGxheWVyIGFzIHRoZSBmaXJzdCBhcmd1bWVudCBhbmQgc2hvdWxkIHJldHVybiBhIGBTdHJpbmdgIG9yIGBIVE1MRWxlbWVudGAuXG5cdGJpbmRUb29sdGlwOiBmdW5jdGlvbiAoY29udGVudCwgb3B0aW9ucykge1xuXG5cdFx0aWYgKGNvbnRlbnQgaW5zdGFuY2VvZiBUb29sdGlwKSB7XG5cdFx0XHRzZXRPcHRpb25zKGNvbnRlbnQsIG9wdGlvbnMpO1xuXHRcdFx0dGhpcy5fdG9vbHRpcCA9IGNvbnRlbnQ7XG5cdFx0XHRjb250ZW50Ll9zb3VyY2UgPSB0aGlzO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRpZiAoIXRoaXMuX3Rvb2x0aXAgfHwgb3B0aW9ucykge1xuXHRcdFx0XHR0aGlzLl90b29sdGlwID0gbmV3IFRvb2x0aXAob3B0aW9ucywgdGhpcyk7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLl90b29sdGlwLnNldENvbnRlbnQoY29udGVudCk7XG5cblx0XHR9XG5cblx0XHR0aGlzLl9pbml0VG9vbHRpcEludGVyYWN0aW9ucygpO1xuXG5cdFx0aWYgKHRoaXMuX3Rvb2x0aXAub3B0aW9ucy5wZXJtYW5lbnQgJiYgdGhpcy5fbWFwICYmIHRoaXMuX21hcC5oYXNMYXllcih0aGlzKSkge1xuXHRcdFx0dGhpcy5vcGVuVG9vbHRpcCgpO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgdW5iaW5kVG9vbHRpcCgpOiB0aGlzXG5cdC8vIFJlbW92ZXMgdGhlIHRvb2x0aXAgcHJldmlvdXNseSBib3VuZCB3aXRoIGBiaW5kVG9vbHRpcGAuXG5cdHVuYmluZFRvb2x0aXA6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAodGhpcy5fdG9vbHRpcCkge1xuXHRcdFx0dGhpcy5faW5pdFRvb2x0aXBJbnRlcmFjdGlvbnModHJ1ZSk7XG5cdFx0XHR0aGlzLmNsb3NlVG9vbHRpcCgpO1xuXHRcdFx0dGhpcy5fdG9vbHRpcCA9IG51bGw7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdF9pbml0VG9vbHRpcEludGVyYWN0aW9uczogZnVuY3Rpb24gKHJlbW92ZSQkMSkge1xuXHRcdGlmICghcmVtb3ZlJCQxICYmIHRoaXMuX3Rvb2x0aXBIYW5kbGVyc0FkZGVkKSB7IHJldHVybjsgfVxuXHRcdHZhciBvbk9mZiA9IHJlbW92ZSQkMSA/ICdvZmYnIDogJ29uJyxcblx0XHQgICAgZXZlbnRzID0ge1xuXHRcdFx0cmVtb3ZlOiB0aGlzLmNsb3NlVG9vbHRpcCxcblx0XHRcdG1vdmU6IHRoaXMuX21vdmVUb29sdGlwXG5cdFx0ICAgIH07XG5cdFx0aWYgKCF0aGlzLl90b29sdGlwLm9wdGlvbnMucGVybWFuZW50KSB7XG5cdFx0XHRldmVudHMubW91c2VvdmVyID0gdGhpcy5fb3BlblRvb2x0aXA7XG5cdFx0XHRldmVudHMubW91c2VvdXQgPSB0aGlzLmNsb3NlVG9vbHRpcDtcblx0XHRcdGlmICh0aGlzLl90b29sdGlwLm9wdGlvbnMuc3RpY2t5KSB7XG5cdFx0XHRcdGV2ZW50cy5tb3VzZW1vdmUgPSB0aGlzLl9tb3ZlVG9vbHRpcDtcblx0XHRcdH1cblx0XHRcdGlmICh0b3VjaCkge1xuXHRcdFx0XHRldmVudHMuY2xpY2sgPSB0aGlzLl9vcGVuVG9vbHRpcDtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0ZXZlbnRzLmFkZCA9IHRoaXMuX29wZW5Ub29sdGlwO1xuXHRcdH1cblx0XHR0aGlzW29uT2ZmXShldmVudHMpO1xuXHRcdHRoaXMuX3Rvb2x0aXBIYW5kbGVyc0FkZGVkID0gIXJlbW92ZSQkMTtcblx0fSxcblxuXHQvLyBAbWV0aG9kIG9wZW5Ub29sdGlwKGxhdGxuZz86IExhdExuZyk6IHRoaXNcblx0Ly8gT3BlbnMgdGhlIGJvdW5kIHRvb2x0aXAgYXQgdGhlIHNwZWNpZmllZCBgbGF0bG5nYCBvciBhdCB0aGUgZGVmYXVsdCB0b29sdGlwIGFuY2hvciBpZiBubyBgbGF0bG5nYCBpcyBwYXNzZWQuXG5cdG9wZW5Ub29sdGlwOiBmdW5jdGlvbiAobGF5ZXIsIGxhdGxuZykge1xuXHRcdGlmICghKGxheWVyIGluc3RhbmNlb2YgTGF5ZXIpKSB7XG5cdFx0XHRsYXRsbmcgPSBsYXllcjtcblx0XHRcdGxheWVyID0gdGhpcztcblx0XHR9XG5cblx0XHRpZiAobGF5ZXIgaW5zdGFuY2VvZiBGZWF0dXJlR3JvdXApIHtcblx0XHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuXHRcdFx0XHRsYXllciA9IHRoaXMuX2xheWVyc1tpZF07XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICghbGF0bG5nKSB7XG5cdFx0XHRsYXRsbmcgPSBsYXllci5nZXRDZW50ZXIgPyBsYXllci5nZXRDZW50ZXIoKSA6IGxheWVyLmdldExhdExuZygpO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLl90b29sdGlwICYmIHRoaXMuX21hcCkge1xuXG5cdFx0XHQvLyBzZXQgdG9vbHRpcCBzb3VyY2UgdG8gdGhpcyBsYXllclxuXHRcdFx0dGhpcy5fdG9vbHRpcC5fc291cmNlID0gbGF5ZXI7XG5cblx0XHRcdC8vIHVwZGF0ZSB0aGUgdG9vbHRpcCAoY29udGVudCwgbGF5b3V0LCBlY3QuLi4pXG5cdFx0XHR0aGlzLl90b29sdGlwLnVwZGF0ZSgpO1xuXG5cdFx0XHQvLyBvcGVuIHRoZSB0b29sdGlwIG9uIHRoZSBtYXBcblx0XHRcdHRoaXMuX21hcC5vcGVuVG9vbHRpcCh0aGlzLl90b29sdGlwLCBsYXRsbmcpO1xuXG5cdFx0XHQvLyBUb29sdGlwIGNvbnRhaW5lciBtYXkgbm90IGJlIGRlZmluZWQgaWYgbm90IHBlcm1hbmVudCBhbmQgbmV2ZXJcblx0XHRcdC8vIG9wZW5lZC5cblx0XHRcdGlmICh0aGlzLl90b29sdGlwLm9wdGlvbnMuaW50ZXJhY3RpdmUgJiYgdGhpcy5fdG9vbHRpcC5fY29udGFpbmVyKSB7XG5cdFx0XHRcdGFkZENsYXNzKHRoaXMuX3Rvb2x0aXAuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY2xpY2thYmxlJyk7XG5cdFx0XHRcdHRoaXMuYWRkSW50ZXJhY3RpdmVUYXJnZXQodGhpcy5fdG9vbHRpcC5fY29udGFpbmVyKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGNsb3NlVG9vbHRpcCgpOiB0aGlzXG5cdC8vIENsb3NlcyB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGlmIGl0IGlzIG9wZW4uXG5cdGNsb3NlVG9vbHRpcDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl90b29sdGlwKSB7XG5cdFx0XHR0aGlzLl90b29sdGlwLl9jbG9zZSgpO1xuXHRcdFx0aWYgKHRoaXMuX3Rvb2x0aXAub3B0aW9ucy5pbnRlcmFjdGl2ZSAmJiB0aGlzLl90b29sdGlwLl9jb250YWluZXIpIHtcblx0XHRcdFx0cmVtb3ZlQ2xhc3ModGhpcy5fdG9vbHRpcC5fY29udGFpbmVyLCAnbGVhZmxldC1jbGlja2FibGUnKTtcblx0XHRcdFx0dGhpcy5yZW1vdmVJbnRlcmFjdGl2ZVRhcmdldCh0aGlzLl90b29sdGlwLl9jb250YWluZXIpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIHRvZ2dsZVRvb2x0aXAoKTogdGhpc1xuXHQvLyBPcGVucyBvciBjbG9zZXMgdGhlIHRvb2x0aXAgYm91bmQgdG8gdGhpcyBsYXllciBkZXBlbmRpbmcgb24gaXRzIGN1cnJlbnQgc3RhdGUuXG5cdHRvZ2dsZVRvb2x0aXA6IGZ1bmN0aW9uICh0YXJnZXQpIHtcblx0XHRpZiAodGhpcy5fdG9vbHRpcCkge1xuXHRcdFx0aWYgKHRoaXMuX3Rvb2x0aXAuX21hcCkge1xuXHRcdFx0XHR0aGlzLmNsb3NlVG9vbHRpcCgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5vcGVuVG9vbHRpcCh0YXJnZXQpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGlzVG9vbHRpcE9wZW4oKTogYm9vbGVhblxuXHQvLyBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyIGlzIGN1cnJlbnRseSBvcGVuLlxuXHRpc1Rvb2x0aXBPcGVuOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX3Rvb2x0aXAuaXNPcGVuKCk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBzZXRUb29sdGlwQ29udGVudChjb250ZW50OiBTdHJpbmd8SFRNTEVsZW1lbnR8VG9vbHRpcCk6IHRoaXNcblx0Ly8gU2V0cyB0aGUgY29udGVudCBvZiB0aGUgdG9vbHRpcCBib3VuZCB0byB0aGlzIGxheWVyLlxuXHRzZXRUb29sdGlwQ29udGVudDogZnVuY3Rpb24gKGNvbnRlbnQpIHtcblx0XHRpZiAodGhpcy5fdG9vbHRpcCkge1xuXHRcdFx0dGhpcy5fdG9vbHRpcC5zZXRDb250ZW50KGNvbnRlbnQpO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGdldFRvb2x0aXAoKTogVG9vbHRpcFxuXHQvLyBSZXR1cm5zIHRoZSB0b29sdGlwIGJvdW5kIHRvIHRoaXMgbGF5ZXIuXG5cdGdldFRvb2x0aXA6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fdG9vbHRpcDtcblx0fSxcblxuXHRfb3BlblRvb2x0aXA6IGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIGxheWVyID0gZS5sYXllciB8fCBlLnRhcmdldDtcblxuXHRcdGlmICghdGhpcy5fdG9vbHRpcCB8fCAhdGhpcy5fbWFwKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMub3BlblRvb2x0aXAobGF5ZXIsIHRoaXMuX3Rvb2x0aXAub3B0aW9ucy5zdGlja3kgPyBlLmxhdGxuZyA6IHVuZGVmaW5lZCk7XG5cdH0sXG5cblx0X21vdmVUb29sdGlwOiBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBsYXRsbmcgPSBlLmxhdGxuZywgY29udGFpbmVyUG9pbnQsIGxheWVyUG9pbnQ7XG5cdFx0aWYgKHRoaXMuX3Rvb2x0aXAub3B0aW9ucy5zdGlja3kgJiYgZS5vcmlnaW5hbEV2ZW50KSB7XG5cdFx0XHRjb250YWluZXJQb2ludCA9IHRoaXMuX21hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLm9yaWdpbmFsRXZlbnQpO1xuXHRcdFx0bGF5ZXJQb2ludCA9IHRoaXMuX21hcC5jb250YWluZXJQb2ludFRvTGF5ZXJQb2ludChjb250YWluZXJQb2ludCk7XG5cdFx0XHRsYXRsbmcgPSB0aGlzLl9tYXAubGF5ZXJQb2ludFRvTGF0TG5nKGxheWVyUG9pbnQpO1xuXHRcdH1cblx0XHR0aGlzLl90b29sdGlwLnNldExhdExuZyhsYXRsbmcpO1xuXHR9XG59KTtcblxuLypcbiAqIEBjbGFzcyBEaXZJY29uXG4gKiBAYWthIEwuRGl2SWNvblxuICogQGluaGVyaXRzIEljb25cbiAqXG4gKiBSZXByZXNlbnRzIGEgbGlnaHR3ZWlnaHQgaWNvbiBmb3IgbWFya2VycyB0aGF0IHVzZXMgYSBzaW1wbGUgYDxkaXY+YFxuICogZWxlbWVudCBpbnN0ZWFkIG9mIGFuIGltYWdlLiBJbmhlcml0cyBmcm9tIGBJY29uYCBidXQgaWdub3JlcyB0aGUgYGljb25VcmxgIGFuZCBzaGFkb3cgb3B0aW9ucy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBganNcbiAqIHZhciBteUljb24gPSBMLmRpdkljb24oe2NsYXNzTmFtZTogJ215LWRpdi1pY29uJ30pO1xuICogLy8geW91IGNhbiBzZXQgLm15LWRpdi1pY29uIHN0eWxlcyBpbiBDU1NcbiAqXG4gKiBMLm1hcmtlcihbNTAuNTA1LCAzMC41N10sIHtpY29uOiBteUljb259KS5hZGRUbyhtYXApO1xuICogYGBgXG4gKlxuICogQnkgZGVmYXVsdCwgaXQgaGFzIGEgJ2xlYWZsZXQtZGl2LWljb24nIENTUyBjbGFzcyBhbmQgaXMgc3R5bGVkIGFzIGEgbGl0dGxlIHdoaXRlIHNxdWFyZSB3aXRoIGEgc2hhZG93LlxuICovXG5cbnZhciBEaXZJY29uID0gSWNvbi5leHRlbmQoe1xuXHRvcHRpb25zOiB7XG5cdFx0Ly8gQHNlY3Rpb25cblx0XHQvLyBAYWthIERpdkljb24gb3B0aW9uc1xuXHRcdGljb25TaXplOiBbMTIsIDEyXSwgLy8gYWxzbyBjYW4gYmUgc2V0IHRocm91Z2ggQ1NTXG5cblx0XHQvLyBpY29uQW5jaG9yOiAoUG9pbnQpLFxuXHRcdC8vIHBvcHVwQW5jaG9yOiAoUG9pbnQpLFxuXG5cdFx0Ly8gQG9wdGlvbiBodG1sOiBTdHJpbmcgPSAnJ1xuXHRcdC8vIEN1c3RvbSBIVE1MIGNvZGUgdG8gcHV0IGluc2lkZSB0aGUgZGl2IGVsZW1lbnQsIGVtcHR5IGJ5IGRlZmF1bHQuXG5cdFx0aHRtbDogZmFsc2UsXG5cblx0XHQvLyBAb3B0aW9uIGJnUG9zOiBQb2ludCA9IFswLCAwXVxuXHRcdC8vIE9wdGlvbmFsIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSBiYWNrZ3JvdW5kLCBpbiBwaXhlbHNcblx0XHRiZ1BvczogbnVsbCxcblxuXHRcdGNsYXNzTmFtZTogJ2xlYWZsZXQtZGl2LWljb24nXG5cdH0sXG5cblx0Y3JlYXRlSWNvbjogZnVuY3Rpb24gKG9sZEljb24pIHtcblx0XHR2YXIgZGl2ID0gKG9sZEljb24gJiYgb2xkSWNvbi50YWdOYW1lID09PSAnRElWJykgPyBvbGRJY29uIDogZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JyksXG5cdFx0ICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cblx0XHRkaXYuaW5uZXJIVE1MID0gb3B0aW9ucy5odG1sICE9PSBmYWxzZSA/IG9wdGlvbnMuaHRtbCA6ICcnO1xuXG5cdFx0aWYgKG9wdGlvbnMuYmdQb3MpIHtcblx0XHRcdHZhciBiZ1BvcyA9IHRvUG9pbnQob3B0aW9ucy5iZ1Bvcyk7XG5cdFx0XHRkaXYuc3R5bGUuYmFja2dyb3VuZFBvc2l0aW9uID0gKC1iZ1Bvcy54KSArICdweCAnICsgKC1iZ1Bvcy55KSArICdweCc7XG5cdFx0fVxuXHRcdHRoaXMuX3NldEljb25TdHlsZXMoZGl2LCAnaWNvbicpO1xuXG5cdFx0cmV0dXJuIGRpdjtcblx0fSxcblxuXHRjcmVhdGVTaGFkb3c6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gbnVsbDtcblx0fVxufSk7XG5cbi8vIEBmYWN0b3J5IEwuZGl2SWNvbihvcHRpb25zOiBEaXZJY29uIG9wdGlvbnMpXG4vLyBDcmVhdGVzIGEgYERpdkljb25gIGluc3RhbmNlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG5mdW5jdGlvbiBkaXZJY29uKG9wdGlvbnMpIHtcblx0cmV0dXJuIG5ldyBEaXZJY29uKG9wdGlvbnMpO1xufVxuXG5JY29uLkRlZmF1bHQgPSBJY29uRGVmYXVsdDtcblxuLypcbiAqIEBjbGFzcyBHcmlkTGF5ZXJcbiAqIEBpbmhlcml0cyBMYXllclxuICogQGFrYSBMLkdyaWRMYXllclxuICpcbiAqIEdlbmVyaWMgY2xhc3MgZm9yIGhhbmRsaW5nIGEgdGlsZWQgZ3JpZCBvZiBIVE1MIGVsZW1lbnRzLiBUaGlzIGlzIHRoZSBiYXNlIGNsYXNzIGZvciBhbGwgdGlsZSBsYXllcnMgYW5kIHJlcGxhY2VzIGBUaWxlTGF5ZXIuQ2FudmFzYC5cbiAqIEdyaWRMYXllciBjYW4gYmUgZXh0ZW5kZWQgdG8gY3JlYXRlIGEgdGlsZWQgZ3JpZCBvZiBIVE1MIGVsZW1lbnRzIGxpa2UgYDxjYW52YXM+YCwgYDxpbWc+YCBvciBgPGRpdj5gLiBHcmlkTGF5ZXIgd2lsbCBoYW5kbGUgY3JlYXRpbmcgYW5kIGFuaW1hdGluZyB0aGVzZSBET00gZWxlbWVudHMgZm9yIHlvdS5cbiAqXG4gKlxuICogQHNlY3Rpb24gU3luY2hyb25vdXMgdXNhZ2VcbiAqIEBleGFtcGxlXG4gKlxuICogVG8gY3JlYXRlIGEgY3VzdG9tIGxheWVyLCBleHRlbmQgR3JpZExheWVyIGFuZCBpbXBsZW1lbnQgdGhlIGBjcmVhdGVUaWxlKClgIG1ldGhvZCwgd2hpY2ggd2lsbCBiZSBwYXNzZWQgYSBgUG9pbnRgIG9iamVjdCB3aXRoIHRoZSBgeGAsIGB5YCwgYW5kIGB6YCAoem9vbSBsZXZlbCkgY29vcmRpbmF0ZXMgdG8gZHJhdyB5b3VyIHRpbGUuXG4gKlxuICogYGBganNcbiAqIHZhciBDYW52YXNMYXllciA9IEwuR3JpZExheWVyLmV4dGVuZCh7XG4gKiAgICAgY3JlYXRlVGlsZTogZnVuY3Rpb24oY29vcmRzKXtcbiAqICAgICAgICAgLy8gY3JlYXRlIGEgPGNhbnZhcz4gZWxlbWVudCBmb3IgZHJhd2luZ1xuICogICAgICAgICB2YXIgdGlsZSA9IEwuRG9tVXRpbC5jcmVhdGUoJ2NhbnZhcycsICdsZWFmbGV0LXRpbGUnKTtcbiAqXG4gKiAgICAgICAgIC8vIHNldHVwIHRpbGUgd2lkdGggYW5kIGhlaWdodCBhY2NvcmRpbmcgdG8gdGhlIG9wdGlvbnNcbiAqICAgICAgICAgdmFyIHNpemUgPSB0aGlzLmdldFRpbGVTaXplKCk7XG4gKiAgICAgICAgIHRpbGUud2lkdGggPSBzaXplLng7XG4gKiAgICAgICAgIHRpbGUuaGVpZ2h0ID0gc2l6ZS55O1xuICpcbiAqICAgICAgICAgLy8gZ2V0IGEgY2FudmFzIGNvbnRleHQgYW5kIGRyYXcgc29tZXRoaW5nIG9uIGl0IHVzaW5nIGNvb3Jkcy54LCBjb29yZHMueSBhbmQgY29vcmRzLnpcbiAqICAgICAgICAgdmFyIGN0eCA9IHRpbGUuZ2V0Q29udGV4dCgnMmQnKTtcbiAqXG4gKiAgICAgICAgIC8vIHJldHVybiB0aGUgdGlsZSBzbyBpdCBjYW4gYmUgcmVuZGVyZWQgb24gc2NyZWVuXG4gKiAgICAgICAgIHJldHVybiB0aWxlO1xuICogICAgIH1cbiAqIH0pO1xuICogYGBgXG4gKlxuICogQHNlY3Rpb24gQXN5bmNocm9ub3VzIHVzYWdlXG4gKiBAZXhhbXBsZVxuICpcbiAqIFRpbGUgY3JlYXRpb24gY2FuIGFsc28gYmUgYXN5bmNocm9ub3VzLCB0aGlzIGlzIHVzZWZ1bCB3aGVuIHVzaW5nIGEgdGhpcmQtcGFydHkgZHJhd2luZyBsaWJyYXJ5LiBPbmNlIHRoZSB0aWxlIGlzIGZpbmlzaGVkIGRyYXdpbmcgaXQgY2FuIGJlIHBhc3NlZCB0byB0aGUgYGRvbmUoKWAgY2FsbGJhY2suXG4gKlxuICogYGBganNcbiAqIHZhciBDYW52YXNMYXllciA9IEwuR3JpZExheWVyLmV4dGVuZCh7XG4gKiAgICAgY3JlYXRlVGlsZTogZnVuY3Rpb24oY29vcmRzLCBkb25lKXtcbiAqICAgICAgICAgdmFyIGVycm9yO1xuICpcbiAqICAgICAgICAgLy8gY3JlYXRlIGEgPGNhbnZhcz4gZWxlbWVudCBmb3IgZHJhd2luZ1xuICogICAgICAgICB2YXIgdGlsZSA9IEwuRG9tVXRpbC5jcmVhdGUoJ2NhbnZhcycsICdsZWFmbGV0LXRpbGUnKTtcbiAqXG4gKiAgICAgICAgIC8vIHNldHVwIHRpbGUgd2lkdGggYW5kIGhlaWdodCBhY2NvcmRpbmcgdG8gdGhlIG9wdGlvbnNcbiAqICAgICAgICAgdmFyIHNpemUgPSB0aGlzLmdldFRpbGVTaXplKCk7XG4gKiAgICAgICAgIHRpbGUud2lkdGggPSBzaXplLng7XG4gKiAgICAgICAgIHRpbGUuaGVpZ2h0ID0gc2l6ZS55O1xuICpcbiAqICAgICAgICAgLy8gZHJhdyBzb21ldGhpbmcgYXN5bmNocm9ub3VzbHkgYW5kIHBhc3MgdGhlIHRpbGUgdG8gdGhlIGRvbmUoKSBjYWxsYmFja1xuICogICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICogICAgICAgICAgICAgZG9uZShlcnJvciwgdGlsZSk7XG4gKiAgICAgICAgIH0sIDEwMDApO1xuICpcbiAqICAgICAgICAgcmV0dXJuIHRpbGU7XG4gKiAgICAgfVxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAc2VjdGlvblxuICovXG5cblxudmFyIEdyaWRMYXllciA9IExheWVyLmV4dGVuZCh7XG5cblx0Ly8gQHNlY3Rpb25cblx0Ly8gQGFrYSBHcmlkTGF5ZXIgb3B0aW9uc1xuXHRvcHRpb25zOiB7XG5cdFx0Ly8gQG9wdGlvbiB0aWxlU2l6ZTogTnVtYmVyfFBvaW50ID0gMjU2XG5cdFx0Ly8gV2lkdGggYW5kIGhlaWdodCBvZiB0aWxlcyBpbiB0aGUgZ3JpZC4gVXNlIGEgbnVtYmVyIGlmIHdpZHRoIGFuZCBoZWlnaHQgYXJlIGVxdWFsLCBvciBgTC5wb2ludCh3aWR0aCwgaGVpZ2h0KWAgb3RoZXJ3aXNlLlxuXHRcdHRpbGVTaXplOiAyNTYsXG5cblx0XHQvLyBAb3B0aW9uIG9wYWNpdHk6IE51bWJlciA9IDEuMFxuXHRcdC8vIE9wYWNpdHkgb2YgdGhlIHRpbGVzLiBDYW4gYmUgdXNlZCBpbiB0aGUgYGNyZWF0ZVRpbGUoKWAgZnVuY3Rpb24uXG5cdFx0b3BhY2l0eTogMSxcblxuXHRcdC8vIEBvcHRpb24gdXBkYXRlV2hlbklkbGU6IEJvb2xlYW4gPSAoZGVwZW5kcylcblx0XHQvLyBMb2FkIG5ldyB0aWxlcyBvbmx5IHdoZW4gcGFubmluZyBlbmRzLlxuXHRcdC8vIGB0cnVlYCBieSBkZWZhdWx0IG9uIG1vYmlsZSBicm93c2VycywgaW4gb3JkZXIgdG8gYXZvaWQgdG9vIG1hbnkgcmVxdWVzdHMgYW5kIGtlZXAgc21vb3RoIG5hdmlnYXRpb24uXG5cdFx0Ly8gYGZhbHNlYCBvdGhlcndpc2UgaW4gb3JkZXIgdG8gZGlzcGxheSBuZXcgdGlsZXMgX2R1cmluZ18gcGFubmluZywgc2luY2UgaXQgaXMgZWFzeSB0byBwYW4gb3V0c2lkZSB0aGVcblx0XHQvLyBbYGtlZXBCdWZmZXJgXSgjZ3JpZGxheWVyLWtlZXBidWZmZXIpIG9wdGlvbiBpbiBkZXNrdG9wIGJyb3dzZXJzLlxuXHRcdHVwZGF0ZVdoZW5JZGxlOiBtb2JpbGUsXG5cblx0XHQvLyBAb3B0aW9uIHVwZGF0ZVdoZW5ab29taW5nOiBCb29sZWFuID0gdHJ1ZVxuXHRcdC8vIEJ5IGRlZmF1bHQsIGEgc21vb3RoIHpvb20gYW5pbWF0aW9uIChkdXJpbmcgYSBbdG91Y2ggem9vbV0oI21hcC10b3VjaHpvb20pIG9yIGEgW2BmbHlUbygpYF0oI21hcC1mbHl0bykpIHdpbGwgdXBkYXRlIGdyaWQgbGF5ZXJzIGV2ZXJ5IGludGVnZXIgem9vbSBsZXZlbC4gU2V0dGluZyB0aGlzIG9wdGlvbiB0byBgZmFsc2VgIHdpbGwgdXBkYXRlIHRoZSBncmlkIGxheWVyIG9ubHkgd2hlbiB0aGUgc21vb3RoIGFuaW1hdGlvbiBlbmRzLlxuXHRcdHVwZGF0ZVdoZW5ab29taW5nOiB0cnVlLFxuXG5cdFx0Ly8gQG9wdGlvbiB1cGRhdGVJbnRlcnZhbDogTnVtYmVyID0gMjAwXG5cdFx0Ly8gVGlsZXMgd2lsbCBub3QgdXBkYXRlIG1vcmUgdGhhbiBvbmNlIGV2ZXJ5IGB1cGRhdGVJbnRlcnZhbGAgbWlsbGlzZWNvbmRzIHdoZW4gcGFubmluZy5cblx0XHR1cGRhdGVJbnRlcnZhbDogMjAwLFxuXG5cdFx0Ly8gQG9wdGlvbiB6SW5kZXg6IE51bWJlciA9IDFcblx0XHQvLyBUaGUgZXhwbGljaXQgekluZGV4IG9mIHRoZSB0aWxlIGxheWVyLlxuXHRcdHpJbmRleDogMSxcblxuXHRcdC8vIEBvcHRpb24gYm91bmRzOiBMYXRMbmdCb3VuZHMgPSB1bmRlZmluZWRcblx0XHQvLyBJZiBzZXQsIHRpbGVzIHdpbGwgb25seSBiZSBsb2FkZWQgaW5zaWRlIHRoZSBzZXQgYExhdExuZ0JvdW5kc2AuXG5cdFx0Ym91bmRzOiBudWxsLFxuXG5cdFx0Ly8gQG9wdGlvbiBtaW5ab29tOiBOdW1iZXIgPSAwXG5cdFx0Ly8gVGhlIG1pbmltdW0gem9vbSBsZXZlbCBkb3duIHRvIHdoaWNoIHRoaXMgbGF5ZXIgd2lsbCBiZSBkaXNwbGF5ZWQgKGluY2x1c2l2ZSkuXG5cdFx0bWluWm9vbTogMCxcblxuXHRcdC8vIEBvcHRpb24gbWF4Wm9vbTogTnVtYmVyID0gdW5kZWZpbmVkXG5cdFx0Ly8gVGhlIG1heGltdW0gem9vbSBsZXZlbCB1cCB0byB3aGljaCB0aGlzIGxheWVyIHdpbGwgYmUgZGlzcGxheWVkIChpbmNsdXNpdmUpLlxuXHRcdG1heFpvb206IHVuZGVmaW5lZCxcblxuXHRcdC8vIEBvcHRpb24gbWF4TmF0aXZlWm9vbTogTnVtYmVyID0gdW5kZWZpbmVkXG5cdFx0Ly8gTWF4aW11bSB6b29tIG51bWJlciB0aGUgdGlsZSBzb3VyY2UgaGFzIGF2YWlsYWJsZS4gSWYgaXQgaXMgc3BlY2lmaWVkLFxuXHRcdC8vIHRoZSB0aWxlcyBvbiBhbGwgem9vbSBsZXZlbHMgaGlnaGVyIHRoYW4gYG1heE5hdGl2ZVpvb21gIHdpbGwgYmUgbG9hZGVkXG5cdFx0Ly8gZnJvbSBgbWF4TmF0aXZlWm9vbWAgbGV2ZWwgYW5kIGF1dG8tc2NhbGVkLlxuXHRcdG1heE5hdGl2ZVpvb206IHVuZGVmaW5lZCxcblxuXHRcdC8vIEBvcHRpb24gbWluTmF0aXZlWm9vbTogTnVtYmVyID0gdW5kZWZpbmVkXG5cdFx0Ly8gTWluaW11bSB6b29tIG51bWJlciB0aGUgdGlsZSBzb3VyY2UgaGFzIGF2YWlsYWJsZS4gSWYgaXQgaXMgc3BlY2lmaWVkLFxuXHRcdC8vIHRoZSB0aWxlcyBvbiBhbGwgem9vbSBsZXZlbHMgbG93ZXIgdGhhbiBgbWluTmF0aXZlWm9vbWAgd2lsbCBiZSBsb2FkZWRcblx0XHQvLyBmcm9tIGBtaW5OYXRpdmVab29tYCBsZXZlbCBhbmQgYXV0by1zY2FsZWQuXG5cdFx0bWluTmF0aXZlWm9vbTogdW5kZWZpbmVkLFxuXG5cdFx0Ly8gQG9wdGlvbiBub1dyYXA6IEJvb2xlYW4gPSBmYWxzZVxuXHRcdC8vIFdoZXRoZXIgdGhlIGxheWVyIGlzIHdyYXBwZWQgYXJvdW5kIHRoZSBhbnRpbWVyaWRpYW4uIElmIGB0cnVlYCwgdGhlXG5cdFx0Ly8gR3JpZExheWVyIHdpbGwgb25seSBiZSBkaXNwbGF5ZWQgb25jZSBhdCBsb3cgem9vbSBsZXZlbHMuIEhhcyBub1xuXHRcdC8vIGVmZmVjdCB3aGVuIHRoZSBbbWFwIENSU10oI21hcC1jcnMpIGRvZXNuJ3Qgd3JhcCBhcm91bmQuIENhbiBiZSB1c2VkXG5cdFx0Ly8gaW4gY29tYmluYXRpb24gd2l0aCBbYGJvdW5kc2BdKCNncmlkbGF5ZXItYm91bmRzKSB0byBwcmV2ZW50IHJlcXVlc3Rpbmdcblx0XHQvLyB0aWxlcyBvdXRzaWRlIHRoZSBDUlMgbGltaXRzLlxuXHRcdG5vV3JhcDogZmFsc2UsXG5cblx0XHQvLyBAb3B0aW9uIHBhbmU6IFN0cmluZyA9ICd0aWxlUGFuZSdcblx0XHQvLyBgTWFwIHBhbmVgIHdoZXJlIHRoZSBncmlkIGxheWVyIHdpbGwgYmUgYWRkZWQuXG5cdFx0cGFuZTogJ3RpbGVQYW5lJyxcblxuXHRcdC8vIEBvcHRpb24gY2xhc3NOYW1lOiBTdHJpbmcgPSAnJ1xuXHRcdC8vIEEgY3VzdG9tIGNsYXNzIG5hbWUgdG8gYXNzaWduIHRvIHRoZSB0aWxlIGxheWVyLiBFbXB0eSBieSBkZWZhdWx0LlxuXHRcdGNsYXNzTmFtZTogJycsXG5cblx0XHQvLyBAb3B0aW9uIGtlZXBCdWZmZXI6IE51bWJlciA9IDJcblx0XHQvLyBXaGVuIHBhbm5pbmcgdGhlIG1hcCwga2VlcCB0aGlzIG1hbnkgcm93cyBhbmQgY29sdW1ucyBvZiB0aWxlcyBiZWZvcmUgdW5sb2FkaW5nIHRoZW0uXG5cdFx0a2VlcEJ1ZmZlcjogMlxuXHR9LFxuXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG5cdFx0c2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcblx0fSxcblxuXHRvbkFkZDogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX2luaXRDb250YWluZXIoKTtcblxuXHRcdHRoaXMuX2xldmVscyA9IHt9O1xuXHRcdHRoaXMuX3RpbGVzID0ge307XG5cblx0XHR0aGlzLl9yZXNldFZpZXcoKTtcblx0XHR0aGlzLl91cGRhdGUoKTtcblx0fSxcblxuXHRiZWZvcmVBZGQ6IGZ1bmN0aW9uIChtYXApIHtcblx0XHRtYXAuX2FkZFpvb21MaW1pdCh0aGlzKTtcblx0fSxcblxuXHRvblJlbW92ZTogZnVuY3Rpb24gKG1hcCkge1xuXHRcdHRoaXMuX3JlbW92ZUFsbFRpbGVzKCk7XG5cdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XG5cdFx0bWFwLl9yZW1vdmVab29tTGltaXQodGhpcyk7XG5cdFx0dGhpcy5fY29udGFpbmVyID0gbnVsbDtcblx0XHR0aGlzLl90aWxlWm9vbSA9IHVuZGVmaW5lZDtcblx0fSxcblxuXHQvLyBAbWV0aG9kIGJyaW5nVG9Gcm9udDogdGhpc1xuXHQvLyBCcmluZ3MgdGhlIHRpbGUgbGF5ZXIgdG8gdGhlIHRvcCBvZiBhbGwgdGlsZSBsYXllcnMuXG5cdGJyaW5nVG9Gcm9udDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9tYXApIHtcblx0XHRcdHRvRnJvbnQodGhpcy5fY29udGFpbmVyKTtcblx0XHRcdHRoaXMuX3NldEF1dG9aSW5kZXgoTWF0aC5tYXgpO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGJyaW5nVG9CYWNrOiB0aGlzXG5cdC8vIEJyaW5ncyB0aGUgdGlsZSBsYXllciB0byB0aGUgYm90dG9tIG9mIGFsbCB0aWxlIGxheWVycy5cblx0YnJpbmdUb0JhY2s6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAodGhpcy5fbWFwKSB7XG5cdFx0XHR0b0JhY2sodGhpcy5fY29udGFpbmVyKTtcblx0XHRcdHRoaXMuX3NldEF1dG9aSW5kZXgoTWF0aC5taW4pO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHQvLyBAbWV0aG9kIGdldENvbnRhaW5lcjogSFRNTEVsZW1lbnRcblx0Ly8gUmV0dXJucyB0aGUgSFRNTCBlbGVtZW50IHRoYXQgY29udGFpbnMgdGhlIHRpbGVzIGZvciB0aGlzIGxheWVyLlxuXHRnZXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fY29udGFpbmVyO1xuXHR9LFxuXG5cdC8vIEBtZXRob2Qgc2V0T3BhY2l0eShvcGFjaXR5OiBOdW1iZXIpOiB0aGlzXG5cdC8vIENoYW5nZXMgdGhlIFtvcGFjaXR5XSgjZ3JpZGxheWVyLW9wYWNpdHkpIG9mIHRoZSBncmlkIGxheWVyLlxuXHRzZXRPcGFjaXR5OiBmdW5jdGlvbiAob3BhY2l0eSkge1xuXHRcdHRoaXMub3B0aW9ucy5vcGFjaXR5ID0gb3BhY2l0eTtcblx0XHR0aGlzLl91cGRhdGVPcGFjaXR5KCk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBzZXRaSW5kZXgoekluZGV4OiBOdW1iZXIpOiB0aGlzXG5cdC8vIENoYW5nZXMgdGhlIFt6SW5kZXhdKCNncmlkbGF5ZXItemluZGV4KSBvZiB0aGUgZ3JpZCBsYXllci5cblx0c2V0WkluZGV4OiBmdW5jdGlvbiAoekluZGV4KSB7XG5cdFx0dGhpcy5vcHRpb25zLnpJbmRleCA9IHpJbmRleDtcblx0XHR0aGlzLl91cGRhdGVaSW5kZXgoKTtcblxuXHRcdHJldHVybiB0aGlzO1xuXHR9LFxuXG5cdC8vIEBtZXRob2QgaXNMb2FkaW5nOiBCb29sZWFuXG5cdC8vIFJldHVybnMgYHRydWVgIGlmIGFueSB0aWxlIGluIHRoZSBncmlkIGxheWVyIGhhcyBub3QgZmluaXNoZWQgbG9hZGluZy5cblx0aXNMb2FkaW5nOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2xvYWRpbmc7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCByZWRyYXc6IHRoaXNcblx0Ly8gQ2F1c2VzIHRoZSBsYXllciB0byBjbGVhciBhbGwgdGhlIHRpbGVzIGFuZCByZXF1ZXN0IHRoZW0gYWdhaW4uXG5cdHJlZHJhdzogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9tYXApIHtcblx0XHRcdHRoaXMuX3JlbW92ZUFsbFRpbGVzKCk7XG5cdFx0XHR0aGlzLl91cGRhdGUoKTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0sXG5cblx0Z2V0RXZlbnRzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGV2ZW50cyA9IHtcblx0XHRcdHZpZXdwcmVyZXNldDogdGhpcy5faW52YWxpZGF0ZUFsbCxcblx0XHRcdHZpZXdyZXNldDogdGhpcy5fcmVzZXRWaWV3LFxuXHRcdFx0em9vbTogdGhpcy5fcmVzZXRWaWV3LFxuXHRcdFx0bW92ZWVuZDogdGhpcy5fb25Nb3ZlRW5kXG5cdFx0fTtcblxuXHRcdGlmICghdGhpcy5vcHRpb25zLnVwZGF0ZVdoZW5JZGxlKSB7XG5cdFx0XHQvLyB1cGRhdGUgdGlsZXMgb24gbW92ZSwgYnV0IG5vdCBtb3JlIG9mdGVuIHRoYW4gb25jZSBwZXIgZ2l2ZW4gaW50ZXJ2YWxcblx0XHRcdGlmICghdGhpcy5fb25Nb3ZlKSB7XG5cdFx0XHRcdHRoaXMuX29uTW92ZSA9IHRocm90dGxlKHRoaXMuX29uTW92ZUVuZCwgdGhpcy5vcHRpb25zLnVwZGF0ZUludGVydmFsLCB0aGlzKTtcblx0XHRcdH1cblxuXHRcdFx0ZXZlbnRzLm1vdmUgPSB0aGlzLl9vbk1vdmU7XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xuXHRcdFx0ZXZlbnRzLnpvb21hbmltID0gdGhpcy5fYW5pbWF0ZVpvb207XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50cztcblx0fSxcblxuXHQvLyBAc2VjdGlvbiBFeHRlbnNpb24gbWV0aG9kc1xuXHQvLyBMYXllcnMgZXh0ZW5kaW5nIGBHcmlkTGF5ZXJgIHNoYWxsIHJlaW1wbGVtZW50IHRoZSBmb2xsb3dpbmcgbWV0aG9kLlxuXHQvLyBAbWV0aG9kIGNyZWF0ZVRpbGUoY29vcmRzOiBPYmplY3QsIGRvbmU/OiBGdW5jdGlvbik6IEhUTUxFbGVtZW50XG5cdC8vIENhbGxlZCBvbmx5IGludGVybmFsbHksIG11c3QgYmUgb3ZlcnJpZGRlbiBieSBjbGFzc2VzIGV4dGVuZGluZyBgR3JpZExheWVyYC5cblx0Ly8gUmV0dXJucyB0aGUgYEhUTUxFbGVtZW50YCBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlbiBgY29vcmRzYC4gSWYgdGhlIGBkb25lYCBjYWxsYmFja1xuXHQvLyBpcyBzcGVjaWZpZWQsIGl0IG11c3QgYmUgY2FsbGVkIHdoZW4gdGhlIHRpbGUgaGFzIGZpbmlzaGVkIGxvYWRpbmcgYW5kIGRyYXdpbmcuXG5cdGNyZWF0ZVRpbGU6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cdH0sXG5cblx0Ly8gQHNlY3Rpb25cblx0Ly8gQG1ldGhvZCBnZXRUaWxlU2l6ZTogUG9pbnRcblx0Ly8gTm9ybWFsaXplcyB0aGUgW3RpbGVTaXplIG9wdGlvbl0oI2dyaWRsYXllci10aWxlc2l6ZSkgaW50byBhIHBvaW50LiBVc2VkIGJ5IHRoZSBgY3JlYXRlVGlsZSgpYCBtZXRob2QuXG5cdGdldFRpbGVTaXplOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHMgPSB0aGlzLm9wdGlvbnMudGlsZVNpemU7XG5cdFx0cmV0dXJuIHMgaW5zdGFuY2VvZiBQb2ludCA/IHMgOiBuZXcgUG9pbnQocywgcyk7XG5cdH0sXG5cblx0X3VwZGF0ZVpJbmRleDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9jb250YWluZXIgJiYgdGhpcy5vcHRpb25zLnpJbmRleCAhPT0gdW5kZWZpbmVkICYmIHRoaXMub3B0aW9ucy56SW5kZXggIT09IG51bGwpIHtcblx0XHRcdHRoaXMuX2NvbnRhaW5lci5zdHlsZS56SW5kZXggPSB0aGlzLm9wdGlvbnMuekluZGV4O1xuXHRcdH1cblx0fSxcblxuXHRfc2V0QXV0b1pJbmRleDogZnVuY3Rpb24gKGNvbXBhcmUpIHtcblx0XHQvLyBnbyB0aHJvdWdoIGFsbCBvdGhlciBsYXllcnMgb2YgdGhlIHNhbWUgcGFuZSwgc2V0IHpJbmRleCB0byBtYXggKyAxIChmcm9udCkgb3IgbWluIC0gMSAoYmFjaylcblxuXHRcdHZhciBsYXllcnMgPSB0aGlzLmdldFBhbmUoKS5jaGlsZHJlbixcblx0XHQgICAgZWRnZVpJbmRleCA9IC1jb21wYXJlKC1JbmZpbml0eSwgSW5maW5pdHkpOyAvLyAtSW5maW5pdHkgZm9yIG1heCwgSW5maW5pdHkgZm9yIG1pblxuXG5cdFx0Zm9yICh2YXIgaSA9IDAsIGxlbiA9IGxheWVycy5sZW5ndGgsIHpJbmRleDsgaSA8IGxlbjsgaSsrKSB7XG5cblx0XHRcdHpJbmRleCA9IGxheWVyc1tpXS5zdHlsZS56SW5kZXg7XG5cblx0XHRcdGlmIChsYXllcnNbaV0gIT09IHRoaXMuX2NvbnRhaW5lciAmJiB6SW5kZXgpIHtcblx0XHRcdFx0ZWRnZVpJbmRleCA9IGNvbXBhcmUoZWRnZVpJbmRleCwgK3pJbmRleCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGlzRmluaXRlKGVkZ2VaSW5kZXgpKSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMuekluZGV4ID0gZWRnZVpJbmRleCArIGNvbXBhcmUoLTEsIDEpO1xuXHRcdFx0dGhpcy5fdXBkYXRlWkluZGV4KCk7XG5cdFx0fVxuXHR9LFxuXG5cdF91cGRhdGVPcGFjaXR5OiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cblx0XHQvLyBJRSBkb2Vzbid0IGluaGVyaXQgZmlsdGVyIG9wYWNpdHkgcHJvcGVybHksIHNvIHdlJ3JlIGZvcmNlZCB0byBzZXQgaXQgb24gdGlsZXNcblx0XHRpZiAoaWVsdDkpIHsgcmV0dXJuOyB9XG5cblx0XHRzZXRPcGFjaXR5KHRoaXMuX2NvbnRhaW5lciwgdGhpcy5vcHRpb25zLm9wYWNpdHkpO1xuXG5cdFx0dmFyIG5vdyA9ICtuZXcgRGF0ZSgpLFxuXHRcdCAgICBuZXh0RnJhbWUgPSBmYWxzZSxcblx0XHQgICAgd2lsbFBydW5lID0gZmFsc2U7XG5cblx0XHRmb3IgKHZhciBrZXkgaW4gdGhpcy5fdGlsZXMpIHtcblx0XHRcdHZhciB0aWxlID0gdGhpcy5fdGlsZXNba2V5XTtcblx0XHRcdGlmICghdGlsZS5jdXJyZW50IHx8ICF0aWxlLmxvYWRlZCkgeyBjb250aW51ZTsgfVxuXG5cdFx0XHR2YXIgZmFkZSA9IE1hdGgubWluKDEsIChub3cgLSB0aWxlLmxvYWRlZCkgLyAyMDApO1xuXG5cdFx0XHRzZXRPcGFjaXR5KHRpbGUuZWwsIGZhZGUpO1xuXHRcdFx0aWYgKGZhZGUgPCAxKSB7XG5cdFx0XHRcdG5leHRGcmFtZSA9IHRydWU7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAodGlsZS5hY3RpdmUpIHtcblx0XHRcdFx0XHR3aWxsUHJ1bmUgPSB0cnVlO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMuX29uT3BhcXVlVGlsZSh0aWxlKTtcblx0XHRcdFx0fVxuXHRcdFx0XHR0aWxlLmFjdGl2ZSA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKHdpbGxQcnVuZSAmJiAhdGhpcy5fbm9QcnVuZSkgeyB0aGlzLl9wcnVuZVRpbGVzKCk7IH1cblxuXHRcdGlmIChuZXh0RnJhbWUpIHtcblx0XHRcdGNhbmNlbEFuaW1GcmFtZSh0aGlzLl9mYWRlRnJhbWUpO1xuXHRcdFx0dGhpcy5fZmFkZUZyYW1lID0gcmVxdWVzdEFuaW1GcmFtZSh0aGlzLl91cGRhdGVPcGFjaXR5LCB0aGlzKTtcblx0XHR9XG5cdH0sXG5cblx0X29uT3BhcXVlVGlsZTogZmFsc2VGbixcblxuXHRfaW5pdENvbnRhaW5lcjogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9jb250YWluZXIpIHsgcmV0dXJuOyB9XG5cblx0XHR0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMSgnZGl2JywgJ2xlYWZsZXQtbGF5ZXIgJyArICh0aGlzLm9wdGlvbnMuY2xhc3NOYW1lIHx8ICcnKSk7XG5cdFx0dGhpcy5fdXBkYXRlWkluZGV4KCk7XG5cblx0XHRpZiAodGhpcy5vcHRpb25zLm9wYWNpdHkgPCAxKSB7XG5cdFx0XHR0aGlzLl91cGRhdGVPcGFjaXR5KCk7XG5cdFx0fVxuXG5cdFx0dGhpcy5nZXRQYW5lKCkuYXBwZW5kQ2hpbGQodGhpcy5fY29udGFpbmVyKTtcblx0fSxcblxuXHRfdXBkYXRlTGV2ZWxzOiBmdW5jdGlvbiAoKSB7XG5cblx0XHR2YXIgem9vbSA9IHRoaXMuX3RpbGVab29tLFxuXHRcdCAgICBtYXhab29tID0gdGhpcy5vcHRpb25zLm1heFpvb207XG5cblx0XHRpZiAoem9vbSA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cblxuXHRcdGZvciAodmFyIHogaW4gdGhpcy5fbGV2ZWxzKSB7XG5cdFx0XHRpZiAodGhpcy5fbGV2ZWxzW3pdLmVsLmNoaWxkcmVuLmxlbmd0aCB8fCB6ID09PSB6b29tKSB7XG5cdFx0XHRcdHRoaXMuX2xldmVsc1t6XS5lbC5zdHlsZS56SW5kZXggPSBtYXhab29tIC0gTWF0aC5hYnMoem9vbSAtIHopO1xuXHRcdFx0XHR0aGlzLl9vblVwZGF0ZUxldmVsKHopO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmVtb3ZlKHRoaXMuX2xldmVsc1t6XS5lbCk7XG5cdFx0XHRcdHRoaXMuX3JlbW92ZVRpbGVzQXRab29tKHopO1xuXHRcdFx0XHR0aGlzLl9vblJlbW92ZUxldmVsKHopO1xuXHRcdFx0XHRkZWxldGUgdGhpcy5fbGV2ZWxzW3pdO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHZhciBsZXZlbCA9IHRoaXMuX2xldmVsc1t6b29tXSxcblx0XHQgICAgbWFwID0gdGhpcy5fbWFwO1xuXG5cdFx0aWYgKCFsZXZlbCkge1xuXHRcdFx0bGV2ZWwgPSB0aGlzLl9sZXZlbHNbem9vbV0gPSB7fTtcblxuXHRcdFx0bGV2ZWwuZWwgPSBjcmVhdGUkMSgnZGl2JywgJ2xlYWZsZXQtdGlsZS1jb250YWluZXIgbGVhZmxldC16b29tLWFuaW1hdGVkJywgdGhpcy5fY29udGFpbmVyKTtcblx0XHRcdGxldmVsLmVsLnN0eWxlLnpJbmRleCA9IG1heFpvb207XG5cblx0XHRcdGxldmVsLm9yaWdpbiA9IG1hcC5wcm9qZWN0KG1hcC51bnByb2plY3QobWFwLmdldFBpeGVsT3JpZ2luKCkpLCB6b29tKS5yb3VuZCgpO1xuXHRcdFx0bGV2ZWwuem9vbSA9IHpvb207XG5cblx0XHRcdHRoaXMuX3NldFpvb21UcmFuc2Zvcm0obGV2ZWwsIG1hcC5nZXRDZW50ZXIoKSwgbWFwLmdldFpvb20oKSk7XG5cblx0XHRcdC8vIGZvcmNlIHRoZSBicm93c2VyIHRvIGNvbnNpZGVyIHRoZSBuZXdseSBhZGRlZCBlbGVtZW50IGZvciB0cmFuc2l0aW9uXG5cdFx0XHRmYWxzZUZuKGxldmVsLmVsLm9mZnNldFdpZHRoKTtcblxuXHRcdFx0dGhpcy5fb25DcmVhdGVMZXZlbChsZXZlbCk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fbGV2ZWwgPSBsZXZlbDtcblxuXHRcdHJldHVybiBsZXZlbDtcblx0fSxcblxuXHRfb25VcGRhdGVMZXZlbDogZmFsc2VGbixcblxuXHRfb25SZW1vdmVMZXZlbDogZmFsc2VGbixcblxuXHRfb25DcmVhdGVMZXZlbDogZmFsc2VGbixcblxuXHRfcHJ1bmVUaWxlczogZnVuY3Rpb24gKCkge1xuXHRcdGlmICghdGhpcy5fbWFwKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIGtleSwgdGlsZTtcblxuXHRcdHZhciB6b29tID0gdGhpcy5fbWFwLmdldFpvb20oKTtcblx0XHRpZiAoem9vbSA+IHRoaXMub3B0aW9ucy5tYXhab29tIHx8XG5cdFx0XHR6b29tIDwgdGhpcy5vcHRpb25zLm1pblpvb20pIHtcblx0XHRcdHRoaXMuX3JlbW92ZUFsbFRpbGVzKCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Zm9yIChrZXkgaW4gdGhpcy5fdGlsZXMpIHtcblx0XHRcdHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xuXHRcdFx0dGlsZS5yZXRhaW4gPSB0aWxlLmN1cnJlbnQ7XG5cdFx0fVxuXG5cdFx0Zm9yIChrZXkgaW4gdGhpcy5fdGlsZXMpIHtcblx0XHRcdHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xuXHRcdFx0aWYgKHRpbGUuY3VycmVudCAmJiAhdGlsZS5hY3RpdmUpIHtcblx0XHRcdFx0dmFyIGNvb3JkcyA9IHRpbGUuY29vcmRzO1xuXHRcdFx0XHRpZiAoIXRoaXMuX3JldGFpblBhcmVudChjb29yZHMueCwgY29vcmRzLnksIGNvb3Jkcy56LCBjb29yZHMueiAtIDUpKSB7XG5cdFx0XHRcdFx0dGhpcy5fcmV0YWluQ2hpbGRyZW4oY29vcmRzLngsIGNvb3Jkcy55LCBjb29yZHMueiwgY29vcmRzLnogKyAyKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZvciAoa2V5IGluIHRoaXMuX3RpbGVzKSB7XG5cdFx0XHRpZiAoIXRoaXMuX3RpbGVzW2tleV0ucmV0YWluKSB7XG5cdFx0XHRcdHRoaXMuX3JlbW92ZVRpbGUoa2V5KTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0X3JlbW92ZVRpbGVzQXRab29tOiBmdW5jdGlvbiAoem9vbSkge1xuXHRcdGZvciAodmFyIGtleSBpbiB0aGlzLl90aWxlcykge1xuXHRcdFx0aWYgKHRoaXMuX3RpbGVzW2tleV0uY29vcmRzLnogIT09IHpvb20pIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFx0XHR0aGlzLl9yZW1vdmVUaWxlKGtleSk7XG5cdFx0fVxuXHR9LFxuXG5cdF9yZW1vdmVBbGxUaWxlczogZnVuY3Rpb24gKCkge1xuXHRcdGZvciAodmFyIGtleSBpbiB0aGlzLl90aWxlcykge1xuXHRcdFx0dGhpcy5fcmVtb3ZlVGlsZShrZXkpO1xuXHRcdH1cblx0fSxcblxuXHRfaW52YWxpZGF0ZUFsbDogZnVuY3Rpb24gKCkge1xuXHRcdGZvciAodmFyIHogaW4gdGhpcy5fbGV2ZWxzKSB7XG5cdFx0XHRyZW1vdmUodGhpcy5fbGV2ZWxzW3pdLmVsKTtcblx0XHRcdHRoaXMuX29uUmVtb3ZlTGV2ZWwoeik7XG5cdFx0XHRkZWxldGUgdGhpcy5fbGV2ZWxzW3pdO1xuXHRcdH1cblx0XHR0aGlzLl9yZW1vdmVBbGxUaWxlcygpO1xuXG5cdFx0dGhpcy5fdGlsZVpvb20gPSB1bmRlZmluZWQ7XG5cdH0sXG5cblx0X3JldGFpblBhcmVudDogZnVuY3Rpb24gKHgsIHksIHosIG1pblpvb20pIHtcblx0XHR2YXIgeDIgPSBNYXRoLmZsb29yKHggLyAyKSxcblx0XHQgICAgeTIgPSBNYXRoLmZsb29yKHkgLyAyKSxcblx0XHQgICAgejIgPSB6IC0gMSxcblx0XHQgICAgY29vcmRzMiA9IG5ldyBQb2ludCgreDIsICt5Mik7XG5cdFx0Y29vcmRzMi56ID0gK3oyO1xuXG5cdFx0dmFyIGtleSA9IHRoaXMuX3RpbGVDb29yZHNUb0tleShjb29yZHMyKSxcblx0XHQgICAgdGlsZSA9IHRoaXMuX3RpbGVzW2tleV07XG5cblx0XHRpZiAodGlsZSAmJiB0aWxlLmFjdGl2ZSkge1xuXHRcdFx0dGlsZS5yZXRhaW4gPSB0cnVlO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cblx0XHR9IGVsc2UgaWYgKHRpbGUgJiYgdGlsZS5sb2FkZWQpIHtcblx0XHRcdHRpbGUucmV0YWluID0gdHJ1ZTtcblx0XHR9XG5cblx0XHRpZiAoejIgPiBtaW5ab29tKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fcmV0YWluUGFyZW50KHgyLCB5MiwgejIsIG1pblpvb20pO1xuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fSxcblxuXHRfcmV0YWluQ2hpbGRyZW46IGZ1bmN0aW9uICh4LCB5LCB6LCBtYXhab29tKSB7XG5cblx0XHRmb3IgKHZhciBpID0gMiAqIHg7IGkgPCAyICogeCArIDI7IGkrKykge1xuXHRcdFx0Zm9yICh2YXIgaiA9IDIgKiB5OyBqIDwgMiAqIHkgKyAyOyBqKyspIHtcblxuXHRcdFx0XHR2YXIgY29vcmRzID0gbmV3IFBvaW50KGksIGopO1xuXHRcdFx0XHRjb29yZHMueiA9IHogKyAxO1xuXG5cdFx0XHRcdHZhciBrZXkgPSB0aGlzLl90aWxlQ29vcmRzVG9LZXkoY29vcmRzKSxcblx0XHRcdFx0ICAgIHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xuXG5cdFx0XHRcdGlmICh0aWxlICYmIHRpbGUuYWN0aXZlKSB7XG5cdFx0XHRcdFx0dGlsZS5yZXRhaW4gPSB0cnVlO1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXG5cdFx0XHRcdH0gZWxzZSBpZiAodGlsZSAmJiB0aWxlLmxvYWRlZCkge1xuXHRcdFx0XHRcdHRpbGUucmV0YWluID0gdHJ1ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICh6ICsgMSA8IG1heFpvb20pIHtcblx0XHRcdFx0XHR0aGlzLl9yZXRhaW5DaGlsZHJlbihpLCBqLCB6ICsgMSwgbWF4Wm9vbSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0X3Jlc2V0VmlldzogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgYW5pbWF0aW5nID0gZSAmJiAoZS5waW5jaCB8fCBlLmZseVRvKTtcblx0XHR0aGlzLl9zZXRWaWV3KHRoaXMuX21hcC5nZXRDZW50ZXIoKSwgdGhpcy5fbWFwLmdldFpvb20oKSwgYW5pbWF0aW5nLCBhbmltYXRpbmcpO1xuXHR9LFxuXG5cdF9hbmltYXRlWm9vbTogZnVuY3Rpb24gKGUpIHtcblx0XHR0aGlzLl9zZXRWaWV3KGUuY2VudGVyLCBlLnpvb20sIHRydWUsIGUubm9VcGRhdGUpO1xuXHR9LFxuXG5cdF9jbGFtcFpvb206IGZ1bmN0aW9uICh6b29tKSB7XG5cdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cblx0XHRpZiAodW5kZWZpbmVkICE9PSBvcHRpb25zLm1pbk5hdGl2ZVpvb20gJiYgem9vbSA8IG9wdGlvbnMubWluTmF0aXZlWm9vbSkge1xuXHRcdFx0cmV0dXJuIG9wdGlvbnMubWluTmF0aXZlWm9vbTtcblx0XHR9XG5cblx0XHRpZiAodW5kZWZpbmVkICE9PSBvcHRpb25zLm1heE5hdGl2ZVpvb20gJiYgb3B0aW9ucy5tYXhOYXRpdmVab29tIDwgem9vbSkge1xuXHRcdFx0cmV0dXJuIG9wdGlvbnMubWF4TmF0aXZlWm9vbTtcblx0XHR9XG5cblx0XHRyZXR1cm4gem9vbTtcblx0fSxcblxuXHRfc2V0VmlldzogZnVuY3Rpb24gKGNlbnRlciwgem9vbSwgbm9QcnVuZSwgbm9VcGRhdGUpIHtcblx0XHR2YXIgdGlsZVpvb20gPSB0aGlzLl9jbGFtcFpvb20oTWF0aC5yb3VuZCh6b29tKSk7XG5cdFx0aWYgKCh0aGlzLm9wdGlvbnMubWF4Wm9vbSAhPT0gdW5kZWZpbmVkICYmIHRpbGVab29tID4gdGhpcy5vcHRpb25zLm1heFpvb20pIHx8XG5cdFx0ICAgICh0aGlzLm9wdGlvbnMubWluWm9vbSAhPT0gdW5kZWZpbmVkICYmIHRpbGVab29tIDwgdGhpcy5vcHRpb25zLm1pblpvb20pKSB7XG5cdFx0XHR0aWxlWm9vbSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cblx0XHR2YXIgdGlsZVpvb21DaGFuZ2VkID0gdGhpcy5vcHRpb25zLnVwZGF0ZVdoZW5ab29taW5nICYmICh0aWxlWm9vbSAhPT0gdGhpcy5fdGlsZVpvb20pO1xuXG5cdFx0aWYgKCFub1VwZGF0ZSB8fCB0aWxlWm9vbUNoYW5nZWQpIHtcblxuXHRcdFx0dGhpcy5fdGlsZVpvb20gPSB0aWxlWm9vbTtcblxuXHRcdFx0aWYgKHRoaXMuX2Fib3J0TG9hZGluZykge1xuXHRcdFx0XHR0aGlzLl9hYm9ydExvYWRpbmcoKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5fdXBkYXRlTGV2ZWxzKCk7XG5cdFx0XHR0aGlzLl9yZXNldEdyaWQoKTtcblxuXHRcdFx0aWYgKHRpbGVab29tICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0dGhpcy5fdXBkYXRlKGNlbnRlcik7XG5cdFx0XHR9XG5cblx0XHRcdGlmICghbm9QcnVuZSkge1xuXHRcdFx0XHR0aGlzLl9wcnVuZVRpbGVzKCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEZsYWcgdG8gcHJldmVudCBfdXBkYXRlT3BhY2l0eSBmcm9tIHBydW5pbmcgdGlsZXMgZHVyaW5nXG5cdFx0XHQvLyBhIHpvb20gYW5pbSBvciBhIHBpbmNoIGdlc3R1cmVcblx0XHRcdHRoaXMuX25vUHJ1bmUgPSAhIW5vUHJ1bmU7XG5cdFx0fVxuXG5cdFx0dGhpcy5fc2V0Wm9vbVRyYW5zZm9ybXMoY2VudGVyLCB6b29tKTtcblx0fSxcblxuXHRfc2V0Wm9vbVRyYW5zZm9ybXM6IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20pIHtcblx0XHRmb3IgKHZhciBpIGluIHRoaXMuX2xldmVscykge1xuXHRcdFx0dGhpcy5fc2V0Wm9vbVRyYW5zZm9ybSh0aGlzLl9sZXZlbHNbaV0sIGNlbnRlciwgem9vbSk7XG5cdFx0fVxuXHR9LFxuXG5cdF9zZXRab29tVHJhbnNmb3JtOiBmdW5jdGlvbiAobGV2ZWwsIGNlbnRlciwgem9vbSkge1xuXHRcdHZhciBzY2FsZSA9IHRoaXMuX21hcC5nZXRab29tU2NhbGUoem9vbSwgbGV2ZWwuem9vbSksXG5cdFx0ICAgIHRyYW5zbGF0ZSA9IGxldmVsLm9yaWdpbi5tdWx0aXBseUJ5KHNjYWxlKVxuXHRcdCAgICAgICAgLnN1YnRyYWN0KHRoaXMuX21hcC5fZ2V0TmV3UGl4ZWxPcmlnaW4oY2VudGVyLCB6b29tKSkucm91bmQoKTtcblxuXHRcdGlmIChhbnkzZCkge1xuXHRcdFx0c2V0VHJhbnNmb3JtKGxldmVsLmVsLCB0cmFuc2xhdGUsIHNjYWxlKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0c2V0UG9zaXRpb24obGV2ZWwuZWwsIHRyYW5zbGF0ZSk7XG5cdFx0fVxuXHR9LFxuXG5cdF9yZXNldEdyaWQ6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuXHRcdCAgICBjcnMgPSBtYXAub3B0aW9ucy5jcnMsXG5cdFx0ICAgIHRpbGVTaXplID0gdGhpcy5fdGlsZVNpemUgPSB0aGlzLmdldFRpbGVTaXplKCksXG5cdFx0ICAgIHRpbGVab29tID0gdGhpcy5fdGlsZVpvb207XG5cblx0XHR2YXIgYm91bmRzID0gdGhpcy5fbWFwLmdldFBpeGVsV29ybGRCb3VuZHModGhpcy5fdGlsZVpvb20pO1xuXHRcdGlmIChib3VuZHMpIHtcblx0XHRcdHRoaXMuX2dsb2JhbFRpbGVSYW5nZSA9IHRoaXMuX3B4Qm91bmRzVG9UaWxlUmFuZ2UoYm91bmRzKTtcblx0XHR9XG5cblx0XHR0aGlzLl93cmFwWCA9IGNycy53cmFwTG5nICYmICF0aGlzLm9wdGlvbnMubm9XcmFwICYmIFtcblx0XHRcdE1hdGguZmxvb3IobWFwLnByb2plY3QoWzAsIGNycy53cmFwTG5nWzBdXSwgdGlsZVpvb20pLnggLyB0aWxlU2l6ZS54KSxcblx0XHRcdE1hdGguY2VpbChtYXAucHJvamVjdChbMCwgY3JzLndyYXBMbmdbMV1dLCB0aWxlWm9vbSkueCAvIHRpbGVTaXplLnkpXG5cdFx0XTtcblx0XHR0aGlzLl93cmFwWSA9IGNycy53cmFwTGF0ICYmICF0aGlzLm9wdGlvbnMubm9XcmFwICYmIFtcblx0XHRcdE1hdGguZmxvb3IobWFwLnByb2plY3QoW2Nycy53cmFwTGF0WzBdLCAwXSwgdGlsZVpvb20pLnkgLyB0aWxlU2l6ZS54KSxcblx0XHRcdE1hdGguY2VpbChtYXAucHJvamVjdChbY3JzLndyYXBMYXRbMV0sIDBdLCB0aWxlWm9vbSkueSAvIHRpbGVTaXplLnkpXG5cdFx0XTtcblx0fSxcblxuXHRfb25Nb3ZlRW5kOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKCF0aGlzLl9tYXAgfHwgdGhpcy5fbWFwLl9hbmltYXRpbmdab29tKSB7IHJldHVybjsgfVxuXG5cdFx0dGhpcy5fdXBkYXRlKCk7XG5cdH0sXG5cblx0X2dldFRpbGVkUGl4ZWxCb3VuZHM6IGZ1bmN0aW9uIChjZW50ZXIpIHtcblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuXHRcdCAgICBtYXBab29tID0gbWFwLl9hbmltYXRpbmdab29tID8gTWF0aC5tYXgobWFwLl9hbmltYXRlVG9ab29tLCBtYXAuZ2V0Wm9vbSgpKSA6IG1hcC5nZXRab29tKCksXG5cdFx0ICAgIHNjYWxlID0gbWFwLmdldFpvb21TY2FsZShtYXBab29tLCB0aGlzLl90aWxlWm9vbSksXG5cdFx0ICAgIHBpeGVsQ2VudGVyID0gbWFwLnByb2plY3QoY2VudGVyLCB0aGlzLl90aWxlWm9vbSkuZmxvb3IoKSxcblx0XHQgICAgaGFsZlNpemUgPSBtYXAuZ2V0U2l6ZSgpLmRpdmlkZUJ5KHNjYWxlICogMik7XG5cblx0XHRyZXR1cm4gbmV3IEJvdW5kcyhwaXhlbENlbnRlci5zdWJ0cmFjdChoYWxmU2l6ZSksIHBpeGVsQ2VudGVyLmFkZChoYWxmU2l6ZSkpO1xuXHR9LFxuXG5cdC8vIFByaXZhdGUgbWV0aG9kIHRvIGxvYWQgdGlsZXMgaW4gdGhlIGdyaWQncyBhY3RpdmUgem9vbSBsZXZlbCBhY2NvcmRpbmcgdG8gbWFwIGJvdW5kc1xuXHRfdXBkYXRlOiBmdW5jdGlvbiAoY2VudGVyKSB7XG5cdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcblx0XHRpZiAoIW1hcCkgeyByZXR1cm47IH1cblx0XHR2YXIgem9vbSA9IHRoaXMuX2NsYW1wWm9vbShtYXAuZ2V0Wm9vbSgpKTtcblxuXHRcdGlmIChjZW50ZXIgPT09IHVuZGVmaW5lZCkgeyBjZW50ZXIgPSBtYXAuZ2V0Q2VudGVyKCk7IH1cblx0XHRpZiAodGhpcy5fdGlsZVpvb20gPT09IHVuZGVmaW5lZCkgeyByZXR1cm47IH1cdC8vIGlmIG91dCBvZiBtaW56b29tL21heHpvb21cblxuXHRcdHZhciBwaXhlbEJvdW5kcyA9IHRoaXMuX2dldFRpbGVkUGl4ZWxCb3VuZHMoY2VudGVyKSxcblx0XHQgICAgdGlsZVJhbmdlID0gdGhpcy5fcHhCb3VuZHNUb1RpbGVSYW5nZShwaXhlbEJvdW5kcyksXG5cdFx0ICAgIHRpbGVDZW50ZXIgPSB0aWxlUmFuZ2UuZ2V0Q2VudGVyKCksXG5cdFx0ICAgIHF1ZXVlID0gW10sXG5cdFx0ICAgIG1hcmdpbiA9IHRoaXMub3B0aW9ucy5rZWVwQnVmZmVyLFxuXHRcdCAgICBub1BydW5lUmFuZ2UgPSBuZXcgQm91bmRzKHRpbGVSYW5nZS5nZXRCb3R0b21MZWZ0KCkuc3VidHJhY3QoW21hcmdpbiwgLW1hcmdpbl0pLFxuXHRcdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVSYW5nZS5nZXRUb3BSaWdodCgpLmFkZChbbWFyZ2luLCAtbWFyZ2luXSkpO1xuXG5cdFx0Ly8gU2FuaXR5IGNoZWNrOiBwYW5pYyBpZiB0aGUgdGlsZSByYW5nZSBjb250YWlucyBJbmZpbml0eSBzb21ld2hlcmUuXG5cdFx0aWYgKCEoaXNGaW5pdGUodGlsZVJhbmdlLm1pbi54KSAmJlxuXHRcdCAgICAgIGlzRmluaXRlKHRpbGVSYW5nZS5taW4ueSkgJiZcblx0XHQgICAgICBpc0Zpbml0ZSh0aWxlUmFuZ2UubWF4LngpICYmXG5cdFx0ICAgICAgaXNGaW5pdGUodGlsZVJhbmdlLm1heC55KSkpIHsgdGhyb3cgbmV3IEVycm9yKCdBdHRlbXB0ZWQgdG8gbG9hZCBhbiBpbmZpbml0ZSBudW1iZXIgb2YgdGlsZXMnKTsgfVxuXG5cdFx0Zm9yICh2YXIga2V5IGluIHRoaXMuX3RpbGVzKSB7XG5cdFx0XHR2YXIgYyA9IHRoaXMuX3RpbGVzW2tleV0uY29vcmRzO1xuXHRcdFx0aWYgKGMueiAhPT0gdGhpcy5fdGlsZVpvb20gfHwgIW5vUHJ1bmVSYW5nZS5jb250YWlucyhuZXcgUG9pbnQoYy54LCBjLnkpKSkge1xuXHRcdFx0XHR0aGlzLl90aWxlc1trZXldLmN1cnJlbnQgPSBmYWxzZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBfdXBkYXRlIGp1c3QgbG9hZHMgbW9yZSB0aWxlcy4gSWYgdGhlIHRpbGUgem9vbSBsZXZlbCBkaWZmZXJzIHRvbyBtdWNoXG5cdFx0Ly8gZnJvbSB0aGUgbWFwJ3MsIGxldCBfc2V0VmlldyByZXNldCBsZXZlbHMgYW5kIHBydW5lIG9sZCB0aWxlcy5cblx0XHRpZiAoTWF0aC5hYnMoem9vbSAtIHRoaXMuX3RpbGVab29tKSA+IDEpIHsgdGhpcy5fc2V0VmlldyhjZW50ZXIsIHpvb20pOyByZXR1cm47IH1cblxuXHRcdC8vIGNyZWF0ZSBhIHF1ZXVlIG9mIGNvb3JkaW5hdGVzIHRvIGxvYWQgdGlsZXMgZnJvbVxuXHRcdGZvciAodmFyIGogPSB0aWxlUmFuZ2UubWluLnk7IGogPD0gdGlsZVJhbmdlLm1heC55OyBqKyspIHtcblx0XHRcdGZvciAodmFyIGkgPSB0aWxlUmFuZ2UubWluLng7IGkgPD0gdGlsZVJhbmdlLm1heC54OyBpKyspIHtcblx0XHRcdFx0dmFyIGNvb3JkcyA9IG5ldyBQb2ludChpLCBqKTtcblx0XHRcdFx0Y29vcmRzLnogPSB0aGlzLl90aWxlWm9vbTtcblxuXHRcdFx0XHRpZiAoIXRoaXMuX2lzVmFsaWRUaWxlKGNvb3JkcykpIHsgY29udGludWU7IH1cblxuXHRcdFx0XHR2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW3RoaXMuX3RpbGVDb29yZHNUb0tleShjb29yZHMpXTtcblx0XHRcdFx0aWYgKHRpbGUpIHtcblx0XHRcdFx0XHR0aWxlLmN1cnJlbnQgPSB0cnVlO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHF1ZXVlLnB1c2goY29vcmRzKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIHNvcnQgdGlsZSBxdWV1ZSB0byBsb2FkIHRpbGVzIGluIG9yZGVyIG9mIHRoZWlyIGRpc3RhbmNlIHRvIGNlbnRlclxuXHRcdHF1ZXVlLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcblx0XHRcdHJldHVybiBhLmRpc3RhbmNlVG8odGlsZUNlbnRlcikgLSBiLmRpc3RhbmNlVG8odGlsZUNlbnRlcik7XG5cdFx0fSk7XG5cblx0XHRpZiAocXVldWUubGVuZ3RoICE9PSAwKSB7XG5cdFx0XHQvLyBpZiBpdCdzIHRoZSBmaXJzdCBiYXRjaCBvZiB0aWxlcyB0byBsb2FkXG5cdFx0XHRpZiAoIXRoaXMuX2xvYWRpbmcpIHtcblx0XHRcdFx0dGhpcy5fbG9hZGluZyA9IHRydWU7XG5cdFx0XHRcdC8vIEBldmVudCBsb2FkaW5nOiBFdmVudFxuXHRcdFx0XHQvLyBGaXJlZCB3aGVuIHRoZSBncmlkIGxheWVyIHN0YXJ0cyBsb2FkaW5nIHRpbGVzLlxuXHRcdFx0XHR0aGlzLmZpcmUoJ2xvYWRpbmcnKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gY3JlYXRlIERPTSBmcmFnbWVudCB0byBhcHBlbmQgdGlsZXMgaW4gb25lIGJhdGNoXG5cdFx0XHR2YXIgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG5cblx0XHRcdGZvciAoaSA9IDA7IGkgPCBxdWV1ZS5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHR0aGlzLl9hZGRUaWxlKHF1ZXVlW2ldLCBmcmFnbWVudCk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuX2xldmVsLmVsLmFwcGVuZENoaWxkKGZyYWdtZW50KTtcblx0XHR9XG5cdH0sXG5cblx0X2lzVmFsaWRUaWxlOiBmdW5jdGlvbiAoY29vcmRzKSB7XG5cdFx0dmFyIGNycyA9IHRoaXMuX21hcC5vcHRpb25zLmNycztcblxuXHRcdGlmICghY3JzLmluZmluaXRlKSB7XG5cdFx0XHQvLyBkb24ndCBsb2FkIHRpbGUgaWYgaXQncyBvdXQgb2YgYm91bmRzIGFuZCBub3Qgd3JhcHBlZFxuXHRcdFx0dmFyIGJvdW5kcyA9IHRoaXMuX2dsb2JhbFRpbGVSYW5nZTtcblx0XHRcdGlmICgoIWNycy53cmFwTG5nICYmIChjb29yZHMueCA8IGJvdW5kcy5taW4ueCB8fCBjb29yZHMueCA+IGJvdW5kcy5tYXgueCkpIHx8XG5cdFx0XHQgICAgKCFjcnMud3JhcExhdCAmJiAoY29vcmRzLnkgPCBib3VuZHMubWluLnkgfHwgY29vcmRzLnkgPiBib3VuZHMubWF4LnkpKSkgeyByZXR1cm4gZmFsc2U7IH1cblx0XHR9XG5cblx0XHRpZiAoIXRoaXMub3B0aW9ucy5ib3VuZHMpIHsgcmV0dXJuIHRydWU7IH1cblxuXHRcdC8vIGRvbid0IGxvYWQgdGlsZSBpZiBpdCBkb2Vzbid0IGludGVyc2VjdCB0aGUgYm91bmRzIGluIG9wdGlvbnNcblx0XHR2YXIgdGlsZUJvdW5kcyA9IHRoaXMuX3RpbGVDb29yZHNUb0JvdW5kcyhjb29yZHMpO1xuXHRcdHJldHVybiB0b0xhdExuZ0JvdW5kcyh0aGlzLm9wdGlvbnMuYm91bmRzKS5vdmVybGFwcyh0aWxlQm91bmRzKTtcblx0fSxcblxuXHRfa2V5VG9Cb3VuZHM6IGZ1bmN0aW9uIChrZXkpIHtcblx0XHRyZXR1cm4gdGhpcy5fdGlsZUNvb3Jkc1RvQm91bmRzKHRoaXMuX2tleVRvVGlsZUNvb3JkcyhrZXkpKTtcblx0fSxcblxuXHRfdGlsZUNvb3Jkc1RvTndTZTogZnVuY3Rpb24gKGNvb3Jkcykge1xuXHRcdHZhciBtYXAgPSB0aGlzLl9tYXAsXG5cdFx0ICAgIHRpbGVTaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpLFxuXHRcdCAgICBud1BvaW50ID0gY29vcmRzLnNjYWxlQnkodGlsZVNpemUpLFxuXHRcdCAgICBzZVBvaW50ID0gbndQb2ludC5hZGQodGlsZVNpemUpLFxuXHRcdCAgICBudyA9IG1hcC51bnByb2plY3QobndQb2ludCwgY29vcmRzLnopLFxuXHRcdCAgICBzZSA9IG1hcC51bnByb2plY3Qoc2VQb2ludCwgY29vcmRzLnopO1xuXHRcdHJldHVybiBbbncsIHNlXTtcblx0fSxcblxuXHQvLyBjb252ZXJ0cyB0aWxlIGNvb3JkaW5hdGVzIHRvIGl0cyBnZW9ncmFwaGljYWwgYm91bmRzXG5cdF90aWxlQ29vcmRzVG9Cb3VuZHM6IGZ1bmN0aW9uIChjb29yZHMpIHtcblx0XHR2YXIgYnAgPSB0aGlzLl90aWxlQ29vcmRzVG9Od1NlKGNvb3JkcyksXG5cdFx0ICAgIGJvdW5kcyA9IG5ldyBMYXRMbmdCb3VuZHMoYnBbMF0sIGJwWzFdKTtcblxuXHRcdGlmICghdGhpcy5vcHRpb25zLm5vV3JhcCkge1xuXHRcdFx0Ym91bmRzID0gdGhpcy5fbWFwLndyYXBMYXRMbmdCb3VuZHMoYm91bmRzKTtcblx0XHR9XG5cdFx0cmV0dXJuIGJvdW5kcztcblx0fSxcblx0Ly8gY29udmVydHMgdGlsZSBjb29yZGluYXRlcyB0byBrZXkgZm9yIHRoZSB0aWxlIGNhY2hlXG5cdF90aWxlQ29vcmRzVG9LZXk6IGZ1bmN0aW9uIChjb29yZHMpIHtcblx0XHRyZXR1cm4gY29vcmRzLnggKyAnOicgKyBjb29yZHMueSArICc6JyArIGNvb3Jkcy56O1xuXHR9LFxuXG5cdC8vIGNvbnZlcnRzIHRpbGUgY2FjaGUga2V5IHRvIGNvb3JkaW5hdGVzXG5cdF9rZXlUb1RpbGVDb29yZHM6IGZ1bmN0aW9uIChrZXkpIHtcblx0XHR2YXIgayA9IGtleS5zcGxpdCgnOicpLFxuXHRcdCAgICBjb29yZHMgPSBuZXcgUG9pbnQoK2tbMF0sICtrWzFdKTtcblx0XHRjb29yZHMueiA9ICtrWzJdO1xuXHRcdHJldHVybiBjb29yZHM7XG5cdH0sXG5cblx0X3JlbW92ZVRpbGU6IGZ1bmN0aW9uIChrZXkpIHtcblx0XHR2YXIgdGlsZSA9IHRoaXMuX3RpbGVzW2tleV07XG5cdFx0aWYgKCF0aWxlKSB7IHJldHVybjsgfVxuXG5cdFx0Ly8gQ2FuY2VscyBhbnkgcGVuZGluZyBodHRwIHJlcXVlc3RzIGFzc29jaWF0ZWQgd2l0aCB0aGUgdGlsZVxuXHRcdC8vIHVubGVzcyB3ZSdyZSBvbiBBbmRyb2lkJ3Mgc3RvY2sgYnJvd3Nlcixcblx0XHQvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMTM3XG5cdFx0aWYgKCFhbmRyb2lkU3RvY2spIHtcblx0XHRcdHRpbGUuZWwuc2V0QXR0cmlidXRlKCdzcmMnLCBlbXB0eUltYWdlVXJsKTtcblx0XHR9XG5cdFx0cmVtb3ZlKHRpbGUuZWwpO1xuXG5cdFx0ZGVsZXRlIHRoaXMuX3RpbGVzW2tleV07XG5cblx0XHQvLyBAZXZlbnQgdGlsZXVubG9hZDogVGlsZUV2ZW50XG5cdFx0Ly8gRmlyZWQgd2hlbiBhIHRpbGUgaXMgcmVtb3ZlZCAoZS5nLiB3aGVuIGEgdGlsZSBnb2VzIG9mZiB0aGUgc2NyZWVuKS5cblx0XHR0aGlzLmZpcmUoJ3RpbGV1bmxvYWQnLCB7XG5cdFx0XHR0aWxlOiB0aWxlLmVsLFxuXHRcdFx0Y29vcmRzOiB0aGlzLl9rZXlUb1RpbGVDb29yZHMoa2V5KVxuXHRcdH0pO1xuXHR9LFxuXG5cdF9pbml0VGlsZTogZnVuY3Rpb24gKHRpbGUpIHtcblx0XHRhZGRDbGFzcyh0aWxlLCAnbGVhZmxldC10aWxlJyk7XG5cblx0XHR2YXIgdGlsZVNpemUgPSB0aGlzLmdldFRpbGVTaXplKCk7XG5cdFx0dGlsZS5zdHlsZS53aWR0aCA9IHRpbGVTaXplLnggKyAncHgnO1xuXHRcdHRpbGUuc3R5bGUuaGVpZ2h0ID0gdGlsZVNpemUueSArICdweCc7XG5cblx0XHR0aWxlLm9uc2VsZWN0c3RhcnQgPSBmYWxzZUZuO1xuXHRcdHRpbGUub25tb3VzZW1vdmUgPSBmYWxzZUZuO1xuXG5cdFx0Ly8gdXBkYXRlIG9wYWNpdHkgb24gdGlsZXMgaW4gSUU3LTggYmVjYXVzZSBvZiBmaWx0ZXIgaW5oZXJpdGFuY2UgcHJvYmxlbXNcblx0XHRpZiAoaWVsdDkgJiYgdGhpcy5vcHRpb25zLm9wYWNpdHkgPCAxKSB7XG5cdFx0XHRzZXRPcGFjaXR5KHRpbGUsIHRoaXMub3B0aW9ucy5vcGFjaXR5KTtcblx0XHR9XG5cblx0XHQvLyB3aXRob3V0IHRoaXMgaGFjaywgdGlsZXMgZGlzYXBwZWFyIGFmdGVyIHpvb20gb24gQ2hyb21lIGZvciBBbmRyb2lkXG5cdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL0xlYWZsZXQvTGVhZmxldC9pc3N1ZXMvMjA3OFxuXHRcdGlmIChhbmRyb2lkICYmICFhbmRyb2lkMjMpIHtcblx0XHRcdHRpbGUuc3R5bGUuV2Via2l0QmFja2ZhY2VWaXNpYmlsaXR5ID0gJ2hpZGRlbic7XG5cdFx0fVxuXHR9LFxuXG5cdF9hZGRUaWxlOiBmdW5jdGlvbiAoY29vcmRzLCBjb250YWluZXIpIHtcblx0XHR2YXIgdGlsZVBvcyA9IHRoaXMuX2dldFRpbGVQb3MoY29vcmRzKSxcblx0XHQgICAga2V5ID0gdGhpcy5fdGlsZUNvb3Jkc1RvS2V5KGNvb3Jkcyk7XG5cblx0XHR2YXIgdGlsZSA9IHRoaXMuY3JlYXRlVGlsZSh0aGlzLl93cmFwQ29vcmRzKGNvb3JkcyksIGJpbmQodGhpcy5fdGlsZVJlYWR5LCB0aGlzLCBjb29yZHMpKTtcblxuXHRcdHRoaXMuX2luaXRUaWxlKHRpbGUpO1xuXG5cdFx0Ly8gaWYgY3JlYXRlVGlsZSBpcyBkZWZpbmVkIHdpdGggYSBzZWNvbmQgYXJndW1lbnQgKFwiZG9uZVwiIGNhbGxiYWNrKSxcblx0XHQvLyB3ZSBrbm93IHRoYXQgdGlsZSBpcyBhc3luYyBhbmQgd2lsbCBiZSByZWFkeSBsYXRlcjsgb3RoZXJ3aXNlXG5cdFx0aWYgKHRoaXMuY3JlYXRlVGlsZS5sZW5ndGggPCAyKSB7XG5cdFx0XHQvLyBtYXJrIHRpbGUgYXMgcmVhZHksIGJ1dCBkZWxheSBvbmUgZnJhbWUgZm9yIG9wYWNpdHkgYW5pbWF0aW9uIHRvIGhhcHBlblxuXHRcdFx0cmVxdWVzdEFuaW1GcmFtZShiaW5kKHRoaXMuX3RpbGVSZWFkeSwgdGhpcywgY29vcmRzLCBudWxsLCB0aWxlKSk7XG5cdFx0fVxuXG5cdFx0c2V0UG9zaXRpb24odGlsZSwgdGlsZVBvcyk7XG5cblx0XHQvLyBzYXZlIHRpbGUgaW4gY2FjaGVcblx0XHR0aGlzLl90aWxlc1trZXldID0ge1xuXHRcdFx0ZWw6IHRpbGUsXG5cdFx0XHRjb29yZHM6IGNvb3Jkcyxcblx0XHRcdGN1cnJlbnQ6IHRydWVcblx0XHR9O1xuXG5cdFx0Y29udGFpbmVyLmFwcGVuZENoaWxkKHRpbGUpO1xuXHRcdC8vIEBldmVudCB0aWxlbG9hZHN0YXJ0OiBUaWxlRXZlbnRcblx0XHQvLyBGaXJlZCB3aGVuIGEgdGlsZSBpcyByZXF1ZXN0ZWQgYW5kIHN0YXJ0cyBsb2FkaW5nLlxuXHRcdHRoaXMuZmlyZSgndGlsZWxvYWRzdGFydCcsIHtcblx0XHRcdHRpbGU6IHRpbGUsXG5cdFx0XHRjb29yZHM6IGNvb3Jkc1xuXHRcdH0pO1xuXHR9LFxuXG5cdF90aWxlUmVhZHk6IGZ1bmN0aW9uIChjb29yZHMsIGVyciwgdGlsZSkge1xuXHRcdGlmICghdGhpcy5fbWFwKSB7IHJldHVybjsgfVxuXG5cdFx0aWYgKGVycikge1xuXHRcdFx0Ly8gQGV2ZW50IHRpbGVlcnJvcjogVGlsZUVycm9yRXZlbnRcblx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlcmUgaXMgYW4gZXJyb3IgbG9hZGluZyBhIHRpbGUuXG5cdFx0XHR0aGlzLmZpcmUoJ3RpbGVlcnJvcicsIHtcblx0XHRcdFx0ZXJyb3I6IGVycixcblx0XHRcdFx0dGlsZTogdGlsZSxcblx0XHRcdFx0Y29vcmRzOiBjb29yZHNcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdHZhciBrZXkgPSB0aGlzLl90aWxlQ29vcmRzVG9LZXkoY29vcmRzKTtcblxuXHRcdHRpbGUgPSB0aGlzLl90aWxlc1trZXldO1xuXHRcdGlmICghdGlsZSkgeyByZXR1cm47IH1cblxuXHRcdHRpbGUubG9hZGVkID0gK25ldyBEYXRlKCk7XG5cdFx0aWYgKHRoaXMuX21hcC5fZmFkZUFuaW1hdGVkKSB7XG5cdFx0XHRzZXRPcGFjaXR5KHRpbGUuZWwsIDApO1xuXHRcdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2ZhZGVGcmFtZSk7XG5cdFx0XHR0aGlzLl9mYWRlRnJhbWUgPSByZXF1ZXN0QW5pbUZyYW1lKHRoaXMuX3VwZGF0ZU9wYWNpdHksIHRoaXMpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aWxlLmFjdGl2ZSA9IHRydWU7XG5cdFx0XHR0aGlzLl9wcnVuZVRpbGVzKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCFlcnIpIHtcblx0XHRcdGFkZENsYXNzKHRpbGUuZWwsICdsZWFmbGV0LXRpbGUtbG9hZGVkJyk7XG5cblx0XHRcdC8vIEBldmVudCB0aWxlbG9hZDogVGlsZUV2ZW50XG5cdFx0XHQvLyBGaXJlZCB3aGVuIGEgdGlsZSBsb2Fkcy5cblx0XHRcdHRoaXMuZmlyZSgndGlsZWxvYWQnLCB7XG5cdFx0XHRcdHRpbGU6IHRpbGUuZWwsXG5cdFx0XHRcdGNvb3JkczogY29vcmRzXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRpZiAodGhpcy5fbm9UaWxlc1RvTG9hZCgpKSB7XG5cdFx0XHR0aGlzLl9sb2FkaW5nID0gZmFsc2U7XG5cdFx0XHQvLyBAZXZlbnQgbG9hZDogRXZlbnRcblx0XHRcdC8vIEZpcmVkIHdoZW4gdGhlIGdyaWQgbGF5ZXIgbG9hZGVkIGFsbCB2aXNpYmxlIHRpbGVzLlxuXHRcdFx0dGhpcy5maXJlKCdsb2FkJyk7XG5cblx0XHRcdGlmIChpZWx0OSB8fCAhdGhpcy5fbWFwLl9mYWRlQW5pbWF0ZWQpIHtcblx0XHRcdFx0cmVxdWVzdEFuaW1GcmFtZSh0aGlzLl9wcnVuZVRpbGVzLCB0aGlzKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIFdhaXQgYSBiaXQgbW9yZSB0aGFuIDAuMiBzZWNzICh0aGUgZHVyYXRpb24gb2YgdGhlIHRpbGUgZmFkZS1pbilcblx0XHRcdFx0Ly8gdG8gdHJpZ2dlciBhIHBydW5pbmcuXG5cdFx0XHRcdHNldFRpbWVvdXQoYmluZCh0aGlzLl9wcnVuZVRpbGVzLCB0aGlzKSwgMjUwKTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0X2dldFRpbGVQb3M6IGZ1bmN0aW9uIChjb29yZHMpIHtcblx0XHRyZXR1cm4gY29vcmRzLnNjYWxlQnkodGhpcy5nZXRUaWxlU2l6ZSgpKS5zdWJ0cmFjdCh0aGlzLl9sZXZlbC5vcmlnaW4pO1xuXHR9LFxuXG5cdF93cmFwQ29vcmRzOiBmdW5jdGlvbiAoY29vcmRzKSB7XG5cdFx0dmFyIG5ld0Nvb3JkcyA9IG5ldyBQb2ludChcblx0XHRcdHRoaXMuX3dyYXBYID8gd3JhcE51bShjb29yZHMueCwgdGhpcy5fd3JhcFgpIDogY29vcmRzLngsXG5cdFx0XHR0aGlzLl93cmFwWSA/IHdyYXBOdW0oY29vcmRzLnksIHRoaXMuX3dyYXBZKSA6IGNvb3Jkcy55KTtcblx0XHRuZXdDb29yZHMueiA9IGNvb3Jkcy56O1xuXHRcdHJldHVybiBuZXdDb29yZHM7XG5cdH0sXG5cblx0X3B4Qm91bmRzVG9UaWxlUmFuZ2U6IGZ1bmN0aW9uIChib3VuZHMpIHtcblx0XHR2YXIgdGlsZVNpemUgPSB0aGlzLmdldFRpbGVTaXplKCk7XG5cdFx0cmV0dXJuIG5ldyBCb3VuZHMoXG5cdFx0XHRib3VuZHMubWluLnVuc2NhbGVCeSh0aWxlU2l6ZSkuZmxvb3IoKSxcblx0XHRcdGJvdW5kcy5tYXgudW5zY2FsZUJ5KHRpbGVTaXplKS5jZWlsKCkuc3VidHJhY3QoWzEsIDFdKSk7XG5cdH0sXG5cblx0X25vVGlsZXNUb0xvYWQ6IGZ1bmN0aW9uICgpIHtcblx0XHRmb3IgKHZhciBrZXkgaW4gdGhpcy5fdGlsZXMpIHtcblx0XHRcdGlmICghdGhpcy5fdGlsZXNba2V5XS5sb2FkZWQpIHsgcmV0dXJuIGZhbHNlOyB9XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG59KTtcblxuLy8gQGZhY3RvcnkgTC5ncmlkTGF5ZXIob3B0aW9ucz86IEdyaWRMYXllciBvcHRpb25zKVxuLy8gQ3JlYXRlcyBhIG5ldyBpbnN0YW5jZSBvZiBHcmlkTGF5ZXIgd2l0aCB0aGUgc3VwcGxpZWQgb3B0aW9ucy5cbmZ1bmN0aW9uIGdyaWRMYXllcihvcHRpb25zKSB7XG5cdHJldHVybiBuZXcgR3JpZExheWVyKG9wdGlvbnMpO1xufVxuXG4vKlxyXG4gKiBAY2xhc3MgVGlsZUxheWVyXHJcbiAqIEBpbmhlcml0cyBHcmlkTGF5ZXJcclxuICogQGFrYSBMLlRpbGVMYXllclxyXG4gKiBVc2VkIHRvIGxvYWQgYW5kIGRpc3BsYXkgdGlsZSBsYXllcnMgb24gdGhlIG1hcC4gRXh0ZW5kcyBgR3JpZExheWVyYC5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogTC50aWxlTGF5ZXIoJ2h0dHA6Ly97c30udGlsZS5vcGVuc3RyZWV0bWFwLm9yZy97en0ve3h9L3t5fS5wbmc/e2Zvb30nLCB7Zm9vOiAnYmFyJ30pLmFkZFRvKG1hcCk7XHJcbiAqIGBgYFxyXG4gKlxyXG4gKiBAc2VjdGlvbiBVUkwgdGVtcGxhdGVcclxuICogQGV4YW1wbGVcclxuICpcclxuICogQSBzdHJpbmcgb2YgdGhlIGZvbGxvd2luZyBmb3JtOlxyXG4gKlxyXG4gKiBgYGBcclxuICogJ2h0dHA6Ly97c30uc29tZWRvbWFpbi5jb20vYmxhYmxhL3t6fS97eH0ve3l9e3J9LnBuZydcclxuICogYGBgXHJcbiAqXHJcbiAqIGB7c31gIG1lYW5zIG9uZSBvZiB0aGUgYXZhaWxhYmxlIHN1YmRvbWFpbnMgKHVzZWQgc2VxdWVudGlhbGx5IHRvIGhlbHAgd2l0aCBicm93c2VyIHBhcmFsbGVsIHJlcXVlc3RzIHBlciBkb21haW4gbGltaXRhdGlvbjsgc3ViZG9tYWluIHZhbHVlcyBhcmUgc3BlY2lmaWVkIGluIG9wdGlvbnM7IGBhYCwgYGJgIG9yIGBjYCBieSBkZWZhdWx0LCBjYW4gYmUgb21pdHRlZCksIGB7en1gIOKAlCB6b29tIGxldmVsLCBge3h9YCBhbmQgYHt5fWAg4oCUIHRpbGUgY29vcmRpbmF0ZXMuIGB7cn1gIGNhbiBiZSB1c2VkIHRvIGFkZCBcIiZjb21tYXQ7MnhcIiB0byB0aGUgVVJMIHRvIGxvYWQgcmV0aW5hIHRpbGVzLlxyXG4gKlxyXG4gKiBZb3UgY2FuIHVzZSBjdXN0b20ga2V5cyBpbiB0aGUgdGVtcGxhdGUsIHdoaWNoIHdpbGwgYmUgW2V2YWx1YXRlZF0oI3V0aWwtdGVtcGxhdGUpIGZyb20gVGlsZUxheWVyIG9wdGlvbnMsIGxpa2UgdGhpczpcclxuICpcclxuICogYGBgXHJcbiAqIEwudGlsZUxheWVyKCdodHRwOi8ve3N9LnNvbWVkb21haW4uY29tL3tmb299L3t6fS97eH0ve3l9LnBuZycsIHtmb286ICdiYXInfSk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcblxyXG52YXIgVGlsZUxheWVyID0gR3JpZExheWVyLmV4dGVuZCh7XHJcblxyXG5cdC8vIEBzZWN0aW9uXHJcblx0Ly8gQGFrYSBUaWxlTGF5ZXIgb3B0aW9uc1xyXG5cdG9wdGlvbnM6IHtcclxuXHRcdC8vIEBvcHRpb24gbWluWm9vbTogTnVtYmVyID0gMFxyXG5cdFx0Ly8gVGhlIG1pbmltdW0gem9vbSBsZXZlbCBkb3duIHRvIHdoaWNoIHRoaXMgbGF5ZXIgd2lsbCBiZSBkaXNwbGF5ZWQgKGluY2x1c2l2ZSkuXHJcblx0XHRtaW5ab29tOiAwLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gbWF4Wm9vbTogTnVtYmVyID0gMThcclxuXHRcdC8vIFRoZSBtYXhpbXVtIHpvb20gbGV2ZWwgdXAgdG8gd2hpY2ggdGhpcyBsYXllciB3aWxsIGJlIGRpc3BsYXllZCAoaW5jbHVzaXZlKS5cclxuXHRcdG1heFpvb206IDE4LFxyXG5cclxuXHRcdC8vIEBvcHRpb24gc3ViZG9tYWluczogU3RyaW5nfFN0cmluZ1tdID0gJ2FiYydcclxuXHRcdC8vIFN1YmRvbWFpbnMgb2YgdGhlIHRpbGUgc2VydmljZS4gQ2FuIGJlIHBhc3NlZCBpbiB0aGUgZm9ybSBvZiBvbmUgc3RyaW5nICh3aGVyZSBlYWNoIGxldHRlciBpcyBhIHN1YmRvbWFpbiBuYW1lKSBvciBhbiBhcnJheSBvZiBzdHJpbmdzLlxyXG5cdFx0c3ViZG9tYWluczogJ2FiYycsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBlcnJvclRpbGVVcmw6IFN0cmluZyA9ICcnXHJcblx0XHQvLyBVUkwgdG8gdGhlIHRpbGUgaW1hZ2UgdG8gc2hvdyBpbiBwbGFjZSBvZiB0aGUgdGlsZSB0aGF0IGZhaWxlZCB0byBsb2FkLlxyXG5cdFx0ZXJyb3JUaWxlVXJsOiAnJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHpvb21PZmZzZXQ6IE51bWJlciA9IDBcclxuXHRcdC8vIFRoZSB6b29tIG51bWJlciB1c2VkIGluIHRpbGUgVVJMcyB3aWxsIGJlIG9mZnNldCB3aXRoIHRoaXMgdmFsdWUuXHJcblx0XHR6b29tT2Zmc2V0OiAwLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gdG1zOiBCb29sZWFuID0gZmFsc2VcclxuXHRcdC8vIElmIGB0cnVlYCwgaW52ZXJzZXMgWSBheGlzIG51bWJlcmluZyBmb3IgdGlsZXMgKHR1cm4gdGhpcyBvbiBmb3IgW1RNU10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVGlsZV9NYXBfU2VydmljZSkgc2VydmljZXMpLlxyXG5cdFx0dG1zOiBmYWxzZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHpvb21SZXZlcnNlOiBCb29sZWFuID0gZmFsc2VcclxuXHRcdC8vIElmIHNldCB0byB0cnVlLCB0aGUgem9vbSBudW1iZXIgdXNlZCBpbiB0aWxlIFVSTHMgd2lsbCBiZSByZXZlcnNlZCAoYG1heFpvb20gLSB6b29tYCBpbnN0ZWFkIG9mIGB6b29tYClcclxuXHRcdHpvb21SZXZlcnNlOiBmYWxzZSxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGRldGVjdFJldGluYTogQm9vbGVhbiA9IGZhbHNlXHJcblx0XHQvLyBJZiBgdHJ1ZWAgYW5kIHVzZXIgaXMgb24gYSByZXRpbmEgZGlzcGxheSwgaXQgd2lsbCByZXF1ZXN0IGZvdXIgdGlsZXMgb2YgaGFsZiB0aGUgc3BlY2lmaWVkIHNpemUgYW5kIGEgYmlnZ2VyIHpvb20gbGV2ZWwgaW4gcGxhY2Ugb2Ygb25lIHRvIHV0aWxpemUgdGhlIGhpZ2ggcmVzb2x1dGlvbi5cclxuXHRcdGRldGVjdFJldGluYTogZmFsc2UsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBjcm9zc09yaWdpbjogQm9vbGVhbiA9IGZhbHNlXHJcblx0XHQvLyBJZiB0cnVlLCBhbGwgdGlsZXMgd2lsbCBoYXZlIHRoZWlyIGNyb3NzT3JpZ2luIGF0dHJpYnV0ZSBzZXQgdG8gJycuIFRoaXMgaXMgbmVlZGVkIGlmIHlvdSB3YW50IHRvIGFjY2VzcyB0aWxlIHBpeGVsIGRhdGEuXHJcblx0XHRjcm9zc09yaWdpbjogZmFsc2VcclxuXHR9LFxyXG5cclxuXHRpbml0aWFsaXplOiBmdW5jdGlvbiAodXJsLCBvcHRpb25zKSB7XHJcblxyXG5cdFx0dGhpcy5fdXJsID0gdXJsO1xyXG5cclxuXHRcdG9wdGlvbnMgPSBzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xyXG5cclxuXHRcdC8vIGRldGVjdGluZyByZXRpbmEgZGlzcGxheXMsIGFkanVzdGluZyB0aWxlU2l6ZSBhbmQgem9vbSBsZXZlbHNcclxuXHRcdGlmIChvcHRpb25zLmRldGVjdFJldGluYSAmJiByZXRpbmEgJiYgb3B0aW9ucy5tYXhab29tID4gMCkge1xyXG5cclxuXHRcdFx0b3B0aW9ucy50aWxlU2l6ZSA9IE1hdGguZmxvb3Iob3B0aW9ucy50aWxlU2l6ZSAvIDIpO1xyXG5cclxuXHRcdFx0aWYgKCFvcHRpb25zLnpvb21SZXZlcnNlKSB7XHJcblx0XHRcdFx0b3B0aW9ucy56b29tT2Zmc2V0Kys7XHJcblx0XHRcdFx0b3B0aW9ucy5tYXhab29tLS07XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0b3B0aW9ucy56b29tT2Zmc2V0LS07XHJcblx0XHRcdFx0b3B0aW9ucy5taW5ab29tKys7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdG9wdGlvbnMubWluWm9vbSA9IE1hdGgubWF4KDAsIG9wdGlvbnMubWluWm9vbSk7XHJcblx0XHR9XHJcblxyXG5cdFx0aWYgKHR5cGVvZiBvcHRpb25zLnN1YmRvbWFpbnMgPT09ICdzdHJpbmcnKSB7XHJcblx0XHRcdG9wdGlvbnMuc3ViZG9tYWlucyA9IG9wdGlvbnMuc3ViZG9tYWlucy5zcGxpdCgnJyk7XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gZm9yIGh0dHBzOi8vZ2l0aHViLmNvbS9MZWFmbGV0L0xlYWZsZXQvaXNzdWVzLzEzN1xyXG5cdFx0aWYgKCFhbmRyb2lkKSB7XHJcblx0XHRcdHRoaXMub24oJ3RpbGV1bmxvYWQnLCB0aGlzLl9vblRpbGVSZW1vdmUpO1xyXG5cdFx0fVxyXG5cdH0sXHJcblxyXG5cdC8vIEBtZXRob2Qgc2V0VXJsKHVybDogU3RyaW5nLCBub1JlZHJhdz86IEJvb2xlYW4pOiB0aGlzXHJcblx0Ly8gVXBkYXRlcyB0aGUgbGF5ZXIncyBVUkwgdGVtcGxhdGUgYW5kIHJlZHJhd3MgaXQgKHVubGVzcyBgbm9SZWRyYXdgIGlzIHNldCB0byBgdHJ1ZWApLlxyXG5cdHNldFVybDogZnVuY3Rpb24gKHVybCwgbm9SZWRyYXcpIHtcclxuXHRcdHRoaXMuX3VybCA9IHVybDtcclxuXHJcblx0XHRpZiAoIW5vUmVkcmF3KSB7XHJcblx0XHRcdHRoaXMucmVkcmF3KCk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9LFxyXG5cclxuXHQvLyBAbWV0aG9kIGNyZWF0ZVRpbGUoY29vcmRzOiBPYmplY3QsIGRvbmU/OiBGdW5jdGlvbik6IEhUTUxFbGVtZW50XHJcblx0Ly8gQ2FsbGVkIG9ubHkgaW50ZXJuYWxseSwgb3ZlcnJpZGVzIEdyaWRMYXllcidzIFtgY3JlYXRlVGlsZSgpYF0oI2dyaWRsYXllci1jcmVhdGV0aWxlKVxyXG5cdC8vIHRvIHJldHVybiBhbiBgPGltZz5gIEhUTUwgZWxlbWVudCB3aXRoIHRoZSBhcHByb3ByaWF0ZSBpbWFnZSBVUkwgZ2l2ZW4gYGNvb3Jkc2AuIFRoZSBgZG9uZWBcclxuXHQvLyBjYWxsYmFjayBpcyBjYWxsZWQgd2hlbiB0aGUgdGlsZSBoYXMgYmVlbiBsb2FkZWQuXHJcblx0Y3JlYXRlVGlsZTogZnVuY3Rpb24gKGNvb3JkcywgZG9uZSkge1xyXG5cdFx0dmFyIHRpbGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTtcclxuXHJcblx0XHRvbih0aWxlLCAnbG9hZCcsIGJpbmQodGhpcy5fdGlsZU9uTG9hZCwgdGhpcywgZG9uZSwgdGlsZSkpO1xyXG5cdFx0b24odGlsZSwgJ2Vycm9yJywgYmluZCh0aGlzLl90aWxlT25FcnJvciwgdGhpcywgZG9uZSwgdGlsZSkpO1xyXG5cclxuXHRcdGlmICh0aGlzLm9wdGlvbnMuY3Jvc3NPcmlnaW4pIHtcclxuXHRcdFx0dGlsZS5jcm9zc09yaWdpbiA9ICcnO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8qXHJcblx0XHQgQWx0IHRhZyBpcyBzZXQgdG8gZW1wdHkgc3RyaW5nIHRvIGtlZXAgc2NyZWVuIHJlYWRlcnMgZnJvbSByZWFkaW5nIFVSTCBhbmQgZm9yIGNvbXBsaWFuY2UgcmVhc29uc1xyXG5cdFx0IGh0dHA6Ly93d3cudzMub3JnL1RSL1dDQUcyMC1URUNIUy9INjdcclxuXHRcdCovXHJcblx0XHR0aWxlLmFsdCA9ICcnO1xyXG5cclxuXHRcdC8qXHJcblx0XHQgU2V0IHJvbGU9XCJwcmVzZW50YXRpb25cIiB0byBmb3JjZSBzY3JlZW4gcmVhZGVycyB0byBpZ25vcmUgdGhpc1xyXG5cdFx0IGh0dHBzOi8vd3d3LnczLm9yZy9UUi93YWktYXJpYS9yb2xlcyN0ZXh0YWx0ZXJuYXRpdmVjb21wdXRhdGlvblxyXG5cdFx0Ki9cclxuXHRcdHRpbGUuc2V0QXR0cmlidXRlKCdyb2xlJywgJ3ByZXNlbnRhdGlvbicpO1xyXG5cclxuXHRcdHRpbGUuc3JjID0gdGhpcy5nZXRUaWxlVXJsKGNvb3Jkcyk7XHJcblxyXG5cdFx0cmV0dXJuIHRpbGU7XHJcblx0fSxcclxuXHJcblx0Ly8gQHNlY3Rpb24gRXh0ZW5zaW9uIG1ldGhvZHNcclxuXHQvLyBAdW5pbmhlcml0YWJsZVxyXG5cdC8vIExheWVycyBleHRlbmRpbmcgYFRpbGVMYXllcmAgbWlnaHQgcmVpbXBsZW1lbnQgdGhlIGZvbGxvd2luZyBtZXRob2QuXHJcblx0Ly8gQG1ldGhvZCBnZXRUaWxlVXJsKGNvb3JkczogT2JqZWN0KTogU3RyaW5nXHJcblx0Ly8gQ2FsbGVkIG9ubHkgaW50ZXJuYWxseSwgcmV0dXJucyB0aGUgVVJMIGZvciBhIHRpbGUgZ2l2ZW4gaXRzIGNvb3JkaW5hdGVzLlxyXG5cdC8vIENsYXNzZXMgZXh0ZW5kaW5nIGBUaWxlTGF5ZXJgIGNhbiBvdmVycmlkZSB0aGlzIGZ1bmN0aW9uIHRvIHByb3ZpZGUgY3VzdG9tIHRpbGUgVVJMIG5hbWluZyBzY2hlbWVzLlxyXG5cdGdldFRpbGVVcmw6IGZ1bmN0aW9uIChjb29yZHMpIHtcclxuXHRcdHZhciBkYXRhID0ge1xyXG5cdFx0XHRyOiByZXRpbmEgPyAnQDJ4JyA6ICcnLFxyXG5cdFx0XHRzOiB0aGlzLl9nZXRTdWJkb21haW4oY29vcmRzKSxcclxuXHRcdFx0eDogY29vcmRzLngsXHJcblx0XHRcdHk6IGNvb3Jkcy55LFxyXG5cdFx0XHR6OiB0aGlzLl9nZXRab29tRm9yVXJsKClcclxuXHRcdH07XHJcblx0XHRpZiAodGhpcy5fbWFwICYmICF0aGlzLl9tYXAub3B0aW9ucy5jcnMuaW5maW5pdGUpIHtcclxuXHRcdFx0dmFyIGludmVydGVkWSA9IHRoaXMuX2dsb2JhbFRpbGVSYW5nZS5tYXgueSAtIGNvb3Jkcy55O1xyXG5cdFx0XHRpZiAodGhpcy5vcHRpb25zLnRtcykge1xyXG5cdFx0XHRcdGRhdGFbJ3knXSA9IGludmVydGVkWTtcclxuXHRcdFx0fVxyXG5cdFx0XHRkYXRhWycteSddID0gaW52ZXJ0ZWRZO1xyXG5cdFx0fVxyXG5cclxuXHRcdHJldHVybiB0ZW1wbGF0ZSh0aGlzLl91cmwsIGV4dGVuZChkYXRhLCB0aGlzLm9wdGlvbnMpKTtcclxuXHR9LFxyXG5cclxuXHRfdGlsZU9uTG9hZDogZnVuY3Rpb24gKGRvbmUsIHRpbGUpIHtcclxuXHRcdC8vIEZvciBodHRwczovL2dpdGh1Yi5jb20vTGVhZmxldC9MZWFmbGV0L2lzc3Vlcy8zMzMyXHJcblx0XHRpZiAoaWVsdDkpIHtcclxuXHRcdFx0c2V0VGltZW91dChiaW5kKGRvbmUsIHRoaXMsIG51bGwsIHRpbGUpLCAwKTtcclxuXHRcdH0gZWxzZSB7XHJcblx0XHRcdGRvbmUobnVsbCwgdGlsZSk7XHJcblx0XHR9XHJcblx0fSxcclxuXHJcblx0X3RpbGVPbkVycm9yOiBmdW5jdGlvbiAoZG9uZSwgdGlsZSwgZSkge1xyXG5cdFx0dmFyIGVycm9yVXJsID0gdGhpcy5vcHRpb25zLmVycm9yVGlsZVVybDtcclxuXHRcdGlmIChlcnJvclVybCAmJiB0aWxlLmdldEF0dHJpYnV0ZSgnc3JjJykgIT09IGVycm9yVXJsKSB7XHJcblx0XHRcdHRpbGUuc3JjID0gZXJyb3JVcmw7XHJcblx0XHR9XHJcblx0XHRkb25lKGUsIHRpbGUpO1xyXG5cdH0sXHJcblxyXG5cdF9vblRpbGVSZW1vdmU6IGZ1bmN0aW9uIChlKSB7XHJcblx0XHRlLnRpbGUub25sb2FkID0gbnVsbDtcclxuXHR9LFxyXG5cclxuXHRfZ2V0Wm9vbUZvclVybDogZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIHpvb20gPSB0aGlzLl90aWxlWm9vbSxcclxuXHRcdG1heFpvb20gPSB0aGlzLm9wdGlvbnMubWF4Wm9vbSxcclxuXHRcdHpvb21SZXZlcnNlID0gdGhpcy5vcHRpb25zLnpvb21SZXZlcnNlLFxyXG5cdFx0em9vbU9mZnNldCA9IHRoaXMub3B0aW9ucy56b29tT2Zmc2V0O1xyXG5cclxuXHRcdGlmICh6b29tUmV2ZXJzZSkge1xyXG5cdFx0XHR6b29tID0gbWF4Wm9vbSAtIHpvb207XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHpvb20gKyB6b29tT2Zmc2V0O1xyXG5cdH0sXHJcblxyXG5cdF9nZXRTdWJkb21haW46IGZ1bmN0aW9uICh0aWxlUG9pbnQpIHtcclxuXHRcdHZhciBpbmRleCA9IE1hdGguYWJzKHRpbGVQb2ludC54ICsgdGlsZVBvaW50LnkpICUgdGhpcy5vcHRpb25zLnN1YmRvbWFpbnMubGVuZ3RoO1xyXG5cdFx0cmV0dXJuIHRoaXMub3B0aW9ucy5zdWJkb21haW5zW2luZGV4XTtcclxuXHR9LFxyXG5cclxuXHQvLyBzdG9wcyBsb2FkaW5nIGFsbCB0aWxlcyBpbiB0aGUgYmFja2dyb3VuZCBsYXllclxyXG5cdF9hYm9ydExvYWRpbmc6IGZ1bmN0aW9uICgpIHtcclxuXHRcdHZhciBpLCB0aWxlO1xyXG5cdFx0Zm9yIChpIGluIHRoaXMuX3RpbGVzKSB7XHJcblx0XHRcdGlmICh0aGlzLl90aWxlc1tpXS5jb29yZHMueiAhPT0gdGhpcy5fdGlsZVpvb20pIHtcclxuXHRcdFx0XHR0aWxlID0gdGhpcy5fdGlsZXNbaV0uZWw7XHJcblxyXG5cdFx0XHRcdHRpbGUub25sb2FkID0gZmFsc2VGbjtcclxuXHRcdFx0XHR0aWxlLm9uZXJyb3IgPSBmYWxzZUZuO1xyXG5cclxuXHRcdFx0XHRpZiAoIXRpbGUuY29tcGxldGUpIHtcclxuXHRcdFx0XHRcdHRpbGUuc3JjID0gZW1wdHlJbWFnZVVybDtcclxuXHRcdFx0XHRcdHJlbW92ZSh0aWxlKTtcclxuXHRcdFx0XHRcdGRlbGV0ZSB0aGlzLl90aWxlc1tpXTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcbn0pO1xyXG5cclxuXHJcbi8vIEBmYWN0b3J5IEwudGlsZWxheWVyKHVybFRlbXBsYXRlOiBTdHJpbmcsIG9wdGlvbnM/OiBUaWxlTGF5ZXIgb3B0aW9ucylcclxuLy8gSW5zdGFudGlhdGVzIGEgdGlsZSBsYXllciBvYmplY3QgZ2l2ZW4gYSBgVVJMIHRlbXBsYXRlYCBhbmQgb3B0aW9uYWxseSBhbiBvcHRpb25zIG9iamVjdC5cclxuXHJcbmZ1bmN0aW9uIHRpbGVMYXllcih1cmwsIG9wdGlvbnMpIHtcclxuXHRyZXR1cm4gbmV3IFRpbGVMYXllcih1cmwsIG9wdGlvbnMpO1xyXG59XG5cbi8qXHJcbiAqIEBjbGFzcyBUaWxlTGF5ZXIuV01TXHJcbiAqIEBpbmhlcml0cyBUaWxlTGF5ZXJcclxuICogQGFrYSBMLlRpbGVMYXllci5XTVNcclxuICogVXNlZCB0byBkaXNwbGF5IFtXTVNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dlYl9NYXBfU2VydmljZSkgc2VydmljZXMgYXMgdGlsZSBsYXllcnMgb24gdGhlIG1hcC4gRXh0ZW5kcyBgVGlsZUxheWVyYC5cclxuICpcclxuICogQGV4YW1wbGVcclxuICpcclxuICogYGBganNcclxuICogdmFyIG5leHJhZCA9IEwudGlsZUxheWVyLndtcyhcImh0dHA6Ly9tZXNvbmV0LmFncm9uLmlhc3RhdGUuZWR1L2NnaS1iaW4vd21zL25leHJhZC9uMHIuY2dpXCIsIHtcclxuICogXHRsYXllcnM6ICduZXhyYWQtbjByLTkwMDkxMycsXHJcbiAqIFx0Zm9ybWF0OiAnaW1hZ2UvcG5nJyxcclxuICogXHR0cmFuc3BhcmVudDogdHJ1ZSxcclxuICogXHRhdHRyaWJ1dGlvbjogXCJXZWF0aGVyIGRhdGEgwqkgMjAxMiBJRU0gTmV4cmFkXCJcclxuICogfSk7XHJcbiAqIGBgYFxyXG4gKi9cclxuXHJcbnZhciBUaWxlTGF5ZXJXTVMgPSBUaWxlTGF5ZXIuZXh0ZW5kKHtcclxuXHJcblx0Ly8gQHNlY3Rpb25cclxuXHQvLyBAYWthIFRpbGVMYXllci5XTVMgb3B0aW9uc1xyXG5cdC8vIElmIGFueSBjdXN0b20gb3B0aW9ucyBub3QgZG9jdW1lbnRlZCBoZXJlIGFyZSB1c2VkLCB0aGV5IHdpbGwgYmUgc2VudCB0byB0aGVcclxuXHQvLyBXTVMgc2VydmVyIGFzIGV4dHJhIHBhcmFtZXRlcnMgaW4gZWFjaCByZXF1ZXN0IFVSTC4gVGhpcyBjYW4gYmUgdXNlZnVsIGZvclxyXG5cdC8vIFtub24tc3RhbmRhcmQgdmVuZG9yIFdNUyBwYXJhbWV0ZXJzXShodHRwOi8vZG9jcy5nZW9zZXJ2ZXIub3JnL3N0YWJsZS9lbi91c2VyL3NlcnZpY2VzL3dtcy92ZW5kb3IuaHRtbCkuXHJcblx0ZGVmYXVsdFdtc1BhcmFtczoge1xyXG5cdFx0c2VydmljZTogJ1dNUycsXHJcblx0XHRyZXF1ZXN0OiAnR2V0TWFwJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGxheWVyczogU3RyaW5nID0gJydcclxuXHRcdC8vICoqKHJlcXVpcmVkKSoqIENvbW1hLXNlcGFyYXRlZCBsaXN0IG9mIFdNUyBsYXllcnMgdG8gc2hvdy5cclxuXHRcdGxheWVyczogJycsXHJcblxyXG5cdFx0Ly8gQG9wdGlvbiBzdHlsZXM6IFN0cmluZyA9ICcnXHJcblx0XHQvLyBDb21tYS1zZXBhcmF0ZWQgbGlzdCBvZiBXTVMgc3R5bGVzLlxyXG5cdFx0c3R5bGVzOiAnJyxcclxuXHJcblx0XHQvLyBAb3B0aW9uIGZvcm1hdDogU3RyaW5nID0gJ2ltYWdlL2pwZWcnXHJcblx0XHQvLyBXTVMgaW1hZ2UgZm9ybWF0ICh1c2UgYCdpbWFnZS9wbmcnYCBmb3IgbGF5ZXJzIHdpdGggdHJhbnNwYXJlbmN5KS5cclxuXHRcdGZvcm1hdDogJ2ltYWdlL2pwZWcnLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gdHJhbnNwYXJlbnQ6IEJvb2xlYW4gPSBmYWxzZVxyXG5cdFx0Ly8gSWYgYHRydWVgLCB0aGUgV01TIHNlcnZpY2Ugd2lsbCByZXR1cm4gaW1hZ2VzIHdpdGggdHJhbnNwYXJlbmN5LlxyXG5cdFx0dHJhbnNwYXJlbnQ6IGZhbHNlLFxyXG5cclxuXHRcdC8vIEBvcHRpb24gdmVyc2lvbjogU3RyaW5nID0gJzEuMS4xJ1xyXG5cdFx0Ly8gVmVyc2lvbiBvZiB0aGUgV01TIHNlcnZpY2UgdG8gdXNlXHJcblx0XHR2ZXJzaW9uOiAnMS4xLjEnXHJcblx0fSxcclxuXHJcblx0b3B0aW9uczoge1xyXG5cdFx0Ly8gQG9wdGlvbiBjcnM6IENSUyA9IG51bGxcclxuXHRcdC8vIENvb3JkaW5hdGUgUmVmZXJlbmNlIFN5c3RlbSB0byB1c2UgZm9yIHRoZSBXTVMgcmVxdWVzdHMsIGRlZmF1bHRzIHRvXHJcblx0XHQvLyBtYXAgQ1JTLiBEb24ndCBjaGFuZ2UgdGhpcyBpZiB5b3UncmUgbm90IHN1cmUgd2hhdCBpdCBtZWFucy5cclxuXHRcdGNyczogbnVsbCxcclxuXHJcblx0XHQvLyBAb3B0aW9uIHVwcGVyY2FzZTogQm9vbGVhbiA9IGZhbHNlXHJcblx0XHQvLyBJZiBgdHJ1ZWAsIFdNUyByZXF1ZXN0IHBhcmFtZXRlciBrZXlzIHdpbGwgYmUgdXBwZXJjYXNlLlxyXG5cdFx0dXBwZXJjYXNlOiBmYWxzZVxyXG5cdH0sXHJcblxyXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uICh1cmwsIG9wdGlvbnMpIHtcclxuXHJcblx0XHR0aGlzLl91cmwgPSB1cmw7XHJcblxyXG5cdFx0dmFyIHdtc1BhcmFtcyA9IGV4dGVuZCh7fSwgdGhpcy5kZWZhdWx0V21zUGFyYW1zKTtcclxuXHJcblx0XHQvLyBhbGwga2V5cyB0aGF0IGFyZSBub3QgVGlsZUxheWVyIG9wdGlvbnMgZ28gdG8gV01TIHBhcmFtc1xyXG5cdFx0Zm9yICh2YXIgaSBpbiBvcHRpb25zKSB7XHJcblx0XHRcdGlmICghKGkgaW4gdGhpcy5vcHRpb25zKSkge1xyXG5cdFx0XHRcdHdtc1BhcmFtc1tpXSA9IG9wdGlvbnNbaV07XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRvcHRpb25zID0gc2V0T3B0aW9ucyh0aGlzLCBvcHRpb25zKTtcclxuXHJcblx0XHR2YXIgcmVhbFJldGluYSA9IG9wdGlvbnMuZGV0ZWN0UmV0aW5hICYmIHJldGluYSA/IDIgOiAxO1xyXG5cdFx0dmFyIHRpbGVTaXplID0gdGhpcy5nZXRUaWxlU2l6ZSgpO1xyXG5cdFx0d21zUGFyYW1zLndpZHRoID0gdGlsZVNpemUueCAqIHJlYWxSZXRpbmE7XHJcblx0XHR3bXNQYXJhbXMuaGVpZ2h0ID0gdGlsZVNpemUueSAqIHJlYWxSZXRpbmE7XHJcblxyXG5cdFx0dGhpcy53bXNQYXJhbXMgPSB3bXNQYXJhbXM7XHJcblx0fSxcclxuXHJcblx0b25BZGQ6IGZ1bmN0aW9uIChtYXApIHtcclxuXHJcblx0XHR0aGlzLl9jcnMgPSB0aGlzLm9wdGlvbnMuY3JzIHx8IG1hcC5vcHRpb25zLmNycztcclxuXHRcdHRoaXMuX3dtc1ZlcnNpb24gPSBwYXJzZUZsb2F0KHRoaXMud21zUGFyYW1zLnZlcnNpb24pO1xyXG5cclxuXHRcdHZhciBwcm9qZWN0aW9uS2V5ID0gdGhpcy5fd21zVmVyc2lvbiA+PSAxLjMgPyAnY3JzJyA6ICdzcnMnO1xyXG5cdFx0dGhpcy53bXNQYXJhbXNbcHJvamVjdGlvbktleV0gPSB0aGlzLl9jcnMuY29kZTtcclxuXHJcblx0XHRUaWxlTGF5ZXIucHJvdG90eXBlLm9uQWRkLmNhbGwodGhpcywgbWFwKTtcclxuXHR9LFxyXG5cclxuXHRnZXRUaWxlVXJsOiBmdW5jdGlvbiAoY29vcmRzKSB7XHJcblxyXG5cdFx0dmFyIHRpbGVCb3VuZHMgPSB0aGlzLl90aWxlQ29vcmRzVG9Od1NlKGNvb3JkcyksXHJcblx0XHQgICAgY3JzID0gdGhpcy5fY3JzLFxyXG5cdFx0ICAgIGJvdW5kcyA9IHRvQm91bmRzKGNycy5wcm9qZWN0KHRpbGVCb3VuZHNbMF0pLCBjcnMucHJvamVjdCh0aWxlQm91bmRzWzFdKSksXHJcblx0XHQgICAgbWluID0gYm91bmRzLm1pbixcclxuXHRcdCAgICBtYXggPSBib3VuZHMubWF4LFxyXG5cdFx0ICAgIGJib3ggPSAodGhpcy5fd21zVmVyc2lvbiA+PSAxLjMgJiYgdGhpcy5fY3JzID09PSBFUFNHNDMyNiA/XHJcblx0XHQgICAgW21pbi55LCBtaW4ueCwgbWF4LnksIG1heC54XSA6XHJcblx0XHQgICAgW21pbi54LCBtaW4ueSwgbWF4LngsIG1heC55XSkuam9pbignLCcpLFxyXG5cdFx0dXJsID0gTC5UaWxlTGF5ZXIucHJvdG90eXBlLmdldFRpbGVVcmwuY2FsbCh0aGlzLCBjb29yZHMpO1xyXG5cdFx0cmV0dXJuIHVybCArXHJcblx0XHRcdGdldFBhcmFtU3RyaW5nKHRoaXMud21zUGFyYW1zLCB1cmwsIHRoaXMub3B0aW9ucy51cHBlcmNhc2UpICtcclxuXHRcdFx0KHRoaXMub3B0aW9ucy51cHBlcmNhc2UgPyAnJkJCT1g9JyA6ICcmYmJveD0nKSArIGJib3g7XHJcblx0fSxcclxuXHJcblx0Ly8gQG1ldGhvZCBzZXRQYXJhbXMocGFyYW1zOiBPYmplY3QsIG5vUmVkcmF3PzogQm9vbGVhbik6IHRoaXNcclxuXHQvLyBNZXJnZXMgYW4gb2JqZWN0IHdpdGggdGhlIG5ldyBwYXJhbWV0ZXJzIGFuZCByZS1yZXF1ZXN0cyB0aWxlcyBvbiB0aGUgY3VycmVudCBzY3JlZW4gKHVubGVzcyBgbm9SZWRyYXdgIHdhcyBzZXQgdG8gdHJ1ZSkuXHJcblx0c2V0UGFyYW1zOiBmdW5jdGlvbiAocGFyYW1zLCBub1JlZHJhdykge1xyXG5cclxuXHRcdGV4dGVuZCh0aGlzLndtc1BhcmFtcywgcGFyYW1zKTtcclxuXHJcblx0XHRpZiAoIW5vUmVkcmF3KSB7XHJcblx0XHRcdHRoaXMucmVkcmF3KCk7XHJcblx0XHR9XHJcblxyXG5cdFx0cmV0dXJuIHRoaXM7XHJcblx0fVxyXG59KTtcclxuXHJcblxyXG4vLyBAZmFjdG9yeSBMLnRpbGVMYXllci53bXMoYmFzZVVybDogU3RyaW5nLCBvcHRpb25zOiBUaWxlTGF5ZXIuV01TIG9wdGlvbnMpXHJcbi8vIEluc3RhbnRpYXRlcyBhIFdNUyB0aWxlIGxheWVyIG9iamVjdCBnaXZlbiBhIGJhc2UgVVJMIG9mIHRoZSBXTVMgc2VydmljZSBhbmQgYSBXTVMgcGFyYW1ldGVycy9vcHRpb25zIG9iamVjdC5cclxuZnVuY3Rpb24gdGlsZUxheWVyV01TKHVybCwgb3B0aW9ucykge1xyXG5cdHJldHVybiBuZXcgVGlsZUxheWVyV01TKHVybCwgb3B0aW9ucyk7XHJcbn1cblxuVGlsZUxheWVyLldNUyA9IFRpbGVMYXllcldNUztcbnRpbGVMYXllci53bXMgPSB0aWxlTGF5ZXJXTVM7XG5cbi8qXG4gKiBAY2xhc3MgUmVuZGVyZXJcbiAqIEBpbmhlcml0cyBMYXllclxuICogQGFrYSBMLlJlbmRlcmVyXG4gKlxuICogQmFzZSBjbGFzcyBmb3IgdmVjdG9yIHJlbmRlcmVyIGltcGxlbWVudGF0aW9ucyAoYFNWR2AsIGBDYW52YXNgKS4gSGFuZGxlcyB0aGVcbiAqIERPTSBjb250YWluZXIgb2YgdGhlIHJlbmRlcmVyLCBpdHMgYm91bmRzLCBhbmQgaXRzIHpvb20gYW5pbWF0aW9uLlxuICpcbiAqIEEgYFJlbmRlcmVyYCB3b3JrcyBhcyBhbiBpbXBsaWNpdCBsYXllciBncm91cCBmb3IgYWxsIGBQYXRoYHMgLSB0aGUgcmVuZGVyZXJcbiAqIGl0c2VsZiBjYW4gYmUgYWRkZWQgb3IgcmVtb3ZlZCB0byB0aGUgbWFwLiBBbGwgcGF0aHMgdXNlIGEgcmVuZGVyZXIsIHdoaWNoIGNhblxuICogYmUgaW1wbGljaXQgKHRoZSBtYXAgd2lsbCBkZWNpZGUgdGhlIHR5cGUgb2YgcmVuZGVyZXIgYW5kIHVzZSBpdCBhdXRvbWF0aWNhbGx5KVxuICogb3IgZXhwbGljaXQgKHVzaW5nIHRoZSBbYHJlbmRlcmVyYF0oI3BhdGgtcmVuZGVyZXIpIG9wdGlvbiBvZiB0aGUgcGF0aCkuXG4gKlxuICogRG8gbm90IHVzZSB0aGlzIGNsYXNzIGRpcmVjdGx5LCB1c2UgYFNWR2AgYW5kIGBDYW52YXNgIGluc3RlYWQuXG4gKlxuICogQGV2ZW50IHVwZGF0ZTogRXZlbnRcbiAqIEZpcmVkIHdoZW4gdGhlIHJlbmRlcmVyIHVwZGF0ZXMgaXRzIGJvdW5kcywgY2VudGVyIGFuZCB6b29tLCBmb3IgZXhhbXBsZSB3aGVuXG4gKiBpdHMgbWFwIGhhcyBtb3ZlZFxuICovXG5cbnZhciBSZW5kZXJlciA9IExheWVyLmV4dGVuZCh7XG5cblx0Ly8gQHNlY3Rpb25cblx0Ly8gQGFrYSBSZW5kZXJlciBvcHRpb25zXG5cdG9wdGlvbnM6IHtcblx0XHQvLyBAb3B0aW9uIHBhZGRpbmc6IE51bWJlciA9IDAuMVxuXHRcdC8vIEhvdyBtdWNoIHRvIGV4dGVuZCB0aGUgY2xpcCBhcmVhIGFyb3VuZCB0aGUgbWFwIHZpZXcgKHJlbGF0aXZlIHRvIGl0cyBzaXplKVxuXHRcdC8vIGUuZy4gMC4xIHdvdWxkIGJlIDEwJSBvZiBtYXAgdmlldyBpbiBlYWNoIGRpcmVjdGlvblxuXHRcdHBhZGRpbmc6IDAuMSxcblxuXHRcdC8vIEBvcHRpb24gdG9sZXJhbmNlOiBOdW1iZXIgPSAwXG5cdFx0Ly8gSG93IG11Y2ggdG8gZXh0ZW5kIGNsaWNrIHRvbGVyYW5jZSByb3VuZCBhIHBhdGgvb2JqZWN0IG9uIHRoZSBtYXBcblx0XHR0b2xlcmFuY2UgOiAwXG5cdH0sXG5cblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcblx0XHRzZXRPcHRpb25zKHRoaXMsIG9wdGlvbnMpO1xuXHRcdHN0YW1wKHRoaXMpO1xuXHRcdHRoaXMuX2xheWVycyA9IHRoaXMuX2xheWVycyB8fCB7fTtcblx0fSxcblxuXHRvbkFkZDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICghdGhpcy5fY29udGFpbmVyKSB7XG5cdFx0XHR0aGlzLl9pbml0Q29udGFpbmVyKCk7IC8vIGRlZmluZWQgYnkgcmVuZGVyZXIgaW1wbGVtZW50YXRpb25zXG5cblx0XHRcdGlmICh0aGlzLl96b29tQW5pbWF0ZWQpIHtcblx0XHRcdFx0YWRkQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC16b29tLWFuaW1hdGVkJyk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5nZXRQYW5lKCkuYXBwZW5kQ2hpbGQodGhpcy5fY29udGFpbmVyKTtcblx0XHR0aGlzLl91cGRhdGUoKTtcblx0XHR0aGlzLm9uKCd1cGRhdGUnLCB0aGlzLl91cGRhdGVQYXRocywgdGhpcyk7XG5cdH0sXG5cblx0b25SZW1vdmU6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLm9mZigndXBkYXRlJywgdGhpcy5fdXBkYXRlUGF0aHMsIHRoaXMpO1xuXHRcdHRoaXMuX2Rlc3Ryb3lDb250YWluZXIoKTtcblx0fSxcblxuXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgZXZlbnRzID0ge1xuXHRcdFx0dmlld3Jlc2V0OiB0aGlzLl9yZXNldCxcblx0XHRcdHpvb206IHRoaXMuX29uWm9vbSxcblx0XHRcdG1vdmVlbmQ6IHRoaXMuX3VwZGF0ZSxcblx0XHRcdHpvb21lbmQ6IHRoaXMuX29uWm9vbUVuZFxuXHRcdH07XG5cdFx0aWYgKHRoaXMuX3pvb21BbmltYXRlZCkge1xuXHRcdFx0ZXZlbnRzLnpvb21hbmltID0gdGhpcy5fb25BbmltWm9vbTtcblx0XHR9XG5cdFx0cmV0dXJuIGV2ZW50cztcblx0fSxcblxuXHRfb25BbmltWm9vbTogZnVuY3Rpb24gKGV2KSB7XG5cdFx0dGhpcy5fdXBkYXRlVHJhbnNmb3JtKGV2LmNlbnRlciwgZXYuem9vbSk7XG5cdH0sXG5cblx0X29uWm9vbTogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3VwZGF0ZVRyYW5zZm9ybSh0aGlzLl9tYXAuZ2V0Q2VudGVyKCksIHRoaXMuX21hcC5nZXRab29tKCkpO1xuXHR9LFxuXG5cdF91cGRhdGVUcmFuc2Zvcm06IGZ1bmN0aW9uIChjZW50ZXIsIHpvb20pIHtcblx0XHR2YXIgc2NhbGUgPSB0aGlzLl9tYXAuZ2V0Wm9vbVNjYWxlKHpvb20sIHRoaXMuX3pvb20pLFxuXHRcdCAgICBwb3NpdGlvbiA9IGdldFBvc2l0aW9uKHRoaXMuX2NvbnRhaW5lciksXG5cdFx0ICAgIHZpZXdIYWxmID0gdGhpcy5fbWFwLmdldFNpemUoKS5tdWx0aXBseUJ5KDAuNSArIHRoaXMub3B0aW9ucy5wYWRkaW5nKSxcblx0XHQgICAgY3VycmVudENlbnRlclBvaW50ID0gdGhpcy5fbWFwLnByb2plY3QodGhpcy5fY2VudGVyLCB6b29tKSxcblx0XHQgICAgZGVzdENlbnRlclBvaW50ID0gdGhpcy5fbWFwLnByb2plY3QoY2VudGVyLCB6b29tKSxcblx0XHQgICAgY2VudGVyT2Zmc2V0ID0gZGVzdENlbnRlclBvaW50LnN1YnRyYWN0KGN1cnJlbnRDZW50ZXJQb2ludCksXG5cblx0XHQgICAgdG9wTGVmdE9mZnNldCA9IHZpZXdIYWxmLm11bHRpcGx5QnkoLXNjYWxlKS5hZGQocG9zaXRpb24pLmFkZCh2aWV3SGFsZikuc3VidHJhY3QoY2VudGVyT2Zmc2V0KTtcblxuXHRcdGlmIChhbnkzZCkge1xuXHRcdFx0c2V0VHJhbnNmb3JtKHRoaXMuX2NvbnRhaW5lciwgdG9wTGVmdE9mZnNldCwgc2NhbGUpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzZXRQb3NpdGlvbih0aGlzLl9jb250YWluZXIsIHRvcExlZnRPZmZzZXQpO1xuXHRcdH1cblx0fSxcblxuXHRfcmVzZXQ6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl91cGRhdGUoKTtcblx0XHR0aGlzLl91cGRhdGVUcmFuc2Zvcm0odGhpcy5fY2VudGVyLCB0aGlzLl96b29tKTtcblxuXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuXHRcdFx0dGhpcy5fbGF5ZXJzW2lkXS5fcmVzZXQoKTtcblx0XHR9XG5cdH0sXG5cblx0X29uWm9vbUVuZDogZnVuY3Rpb24gKCkge1xuXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuXHRcdFx0dGhpcy5fbGF5ZXJzW2lkXS5fcHJvamVjdCgpO1xuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlUGF0aHM6IGZ1bmN0aW9uICgpIHtcblx0XHRmb3IgKHZhciBpZCBpbiB0aGlzLl9sYXllcnMpIHtcblx0XHRcdHRoaXMuX2xheWVyc1tpZF0uX3VwZGF0ZSgpO1xuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0Ly8gVXBkYXRlIHBpeGVsIGJvdW5kcyBvZiByZW5kZXJlciBjb250YWluZXIgKGZvciBwb3NpdGlvbmluZy9zaXppbmcvY2xpcHBpbmcgbGF0ZXIpXG5cdFx0Ly8gU3ViY2xhc3NlcyBhcmUgcmVzcG9uc2libGUgb2YgZmlyaW5nIHRoZSAndXBkYXRlJyBldmVudC5cblx0XHR2YXIgcCA9IHRoaXMub3B0aW9ucy5wYWRkaW5nLFxuXHRcdCAgICBzaXplID0gdGhpcy5fbWFwLmdldFNpemUoKSxcblx0XHQgICAgbWluID0gdGhpcy5fbWFwLmNvbnRhaW5lclBvaW50VG9MYXllclBvaW50KHNpemUubXVsdGlwbHlCeSgtcCkpLnJvdW5kKCk7XG5cblx0XHR0aGlzLl9ib3VuZHMgPSBuZXcgQm91bmRzKG1pbiwgbWluLmFkZChzaXplLm11bHRpcGx5QnkoMSArIHAgKiAyKSkucm91bmQoKSk7XG5cblx0XHR0aGlzLl9jZW50ZXIgPSB0aGlzLl9tYXAuZ2V0Q2VudGVyKCk7XG5cdFx0dGhpcy5fem9vbSA9IHRoaXMuX21hcC5nZXRab29tKCk7XG5cdH1cbn0pO1xuXG4vKlxuICogQGNsYXNzIENhbnZhc1xuICogQGluaGVyaXRzIFJlbmRlcmVyXG4gKiBAYWthIEwuQ2FudmFzXG4gKlxuICogQWxsb3dzIHZlY3RvciBsYXllcnMgdG8gYmUgZGlzcGxheWVkIHdpdGggW2A8Y2FudmFzPmBdKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0FQSS9DYW52YXNfQVBJKS5cbiAqIEluaGVyaXRzIGBSZW5kZXJlcmAuXG4gKlxuICogRHVlIHRvIFt0ZWNobmljYWwgbGltaXRhdGlvbnNdKGh0dHA6Ly9jYW5pdXNlLmNvbS8jc2VhcmNoPWNhbnZhcyksIENhbnZhcyBpcyBub3RcbiAqIGF2YWlsYWJsZSBpbiBhbGwgd2ViIGJyb3dzZXJzLCBub3RhYmx5IElFOCwgYW5kIG92ZXJsYXBwaW5nIGdlb21ldHJpZXMgbWlnaHRcbiAqIG5vdCBkaXNwbGF5IHByb3Blcmx5IGluIHNvbWUgZWRnZSBjYXNlcy5cbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIFVzZSBDYW52YXMgYnkgZGVmYXVsdCBmb3IgYWxsIHBhdGhzIGluIHRoZSBtYXA6XG4gKlxuICogYGBganNcbiAqIHZhciBtYXAgPSBMLm1hcCgnbWFwJywge1xuICogXHRyZW5kZXJlcjogTC5jYW52YXMoKVxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBVc2UgYSBDYW52YXMgcmVuZGVyZXIgd2l0aCBleHRyYSBwYWRkaW5nIGZvciBzcGVjaWZpYyB2ZWN0b3IgZ2VvbWV0cmllczpcbiAqXG4gKiBgYGBqc1xuICogdmFyIG1hcCA9IEwubWFwKCdtYXAnKTtcbiAqIHZhciBteVJlbmRlcmVyID0gTC5jYW52YXMoeyBwYWRkaW5nOiAwLjUgfSk7XG4gKiB2YXIgbGluZSA9IEwucG9seWxpbmUoIGNvb3JkaW5hdGVzLCB7IHJlbmRlcmVyOiBteVJlbmRlcmVyIH0gKTtcbiAqIHZhciBjaXJjbGUgPSBMLmNpcmNsZSggY2VudGVyLCB7IHJlbmRlcmVyOiBteVJlbmRlcmVyIH0gKTtcbiAqIGBgYFxuICovXG5cbnZhciBDYW52YXMgPSBSZW5kZXJlci5leHRlbmQoe1xuXHRnZXRFdmVudHM6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgZXZlbnRzID0gUmVuZGVyZXIucHJvdG90eXBlLmdldEV2ZW50cy5jYWxsKHRoaXMpO1xuXHRcdGV2ZW50cy52aWV3cHJlcmVzZXQgPSB0aGlzLl9vblZpZXdQcmVSZXNldDtcblx0XHRyZXR1cm4gZXZlbnRzO1xuXHR9LFxuXG5cdF9vblZpZXdQcmVSZXNldDogZnVuY3Rpb24gKCkge1xuXHRcdC8vIFNldCBhIGZsYWcgc28gdGhhdCBhIHZpZXdwcmVyZXNldCttb3ZlZW5kK3ZpZXdyZXNldCBvbmx5IHVwZGF0ZXMmcmVkcmF3cyBvbmNlXG5cdFx0dGhpcy5fcG9zdHBvbmVVcGRhdGVQYXRocyA9IHRydWU7XG5cdH0sXG5cblx0b25BZGQ6IGZ1bmN0aW9uICgpIHtcblx0XHRSZW5kZXJlci5wcm90b3R5cGUub25BZGQuY2FsbCh0aGlzKTtcblxuXHRcdC8vIFJlZHJhdyB2ZWN0b3JzIHNpbmNlIGNhbnZhcyBpcyBjbGVhcmVkIHVwb24gcmVtb3ZhbCxcblx0XHQvLyBpbiBjYXNlIG9mIHJlbW92aW5nIHRoZSByZW5kZXJlciBpdHNlbGYgZnJvbSB0aGUgbWFwLlxuXHRcdHRoaXMuX2RyYXcoKTtcblx0fSxcblxuXHRfaW5pdENvbnRhaW5lcjogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcblxuXHRcdG9uKGNvbnRhaW5lciwgJ21vdXNlbW92ZScsIHRocm90dGxlKHRoaXMuX29uTW91c2VNb3ZlLCAzMiwgdGhpcyksIHRoaXMpO1xuXHRcdG9uKGNvbnRhaW5lciwgJ2NsaWNrIGRibGNsaWNrIG1vdXNlZG93biBtb3VzZXVwIGNvbnRleHRtZW51JywgdGhpcy5fb25DbGljaywgdGhpcyk7XG5cdFx0b24oY29udGFpbmVyLCAnbW91c2VvdXQnLCB0aGlzLl9oYW5kbGVNb3VzZU91dCwgdGhpcyk7XG5cblx0XHR0aGlzLl9jdHggPSBjb250YWluZXIuZ2V0Q29udGV4dCgnMmQnKTtcblx0fSxcblxuXHRfZGVzdHJveUNvbnRhaW5lcjogZnVuY3Rpb24gKCkge1xuXHRcdGRlbGV0ZSB0aGlzLl9jdHg7XG5cdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XG5cdFx0b2ZmKHRoaXMuX2NvbnRhaW5lcik7XG5cdFx0ZGVsZXRlIHRoaXMuX2NvbnRhaW5lcjtcblx0fSxcblxuXHRfdXBkYXRlUGF0aHM6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAodGhpcy5fcG9zdHBvbmVVcGRhdGVQYXRocykgeyByZXR1cm47IH1cblxuXHRcdHZhciBsYXllcjtcblx0XHR0aGlzLl9yZWRyYXdCb3VuZHMgPSBudWxsO1xuXHRcdGZvciAodmFyIGlkIGluIHRoaXMuX2xheWVycykge1xuXHRcdFx0bGF5ZXIgPSB0aGlzLl9sYXllcnNbaWRdO1xuXHRcdFx0bGF5ZXIuX3VwZGF0ZSgpO1xuXHRcdH1cblx0XHR0aGlzLl9yZWRyYXcoKTtcblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSAmJiB0aGlzLl9ib3VuZHMpIHsgcmV0dXJuOyB9XG5cblx0XHR0aGlzLl9kcmF3bkxheWVycyA9IHt9O1xuXG5cdFx0UmVuZGVyZXIucHJvdG90eXBlLl91cGRhdGUuY2FsbCh0aGlzKTtcblxuXHRcdHZhciBiID0gdGhpcy5fYm91bmRzLFxuXHRcdCAgICBjb250YWluZXIgPSB0aGlzLl9jb250YWluZXIsXG5cdFx0ICAgIHNpemUgPSBiLmdldFNpemUoKSxcblx0XHQgICAgbSA9IHJldGluYSA/IDIgOiAxO1xuXG5cdFx0c2V0UG9zaXRpb24oY29udGFpbmVyLCBiLm1pbik7XG5cblx0XHQvLyBzZXQgY2FudmFzIHNpemUgKGFsc28gY2xlYXJpbmcgaXQpOyB1c2UgZG91YmxlIHNpemUgb24gcmV0aW5hXG5cdFx0Y29udGFpbmVyLndpZHRoID0gbSAqIHNpemUueDtcblx0XHRjb250YWluZXIuaGVpZ2h0ID0gbSAqIHNpemUueTtcblx0XHRjb250YWluZXIuc3R5bGUud2lkdGggPSBzaXplLnggKyAncHgnO1xuXHRcdGNvbnRhaW5lci5zdHlsZS5oZWlnaHQgPSBzaXplLnkgKyAncHgnO1xuXG5cdFx0aWYgKHJldGluYSkge1xuXHRcdFx0dGhpcy5fY3R4LnNjYWxlKDIsIDIpO1xuXHRcdH1cblxuXHRcdC8vIHRyYW5zbGF0ZSBzbyB3ZSB1c2UgdGhlIHNhbWUgcGF0aCBjb29yZGluYXRlcyBhZnRlciBjYW52YXMgZWxlbWVudCBtb3Zlc1xuXHRcdHRoaXMuX2N0eC50cmFuc2xhdGUoLWIubWluLngsIC1iLm1pbi55KTtcblxuXHRcdC8vIFRlbGwgcGF0aHMgdG8gcmVkcmF3IHRoZW1zZWx2ZXNcblx0XHR0aGlzLmZpcmUoJ3VwZGF0ZScpO1xuXHR9LFxuXG5cdF9yZXNldDogZnVuY3Rpb24gKCkge1xuXHRcdFJlbmRlcmVyLnByb3RvdHlwZS5fcmVzZXQuY2FsbCh0aGlzKTtcblxuXHRcdGlmICh0aGlzLl9wb3N0cG9uZVVwZGF0ZVBhdGhzKSB7XG5cdFx0XHR0aGlzLl9wb3N0cG9uZVVwZGF0ZVBhdGhzID0gZmFsc2U7XG5cdFx0XHR0aGlzLl91cGRhdGVQYXRocygpO1xuXHRcdH1cblx0fSxcblxuXHRfaW5pdFBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHRoaXMuX3VwZGF0ZURhc2hBcnJheShsYXllcik7XG5cdFx0dGhpcy5fbGF5ZXJzW3N0YW1wKGxheWVyKV0gPSBsYXllcjtcblxuXHRcdHZhciBvcmRlciA9IGxheWVyLl9vcmRlciA9IHtcblx0XHRcdGxheWVyOiBsYXllcixcblx0XHRcdHByZXY6IHRoaXMuX2RyYXdMYXN0LFxuXHRcdFx0bmV4dDogbnVsbFxuXHRcdH07XG5cdFx0aWYgKHRoaXMuX2RyYXdMYXN0KSB7IHRoaXMuX2RyYXdMYXN0Lm5leHQgPSBvcmRlcjsgfVxuXHRcdHRoaXMuX2RyYXdMYXN0ID0gb3JkZXI7XG5cdFx0dGhpcy5fZHJhd0ZpcnN0ID0gdGhpcy5fZHJhd0ZpcnN0IHx8IHRoaXMuX2RyYXdMYXN0O1xuXHR9LFxuXG5cdF9hZGRQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcblx0fSxcblxuXHRfcmVtb3ZlUGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dmFyIG9yZGVyID0gbGF5ZXIuX29yZGVyO1xuXHRcdHZhciBuZXh0ID0gb3JkZXIubmV4dDtcblx0XHR2YXIgcHJldiA9IG9yZGVyLnByZXY7XG5cblx0XHRpZiAobmV4dCkge1xuXHRcdFx0bmV4dC5wcmV2ID0gcHJldjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5fZHJhd0xhc3QgPSBwcmV2O1xuXHRcdH1cblx0XHRpZiAocHJldikge1xuXHRcdFx0cHJldi5uZXh0ID0gbmV4dDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5fZHJhd0ZpcnN0ID0gbmV4dDtcblx0XHR9XG5cblx0XHRkZWxldGUgbGF5ZXIuX29yZGVyO1xuXG5cdFx0ZGVsZXRlIHRoaXMuX2xheWVyc1tMLnN0YW1wKGxheWVyKV07XG5cblx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcblx0fSxcblxuXHRfdXBkYXRlUGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0Ly8gUmVkcmF3IHRoZSB1bmlvbiBvZiB0aGUgbGF5ZXIncyBvbGQgcGl4ZWxcblx0XHQvLyBib3VuZHMgYW5kIHRoZSBuZXcgcGl4ZWwgYm91bmRzLlxuXHRcdHRoaXMuX2V4dGVuZFJlZHJhd0JvdW5kcyhsYXllcik7XG5cdFx0bGF5ZXIuX3Byb2plY3QoKTtcblx0XHRsYXllci5fdXBkYXRlKCk7XG5cdFx0Ly8gVGhlIHJlZHJhdyB3aWxsIGV4dGVuZCB0aGUgcmVkcmF3IGJvdW5kc1xuXHRcdC8vIHdpdGggdGhlIG5ldyBwaXhlbCBib3VuZHMuXG5cdFx0dGhpcy5fcmVxdWVzdFJlZHJhdyhsYXllcik7XG5cdH0sXG5cblx0X3VwZGF0ZVN0eWxlOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR0aGlzLl91cGRhdGVEYXNoQXJyYXkobGF5ZXIpO1xuXHRcdHRoaXMuX3JlcXVlc3RSZWRyYXcobGF5ZXIpO1xuXHR9LFxuXG5cdF91cGRhdGVEYXNoQXJyYXk6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdGlmIChsYXllci5vcHRpb25zLmRhc2hBcnJheSkge1xuXHRcdFx0dmFyIHBhcnRzID0gbGF5ZXIub3B0aW9ucy5kYXNoQXJyYXkuc3BsaXQoJywnKSxcblx0XHRcdCAgICBkYXNoQXJyYXkgPSBbXSxcblx0XHRcdCAgICBpO1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IHBhcnRzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGRhc2hBcnJheS5wdXNoKE51bWJlcihwYXJ0c1tpXSkpO1xuXHRcdFx0fVxuXHRcdFx0bGF5ZXIub3B0aW9ucy5fZGFzaEFycmF5ID0gZGFzaEFycmF5O1xuXHRcdH1cblx0fSxcblxuXHRfcmVxdWVzdFJlZHJhdzogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0aWYgKCF0aGlzLl9tYXApIHsgcmV0dXJuOyB9XG5cblx0XHR0aGlzLl9leHRlbmRSZWRyYXdCb3VuZHMobGF5ZXIpO1xuXHRcdHRoaXMuX3JlZHJhd1JlcXVlc3QgPSB0aGlzLl9yZWRyYXdSZXF1ZXN0IHx8IHJlcXVlc3RBbmltRnJhbWUodGhpcy5fcmVkcmF3LCB0aGlzKTtcblx0fSxcblxuXHRfZXh0ZW5kUmVkcmF3Qm91bmRzOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHRpZiAobGF5ZXIuX3B4Qm91bmRzKSB7XG5cdFx0XHR2YXIgcGFkZGluZyA9IChsYXllci5vcHRpb25zLndlaWdodCB8fCAwKSArIDE7XG5cdFx0XHR0aGlzLl9yZWRyYXdCb3VuZHMgPSB0aGlzLl9yZWRyYXdCb3VuZHMgfHwgbmV3IEJvdW5kcygpO1xuXHRcdFx0dGhpcy5fcmVkcmF3Qm91bmRzLmV4dGVuZChsYXllci5fcHhCb3VuZHMubWluLnN1YnRyYWN0KFtwYWRkaW5nLCBwYWRkaW5nXSkpO1xuXHRcdFx0dGhpcy5fcmVkcmF3Qm91bmRzLmV4dGVuZChsYXllci5fcHhCb3VuZHMubWF4LmFkZChbcGFkZGluZywgcGFkZGluZ10pKTtcblx0XHR9XG5cdH0sXG5cblx0X3JlZHJhdzogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3JlZHJhd1JlcXVlc3QgPSBudWxsO1xuXG5cdFx0aWYgKHRoaXMuX3JlZHJhd0JvdW5kcykge1xuXHRcdFx0dGhpcy5fcmVkcmF3Qm91bmRzLm1pbi5fZmxvb3IoKTtcblx0XHRcdHRoaXMuX3JlZHJhd0JvdW5kcy5tYXguX2NlaWwoKTtcblx0XHR9XG5cblx0XHR0aGlzLl9jbGVhcigpOyAvLyBjbGVhciBsYXllcnMgaW4gcmVkcmF3IGJvdW5kc1xuXHRcdHRoaXMuX2RyYXcoKTsgLy8gZHJhdyBsYXllcnNcblxuXHRcdHRoaXMuX3JlZHJhd0JvdW5kcyA9IG51bGw7XG5cdH0sXG5cblx0X2NsZWFyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGJvdW5kcyA9IHRoaXMuX3JlZHJhd0JvdW5kcztcblx0XHRpZiAoYm91bmRzKSB7XG5cdFx0XHR2YXIgc2l6ZSA9IGJvdW5kcy5nZXRTaXplKCk7XG5cdFx0XHR0aGlzLl9jdHguY2xlYXJSZWN0KGJvdW5kcy5taW4ueCwgYm91bmRzLm1pbi55LCBzaXplLngsIHNpemUueSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX2N0eC5jbGVhclJlY3QoMCwgMCwgdGhpcy5fY29udGFpbmVyLndpZHRoLCB0aGlzLl9jb250YWluZXIuaGVpZ2h0KTtcblx0XHR9XG5cdH0sXG5cblx0X2RyYXc6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbGF5ZXIsIGJvdW5kcyA9IHRoaXMuX3JlZHJhd0JvdW5kcztcblx0XHR0aGlzLl9jdHguc2F2ZSgpO1xuXHRcdGlmIChib3VuZHMpIHtcblx0XHRcdHZhciBzaXplID0gYm91bmRzLmdldFNpemUoKTtcblx0XHRcdHRoaXMuX2N0eC5iZWdpblBhdGgoKTtcblx0XHRcdHRoaXMuX2N0eC5yZWN0KGJvdW5kcy5taW4ueCwgYm91bmRzLm1pbi55LCBzaXplLngsIHNpemUueSk7XG5cdFx0XHR0aGlzLl9jdHguY2xpcCgpO1xuXHRcdH1cblxuXHRcdHRoaXMuX2RyYXdpbmcgPSB0cnVlO1xuXG5cdFx0Zm9yICh2YXIgb3JkZXIgPSB0aGlzLl9kcmF3Rmlyc3Q7IG9yZGVyOyBvcmRlciA9IG9yZGVyLm5leHQpIHtcblx0XHRcdGxheWVyID0gb3JkZXIubGF5ZXI7XG5cdFx0XHRpZiAoIWJvdW5kcyB8fCAobGF5ZXIuX3B4Qm91bmRzICYmIGxheWVyLl9weEJvdW5kcy5pbnRlcnNlY3RzKGJvdW5kcykpKSB7XG5cdFx0XHRcdGxheWVyLl91cGRhdGVQYXRoKCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5fZHJhd2luZyA9IGZhbHNlO1xuXG5cdFx0dGhpcy5fY3R4LnJlc3RvcmUoKTsgIC8vIFJlc3RvcmUgc3RhdGUgYmVmb3JlIGNsaXBwaW5nLlxuXHR9LFxuXG5cdF91cGRhdGVQb2x5OiBmdW5jdGlvbiAobGF5ZXIsIGNsb3NlZCkge1xuXHRcdGlmICghdGhpcy5fZHJhd2luZykgeyByZXR1cm47IH1cblxuXHRcdHZhciBpLCBqLCBsZW4yLCBwLFxuXHRcdCAgICBwYXJ0cyA9IGxheWVyLl9wYXJ0cyxcblx0XHQgICAgbGVuID0gcGFydHMubGVuZ3RoLFxuXHRcdCAgICBjdHggPSB0aGlzLl9jdHg7XG5cblx0XHRpZiAoIWxlbikgeyByZXR1cm47IH1cblxuXHRcdHRoaXMuX2RyYXduTGF5ZXJzW2xheWVyLl9sZWFmbGV0X2lkXSA9IGxheWVyO1xuXG5cdFx0Y3R4LmJlZ2luUGF0aCgpO1xuXG5cdFx0Zm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRmb3IgKGogPSAwLCBsZW4yID0gcGFydHNbaV0ubGVuZ3RoOyBqIDwgbGVuMjsgaisrKSB7XG5cdFx0XHRcdHAgPSBwYXJ0c1tpXVtqXTtcblx0XHRcdFx0Y3R4W2ogPyAnbGluZVRvJyA6ICdtb3ZlVG8nXShwLngsIHAueSk7XG5cdFx0XHR9XG5cdFx0XHRpZiAoY2xvc2VkKSB7XG5cdFx0XHRcdGN0eC5jbG9zZVBhdGgoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLl9maWxsU3Ryb2tlKGN0eCwgbGF5ZXIpO1xuXG5cdFx0Ly8gVE9ETyBvcHRpbWl6YXRpb246IDEgZmlsbC9zdHJva2UgZm9yIGFsbCBmZWF0dXJlcyB3aXRoIGVxdWFsIHN0eWxlIGluc3RlYWQgb2YgMSBmb3IgZWFjaCBmZWF0dXJlXG5cdH0sXG5cblx0X3VwZGF0ZUNpcmNsZTogZnVuY3Rpb24gKGxheWVyKSB7XG5cblx0XHRpZiAoIXRoaXMuX2RyYXdpbmcgfHwgbGF5ZXIuX2VtcHR5KCkpIHsgcmV0dXJuOyB9XG5cblx0XHR2YXIgcCA9IGxheWVyLl9wb2ludCxcblx0XHQgICAgY3R4ID0gdGhpcy5fY3R4LFxuXHRcdCAgICByID0gTWF0aC5tYXgoTWF0aC5yb3VuZChsYXllci5fcmFkaXVzKSwgMSksXG5cdFx0ICAgIHMgPSAoTWF0aC5tYXgoTWF0aC5yb3VuZChsYXllci5fcmFkaXVzWSksIDEpIHx8IHIpIC8gcjtcblxuXHRcdHRoaXMuX2RyYXduTGF5ZXJzW2xheWVyLl9sZWFmbGV0X2lkXSA9IGxheWVyO1xuXG5cdFx0aWYgKHMgIT09IDEpIHtcblx0XHRcdGN0eC5zYXZlKCk7XG5cdFx0XHRjdHguc2NhbGUoMSwgcyk7XG5cdFx0fVxuXG5cdFx0Y3R4LmJlZ2luUGF0aCgpO1xuXHRcdGN0eC5hcmMocC54LCBwLnkgLyBzLCByLCAwLCBNYXRoLlBJICogMiwgZmFsc2UpO1xuXG5cdFx0aWYgKHMgIT09IDEpIHtcblx0XHRcdGN0eC5yZXN0b3JlKCk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fZmlsbFN0cm9rZShjdHgsIGxheWVyKTtcblx0fSxcblxuXHRfZmlsbFN0cm9rZTogZnVuY3Rpb24gKGN0eCwgbGF5ZXIpIHtcblx0XHR2YXIgb3B0aW9ucyA9IGxheWVyLm9wdGlvbnM7XG5cblx0XHRpZiAob3B0aW9ucy5maWxsKSB7XG5cdFx0XHRjdHguZ2xvYmFsQWxwaGEgPSBvcHRpb25zLmZpbGxPcGFjaXR5O1xuXHRcdFx0Y3R4LmZpbGxTdHlsZSA9IG9wdGlvbnMuZmlsbENvbG9yIHx8IG9wdGlvbnMuY29sb3I7XG5cdFx0XHRjdHguZmlsbChvcHRpb25zLmZpbGxSdWxlIHx8ICdldmVub2RkJyk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMuc3Ryb2tlICYmIG9wdGlvbnMud2VpZ2h0ICE9PSAwKSB7XG5cdFx0XHRpZiAoY3R4LnNldExpbmVEYXNoKSB7XG5cdFx0XHRcdGN0eC5zZXRMaW5lRGFzaChsYXllci5vcHRpb25zICYmIGxheWVyLm9wdGlvbnMuX2Rhc2hBcnJheSB8fCBbXSk7XG5cdFx0XHR9XG5cdFx0XHRjdHguZ2xvYmFsQWxwaGEgPSBvcHRpb25zLm9wYWNpdHk7XG5cdFx0XHRjdHgubGluZVdpZHRoID0gb3B0aW9ucy53ZWlnaHQ7XG5cdFx0XHRjdHguc3Ryb2tlU3R5bGUgPSBvcHRpb25zLmNvbG9yO1xuXHRcdFx0Y3R4LmxpbmVDYXAgPSBvcHRpb25zLmxpbmVDYXA7XG5cdFx0XHRjdHgubGluZUpvaW4gPSBvcHRpb25zLmxpbmVKb2luO1xuXHRcdFx0Y3R4LnN0cm9rZSgpO1xuXHRcdH1cblx0fSxcblxuXHQvLyBDYW52YXMgb2J2aW91c2x5IGRvZXNuJ3QgaGF2ZSBtb3VzZSBldmVudHMgZm9yIGluZGl2aWR1YWwgZHJhd24gb2JqZWN0cyxcblx0Ly8gc28gd2UgZW11bGF0ZSB0aGF0IGJ5IGNhbGN1bGF0aW5nIHdoYXQncyB1bmRlciB0aGUgbW91c2Ugb24gbW91c2Vtb3ZlL2NsaWNrIG1hbnVhbGx5XG5cblx0X29uQ2xpY2s6IGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIHBvaW50ID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0xheWVyUG9pbnQoZSksIGxheWVyLCBjbGlja2VkTGF5ZXI7XG5cblx0XHRmb3IgKHZhciBvcmRlciA9IHRoaXMuX2RyYXdGaXJzdDsgb3JkZXI7IG9yZGVyID0gb3JkZXIubmV4dCkge1xuXHRcdFx0bGF5ZXIgPSBvcmRlci5sYXllcjtcblx0XHRcdGlmIChsYXllci5vcHRpb25zLmludGVyYWN0aXZlICYmIGxheWVyLl9jb250YWluc1BvaW50KHBvaW50KSAmJiAhdGhpcy5fbWFwLl9kcmFnZ2FibGVNb3ZlZChsYXllcikpIHtcblx0XHRcdFx0Y2xpY2tlZExheWVyID0gbGF5ZXI7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmIChjbGlja2VkTGF5ZXIpICB7XG5cdFx0XHRmYWtlU3RvcChlKTtcblx0XHRcdHRoaXMuX2ZpcmVFdmVudChbY2xpY2tlZExheWVyXSwgZSk7XG5cdFx0fVxuXHR9LFxuXG5cdF9vbk1vdXNlTW92ZTogZnVuY3Rpb24gKGUpIHtcblx0XHRpZiAoIXRoaXMuX21hcCB8fCB0aGlzLl9tYXAuZHJhZ2dpbmcubW92aW5nKCkgfHwgdGhpcy5fbWFwLl9hbmltYXRpbmdab29tKSB7IHJldHVybjsgfVxuXG5cdFx0dmFyIHBvaW50ID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0xheWVyUG9pbnQoZSk7XG5cdFx0dGhpcy5faGFuZGxlTW91c2VIb3ZlcihlLCBwb2ludCk7XG5cdH0sXG5cblxuXHRfaGFuZGxlTW91c2VPdXQ6IGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIGxheWVyID0gdGhpcy5faG92ZXJlZExheWVyO1xuXHRcdGlmIChsYXllcikge1xuXHRcdFx0Ly8gaWYgd2UncmUgbGVhdmluZyB0aGUgbGF5ZXIsIGZpcmUgbW91c2VvdXRcblx0XHRcdHJlbW92ZUNsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtaW50ZXJhY3RpdmUnKTtcblx0XHRcdHRoaXMuX2ZpcmVFdmVudChbbGF5ZXJdLCBlLCAnbW91c2VvdXQnKTtcblx0XHRcdHRoaXMuX2hvdmVyZWRMYXllciA9IG51bGw7XG5cdFx0fVxuXHR9LFxuXG5cdF9oYW5kbGVNb3VzZUhvdmVyOiBmdW5jdGlvbiAoZSwgcG9pbnQpIHtcblx0XHR2YXIgbGF5ZXIsIGNhbmRpZGF0ZUhvdmVyZWRMYXllcjtcblxuXHRcdGZvciAodmFyIG9yZGVyID0gdGhpcy5fZHJhd0ZpcnN0OyBvcmRlcjsgb3JkZXIgPSBvcmRlci5uZXh0KSB7XG5cdFx0XHRsYXllciA9IG9yZGVyLmxheWVyO1xuXHRcdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUgJiYgbGF5ZXIuX2NvbnRhaW5zUG9pbnQocG9pbnQpKSB7XG5cdFx0XHRcdGNhbmRpZGF0ZUhvdmVyZWRMYXllciA9IGxheWVyO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmIChjYW5kaWRhdGVIb3ZlcmVkTGF5ZXIgIT09IHRoaXMuX2hvdmVyZWRMYXllcikge1xuXHRcdFx0dGhpcy5faGFuZGxlTW91c2VPdXQoZSk7XG5cblx0XHRcdGlmIChjYW5kaWRhdGVIb3ZlcmVkTGF5ZXIpIHtcblx0XHRcdFx0YWRkQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC1pbnRlcmFjdGl2ZScpOyAvLyBjaGFuZ2UgY3Vyc29yXG5cdFx0XHRcdHRoaXMuX2ZpcmVFdmVudChbY2FuZGlkYXRlSG92ZXJlZExheWVyXSwgZSwgJ21vdXNlb3ZlcicpO1xuXHRcdFx0XHR0aGlzLl9ob3ZlcmVkTGF5ZXIgPSBjYW5kaWRhdGVIb3ZlcmVkTGF5ZXI7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMuX2hvdmVyZWRMYXllcikge1xuXHRcdFx0dGhpcy5fZmlyZUV2ZW50KFt0aGlzLl9ob3ZlcmVkTGF5ZXJdLCBlKTtcblx0XHR9XG5cdH0sXG5cblx0X2ZpcmVFdmVudDogZnVuY3Rpb24gKGxheWVycywgZSwgdHlwZSkge1xuXHRcdHRoaXMuX21hcC5fZmlyZURPTUV2ZW50KGUsIHR5cGUgfHwgZS50eXBlLCBsYXllcnMpO1xuXHR9LFxuXG5cdF9icmluZ1RvRnJvbnQ6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHZhciBvcmRlciA9IGxheWVyLl9vcmRlcjtcblx0XHR2YXIgbmV4dCA9IG9yZGVyLm5leHQ7XG5cdFx0dmFyIHByZXYgPSBvcmRlci5wcmV2O1xuXG5cdFx0aWYgKG5leHQpIHtcblx0XHRcdG5leHQucHJldiA9IHByZXY7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIEFscmVhZHkgbGFzdFxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRpZiAocHJldikge1xuXHRcdFx0cHJldi5uZXh0ID0gbmV4dDtcblx0XHR9IGVsc2UgaWYgKG5leHQpIHtcblx0XHRcdC8vIFVwZGF0ZSBmaXJzdCBlbnRyeSB1bmxlc3MgdGhpcyBpcyB0aGVcblx0XHRcdC8vIHNpbmdsZSBlbnRyeVxuXHRcdFx0dGhpcy5fZHJhd0ZpcnN0ID0gbmV4dDtcblx0XHR9XG5cblx0XHRvcmRlci5wcmV2ID0gdGhpcy5fZHJhd0xhc3Q7XG5cdFx0dGhpcy5fZHJhd0xhc3QubmV4dCA9IG9yZGVyO1xuXG5cdFx0b3JkZXIubmV4dCA9IG51bGw7XG5cdFx0dGhpcy5fZHJhd0xhc3QgPSBvcmRlcjtcblxuXHRcdHRoaXMuX3JlcXVlc3RSZWRyYXcobGF5ZXIpO1xuXHR9LFxuXG5cdF9icmluZ1RvQmFjazogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dmFyIG9yZGVyID0gbGF5ZXIuX29yZGVyO1xuXHRcdHZhciBuZXh0ID0gb3JkZXIubmV4dDtcblx0XHR2YXIgcHJldiA9IG9yZGVyLnByZXY7XG5cblx0XHRpZiAocHJldikge1xuXHRcdFx0cHJldi5uZXh0ID0gbmV4dDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gQWxyZWFkeSBmaXJzdFxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRpZiAobmV4dCkge1xuXHRcdFx0bmV4dC5wcmV2ID0gcHJldjtcblx0XHR9IGVsc2UgaWYgKHByZXYpIHtcblx0XHRcdC8vIFVwZGF0ZSBsYXN0IGVudHJ5IHVubGVzcyB0aGlzIGlzIHRoZVxuXHRcdFx0Ly8gc2luZ2xlIGVudHJ5XG5cdFx0XHR0aGlzLl9kcmF3TGFzdCA9IHByZXY7XG5cdFx0fVxuXG5cdFx0b3JkZXIucHJldiA9IG51bGw7XG5cblx0XHRvcmRlci5uZXh0ID0gdGhpcy5fZHJhd0ZpcnN0O1xuXHRcdHRoaXMuX2RyYXdGaXJzdC5wcmV2ID0gb3JkZXI7XG5cdFx0dGhpcy5fZHJhd0ZpcnN0ID0gb3JkZXI7XG5cblx0XHR0aGlzLl9yZXF1ZXN0UmVkcmF3KGxheWVyKTtcblx0fVxufSk7XG5cbi8vIEBmYWN0b3J5IEwuY2FudmFzKG9wdGlvbnM/OiBSZW5kZXJlciBvcHRpb25zKVxuLy8gQ3JlYXRlcyBhIENhbnZhcyByZW5kZXJlciB3aXRoIHRoZSBnaXZlbiBvcHRpb25zLlxuZnVuY3Rpb24gY2FudmFzJDEob3B0aW9ucykge1xuXHRyZXR1cm4gY2FudmFzID8gbmV3IENhbnZhcyhvcHRpb25zKSA6IG51bGw7XG59XG5cbi8qXG4gKiBUaGFua3MgdG8gRG1pdHJ5IEJhcmFub3Zza3kgYW5kIGhpcyBSYXBoYWVsIGxpYnJhcnkgZm9yIGluc3BpcmF0aW9uIVxuICovXG5cblxudmFyIHZtbENyZWF0ZSA9IChmdW5jdGlvbiAoKSB7XG5cdHRyeSB7XG5cdFx0ZG9jdW1lbnQubmFtZXNwYWNlcy5hZGQoJ2x2bWwnLCAndXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTp2bWwnKTtcblx0XHRyZXR1cm4gZnVuY3Rpb24gKG5hbWUpIHtcblx0XHRcdHJldHVybiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCc8bHZtbDonICsgbmFtZSArICcgY2xhc3M9XCJsdm1sXCI+Jyk7XG5cdFx0fTtcblx0fSBjYXRjaCAoZSkge1xuXHRcdHJldHVybiBmdW5jdGlvbiAobmFtZSkge1xuXHRcdFx0cmV0dXJuIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJzwnICsgbmFtZSArICcgeG1sbnM9XCJ1cm46c2NoZW1hcy1taWNyb3NvZnQuY29tOnZtbFwiIGNsYXNzPVwibHZtbFwiPicpO1xuXHRcdH07XG5cdH1cbn0pKCk7XG5cblxuLypcbiAqIEBjbGFzcyBTVkdcbiAqXG4gKiBBbHRob3VnaCBTVkcgaXMgbm90IGF2YWlsYWJsZSBvbiBJRTcgYW5kIElFOCwgdGhlc2UgYnJvd3NlcnMgc3VwcG9ydCBbVk1MXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9WZWN0b3JfTWFya3VwX0xhbmd1YWdlKSwgYW5kIHRoZSBTVkcgcmVuZGVyZXIgd2lsbCBmYWxsIGJhY2sgdG8gVk1MIGluIHRoaXMgY2FzZS5cbiAqXG4gKiBWTUwgd2FzIGRlcHJlY2F0ZWQgaW4gMjAxMiwgd2hpY2ggbWVhbnMgVk1MIGZ1bmN0aW9uYWxpdHkgZXhpc3RzIG9ubHkgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5XG4gKiB3aXRoIG9sZCB2ZXJzaW9ucyBvZiBJbnRlcm5ldCBFeHBsb3Jlci5cbiAqL1xuXG4vLyBtaXhpbiB0byByZWRlZmluZSBzb21lIFNWRyBtZXRob2RzIHRvIGhhbmRsZSBWTUwgc3ludGF4IHdoaWNoIGlzIHNpbWlsYXIgYnV0IHdpdGggc29tZSBkaWZmZXJlbmNlc1xudmFyIHZtbE1peGluID0ge1xuXG5cdF9pbml0Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5fY29udGFpbmVyID0gY3JlYXRlJDEoJ2RpdicsICdsZWFmbGV0LXZtbC1jb250YWluZXInKTtcblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSkgeyByZXR1cm47IH1cblx0XHRSZW5kZXJlci5wcm90b3R5cGUuX3VwZGF0ZS5jYWxsKHRoaXMpO1xuXHRcdHRoaXMuZmlyZSgndXBkYXRlJyk7XG5cdH0sXG5cblx0X2luaXRQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR2YXIgY29udGFpbmVyID0gbGF5ZXIuX2NvbnRhaW5lciA9IHZtbENyZWF0ZSgnc2hhcGUnKTtcblxuXHRcdGFkZENsYXNzKGNvbnRhaW5lciwgJ2xlYWZsZXQtdm1sLXNoYXBlICcgKyAodGhpcy5vcHRpb25zLmNsYXNzTmFtZSB8fCAnJykpO1xuXG5cdFx0Y29udGFpbmVyLmNvb3Jkc2l6ZSA9ICcxIDEnO1xuXG5cdFx0bGF5ZXIuX3BhdGggPSB2bWxDcmVhdGUoJ3BhdGgnKTtcblx0XHRjb250YWluZXIuYXBwZW5kQ2hpbGQobGF5ZXIuX3BhdGgpO1xuXG5cdFx0dGhpcy5fdXBkYXRlU3R5bGUobGF5ZXIpO1xuXHRcdHRoaXMuX2xheWVyc1tzdGFtcChsYXllcildID0gbGF5ZXI7XG5cdH0sXG5cblx0X2FkZFBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHZhciBjb250YWluZXIgPSBsYXllci5fY29udGFpbmVyO1xuXHRcdHRoaXMuX2NvbnRhaW5lci5hcHBlbmRDaGlsZChjb250YWluZXIpO1xuXG5cdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHtcblx0XHRcdGxheWVyLmFkZEludGVyYWN0aXZlVGFyZ2V0KGNvbnRhaW5lcik7XG5cdFx0fVxuXHR9LFxuXG5cdF9yZW1vdmVQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR2YXIgY29udGFpbmVyID0gbGF5ZXIuX2NvbnRhaW5lcjtcblx0XHRyZW1vdmUoY29udGFpbmVyKTtcblx0XHRsYXllci5yZW1vdmVJbnRlcmFjdGl2ZVRhcmdldChjb250YWluZXIpO1xuXHRcdGRlbGV0ZSB0aGlzLl9sYXllcnNbc3RhbXAobGF5ZXIpXTtcblx0fSxcblxuXHRfdXBkYXRlU3R5bGU6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHZhciBzdHJva2UgPSBsYXllci5fc3Ryb2tlLFxuXHRcdCAgICBmaWxsID0gbGF5ZXIuX2ZpbGwsXG5cdFx0ICAgIG9wdGlvbnMgPSBsYXllci5vcHRpb25zLFxuXHRcdCAgICBjb250YWluZXIgPSBsYXllci5fY29udGFpbmVyO1xuXG5cdFx0Y29udGFpbmVyLnN0cm9rZWQgPSAhIW9wdGlvbnMuc3Ryb2tlO1xuXHRcdGNvbnRhaW5lci5maWxsZWQgPSAhIW9wdGlvbnMuZmlsbDtcblxuXHRcdGlmIChvcHRpb25zLnN0cm9rZSkge1xuXHRcdFx0aWYgKCFzdHJva2UpIHtcblx0XHRcdFx0c3Ryb2tlID0gbGF5ZXIuX3N0cm9rZSA9IHZtbENyZWF0ZSgnc3Ryb2tlJyk7XG5cdFx0XHR9XG5cdFx0XHRjb250YWluZXIuYXBwZW5kQ2hpbGQoc3Ryb2tlKTtcblx0XHRcdHN0cm9rZS53ZWlnaHQgPSBvcHRpb25zLndlaWdodCArICdweCc7XG5cdFx0XHRzdHJva2UuY29sb3IgPSBvcHRpb25zLmNvbG9yO1xuXHRcdFx0c3Ryb2tlLm9wYWNpdHkgPSBvcHRpb25zLm9wYWNpdHk7XG5cblx0XHRcdGlmIChvcHRpb25zLmRhc2hBcnJheSkge1xuXHRcdFx0XHRzdHJva2UuZGFzaFN0eWxlID0gaXNBcnJheShvcHRpb25zLmRhc2hBcnJheSkgP1xuXHRcdFx0XHQgICAgb3B0aW9ucy5kYXNoQXJyYXkuam9pbignICcpIDpcblx0XHRcdFx0ICAgIG9wdGlvbnMuZGFzaEFycmF5LnJlcGxhY2UoLyggKiwgKikvZywgJyAnKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHN0cm9rZS5kYXNoU3R5bGUgPSAnJztcblx0XHRcdH1cblx0XHRcdHN0cm9rZS5lbmRjYXAgPSBvcHRpb25zLmxpbmVDYXAucmVwbGFjZSgnYnV0dCcsICdmbGF0Jyk7XG5cdFx0XHRzdHJva2Uuam9pbnN0eWxlID0gb3B0aW9ucy5saW5lSm9pbjtcblxuXHRcdH0gZWxzZSBpZiAoc3Ryb2tlKSB7XG5cdFx0XHRjb250YWluZXIucmVtb3ZlQ2hpbGQoc3Ryb2tlKTtcblx0XHRcdGxheWVyLl9zdHJva2UgPSBudWxsO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLmZpbGwpIHtcblx0XHRcdGlmICghZmlsbCkge1xuXHRcdFx0XHRmaWxsID0gbGF5ZXIuX2ZpbGwgPSB2bWxDcmVhdGUoJ2ZpbGwnKTtcblx0XHRcdH1cblx0XHRcdGNvbnRhaW5lci5hcHBlbmRDaGlsZChmaWxsKTtcblx0XHRcdGZpbGwuY29sb3IgPSBvcHRpb25zLmZpbGxDb2xvciB8fCBvcHRpb25zLmNvbG9yO1xuXHRcdFx0ZmlsbC5vcGFjaXR5ID0gb3B0aW9ucy5maWxsT3BhY2l0eTtcblxuXHRcdH0gZWxzZSBpZiAoZmlsbCkge1xuXHRcdFx0Y29udGFpbmVyLnJlbW92ZUNoaWxkKGZpbGwpO1xuXHRcdFx0bGF5ZXIuX2ZpbGwgPSBudWxsO1xuXHRcdH1cblx0fSxcblxuXHRfdXBkYXRlQ2lyY2xlOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR2YXIgcCA9IGxheWVyLl9wb2ludC5yb3VuZCgpLFxuXHRcdCAgICByID0gTWF0aC5yb3VuZChsYXllci5fcmFkaXVzKSxcblx0XHQgICAgcjIgPSBNYXRoLnJvdW5kKGxheWVyLl9yYWRpdXNZIHx8IHIpO1xuXG5cdFx0dGhpcy5fc2V0UGF0aChsYXllciwgbGF5ZXIuX2VtcHR5KCkgPyAnTTAgMCcgOlxuXHRcdFx0J0FMICcgKyBwLnggKyAnLCcgKyBwLnkgKyAnICcgKyByICsgJywnICsgcjIgKyAnIDAsJyArICg2NTUzNSAqIDM2MCkpO1xuXHR9LFxuXG5cdF9zZXRQYXRoOiBmdW5jdGlvbiAobGF5ZXIsIHBhdGgpIHtcblx0XHRsYXllci5fcGF0aC52ID0gcGF0aDtcblx0fSxcblxuXHRfYnJpbmdUb0Zyb250OiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHR0b0Zyb250KGxheWVyLl9jb250YWluZXIpO1xuXHR9LFxuXG5cdF9icmluZ1RvQmFjazogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dG9CYWNrKGxheWVyLl9jb250YWluZXIpO1xuXHR9XG59O1xuXG52YXIgY3JlYXRlJDIgPSB2bWwgPyB2bWxDcmVhdGUgOiBzdmdDcmVhdGU7XG5cbi8qXG4gKiBAY2xhc3MgU1ZHXG4gKiBAaW5oZXJpdHMgUmVuZGVyZXJcbiAqIEBha2EgTC5TVkdcbiAqXG4gKiBBbGxvd3MgdmVjdG9yIGxheWVycyB0byBiZSBkaXNwbGF5ZWQgd2l0aCBbU1ZHXShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9TVkcpLlxuICogSW5oZXJpdHMgYFJlbmRlcmVyYC5cbiAqXG4gKiBEdWUgdG8gW3RlY2huaWNhbCBsaW1pdGF0aW9uc10oaHR0cDovL2Nhbml1c2UuY29tLyNzZWFyY2g9c3ZnKSwgU1ZHIGlzIG5vdFxuICogYXZhaWxhYmxlIGluIGFsbCB3ZWIgYnJvd3NlcnMsIG5vdGFibHkgQW5kcm9pZCAyLnggYW5kIDMueC5cbiAqXG4gKiBBbHRob3VnaCBTVkcgaXMgbm90IGF2YWlsYWJsZSBvbiBJRTcgYW5kIElFOCwgdGhlc2UgYnJvd3NlcnMgc3VwcG9ydFxuICogW1ZNTF0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVmVjdG9yX01hcmt1cF9MYW5ndWFnZSlcbiAqIChhIG5vdyBkZXByZWNhdGVkIHRlY2hub2xvZ3kpLCBhbmQgdGhlIFNWRyByZW5kZXJlciB3aWxsIGZhbGwgYmFjayB0byBWTUwgaW5cbiAqIHRoaXMgY2FzZS5cbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIFVzZSBTVkcgYnkgZGVmYXVsdCBmb3IgYWxsIHBhdGhzIGluIHRoZSBtYXA6XG4gKlxuICogYGBganNcbiAqIHZhciBtYXAgPSBMLm1hcCgnbWFwJywge1xuICogXHRyZW5kZXJlcjogTC5zdmcoKVxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBVc2UgYSBTVkcgcmVuZGVyZXIgd2l0aCBleHRyYSBwYWRkaW5nIGZvciBzcGVjaWZpYyB2ZWN0b3IgZ2VvbWV0cmllczpcbiAqXG4gKiBgYGBqc1xuICogdmFyIG1hcCA9IEwubWFwKCdtYXAnKTtcbiAqIHZhciBteVJlbmRlcmVyID0gTC5zdmcoeyBwYWRkaW5nOiAwLjUgfSk7XG4gKiB2YXIgbGluZSA9IEwucG9seWxpbmUoIGNvb3JkaW5hdGVzLCB7IHJlbmRlcmVyOiBteVJlbmRlcmVyIH0gKTtcbiAqIHZhciBjaXJjbGUgPSBMLmNpcmNsZSggY2VudGVyLCB7IHJlbmRlcmVyOiBteVJlbmRlcmVyIH0gKTtcbiAqIGBgYFxuICovXG5cbnZhciBTVkcgPSBSZW5kZXJlci5leHRlbmQoe1xuXG5cdGdldEV2ZW50czogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBldmVudHMgPSBSZW5kZXJlci5wcm90b3R5cGUuZ2V0RXZlbnRzLmNhbGwodGhpcyk7XG5cdFx0ZXZlbnRzLnpvb21zdGFydCA9IHRoaXMuX29uWm9vbVN0YXJ0O1xuXHRcdHJldHVybiBldmVudHM7XG5cdH0sXG5cblx0X2luaXRDb250YWluZXI6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9jb250YWluZXIgPSBjcmVhdGUkMignc3ZnJyk7XG5cblx0XHQvLyBtYWtlcyBpdCBwb3NzaWJsZSB0byBjbGljayB0aHJvdWdoIHN2ZyByb290OyB3ZSdsbCByZXNldCBpdCBiYWNrIGluIGluZGl2aWR1YWwgcGF0aHNcblx0XHR0aGlzLl9jb250YWluZXIuc2V0QXR0cmlidXRlKCdwb2ludGVyLWV2ZW50cycsICdub25lJyk7XG5cblx0XHR0aGlzLl9yb290R3JvdXAgPSBjcmVhdGUkMignZycpO1xuXHRcdHRoaXMuX2NvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLl9yb290R3JvdXApO1xuXHR9LFxuXG5cdF9kZXN0cm95Q29udGFpbmVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmVtb3ZlKHRoaXMuX2NvbnRhaW5lcik7XG5cdFx0b2ZmKHRoaXMuX2NvbnRhaW5lcik7XG5cdFx0ZGVsZXRlIHRoaXMuX2NvbnRhaW5lcjtcblx0XHRkZWxldGUgdGhpcy5fcm9vdEdyb3VwO1xuXHRcdGRlbGV0ZSB0aGlzLl9zdmdTaXplO1xuXHR9LFxuXG5cdF9vblpvb21TdGFydDogZnVuY3Rpb24gKCkge1xuXHRcdC8vIERyYWctdGhlbi1waW5jaCBpbnRlcmFjdGlvbnMgbWlnaHQgbWVzcyB1cCB0aGUgY2VudGVyIGFuZCB6b29tLlxuXHRcdC8vIEluIHRoaXMgY2FzZSwgdGhlIGVhc2llc3Qgd2F5IHRvIHByZXZlbnQgdGhpcyBpcyByZS1kbyB0aGUgcmVuZGVyZXJcblx0XHQvLyAgIGJvdW5kcyBhbmQgcGFkZGluZyB3aGVuIHRoZSB6b29taW5nIHN0YXJ0cy5cblx0XHR0aGlzLl91cGRhdGUoKTtcblx0fSxcblxuXHRfdXBkYXRlOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21hcC5fYW5pbWF0aW5nWm9vbSAmJiB0aGlzLl9ib3VuZHMpIHsgcmV0dXJuOyB9XG5cblx0XHRSZW5kZXJlci5wcm90b3R5cGUuX3VwZGF0ZS5jYWxsKHRoaXMpO1xuXG5cdFx0dmFyIGIgPSB0aGlzLl9ib3VuZHMsXG5cdFx0ICAgIHNpemUgPSBiLmdldFNpemUoKSxcblx0XHQgICAgY29udGFpbmVyID0gdGhpcy5fY29udGFpbmVyO1xuXG5cdFx0Ly8gc2V0IHNpemUgb2Ygc3ZnLWNvbnRhaW5lciBpZiBjaGFuZ2VkXG5cdFx0aWYgKCF0aGlzLl9zdmdTaXplIHx8ICF0aGlzLl9zdmdTaXplLmVxdWFscyhzaXplKSkge1xuXHRcdFx0dGhpcy5fc3ZnU2l6ZSA9IHNpemU7XG5cdFx0XHRjb250YWluZXIuc2V0QXR0cmlidXRlKCd3aWR0aCcsIHNpemUueCk7XG5cdFx0XHRjb250YWluZXIuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCBzaXplLnkpO1xuXHRcdH1cblxuXHRcdC8vIG1vdmVtZW50OiB1cGRhdGUgY29udGFpbmVyIHZpZXdCb3ggc28gdGhhdCB3ZSBkb24ndCBoYXZlIHRvIGNoYW5nZSBjb29yZGluYXRlcyBvZiBpbmRpdmlkdWFsIGxheWVyc1xuXHRcdHNldFBvc2l0aW9uKGNvbnRhaW5lciwgYi5taW4pO1xuXHRcdGNvbnRhaW5lci5zZXRBdHRyaWJ1dGUoJ3ZpZXdCb3gnLCBbYi5taW4ueCwgYi5taW4ueSwgc2l6ZS54LCBzaXplLnldLmpvaW4oJyAnKSk7XG5cblx0XHR0aGlzLmZpcmUoJ3VwZGF0ZScpO1xuXHR9LFxuXG5cdC8vIG1ldGhvZHMgYmVsb3cgYXJlIGNhbGxlZCBieSB2ZWN0b3IgbGF5ZXJzIGltcGxlbWVudGF0aW9uc1xuXG5cdF9pbml0UGF0aDogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dmFyIHBhdGggPSBsYXllci5fcGF0aCA9IGNyZWF0ZSQyKCdwYXRoJyk7XG5cblx0XHQvLyBAbmFtZXNwYWNlIFBhdGhcblx0XHQvLyBAb3B0aW9uIGNsYXNzTmFtZTogU3RyaW5nID0gbnVsbFxuXHRcdC8vIEN1c3RvbSBjbGFzcyBuYW1lIHNldCBvbiBhbiBlbGVtZW50LiBPbmx5IGZvciBTVkcgcmVuZGVyZXIuXG5cdFx0aWYgKGxheWVyLm9wdGlvbnMuY2xhc3NOYW1lKSB7XG5cdFx0XHRhZGRDbGFzcyhwYXRoLCBsYXllci5vcHRpb25zLmNsYXNzTmFtZSk7XG5cdFx0fVxuXG5cdFx0aWYgKGxheWVyLm9wdGlvbnMuaW50ZXJhY3RpdmUpIHtcblx0XHRcdGFkZENsYXNzKHBhdGgsICdsZWFmbGV0LWludGVyYWN0aXZlJyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fdXBkYXRlU3R5bGUobGF5ZXIpO1xuXHRcdHRoaXMuX2xheWVyc1tzdGFtcChsYXllcildID0gbGF5ZXI7XG5cdH0sXG5cblx0X2FkZFBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdGlmICghdGhpcy5fcm9vdEdyb3VwKSB7IHRoaXMuX2luaXRDb250YWluZXIoKTsgfVxuXHRcdHRoaXMuX3Jvb3RHcm91cC5hcHBlbmRDaGlsZChsYXllci5fcGF0aCk7XG5cdFx0bGF5ZXIuYWRkSW50ZXJhY3RpdmVUYXJnZXQobGF5ZXIuX3BhdGgpO1xuXHR9LFxuXG5cdF9yZW1vdmVQYXRoOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHRyZW1vdmUobGF5ZXIuX3BhdGgpO1xuXHRcdGxheWVyLnJlbW92ZUludGVyYWN0aXZlVGFyZ2V0KGxheWVyLl9wYXRoKTtcblx0XHRkZWxldGUgdGhpcy5fbGF5ZXJzW3N0YW1wKGxheWVyKV07XG5cdH0sXG5cblx0X3VwZGF0ZVBhdGg6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdGxheWVyLl9wcm9qZWN0KCk7XG5cdFx0bGF5ZXIuX3VwZGF0ZSgpO1xuXHR9LFxuXG5cdF91cGRhdGVTdHlsZTogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dmFyIHBhdGggPSBsYXllci5fcGF0aCxcblx0XHQgICAgb3B0aW9ucyA9IGxheWVyLm9wdGlvbnM7XG5cblx0XHRpZiAoIXBhdGgpIHsgcmV0dXJuOyB9XG5cblx0XHRpZiAob3B0aW9ucy5zdHJva2UpIHtcblx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UnLCBvcHRpb25zLmNvbG9yKTtcblx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2Utb3BhY2l0eScsIG9wdGlvbnMub3BhY2l0eSk7XG5cdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLXdpZHRoJywgb3B0aW9ucy53ZWlnaHQpO1xuXHRcdFx0cGF0aC5zZXRBdHRyaWJ1dGUoJ3N0cm9rZS1saW5lY2FwJywgb3B0aW9ucy5saW5lQ2FwKTtcblx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UtbGluZWpvaW4nLCBvcHRpb25zLmxpbmVKb2luKTtcblxuXHRcdFx0aWYgKG9wdGlvbnMuZGFzaEFycmF5KSB7XG5cdFx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UtZGFzaGFycmF5Jywgb3B0aW9ucy5kYXNoQXJyYXkpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cGF0aC5yZW1vdmVBdHRyaWJ1dGUoJ3N0cm9rZS1kYXNoYXJyYXknKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKG9wdGlvbnMuZGFzaE9mZnNldCkge1xuXHRcdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLWRhc2hvZmZzZXQnLCBvcHRpb25zLmRhc2hPZmZzZXQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cGF0aC5yZW1vdmVBdHRyaWJ1dGUoJ3N0cm9rZS1kYXNob2Zmc2V0Jyk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdzdHJva2UnLCAnbm9uZScpO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLmZpbGwpIHtcblx0XHRcdHBhdGguc2V0QXR0cmlidXRlKCdmaWxsJywgb3B0aW9ucy5maWxsQ29sb3IgfHwgb3B0aW9ucy5jb2xvcik7XG5cdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnZmlsbC1vcGFjaXR5Jywgb3B0aW9ucy5maWxsT3BhY2l0eSk7XG5cdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnZmlsbC1ydWxlJywgb3B0aW9ucy5maWxsUnVsZSB8fCAnZXZlbm9kZCcpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRwYXRoLnNldEF0dHJpYnV0ZSgnZmlsbCcsICdub25lJyk7XG5cdFx0fVxuXHR9LFxuXG5cdF91cGRhdGVQb2x5OiBmdW5jdGlvbiAobGF5ZXIsIGNsb3NlZCkge1xuXHRcdHRoaXMuX3NldFBhdGgobGF5ZXIsIHBvaW50c1RvUGF0aChsYXllci5fcGFydHMsIGNsb3NlZCkpO1xuXHR9LFxuXG5cdF91cGRhdGVDaXJjbGU6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHZhciBwID0gbGF5ZXIuX3BvaW50LFxuXHRcdCAgICByID0gTWF0aC5tYXgoTWF0aC5yb3VuZChsYXllci5fcmFkaXVzKSwgMSksXG5cdFx0ICAgIHIyID0gTWF0aC5tYXgoTWF0aC5yb3VuZChsYXllci5fcmFkaXVzWSksIDEpIHx8IHIsXG5cdFx0ICAgIGFyYyA9ICdhJyArIHIgKyAnLCcgKyByMiArICcgMCAxLDAgJztcblxuXHRcdC8vIGRyYXdpbmcgYSBjaXJjbGUgd2l0aCB0d28gaGFsZi1hcmNzXG5cdFx0dmFyIGQgPSBsYXllci5fZW1wdHkoKSA/ICdNMCAwJyA6XG5cdFx0XHQnTScgKyAocC54IC0gcikgKyAnLCcgKyBwLnkgK1xuXHRcdFx0YXJjICsgKHIgKiAyKSArICcsMCAnICtcblx0XHRcdGFyYyArICgtciAqIDIpICsgJywwICc7XG5cblx0XHR0aGlzLl9zZXRQYXRoKGxheWVyLCBkKTtcblx0fSxcblxuXHRfc2V0UGF0aDogZnVuY3Rpb24gKGxheWVyLCBwYXRoKSB7XG5cdFx0bGF5ZXIuX3BhdGguc2V0QXR0cmlidXRlKCdkJywgcGF0aCk7XG5cdH0sXG5cblx0Ly8gU1ZHIGRvZXMgbm90IGhhdmUgdGhlIGNvbmNlcHQgb2YgekluZGV4IHNvIHdlIHJlc29ydCB0byBjaGFuZ2luZyB0aGUgRE9NIG9yZGVyIG9mIGVsZW1lbnRzXG5cdF9icmluZ1RvRnJvbnQ6IGZ1bmN0aW9uIChsYXllcikge1xuXHRcdHRvRnJvbnQobGF5ZXIuX3BhdGgpO1xuXHR9LFxuXG5cdF9icmluZ1RvQmFjazogZnVuY3Rpb24gKGxheWVyKSB7XG5cdFx0dG9CYWNrKGxheWVyLl9wYXRoKTtcblx0fVxufSk7XG5cbmlmICh2bWwpIHtcblx0U1ZHLmluY2x1ZGUodm1sTWl4aW4pO1xufVxuXG4vLyBAbmFtZXNwYWNlIFNWR1xuLy8gQGZhY3RvcnkgTC5zdmcob3B0aW9ucz86IFJlbmRlcmVyIG9wdGlvbnMpXG4vLyBDcmVhdGVzIGEgU1ZHIHJlbmRlcmVyIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXG5mdW5jdGlvbiBzdmckMShvcHRpb25zKSB7XG5cdHJldHVybiBzdmcgfHwgdm1sID8gbmV3IFNWRyhvcHRpb25zKSA6IG51bGw7XG59XG5cbk1hcC5pbmNsdWRlKHtcblx0Ly8gQG5hbWVzcGFjZSBNYXA7IEBtZXRob2QgZ2V0UmVuZGVyZXIobGF5ZXI6IFBhdGgpOiBSZW5kZXJlclxuXHQvLyBSZXR1cm5zIHRoZSBpbnN0YW5jZSBvZiBgUmVuZGVyZXJgIHRoYXQgc2hvdWxkIGJlIHVzZWQgdG8gcmVuZGVyIHRoZSBnaXZlblxuXHQvLyBgUGF0aGAuIEl0IHdpbGwgZW5zdXJlIHRoYXQgdGhlIGByZW5kZXJlcmAgb3B0aW9ucyBvZiB0aGUgbWFwIGFuZCBwYXRoc1xuXHQvLyBhcmUgcmVzcGVjdGVkLCBhbmQgdGhhdCB0aGUgcmVuZGVyZXJzIGRvIGV4aXN0IG9uIHRoZSBtYXAuXG5cdGdldFJlbmRlcmVyOiBmdW5jdGlvbiAobGF5ZXIpIHtcblx0XHQvLyBAbmFtZXNwYWNlIFBhdGg7IEBvcHRpb24gcmVuZGVyZXI6IFJlbmRlcmVyXG5cdFx0Ly8gVXNlIHRoaXMgc3BlY2lmaWMgaW5zdGFuY2Ugb2YgYFJlbmRlcmVyYCBmb3IgdGhpcyBwYXRoLiBUYWtlc1xuXHRcdC8vIHByZWNlZGVuY2Ugb3ZlciB0aGUgbWFwJ3MgW2RlZmF1bHQgcmVuZGVyZXJdKCNtYXAtcmVuZGVyZXIpLlxuXHRcdHZhciByZW5kZXJlciA9IGxheWVyLm9wdGlvbnMucmVuZGVyZXIgfHwgdGhpcy5fZ2V0UGFuZVJlbmRlcmVyKGxheWVyLm9wdGlvbnMucGFuZSkgfHwgdGhpcy5vcHRpb25zLnJlbmRlcmVyIHx8IHRoaXMuX3JlbmRlcmVyO1xuXG5cdFx0aWYgKCFyZW5kZXJlcikge1xuXHRcdFx0Ly8gQG5hbWVzcGFjZSBNYXA7IEBvcHRpb24gcHJlZmVyQ2FudmFzOiBCb29sZWFuID0gZmFsc2Vcblx0XHRcdC8vIFdoZXRoZXIgYFBhdGhgcyBzaG91bGQgYmUgcmVuZGVyZWQgb24gYSBgQ2FudmFzYCByZW5kZXJlci5cblx0XHRcdC8vIEJ5IGRlZmF1bHQsIGFsbCBgUGF0aGBzIGFyZSByZW5kZXJlZCBpbiBhIGBTVkdgIHJlbmRlcmVyLlxuXHRcdFx0cmVuZGVyZXIgPSB0aGlzLl9yZW5kZXJlciA9ICh0aGlzLm9wdGlvbnMucHJlZmVyQ2FudmFzICYmIGNhbnZhcyQxKCkpIHx8IHN2ZyQxKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCF0aGlzLmhhc0xheWVyKHJlbmRlcmVyKSkge1xuXHRcdFx0dGhpcy5hZGRMYXllcihyZW5kZXJlcik7XG5cdFx0fVxuXHRcdHJldHVybiByZW5kZXJlcjtcblx0fSxcblxuXHRfZ2V0UGFuZVJlbmRlcmVyOiBmdW5jdGlvbiAobmFtZSkge1xuXHRcdGlmIChuYW1lID09PSAnb3ZlcmxheVBhbmUnIHx8IG5hbWUgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdHZhciByZW5kZXJlciA9IHRoaXMuX3BhbmVSZW5kZXJlcnNbbmFtZV07XG5cdFx0aWYgKHJlbmRlcmVyID09PSB1bmRlZmluZWQpIHtcblx0XHRcdHJlbmRlcmVyID0gKFNWRyAmJiBzdmckMSh7cGFuZTogbmFtZX0pKSB8fCAoQ2FudmFzICYmIGNhbnZhcyQxKHtwYW5lOiBuYW1lfSkpO1xuXHRcdFx0dGhpcy5fcGFuZVJlbmRlcmVyc1tuYW1lXSA9IHJlbmRlcmVyO1xuXHRcdH1cblx0XHRyZXR1cm4gcmVuZGVyZXI7XG5cdH1cbn0pO1xuXG4vKlxuICogTC5SZWN0YW5nbGUgZXh0ZW5kcyBQb2x5Z29uIGFuZCBjcmVhdGVzIGEgcmVjdGFuZ2xlIHdoZW4gcGFzc2VkIGEgTGF0TG5nQm91bmRzIG9iamVjdC5cbiAqL1xuXG4vKlxuICogQGNsYXNzIFJlY3RhbmdsZVxuICogQGFrYSBMLlJlY3RhbmdsZVxuICogQGluaGVyaXRzIFBvbHlnb25cbiAqXG4gKiBBIGNsYXNzIGZvciBkcmF3aW5nIHJlY3RhbmdsZSBvdmVybGF5cyBvbiBhIG1hcC4gRXh0ZW5kcyBgUG9seWdvbmAuXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGBqc1xuICogLy8gZGVmaW5lIHJlY3RhbmdsZSBnZW9ncmFwaGljYWwgYm91bmRzXG4gKiB2YXIgYm91bmRzID0gW1s1NC41NTkzMjIsIC01Ljc2NzgyMl0sIFs1Ni4xMjEwNjA0LCAtMy4wMjEyNDBdXTtcbiAqXG4gKiAvLyBjcmVhdGUgYW4gb3JhbmdlIHJlY3RhbmdsZVxuICogTC5yZWN0YW5nbGUoYm91bmRzLCB7Y29sb3I6IFwiI2ZmNzgwMFwiLCB3ZWlnaHQ6IDF9KS5hZGRUbyhtYXApO1xuICpcbiAqIC8vIHpvb20gdGhlIG1hcCB0byB0aGUgcmVjdGFuZ2xlIGJvdW5kc1xuICogbWFwLmZpdEJvdW5kcyhib3VuZHMpO1xuICogYGBgXG4gKlxuICovXG5cblxudmFyIFJlY3RhbmdsZSA9IFBvbHlnb24uZXh0ZW5kKHtcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKGxhdExuZ0JvdW5kcywgb3B0aW9ucykge1xuXHRcdFBvbHlnb24ucHJvdG90eXBlLmluaXRpYWxpemUuY2FsbCh0aGlzLCB0aGlzLl9ib3VuZHNUb0xhdExuZ3MobGF0TG5nQm91bmRzKSwgb3B0aW9ucyk7XG5cdH0sXG5cblx0Ly8gQG1ldGhvZCBzZXRCb3VuZHMobGF0TG5nQm91bmRzOiBMYXRMbmdCb3VuZHMpOiB0aGlzXG5cdC8vIFJlZHJhd3MgdGhlIHJlY3RhbmdsZSB3aXRoIHRoZSBwYXNzZWQgYm91bmRzLlxuXHRzZXRCb3VuZHM6IGZ1bmN0aW9uIChsYXRMbmdCb3VuZHMpIHtcblx0XHRyZXR1cm4gdGhpcy5zZXRMYXRMbmdzKHRoaXMuX2JvdW5kc1RvTGF0TG5ncyhsYXRMbmdCb3VuZHMpKTtcblx0fSxcblxuXHRfYm91bmRzVG9MYXRMbmdzOiBmdW5jdGlvbiAobGF0TG5nQm91bmRzKSB7XG5cdFx0bGF0TG5nQm91bmRzID0gdG9MYXRMbmdCb3VuZHMobGF0TG5nQm91bmRzKTtcblx0XHRyZXR1cm4gW1xuXHRcdFx0bGF0TG5nQm91bmRzLmdldFNvdXRoV2VzdCgpLFxuXHRcdFx0bGF0TG5nQm91bmRzLmdldE5vcnRoV2VzdCgpLFxuXHRcdFx0bGF0TG5nQm91bmRzLmdldE5vcnRoRWFzdCgpLFxuXHRcdFx0bGF0TG5nQm91bmRzLmdldFNvdXRoRWFzdCgpXG5cdFx0XTtcblx0fVxufSk7XG5cblxuLy8gQGZhY3RvcnkgTC5yZWN0YW5nbGUobGF0TG5nQm91bmRzOiBMYXRMbmdCb3VuZHMsIG9wdGlvbnM/OiBQb2x5bGluZSBvcHRpb25zKVxuZnVuY3Rpb24gcmVjdGFuZ2xlKGxhdExuZ0JvdW5kcywgb3B0aW9ucykge1xuXHRyZXR1cm4gbmV3IFJlY3RhbmdsZShsYXRMbmdCb3VuZHMsIG9wdGlvbnMpO1xufVxuXG5TVkcuY3JlYXRlID0gY3JlYXRlJDI7XG5TVkcucG9pbnRzVG9QYXRoID0gcG9pbnRzVG9QYXRoO1xuXG5HZW9KU09OLmdlb21ldHJ5VG9MYXllciA9IGdlb21ldHJ5VG9MYXllcjtcbkdlb0pTT04uY29vcmRzVG9MYXRMbmcgPSBjb29yZHNUb0xhdExuZztcbkdlb0pTT04uY29vcmRzVG9MYXRMbmdzID0gY29vcmRzVG9MYXRMbmdzO1xuR2VvSlNPTi5sYXRMbmdUb0Nvb3JkcyA9IGxhdExuZ1RvQ29vcmRzO1xuR2VvSlNPTi5sYXRMbmdzVG9Db29yZHMgPSBsYXRMbmdzVG9Db29yZHM7XG5HZW9KU09OLmdldEZlYXR1cmUgPSBnZXRGZWF0dXJlO1xuR2VvSlNPTi5hc0ZlYXR1cmUgPSBhc0ZlYXR1cmU7XG5cbi8qXG4gKiBMLkhhbmRsZXIuQm94Wm9vbSBpcyB1c2VkIHRvIGFkZCBzaGlmdC1kcmFnIHpvb20gaW50ZXJhY3Rpb24gdG8gdGhlIG1hcFxuICogKHpvb20gdG8gYSBzZWxlY3RlZCBib3VuZGluZyBib3gpLCBlbmFibGVkIGJ5IGRlZmF1bHQuXG4gKi9cblxuLy8gQG5hbWVzcGFjZSBNYXBcbi8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcbk1hcC5tZXJnZU9wdGlvbnMoe1xuXHQvLyBAb3B0aW9uIGJveFpvb206IEJvb2xlYW4gPSB0cnVlXG5cdC8vIFdoZXRoZXIgdGhlIG1hcCBjYW4gYmUgem9vbWVkIHRvIGEgcmVjdGFuZ3VsYXIgYXJlYSBzcGVjaWZpZWQgYnlcblx0Ly8gZHJhZ2dpbmcgdGhlIG1vdXNlIHdoaWxlIHByZXNzaW5nIHRoZSBzaGlmdCBrZXkuXG5cdGJveFpvb206IHRydWVcbn0pO1xuXG52YXIgQm94Wm9vbSA9IEhhbmRsZXIuZXh0ZW5kKHtcblx0aW5pdGlhbGl6ZTogZnVuY3Rpb24gKG1hcCkge1xuXHRcdHRoaXMuX21hcCA9IG1hcDtcblx0XHR0aGlzLl9jb250YWluZXIgPSBtYXAuX2NvbnRhaW5lcjtcblx0XHR0aGlzLl9wYW5lID0gbWFwLl9wYW5lcy5vdmVybGF5UGFuZTtcblx0XHR0aGlzLl9yZXNldFN0YXRlVGltZW91dCA9IDA7XG5cdFx0bWFwLm9uKCd1bmxvYWQnLCB0aGlzLl9kZXN0cm95LCB0aGlzKTtcblx0fSxcblxuXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdG9uKHRoaXMuX2NvbnRhaW5lciwgJ21vdXNlZG93bicsIHRoaXMuX29uTW91c2VEb3duLCB0aGlzKTtcblx0fSxcblxuXHRyZW1vdmVIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdG9mZih0aGlzLl9jb250YWluZXIsICdtb3VzZWRvd24nLCB0aGlzLl9vbk1vdXNlRG93biwgdGhpcyk7XG5cdH0sXG5cblx0bW92ZWQ6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fbW92ZWQ7XG5cdH0sXG5cblx0X2Rlc3Ryb3k6IGZ1bmN0aW9uICgpIHtcblx0XHRyZW1vdmUodGhpcy5fcGFuZSk7XG5cdFx0ZGVsZXRlIHRoaXMuX3BhbmU7XG5cdH0sXG5cblx0X3Jlc2V0U3RhdGU6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9yZXNldFN0YXRlVGltZW91dCA9IDA7XG5cdFx0dGhpcy5fbW92ZWQgPSBmYWxzZTtcblx0fSxcblxuXHRfY2xlYXJEZWZlcnJlZFJlc2V0U3RhdGU6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAodGhpcy5fcmVzZXRTdGF0ZVRpbWVvdXQgIT09IDApIHtcblx0XHRcdGNsZWFyVGltZW91dCh0aGlzLl9yZXNldFN0YXRlVGltZW91dCk7XG5cdFx0XHR0aGlzLl9yZXNldFN0YXRlVGltZW91dCA9IDA7XG5cdFx0fVxuXHR9LFxuXG5cdF9vbk1vdXNlRG93bjogZnVuY3Rpb24gKGUpIHtcblx0XHRpZiAoIWUuc2hpZnRLZXkgfHwgKChlLndoaWNoICE9PSAxKSAmJiAoZS5idXR0b24gIT09IDEpKSkgeyByZXR1cm4gZmFsc2U7IH1cblxuXHRcdC8vIENsZWFyIHRoZSBkZWZlcnJlZCByZXNldFN0YXRlIGlmIGl0IGhhc24ndCBleGVjdXRlZCB5ZXQsIG90aGVyd2lzZSBpdFxuXHRcdC8vIHdpbGwgaW50ZXJydXB0IHRoZSBpbnRlcmFjdGlvbiBhbmQgb3JwaGFuIGEgYm94IGVsZW1lbnQgaW4gdGhlIGNvbnRhaW5lci5cblx0XHR0aGlzLl9jbGVhckRlZmVycmVkUmVzZXRTdGF0ZSgpO1xuXHRcdHRoaXMuX3Jlc2V0U3RhdGUoKTtcblxuXHRcdGRpc2FibGVUZXh0U2VsZWN0aW9uKCk7XG5cdFx0ZGlzYWJsZUltYWdlRHJhZygpO1xuXG5cdFx0dGhpcy5fc3RhcnRQb2ludCA9IHRoaXMuX21hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlKTtcblxuXHRcdG9uKGRvY3VtZW50LCB7XG5cdFx0XHRjb250ZXh0bWVudTogc3RvcCxcblx0XHRcdG1vdXNlbW92ZTogdGhpcy5fb25Nb3VzZU1vdmUsXG5cdFx0XHRtb3VzZXVwOiB0aGlzLl9vbk1vdXNlVXAsXG5cdFx0XHRrZXlkb3duOiB0aGlzLl9vbktleURvd25cblx0XHR9LCB0aGlzKTtcblx0fSxcblxuXHRfb25Nb3VzZU1vdmU6IGZ1bmN0aW9uIChlKSB7XG5cdFx0aWYgKCF0aGlzLl9tb3ZlZCkge1xuXHRcdFx0dGhpcy5fbW92ZWQgPSB0cnVlO1xuXG5cdFx0XHR0aGlzLl9ib3ggPSBjcmVhdGUkMSgnZGl2JywgJ2xlYWZsZXQtem9vbS1ib3gnLCB0aGlzLl9jb250YWluZXIpO1xuXHRcdFx0YWRkQ2xhc3ModGhpcy5fY29udGFpbmVyLCAnbGVhZmxldC1jcm9zc2hhaXInKTtcblxuXHRcdFx0dGhpcy5fbWFwLmZpcmUoJ2JveHpvb21zdGFydCcpO1xuXHRcdH1cblxuXHRcdHRoaXMuX3BvaW50ID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUpO1xuXG5cdFx0dmFyIGJvdW5kcyA9IG5ldyBCb3VuZHModGhpcy5fcG9pbnQsIHRoaXMuX3N0YXJ0UG9pbnQpLFxuXHRcdCAgICBzaXplID0gYm91bmRzLmdldFNpemUoKTtcblxuXHRcdHNldFBvc2l0aW9uKHRoaXMuX2JveCwgYm91bmRzLm1pbik7XG5cblx0XHR0aGlzLl9ib3guc3R5bGUud2lkdGggID0gc2l6ZS54ICsgJ3B4Jztcblx0XHR0aGlzLl9ib3guc3R5bGUuaGVpZ2h0ID0gc2l6ZS55ICsgJ3B4Jztcblx0fSxcblxuXHRfZmluaXNoOiBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKHRoaXMuX21vdmVkKSB7XG5cdFx0XHRyZW1vdmUodGhpcy5fYm94KTtcblx0XHRcdHJlbW92ZUNsYXNzKHRoaXMuX2NvbnRhaW5lciwgJ2xlYWZsZXQtY3Jvc3NoYWlyJyk7XG5cdFx0fVxuXG5cdFx0ZW5hYmxlVGV4dFNlbGVjdGlvbigpO1xuXHRcdGVuYWJsZUltYWdlRHJhZygpO1xuXG5cdFx0b2ZmKGRvY3VtZW50LCB7XG5cdFx0XHRjb250ZXh0bWVudTogc3RvcCxcblx0XHRcdG1vdXNlbW92ZTogdGhpcy5fb25Nb3VzZU1vdmUsXG5cdFx0XHRtb3VzZXVwOiB0aGlzLl9vbk1vdXNlVXAsXG5cdFx0XHRrZXlkb3duOiB0aGlzLl9vbktleURvd25cblx0XHR9LCB0aGlzKTtcblx0fSxcblxuXHRfb25Nb3VzZVVwOiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmICgoZS53aGljaCAhPT0gMSkgJiYgKGUuYnV0dG9uICE9PSAxKSkgeyByZXR1cm47IH1cblxuXHRcdHRoaXMuX2ZpbmlzaCgpO1xuXG5cdFx0aWYgKCF0aGlzLl9tb3ZlZCkgeyByZXR1cm47IH1cblx0XHQvLyBQb3N0cG9uZSB0byBuZXh0IEpTIHRpY2sgc28gaW50ZXJuYWwgY2xpY2sgZXZlbnQgaGFuZGxpbmdcblx0XHQvLyBzdGlsbCBzZWUgaXQgYXMgXCJtb3ZlZFwiLlxuXHRcdHRoaXMuX2NsZWFyRGVmZXJyZWRSZXNldFN0YXRlKCk7XG5cdFx0dGhpcy5fcmVzZXRTdGF0ZVRpbWVvdXQgPSBzZXRUaW1lb3V0KGJpbmQodGhpcy5fcmVzZXRTdGF0ZSwgdGhpcyksIDApO1xuXG5cdFx0dmFyIGJvdW5kcyA9IG5ldyBMYXRMbmdCb3VuZHMoXG5cdFx0ICAgICAgICB0aGlzLl9tYXAuY29udGFpbmVyUG9pbnRUb0xhdExuZyh0aGlzLl9zdGFydFBvaW50KSxcblx0XHQgICAgICAgIHRoaXMuX21hcC5jb250YWluZXJQb2ludFRvTGF0TG5nKHRoaXMuX3BvaW50KSk7XG5cblx0XHR0aGlzLl9tYXBcblx0XHRcdC5maXRCb3VuZHMoYm91bmRzKVxuXHRcdFx0LmZpcmUoJ2JveHpvb21lbmQnLCB7Ym94Wm9vbUJvdW5kczogYm91bmRzfSk7XG5cdH0sXG5cblx0X29uS2V5RG93bjogZnVuY3Rpb24gKGUpIHtcblx0XHRpZiAoZS5rZXlDb2RlID09PSAyNykge1xuXHRcdFx0dGhpcy5fZmluaXNoKCk7XG5cdFx0fVxuXHR9XG59KTtcblxuLy8gQHNlY3Rpb24gSGFuZGxlcnNcbi8vIEBwcm9wZXJ0eSBib3hab29tOiBIYW5kbGVyXG4vLyBCb3ggKHNoaWZ0LWRyYWcgd2l0aCBtb3VzZSkgem9vbSBoYW5kbGVyLlxuTWFwLmFkZEluaXRIb29rKCdhZGRIYW5kbGVyJywgJ2JveFpvb20nLCBCb3hab29tKTtcblxuLypcbiAqIEwuSGFuZGxlci5Eb3VibGVDbGlja1pvb20gaXMgdXNlZCB0byBoYW5kbGUgZG91YmxlLWNsaWNrIHpvb20gb24gdGhlIG1hcCwgZW5hYmxlZCBieSBkZWZhdWx0LlxuICovXG5cbi8vIEBuYW1lc3BhY2UgTWFwXG4vLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG5cbk1hcC5tZXJnZU9wdGlvbnMoe1xuXHQvLyBAb3B0aW9uIGRvdWJsZUNsaWNrWm9vbTogQm9vbGVhbnxTdHJpbmcgPSB0cnVlXG5cdC8vIFdoZXRoZXIgdGhlIG1hcCBjYW4gYmUgem9vbWVkIGluIGJ5IGRvdWJsZSBjbGlja2luZyBvbiBpdCBhbmRcblx0Ly8gem9vbWVkIG91dCBieSBkb3VibGUgY2xpY2tpbmcgd2hpbGUgaG9sZGluZyBzaGlmdC4gSWYgcGFzc2VkXG5cdC8vIGAnY2VudGVyJ2AsIGRvdWJsZS1jbGljayB6b29tIHdpbGwgem9vbSB0byB0aGUgY2VudGVyIG9mIHRoZVxuXHQvLyAgdmlldyByZWdhcmRsZXNzIG9mIHdoZXJlIHRoZSBtb3VzZSB3YXMuXG5cdGRvdWJsZUNsaWNrWm9vbTogdHJ1ZVxufSk7XG5cbnZhciBEb3VibGVDbGlja1pvb20gPSBIYW5kbGVyLmV4dGVuZCh7XG5cdGFkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5fbWFwLm9uKCdkYmxjbGljaycsIHRoaXMuX29uRG91YmxlQ2xpY2ssIHRoaXMpO1xuXHR9LFxuXG5cdHJlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5fbWFwLm9mZignZGJsY2xpY2snLCB0aGlzLl9vbkRvdWJsZUNsaWNrLCB0aGlzKTtcblx0fSxcblxuXHRfb25Eb3VibGVDbGljazogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuXHRcdCAgICBvbGRab29tID0gbWFwLmdldFpvb20oKSxcblx0XHQgICAgZGVsdGEgPSBtYXAub3B0aW9ucy56b29tRGVsdGEsXG5cdFx0ICAgIHpvb20gPSBlLm9yaWdpbmFsRXZlbnQuc2hpZnRLZXkgPyBvbGRab29tIC0gZGVsdGEgOiBvbGRab29tICsgZGVsdGE7XG5cblx0XHRpZiAobWFwLm9wdGlvbnMuZG91YmxlQ2xpY2tab29tID09PSAnY2VudGVyJykge1xuXHRcdFx0bWFwLnNldFpvb20oem9vbSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdG1hcC5zZXRab29tQXJvdW5kKGUuY29udGFpbmVyUG9pbnQsIHpvb20pO1xuXHRcdH1cblx0fVxufSk7XG5cbi8vIEBzZWN0aW9uIEhhbmRsZXJzXG4vL1xuLy8gTWFwIHByb3BlcnRpZXMgaW5jbHVkZSBpbnRlcmFjdGlvbiBoYW5kbGVycyB0aGF0IGFsbG93IHlvdSB0byBjb250cm9sXG4vLyBpbnRlcmFjdGlvbiBiZWhhdmlvciBpbiBydW50aW1lLCBlbmFibGluZyBvciBkaXNhYmxpbmcgY2VydGFpbiBmZWF0dXJlcyBzdWNoXG4vLyBhcyBkcmFnZ2luZyBvciB0b3VjaCB6b29tIChzZWUgYEhhbmRsZXJgIG1ldGhvZHMpLiBGb3IgZXhhbXBsZTpcbi8vXG4vLyBgYGBqc1xuLy8gbWFwLmRvdWJsZUNsaWNrWm9vbS5kaXNhYmxlKCk7XG4vLyBgYGBcbi8vXG4vLyBAcHJvcGVydHkgZG91YmxlQ2xpY2tab29tOiBIYW5kbGVyXG4vLyBEb3VibGUgY2xpY2sgem9vbSBoYW5kbGVyLlxuTWFwLmFkZEluaXRIb29rKCdhZGRIYW5kbGVyJywgJ2RvdWJsZUNsaWNrWm9vbScsIERvdWJsZUNsaWNrWm9vbSk7XG5cbi8qXG4gKiBMLkhhbmRsZXIuTWFwRHJhZyBpcyB1c2VkIHRvIG1ha2UgdGhlIG1hcCBkcmFnZ2FibGUgKHdpdGggcGFubmluZyBpbmVydGlhKSwgZW5hYmxlZCBieSBkZWZhdWx0LlxuICovXG5cbi8vIEBuYW1lc3BhY2UgTWFwXG4vLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG5NYXAubWVyZ2VPcHRpb25zKHtcblx0Ly8gQG9wdGlvbiBkcmFnZ2luZzogQm9vbGVhbiA9IHRydWVcblx0Ly8gV2hldGhlciB0aGUgbWFwIGJlIGRyYWdnYWJsZSB3aXRoIG1vdXNlL3RvdWNoIG9yIG5vdC5cblx0ZHJhZ2dpbmc6IHRydWUsXG5cblx0Ly8gQHNlY3Rpb24gUGFubmluZyBJbmVydGlhIE9wdGlvbnNcblx0Ly8gQG9wdGlvbiBpbmVydGlhOiBCb29sZWFuID0gKlxuXHQvLyBJZiBlbmFibGVkLCBwYW5uaW5nIG9mIHRoZSBtYXAgd2lsbCBoYXZlIGFuIGluZXJ0aWEgZWZmZWN0IHdoZXJlXG5cdC8vIHRoZSBtYXAgYnVpbGRzIG1vbWVudHVtIHdoaWxlIGRyYWdnaW5nIGFuZCBjb250aW51ZXMgbW92aW5nIGluXG5cdC8vIHRoZSBzYW1lIGRpcmVjdGlvbiBmb3Igc29tZSB0aW1lLiBGZWVscyBlc3BlY2lhbGx5IG5pY2Ugb24gdG91Y2hcblx0Ly8gZGV2aWNlcy4gRW5hYmxlZCBieSBkZWZhdWx0IHVubGVzcyBydW5uaW5nIG9uIG9sZCBBbmRyb2lkIGRldmljZXMuXG5cdGluZXJ0aWE6ICFhbmRyb2lkMjMsXG5cblx0Ly8gQG9wdGlvbiBpbmVydGlhRGVjZWxlcmF0aW9uOiBOdW1iZXIgPSAzMDAwXG5cdC8vIFRoZSByYXRlIHdpdGggd2hpY2ggdGhlIGluZXJ0aWFsIG1vdmVtZW50IHNsb3dzIGRvd24sIGluIHBpeGVscy9zZWNvbmTCsi5cblx0aW5lcnRpYURlY2VsZXJhdGlvbjogMzQwMCwgLy8gcHgvc14yXG5cblx0Ly8gQG9wdGlvbiBpbmVydGlhTWF4U3BlZWQ6IE51bWJlciA9IEluZmluaXR5XG5cdC8vIE1heCBzcGVlZCBvZiB0aGUgaW5lcnRpYWwgbW92ZW1lbnQsIGluIHBpeGVscy9zZWNvbmQuXG5cdGluZXJ0aWFNYXhTcGVlZDogSW5maW5pdHksIC8vIHB4L3NcblxuXHQvLyBAb3B0aW9uIGVhc2VMaW5lYXJpdHk6IE51bWJlciA9IDAuMlxuXHRlYXNlTGluZWFyaXR5OiAwLjIsXG5cblx0Ly8gVE9ETyByZWZhY3RvciwgbW92ZSB0byBDUlNcblx0Ly8gQG9wdGlvbiB3b3JsZENvcHlKdW1wOiBCb29sZWFuID0gZmFsc2Vcblx0Ly8gV2l0aCB0aGlzIG9wdGlvbiBlbmFibGVkLCB0aGUgbWFwIHRyYWNrcyB3aGVuIHlvdSBwYW4gdG8gYW5vdGhlciBcImNvcHlcIlxuXHQvLyBvZiB0aGUgd29ybGQgYW5kIHNlYW1sZXNzbHkganVtcHMgdG8gdGhlIG9yaWdpbmFsIG9uZSBzbyB0aGF0IGFsbCBvdmVybGF5c1xuXHQvLyBsaWtlIG1hcmtlcnMgYW5kIHZlY3RvciBsYXllcnMgYXJlIHN0aWxsIHZpc2libGUuXG5cdHdvcmxkQ29weUp1bXA6IGZhbHNlLFxuXG5cdC8vIEBvcHRpb24gbWF4Qm91bmRzVmlzY29zaXR5OiBOdW1iZXIgPSAwLjBcblx0Ly8gSWYgYG1heEJvdW5kc2AgaXMgc2V0LCB0aGlzIG9wdGlvbiB3aWxsIGNvbnRyb2wgaG93IHNvbGlkIHRoZSBib3VuZHNcblx0Ly8gYXJlIHdoZW4gZHJhZ2dpbmcgdGhlIG1hcCBhcm91bmQuIFRoZSBkZWZhdWx0IHZhbHVlIG9mIGAwLjBgIGFsbG93cyB0aGVcblx0Ly8gdXNlciB0byBkcmFnIG91dHNpZGUgdGhlIGJvdW5kcyBhdCBub3JtYWwgc3BlZWQsIGhpZ2hlciB2YWx1ZXMgd2lsbFxuXHQvLyBzbG93IGRvd24gbWFwIGRyYWdnaW5nIG91dHNpZGUgYm91bmRzLCBhbmQgYDEuMGAgbWFrZXMgdGhlIGJvdW5kcyBmdWxseVxuXHQvLyBzb2xpZCwgcHJldmVudGluZyB0aGUgdXNlciBmcm9tIGRyYWdnaW5nIG91dHNpZGUgdGhlIGJvdW5kcy5cblx0bWF4Qm91bmRzVmlzY29zaXR5OiAwLjBcbn0pO1xuXG52YXIgRHJhZyA9IEhhbmRsZXIuZXh0ZW5kKHtcblx0YWRkSG9va3M6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoIXRoaXMuX2RyYWdnYWJsZSkge1xuXHRcdFx0dmFyIG1hcCA9IHRoaXMuX21hcDtcblxuXHRcdFx0dGhpcy5fZHJhZ2dhYmxlID0gbmV3IERyYWdnYWJsZShtYXAuX21hcFBhbmUsIG1hcC5fY29udGFpbmVyKTtcblxuXHRcdFx0dGhpcy5fZHJhZ2dhYmxlLm9uKHtcblx0XHRcdFx0ZHJhZ3N0YXJ0OiB0aGlzLl9vbkRyYWdTdGFydCxcblx0XHRcdFx0ZHJhZzogdGhpcy5fb25EcmFnLFxuXHRcdFx0XHRkcmFnZW5kOiB0aGlzLl9vbkRyYWdFbmRcblx0XHRcdH0sIHRoaXMpO1xuXG5cdFx0XHR0aGlzLl9kcmFnZ2FibGUub24oJ3ByZWRyYWcnLCB0aGlzLl9vblByZURyYWdMaW1pdCwgdGhpcyk7XG5cdFx0XHRpZiAobWFwLm9wdGlvbnMud29ybGRDb3B5SnVtcCkge1xuXHRcdFx0XHR0aGlzLl9kcmFnZ2FibGUub24oJ3ByZWRyYWcnLCB0aGlzLl9vblByZURyYWdXcmFwLCB0aGlzKTtcblx0XHRcdFx0bWFwLm9uKCd6b29tZW5kJywgdGhpcy5fb25ab29tRW5kLCB0aGlzKTtcblxuXHRcdFx0XHRtYXAud2hlblJlYWR5KHRoaXMuX29uWm9vbUVuZCwgdGhpcyk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGFkZENsYXNzKHRoaXMuX21hcC5fY29udGFpbmVyLCAnbGVhZmxldC1ncmFiIGxlYWZsZXQtdG91Y2gtZHJhZycpO1xuXHRcdHRoaXMuX2RyYWdnYWJsZS5lbmFibGUoKTtcblx0XHR0aGlzLl9wb3NpdGlvbnMgPSBbXTtcblx0XHR0aGlzLl90aW1lcyA9IFtdO1xuXHR9LFxuXG5cdHJlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmVtb3ZlQ2xhc3ModGhpcy5fbWFwLl9jb250YWluZXIsICdsZWFmbGV0LWdyYWInKTtcblx0XHRyZW1vdmVDbGFzcyh0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ2xlYWZsZXQtdG91Y2gtZHJhZycpO1xuXHRcdHRoaXMuX2RyYWdnYWJsZS5kaXNhYmxlKCk7XG5cdH0sXG5cblx0bW92ZWQ6IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5fZHJhZ2dhYmxlICYmIHRoaXMuX2RyYWdnYWJsZS5fbW92ZWQ7XG5cdH0sXG5cblx0bW92aW5nOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX2RyYWdnYWJsZSAmJiB0aGlzLl9kcmFnZ2FibGUuX21vdmluZztcblx0fSxcblxuXHRfb25EcmFnU3RhcnQ6IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwO1xuXG5cdFx0bWFwLl9zdG9wKCk7XG5cdFx0aWYgKHRoaXMuX21hcC5vcHRpb25zLm1heEJvdW5kcyAmJiB0aGlzLl9tYXAub3B0aW9ucy5tYXhCb3VuZHNWaXNjb3NpdHkpIHtcblx0XHRcdHZhciBib3VuZHMgPSB0b0xhdExuZ0JvdW5kcyh0aGlzLl9tYXAub3B0aW9ucy5tYXhCb3VuZHMpO1xuXG5cdFx0XHR0aGlzLl9vZmZzZXRMaW1pdCA9IHRvQm91bmRzKFxuXHRcdFx0XHR0aGlzLl9tYXAubGF0TG5nVG9Db250YWluZXJQb2ludChib3VuZHMuZ2V0Tm9ydGhXZXN0KCkpLm11bHRpcGx5QnkoLTEpLFxuXHRcdFx0XHR0aGlzLl9tYXAubGF0TG5nVG9Db250YWluZXJQb2ludChib3VuZHMuZ2V0U291dGhFYXN0KCkpLm11bHRpcGx5QnkoLTEpXG5cdFx0XHRcdFx0LmFkZCh0aGlzLl9tYXAuZ2V0U2l6ZSgpKSk7XG5cblx0XHRcdHRoaXMuX3Zpc2Nvc2l0eSA9IE1hdGgubWluKDEuMCwgTWF0aC5tYXgoMC4wLCB0aGlzLl9tYXAub3B0aW9ucy5tYXhCb3VuZHNWaXNjb3NpdHkpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5fb2Zmc2V0TGltaXQgPSBudWxsO1xuXHRcdH1cblxuXHRcdG1hcFxuXHRcdCAgICAuZmlyZSgnbW92ZXN0YXJ0Jylcblx0XHQgICAgLmZpcmUoJ2RyYWdzdGFydCcpO1xuXG5cdFx0aWYgKG1hcC5vcHRpb25zLmluZXJ0aWEpIHtcblx0XHRcdHRoaXMuX3Bvc2l0aW9ucyA9IFtdO1xuXHRcdFx0dGhpcy5fdGltZXMgPSBbXTtcblx0XHR9XG5cdH0sXG5cblx0X29uRHJhZzogZnVuY3Rpb24gKGUpIHtcblx0XHRpZiAodGhpcy5fbWFwLm9wdGlvbnMuaW5lcnRpYSkge1xuXHRcdFx0dmFyIHRpbWUgPSB0aGlzLl9sYXN0VGltZSA9ICtuZXcgRGF0ZSgpLFxuXHRcdFx0ICAgIHBvcyA9IHRoaXMuX2xhc3RQb3MgPSB0aGlzLl9kcmFnZ2FibGUuX2Fic1BvcyB8fCB0aGlzLl9kcmFnZ2FibGUuX25ld1BvcztcblxuXHRcdFx0dGhpcy5fcG9zaXRpb25zLnB1c2gocG9zKTtcblx0XHRcdHRoaXMuX3RpbWVzLnB1c2godGltZSk7XG5cblx0XHRcdHRoaXMuX3BydW5lUG9zaXRpb25zKHRpbWUpO1xuXHRcdH1cblxuXHRcdHRoaXMuX21hcFxuXHRcdCAgICAuZmlyZSgnbW92ZScsIGUpXG5cdFx0ICAgIC5maXJlKCdkcmFnJywgZSk7XG5cdH0sXG5cblx0X3BydW5lUG9zaXRpb25zOiBmdW5jdGlvbiAodGltZSkge1xuXHRcdHdoaWxlICh0aGlzLl9wb3NpdGlvbnMubGVuZ3RoID4gMSAmJiB0aW1lIC0gdGhpcy5fdGltZXNbMF0gPiA1MCkge1xuXHRcdFx0dGhpcy5fcG9zaXRpb25zLnNoaWZ0KCk7XG5cdFx0XHR0aGlzLl90aW1lcy5zaGlmdCgpO1xuXHRcdH1cblx0fSxcblxuXHRfb25ab29tRW5kOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIHB4Q2VudGVyID0gdGhpcy5fbWFwLmdldFNpemUoKS5kaXZpZGVCeSgyKSxcblx0XHQgICAgcHhXb3JsZENlbnRlciA9IHRoaXMuX21hcC5sYXRMbmdUb0xheWVyUG9pbnQoWzAsIDBdKTtcblxuXHRcdHRoaXMuX2luaXRpYWxXb3JsZE9mZnNldCA9IHB4V29ybGRDZW50ZXIuc3VidHJhY3QocHhDZW50ZXIpLng7XG5cdFx0dGhpcy5fd29ybGRXaWR0aCA9IHRoaXMuX21hcC5nZXRQaXhlbFdvcmxkQm91bmRzKCkuZ2V0U2l6ZSgpLng7XG5cdH0sXG5cblx0X3Zpc2NvdXNMaW1pdDogZnVuY3Rpb24gKHZhbHVlLCB0aHJlc2hvbGQpIHtcblx0XHRyZXR1cm4gdmFsdWUgLSAodmFsdWUgLSB0aHJlc2hvbGQpICogdGhpcy5fdmlzY29zaXR5O1xuXHR9LFxuXG5cdF9vblByZURyYWdMaW1pdDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICghdGhpcy5fdmlzY29zaXR5IHx8ICF0aGlzLl9vZmZzZXRMaW1pdCkgeyByZXR1cm47IH1cblxuXHRcdHZhciBvZmZzZXQgPSB0aGlzLl9kcmFnZ2FibGUuX25ld1Bvcy5zdWJ0cmFjdCh0aGlzLl9kcmFnZ2FibGUuX3N0YXJ0UG9zKTtcblxuXHRcdHZhciBsaW1pdCA9IHRoaXMuX29mZnNldExpbWl0O1xuXHRcdGlmIChvZmZzZXQueCA8IGxpbWl0Lm1pbi54KSB7IG9mZnNldC54ID0gdGhpcy5fdmlzY291c0xpbWl0KG9mZnNldC54LCBsaW1pdC5taW4ueCk7IH1cblx0XHRpZiAob2Zmc2V0LnkgPCBsaW1pdC5taW4ueSkgeyBvZmZzZXQueSA9IHRoaXMuX3Zpc2NvdXNMaW1pdChvZmZzZXQueSwgbGltaXQubWluLnkpOyB9XG5cdFx0aWYgKG9mZnNldC54ID4gbGltaXQubWF4LngpIHsgb2Zmc2V0LnggPSB0aGlzLl92aXNjb3VzTGltaXQob2Zmc2V0LngsIGxpbWl0Lm1heC54KTsgfVxuXHRcdGlmIChvZmZzZXQueSA+IGxpbWl0Lm1heC55KSB7IG9mZnNldC55ID0gdGhpcy5fdmlzY291c0xpbWl0KG9mZnNldC55LCBsaW1pdC5tYXgueSk7IH1cblxuXHRcdHRoaXMuX2RyYWdnYWJsZS5fbmV3UG9zID0gdGhpcy5fZHJhZ2dhYmxlLl9zdGFydFBvcy5hZGQob2Zmc2V0KTtcblx0fSxcblxuXHRfb25QcmVEcmFnV3JhcDogZnVuY3Rpb24gKCkge1xuXHRcdC8vIFRPRE8gcmVmYWN0b3IgdG8gYmUgYWJsZSB0byBhZGp1c3QgbWFwIHBhbmUgcG9zaXRpb24gYWZ0ZXIgem9vbVxuXHRcdHZhciB3b3JsZFdpZHRoID0gdGhpcy5fd29ybGRXaWR0aCxcblx0XHQgICAgaGFsZldpZHRoID0gTWF0aC5yb3VuZCh3b3JsZFdpZHRoIC8gMiksXG5cdFx0ICAgIGR4ID0gdGhpcy5faW5pdGlhbFdvcmxkT2Zmc2V0LFxuXHRcdCAgICB4ID0gdGhpcy5fZHJhZ2dhYmxlLl9uZXdQb3MueCxcblx0XHQgICAgbmV3WDEgPSAoeCAtIGhhbGZXaWR0aCArIGR4KSAlIHdvcmxkV2lkdGggKyBoYWxmV2lkdGggLSBkeCxcblx0XHQgICAgbmV3WDIgPSAoeCArIGhhbGZXaWR0aCArIGR4KSAlIHdvcmxkV2lkdGggLSBoYWxmV2lkdGggLSBkeCxcblx0XHQgICAgbmV3WCA9IE1hdGguYWJzKG5ld1gxICsgZHgpIDwgTWF0aC5hYnMobmV3WDIgKyBkeCkgPyBuZXdYMSA6IG5ld1gyO1xuXG5cdFx0dGhpcy5fZHJhZ2dhYmxlLl9hYnNQb3MgPSB0aGlzLl9kcmFnZ2FibGUuX25ld1Bvcy5jbG9uZSgpO1xuXHRcdHRoaXMuX2RyYWdnYWJsZS5fbmV3UG9zLnggPSBuZXdYO1xuXHR9LFxuXG5cdF9vbkRyYWdFbmQ6IGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcblx0XHQgICAgb3B0aW9ucyA9IG1hcC5vcHRpb25zLFxuXG5cdFx0ICAgIG5vSW5lcnRpYSA9ICFvcHRpb25zLmluZXJ0aWEgfHwgdGhpcy5fdGltZXMubGVuZ3RoIDwgMjtcblxuXHRcdG1hcC5maXJlKCdkcmFnZW5kJywgZSk7XG5cblx0XHRpZiAobm9JbmVydGlhKSB7XG5cdFx0XHRtYXAuZmlyZSgnbW92ZWVuZCcpO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX3BydW5lUG9zaXRpb25zKCtuZXcgRGF0ZSgpKTtcblxuXHRcdFx0dmFyIGRpcmVjdGlvbiA9IHRoaXMuX2xhc3RQb3Muc3VidHJhY3QodGhpcy5fcG9zaXRpb25zWzBdKSxcblx0XHRcdCAgICBkdXJhdGlvbiA9ICh0aGlzLl9sYXN0VGltZSAtIHRoaXMuX3RpbWVzWzBdKSAvIDEwMDAsXG5cdFx0XHQgICAgZWFzZSA9IG9wdGlvbnMuZWFzZUxpbmVhcml0eSxcblxuXHRcdFx0ICAgIHNwZWVkVmVjdG9yID0gZGlyZWN0aW9uLm11bHRpcGx5QnkoZWFzZSAvIGR1cmF0aW9uKSxcblx0XHRcdCAgICBzcGVlZCA9IHNwZWVkVmVjdG9yLmRpc3RhbmNlVG8oWzAsIDBdKSxcblxuXHRcdFx0ICAgIGxpbWl0ZWRTcGVlZCA9IE1hdGgubWluKG9wdGlvbnMuaW5lcnRpYU1heFNwZWVkLCBzcGVlZCksXG5cdFx0XHQgICAgbGltaXRlZFNwZWVkVmVjdG9yID0gc3BlZWRWZWN0b3IubXVsdGlwbHlCeShsaW1pdGVkU3BlZWQgLyBzcGVlZCksXG5cblx0XHRcdCAgICBkZWNlbGVyYXRpb25EdXJhdGlvbiA9IGxpbWl0ZWRTcGVlZCAvIChvcHRpb25zLmluZXJ0aWFEZWNlbGVyYXRpb24gKiBlYXNlKSxcblx0XHRcdCAgICBvZmZzZXQgPSBsaW1pdGVkU3BlZWRWZWN0b3IubXVsdGlwbHlCeSgtZGVjZWxlcmF0aW9uRHVyYXRpb24gLyAyKS5yb3VuZCgpO1xuXG5cdFx0XHRpZiAoIW9mZnNldC54ICYmICFvZmZzZXQueSkge1xuXHRcdFx0XHRtYXAuZmlyZSgnbW92ZWVuZCcpO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvZmZzZXQgPSBtYXAuX2xpbWl0T2Zmc2V0KG9mZnNldCwgbWFwLm9wdGlvbnMubWF4Qm91bmRzKTtcblxuXHRcdFx0XHRyZXF1ZXN0QW5pbUZyYW1lKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRtYXAucGFuQnkob2Zmc2V0LCB7XG5cdFx0XHRcdFx0XHRkdXJhdGlvbjogZGVjZWxlcmF0aW9uRHVyYXRpb24sXG5cdFx0XHRcdFx0XHRlYXNlTGluZWFyaXR5OiBlYXNlLFxuXHRcdFx0XHRcdFx0bm9Nb3ZlU3RhcnQ6IHRydWUsXG5cdFx0XHRcdFx0XHRhbmltYXRlOiB0cnVlXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufSk7XG5cbi8vIEBzZWN0aW9uIEhhbmRsZXJzXG4vLyBAcHJvcGVydHkgZHJhZ2dpbmc6IEhhbmRsZXJcbi8vIE1hcCBkcmFnZ2luZyBoYW5kbGVyIChieSBib3RoIG1vdXNlIGFuZCB0b3VjaCkuXG5NYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAnZHJhZ2dpbmcnLCBEcmFnKTtcblxuLypcbiAqIEwuTWFwLktleWJvYXJkIGlzIGhhbmRsaW5nIGtleWJvYXJkIGludGVyYWN0aW9uIHdpdGggdGhlIG1hcCwgZW5hYmxlZCBieSBkZWZhdWx0LlxuICovXG5cbi8vIEBuYW1lc3BhY2UgTWFwXG4vLyBAc2VjdGlvbiBLZXlib2FyZCBOYXZpZ2F0aW9uIE9wdGlvbnNcbk1hcC5tZXJnZU9wdGlvbnMoe1xuXHQvLyBAb3B0aW9uIGtleWJvYXJkOiBCb29sZWFuID0gdHJ1ZVxuXHQvLyBNYWtlcyB0aGUgbWFwIGZvY3VzYWJsZSBhbmQgYWxsb3dzIHVzZXJzIHRvIG5hdmlnYXRlIHRoZSBtYXAgd2l0aCBrZXlib2FyZFxuXHQvLyBhcnJvd3MgYW5kIGArYC9gLWAga2V5cy5cblx0a2V5Ym9hcmQ6IHRydWUsXG5cblx0Ly8gQG9wdGlvbiBrZXlib2FyZFBhbkRlbHRhOiBOdW1iZXIgPSA4MFxuXHQvLyBBbW91bnQgb2YgcGl4ZWxzIHRvIHBhbiB3aGVuIHByZXNzaW5nIGFuIGFycm93IGtleS5cblx0a2V5Ym9hcmRQYW5EZWx0YTogODBcbn0pO1xuXG52YXIgS2V5Ym9hcmQgPSBIYW5kbGVyLmV4dGVuZCh7XG5cblx0a2V5Q29kZXM6IHtcblx0XHRsZWZ0OiAgICBbMzddLFxuXHRcdHJpZ2h0OiAgIFszOV0sXG5cdFx0ZG93bjogICAgWzQwXSxcblx0XHR1cDogICAgICBbMzhdLFxuXHRcdHpvb21JbjogIFsxODcsIDEwNywgNjEsIDE3MV0sXG5cdFx0em9vbU91dDogWzE4OSwgMTA5LCA1NCwgMTczXVxuXHR9LFxuXG5cdGluaXRpYWxpemU6IGZ1bmN0aW9uIChtYXApIHtcblx0XHR0aGlzLl9tYXAgPSBtYXA7XG5cblx0XHR0aGlzLl9zZXRQYW5EZWx0YShtYXAub3B0aW9ucy5rZXlib2FyZFBhbkRlbHRhKTtcblx0XHR0aGlzLl9zZXRab29tRGVsdGEobWFwLm9wdGlvbnMuem9vbURlbHRhKTtcblx0fSxcblxuXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBjb250YWluZXIgPSB0aGlzLl9tYXAuX2NvbnRhaW5lcjtcblxuXHRcdC8vIG1ha2UgdGhlIGNvbnRhaW5lciBmb2N1c2FibGUgYnkgdGFiYmluZ1xuXHRcdGlmIChjb250YWluZXIudGFiSW5kZXggPD0gMCkge1xuXHRcdFx0Y29udGFpbmVyLnRhYkluZGV4ID0gJzAnO1xuXHRcdH1cblxuXHRcdG9uKGNvbnRhaW5lciwge1xuXHRcdFx0Zm9jdXM6IHRoaXMuX29uRm9jdXMsXG5cdFx0XHRibHVyOiB0aGlzLl9vbkJsdXIsXG5cdFx0XHRtb3VzZWRvd246IHRoaXMuX29uTW91c2VEb3duXG5cdFx0fSwgdGhpcyk7XG5cblx0XHR0aGlzLl9tYXAub24oe1xuXHRcdFx0Zm9jdXM6IHRoaXMuX2FkZEhvb2tzLFxuXHRcdFx0Ymx1cjogdGhpcy5fcmVtb3ZlSG9va3Ncblx0XHR9LCB0aGlzKTtcblx0fSxcblxuXHRyZW1vdmVIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuX3JlbW92ZUhvb2tzKCk7XG5cblx0XHRvZmYodGhpcy5fbWFwLl9jb250YWluZXIsIHtcblx0XHRcdGZvY3VzOiB0aGlzLl9vbkZvY3VzLFxuXHRcdFx0Ymx1cjogdGhpcy5fb25CbHVyLFxuXHRcdFx0bW91c2Vkb3duOiB0aGlzLl9vbk1vdXNlRG93blxuXHRcdH0sIHRoaXMpO1xuXG5cdFx0dGhpcy5fbWFwLm9mZih7XG5cdFx0XHRmb2N1czogdGhpcy5fYWRkSG9va3MsXG5cdFx0XHRibHVyOiB0aGlzLl9yZW1vdmVIb29rc1xuXHRcdH0sIHRoaXMpO1xuXHR9LFxuXG5cdF9vbk1vdXNlRG93bjogZnVuY3Rpb24gKCkge1xuXHRcdGlmICh0aGlzLl9mb2N1c2VkKSB7IHJldHVybjsgfVxuXG5cdFx0dmFyIGJvZHkgPSBkb2N1bWVudC5ib2R5LFxuXHRcdCAgICBkb2NFbCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCxcblx0XHQgICAgdG9wID0gYm9keS5zY3JvbGxUb3AgfHwgZG9jRWwuc2Nyb2xsVG9wLFxuXHRcdCAgICBsZWZ0ID0gYm9keS5zY3JvbGxMZWZ0IHx8IGRvY0VsLnNjcm9sbExlZnQ7XG5cblx0XHR0aGlzLl9tYXAuX2NvbnRhaW5lci5mb2N1cygpO1xuXG5cdFx0d2luZG93LnNjcm9sbFRvKGxlZnQsIHRvcCk7XG5cdH0sXG5cblx0X29uRm9jdXM6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9mb2N1c2VkID0gdHJ1ZTtcblx0XHR0aGlzLl9tYXAuZmlyZSgnZm9jdXMnKTtcblx0fSxcblxuXHRfb25CbHVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5fZm9jdXNlZCA9IGZhbHNlO1xuXHRcdHRoaXMuX21hcC5maXJlKCdibHVyJyk7XG5cdH0sXG5cblx0X3NldFBhbkRlbHRhOiBmdW5jdGlvbiAocGFuRGVsdGEpIHtcblx0XHR2YXIga2V5cyA9IHRoaXMuX3BhbktleXMgPSB7fSxcblx0XHQgICAgY29kZXMgPSB0aGlzLmtleUNvZGVzLFxuXHRcdCAgICBpLCBsZW47XG5cblx0XHRmb3IgKGkgPSAwLCBsZW4gPSBjb2Rlcy5sZWZ0Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRrZXlzW2NvZGVzLmxlZnRbaV1dID0gWy0xICogcGFuRGVsdGEsIDBdO1xuXHRcdH1cblx0XHRmb3IgKGkgPSAwLCBsZW4gPSBjb2Rlcy5yaWdodC5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0a2V5c1tjb2Rlcy5yaWdodFtpXV0gPSBbcGFuRGVsdGEsIDBdO1xuXHRcdH1cblx0XHRmb3IgKGkgPSAwLCBsZW4gPSBjb2Rlcy5kb3duLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRrZXlzW2NvZGVzLmRvd25baV1dID0gWzAsIHBhbkRlbHRhXTtcblx0XHR9XG5cdFx0Zm9yIChpID0gMCwgbGVuID0gY29kZXMudXAubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdGtleXNbY29kZXMudXBbaV1dID0gWzAsIC0xICogcGFuRGVsdGFdO1xuXHRcdH1cblx0fSxcblxuXHRfc2V0Wm9vbURlbHRhOiBmdW5jdGlvbiAoem9vbURlbHRhKSB7XG5cdFx0dmFyIGtleXMgPSB0aGlzLl96b29tS2V5cyA9IHt9LFxuXHRcdCAgICBjb2RlcyA9IHRoaXMua2V5Q29kZXMsXG5cdFx0ICAgIGksIGxlbjtcblxuXHRcdGZvciAoaSA9IDAsIGxlbiA9IGNvZGVzLnpvb21Jbi5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0a2V5c1tjb2Rlcy56b29tSW5baV1dID0gem9vbURlbHRhO1xuXHRcdH1cblx0XHRmb3IgKGkgPSAwLCBsZW4gPSBjb2Rlcy56b29tT3V0Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG5cdFx0XHRrZXlzW2NvZGVzLnpvb21PdXRbaV1dID0gLXpvb21EZWx0YTtcblx0XHR9XG5cdH0sXG5cblx0X2FkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0b24oZG9jdW1lbnQsICdrZXlkb3duJywgdGhpcy5fb25LZXlEb3duLCB0aGlzKTtcblx0fSxcblxuXHRfcmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcblx0XHRvZmYoZG9jdW1lbnQsICdrZXlkb3duJywgdGhpcy5fb25LZXlEb3duLCB0aGlzKTtcblx0fSxcblxuXHRfb25LZXlEb3duOiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmIChlLmFsdEtleSB8fCBlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSB7IHJldHVybjsgfVxuXG5cdFx0dmFyIGtleSA9IGUua2V5Q29kZSxcblx0XHQgICAgbWFwID0gdGhpcy5fbWFwLFxuXHRcdCAgICBvZmZzZXQ7XG5cblx0XHRpZiAoa2V5IGluIHRoaXMuX3BhbktleXMpIHtcblxuXHRcdFx0aWYgKG1hcC5fcGFuQW5pbSAmJiBtYXAuX3BhbkFuaW0uX2luUHJvZ3Jlc3MpIHsgcmV0dXJuOyB9XG5cblx0XHRcdG9mZnNldCA9IHRoaXMuX3BhbktleXNba2V5XTtcblx0XHRcdGlmIChlLnNoaWZ0S2V5KSB7XG5cdFx0XHRcdG9mZnNldCA9IHRvUG9pbnQob2Zmc2V0KS5tdWx0aXBseUJ5KDMpO1xuXHRcdFx0fVxuXG5cdFx0XHRtYXAucGFuQnkob2Zmc2V0KTtcblxuXHRcdFx0aWYgKG1hcC5vcHRpb25zLm1heEJvdW5kcykge1xuXHRcdFx0XHRtYXAucGFuSW5zaWRlQm91bmRzKG1hcC5vcHRpb25zLm1heEJvdW5kcyk7XG5cdFx0XHR9XG5cblx0XHR9IGVsc2UgaWYgKGtleSBpbiB0aGlzLl96b29tS2V5cykge1xuXHRcdFx0bWFwLnNldFpvb20obWFwLmdldFpvb20oKSArIChlLnNoaWZ0S2V5ID8gMyA6IDEpICogdGhpcy5fem9vbUtleXNba2V5XSk7XG5cblx0XHR9IGVsc2UgaWYgKGtleSA9PT0gMjcgJiYgbWFwLl9wb3B1cCAmJiBtYXAuX3BvcHVwLm9wdGlvbnMuY2xvc2VPbkVzY2FwZUtleSkge1xuXHRcdFx0bWFwLmNsb3NlUG9wdXAoKTtcblxuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0c3RvcChlKTtcblx0fVxufSk7XG5cbi8vIEBzZWN0aW9uIEhhbmRsZXJzXG4vLyBAc2VjdGlvbiBIYW5kbGVyc1xuLy8gQHByb3BlcnR5IGtleWJvYXJkOiBIYW5kbGVyXG4vLyBLZXlib2FyZCBuYXZpZ2F0aW9uIGhhbmRsZXIuXG5NYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAna2V5Ym9hcmQnLCBLZXlib2FyZCk7XG5cbi8qXG4gKiBMLkhhbmRsZXIuU2Nyb2xsV2hlZWxab29tIGlzIHVzZWQgYnkgTC5NYXAgdG8gZW5hYmxlIG1vdXNlIHNjcm9sbCB3aGVlbCB6b29tIG9uIHRoZSBtYXAuXG4gKi9cblxuLy8gQG5hbWVzcGFjZSBNYXBcbi8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcbk1hcC5tZXJnZU9wdGlvbnMoe1xuXHQvLyBAc2VjdGlvbiBNb3VzZXdoZWVsIG9wdGlvbnNcblx0Ly8gQG9wdGlvbiBzY3JvbGxXaGVlbFpvb206IEJvb2xlYW58U3RyaW5nID0gdHJ1ZVxuXHQvLyBXaGV0aGVyIHRoZSBtYXAgY2FuIGJlIHpvb21lZCBieSB1c2luZyB0aGUgbW91c2Ugd2hlZWwuIElmIHBhc3NlZCBgJ2NlbnRlcidgLFxuXHQvLyBpdCB3aWxsIHpvb20gdG8gdGhlIGNlbnRlciBvZiB0aGUgdmlldyByZWdhcmRsZXNzIG9mIHdoZXJlIHRoZSBtb3VzZSB3YXMuXG5cdHNjcm9sbFdoZWVsWm9vbTogdHJ1ZSxcblxuXHQvLyBAb3B0aW9uIHdoZWVsRGVib3VuY2VUaW1lOiBOdW1iZXIgPSA0MFxuXHQvLyBMaW1pdHMgdGhlIHJhdGUgYXQgd2hpY2ggYSB3aGVlbCBjYW4gZmlyZSAoaW4gbWlsbGlzZWNvbmRzKS4gQnkgZGVmYXVsdFxuXHQvLyB1c2VyIGNhbid0IHpvb20gdmlhIHdoZWVsIG1vcmUgb2Z0ZW4gdGhhbiBvbmNlIHBlciA0MCBtcy5cblx0d2hlZWxEZWJvdW5jZVRpbWU6IDQwLFxuXG5cdC8vIEBvcHRpb24gd2hlZWxQeFBlclpvb21MZXZlbDogTnVtYmVyID0gNjBcblx0Ly8gSG93IG1hbnkgc2Nyb2xsIHBpeGVscyAoYXMgcmVwb3J0ZWQgYnkgW0wuRG9tRXZlbnQuZ2V0V2hlZWxEZWx0YV0oI2RvbWV2ZW50LWdldHdoZWVsZGVsdGEpKVxuXHQvLyBtZWFuIGEgY2hhbmdlIG9mIG9uZSBmdWxsIHpvb20gbGV2ZWwuIFNtYWxsZXIgdmFsdWVzIHdpbGwgbWFrZSB3aGVlbC16b29taW5nXG5cdC8vIGZhc3RlciAoYW5kIHZpY2UgdmVyc2EpLlxuXHR3aGVlbFB4UGVyWm9vbUxldmVsOiA2MFxufSk7XG5cbnZhciBTY3JvbGxXaGVlbFpvb20gPSBIYW5kbGVyLmV4dGVuZCh7XG5cdGFkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0b24odGhpcy5fbWFwLl9jb250YWluZXIsICdtb3VzZXdoZWVsJywgdGhpcy5fb25XaGVlbFNjcm9sbCwgdGhpcyk7XG5cblx0XHR0aGlzLl9kZWx0YSA9IDA7XG5cdH0sXG5cblx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcblx0XHRvZmYodGhpcy5fbWFwLl9jb250YWluZXIsICdtb3VzZXdoZWVsJywgdGhpcy5fb25XaGVlbFNjcm9sbCwgdGhpcyk7XG5cdH0sXG5cblx0X29uV2hlZWxTY3JvbGw6IGZ1bmN0aW9uIChlKSB7XG5cdFx0dmFyIGRlbHRhID0gZ2V0V2hlZWxEZWx0YShlKTtcblxuXHRcdHZhciBkZWJvdW5jZSA9IHRoaXMuX21hcC5vcHRpb25zLndoZWVsRGVib3VuY2VUaW1lO1xuXG5cdFx0dGhpcy5fZGVsdGEgKz0gZGVsdGE7XG5cdFx0dGhpcy5fbGFzdE1vdXNlUG9zID0gdGhpcy5fbWFwLm1vdXNlRXZlbnRUb0NvbnRhaW5lclBvaW50KGUpO1xuXG5cdFx0aWYgKCF0aGlzLl9zdGFydFRpbWUpIHtcblx0XHRcdHRoaXMuX3N0YXJ0VGltZSA9ICtuZXcgRGF0ZSgpO1xuXHRcdH1cblxuXHRcdHZhciBsZWZ0ID0gTWF0aC5tYXgoZGVib3VuY2UgLSAoK25ldyBEYXRlKCkgLSB0aGlzLl9zdGFydFRpbWUpLCAwKTtcblxuXHRcdGNsZWFyVGltZW91dCh0aGlzLl90aW1lcik7XG5cdFx0dGhpcy5fdGltZXIgPSBzZXRUaW1lb3V0KGJpbmQodGhpcy5fcGVyZm9ybVpvb20sIHRoaXMpLCBsZWZ0KTtcblxuXHRcdHN0b3AoZSk7XG5cdH0sXG5cblx0X3BlcmZvcm1ab29tOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG1hcCA9IHRoaXMuX21hcCxcblx0XHQgICAgem9vbSA9IG1hcC5nZXRab29tKCksXG5cdFx0ICAgIHNuYXAgPSB0aGlzLl9tYXAub3B0aW9ucy56b29tU25hcCB8fCAwO1xuXG5cdFx0bWFwLl9zdG9wKCk7IC8vIHN0b3AgcGFubmluZyBhbmQgZmx5IGFuaW1hdGlvbnMgaWYgYW55XG5cblx0XHQvLyBtYXAgdGhlIGRlbHRhIHdpdGggYSBzaWdtb2lkIGZ1bmN0aW9uIHRvIC00Li40IHJhbmdlIGxlYW5pbmcgb24gLTEuLjFcblx0XHR2YXIgZDIgPSB0aGlzLl9kZWx0YSAvICh0aGlzLl9tYXAub3B0aW9ucy53aGVlbFB4UGVyWm9vbUxldmVsICogNCksXG5cdFx0ICAgIGQzID0gNCAqIE1hdGgubG9nKDIgLyAoMSArIE1hdGguZXhwKC1NYXRoLmFicyhkMikpKSkgLyBNYXRoLkxOMixcblx0XHQgICAgZDQgPSBzbmFwID8gTWF0aC5jZWlsKGQzIC8gc25hcCkgKiBzbmFwIDogZDMsXG5cdFx0ICAgIGRlbHRhID0gbWFwLl9saW1pdFpvb20oem9vbSArICh0aGlzLl9kZWx0YSA+IDAgPyBkNCA6IC1kNCkpIC0gem9vbTtcblxuXHRcdHRoaXMuX2RlbHRhID0gMDtcblx0XHR0aGlzLl9zdGFydFRpbWUgPSBudWxsO1xuXG5cdFx0aWYgKCFkZWx0YSkgeyByZXR1cm47IH1cblxuXHRcdGlmIChtYXAub3B0aW9ucy5zY3JvbGxXaGVlbFpvb20gPT09ICdjZW50ZXInKSB7XG5cdFx0XHRtYXAuc2V0Wm9vbSh6b29tICsgZGVsdGEpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRtYXAuc2V0Wm9vbUFyb3VuZCh0aGlzLl9sYXN0TW91c2VQb3MsIHpvb20gKyBkZWx0YSk7XG5cdFx0fVxuXHR9XG59KTtcblxuLy8gQHNlY3Rpb24gSGFuZGxlcnNcbi8vIEBwcm9wZXJ0eSBzY3JvbGxXaGVlbFpvb206IEhhbmRsZXJcbi8vIFNjcm9sbCB3aGVlbCB6b29tIGhhbmRsZXIuXG5NYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAnc2Nyb2xsV2hlZWxab29tJywgU2Nyb2xsV2hlZWxab29tKTtcblxuLypcbiAqIEwuTWFwLlRhcCBpcyB1c2VkIHRvIGVuYWJsZSBtb2JpbGUgaGFja3MgbGlrZSBxdWljayB0YXBzIGFuZCBsb25nIGhvbGQuXG4gKi9cblxuLy8gQG5hbWVzcGFjZSBNYXBcbi8vIEBzZWN0aW9uIEludGVyYWN0aW9uIE9wdGlvbnNcbk1hcC5tZXJnZU9wdGlvbnMoe1xuXHQvLyBAc2VjdGlvbiBUb3VjaCBpbnRlcmFjdGlvbiBvcHRpb25zXG5cdC8vIEBvcHRpb24gdGFwOiBCb29sZWFuID0gdHJ1ZVxuXHQvLyBFbmFibGVzIG1vYmlsZSBoYWNrcyBmb3Igc3VwcG9ydGluZyBpbnN0YW50IHRhcHMgKGZpeGluZyAyMDBtcyBjbGlja1xuXHQvLyBkZWxheSBvbiBpT1MvQW5kcm9pZCkgYW5kIHRvdWNoIGhvbGRzIChmaXJlZCBhcyBgY29udGV4dG1lbnVgIGV2ZW50cykuXG5cdHRhcDogdHJ1ZSxcblxuXHQvLyBAb3B0aW9uIHRhcFRvbGVyYW5jZTogTnVtYmVyID0gMTVcblx0Ly8gVGhlIG1heCBudW1iZXIgb2YgcGl4ZWxzIGEgdXNlciBjYW4gc2hpZnQgaGlzIGZpbmdlciBkdXJpbmcgdG91Y2hcblx0Ly8gZm9yIGl0IHRvIGJlIGNvbnNpZGVyZWQgYSB2YWxpZCB0YXAuXG5cdHRhcFRvbGVyYW5jZTogMTVcbn0pO1xuXG52YXIgVGFwID0gSGFuZGxlci5leHRlbmQoe1xuXHRhZGRIb29rczogZnVuY3Rpb24gKCkge1xuXHRcdG9uKHRoaXMuX21hcC5fY29udGFpbmVyLCAndG91Y2hzdGFydCcsIHRoaXMuX29uRG93biwgdGhpcyk7XG5cdH0sXG5cblx0cmVtb3ZlSG9va3M6IGZ1bmN0aW9uICgpIHtcblx0XHRvZmYodGhpcy5fbWFwLl9jb250YWluZXIsICd0b3VjaHN0YXJ0JywgdGhpcy5fb25Eb3duLCB0aGlzKTtcblx0fSxcblxuXHRfb25Eb3duOiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmICghZS50b3VjaGVzKSB7IHJldHVybjsgfVxuXG5cdFx0cHJldmVudERlZmF1bHQoZSk7XG5cblx0XHR0aGlzLl9maXJlQ2xpY2sgPSB0cnVlO1xuXG5cdFx0Ly8gZG9uJ3Qgc2ltdWxhdGUgY2xpY2sgb3IgdHJhY2sgbG9uZ3ByZXNzIGlmIG1vcmUgdGhhbiAxIHRvdWNoXG5cdFx0aWYgKGUudG91Y2hlcy5sZW5ndGggPiAxKSB7XG5cdFx0XHR0aGlzLl9maXJlQ2xpY2sgPSBmYWxzZTtcblx0XHRcdGNsZWFyVGltZW91dCh0aGlzLl9ob2xkVGltZW91dCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIGZpcnN0ID0gZS50b3VjaGVzWzBdLFxuXHRcdCAgICBlbCA9IGZpcnN0LnRhcmdldDtcblxuXHRcdHRoaXMuX3N0YXJ0UG9zID0gdGhpcy5fbmV3UG9zID0gbmV3IFBvaW50KGZpcnN0LmNsaWVudFgsIGZpcnN0LmNsaWVudFkpO1xuXG5cdFx0Ly8gaWYgdG91Y2hpbmcgYSBsaW5rLCBoaWdobGlnaHQgaXRcblx0XHRpZiAoZWwudGFnTmFtZSAmJiBlbC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdhJykge1xuXHRcdFx0YWRkQ2xhc3MoZWwsICdsZWFmbGV0LWFjdGl2ZScpO1xuXHRcdH1cblxuXHRcdC8vIHNpbXVsYXRlIGxvbmcgaG9sZCBidXQgc2V0dGluZyBhIHRpbWVvdXRcblx0XHR0aGlzLl9ob2xkVGltZW91dCA9IHNldFRpbWVvdXQoYmluZChmdW5jdGlvbiAoKSB7XG5cdFx0XHRpZiAodGhpcy5faXNUYXBWYWxpZCgpKSB7XG5cdFx0XHRcdHRoaXMuX2ZpcmVDbGljayA9IGZhbHNlO1xuXHRcdFx0XHR0aGlzLl9vblVwKCk7XG5cdFx0XHRcdHRoaXMuX3NpbXVsYXRlRXZlbnQoJ2NvbnRleHRtZW51JywgZmlyc3QpO1xuXHRcdFx0fVxuXHRcdH0sIHRoaXMpLCAxMDAwKTtcblxuXHRcdHRoaXMuX3NpbXVsYXRlRXZlbnQoJ21vdXNlZG93bicsIGZpcnN0KTtcblxuXHRcdG9uKGRvY3VtZW50LCB7XG5cdFx0XHR0b3VjaG1vdmU6IHRoaXMuX29uTW92ZSxcblx0XHRcdHRvdWNoZW5kOiB0aGlzLl9vblVwXG5cdFx0fSwgdGhpcyk7XG5cdH0sXG5cblx0X29uVXA6IGZ1bmN0aW9uIChlKSB7XG5cdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX2hvbGRUaW1lb3V0KTtcblxuXHRcdG9mZihkb2N1bWVudCwge1xuXHRcdFx0dG91Y2htb3ZlOiB0aGlzLl9vbk1vdmUsXG5cdFx0XHR0b3VjaGVuZDogdGhpcy5fb25VcFxuXHRcdH0sIHRoaXMpO1xuXG5cdFx0aWYgKHRoaXMuX2ZpcmVDbGljayAmJiBlICYmIGUuY2hhbmdlZFRvdWNoZXMpIHtcblxuXHRcdFx0dmFyIGZpcnN0ID0gZS5jaGFuZ2VkVG91Y2hlc1swXSxcblx0XHRcdCAgICBlbCA9IGZpcnN0LnRhcmdldDtcblxuXHRcdFx0aWYgKGVsICYmIGVsLnRhZ05hbWUgJiYgZWwudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnYScpIHtcblx0XHRcdFx0cmVtb3ZlQ2xhc3MoZWwsICdsZWFmbGV0LWFjdGl2ZScpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl9zaW11bGF0ZUV2ZW50KCdtb3VzZXVwJywgZmlyc3QpO1xuXG5cdFx0XHQvLyBzaW11bGF0ZSBjbGljayBpZiB0aGUgdG91Y2ggZGlkbid0IG1vdmUgdG9vIG11Y2hcblx0XHRcdGlmICh0aGlzLl9pc1RhcFZhbGlkKCkpIHtcblx0XHRcdFx0dGhpcy5fc2ltdWxhdGVFdmVudCgnY2xpY2snLCBmaXJzdCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9LFxuXG5cdF9pc1RhcFZhbGlkOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuX25ld1Bvcy5kaXN0YW5jZVRvKHRoaXMuX3N0YXJ0UG9zKSA8PSB0aGlzLl9tYXAub3B0aW9ucy50YXBUb2xlcmFuY2U7XG5cdH0sXG5cblx0X29uTW92ZTogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgZmlyc3QgPSBlLnRvdWNoZXNbMF07XG5cdFx0dGhpcy5fbmV3UG9zID0gbmV3IFBvaW50KGZpcnN0LmNsaWVudFgsIGZpcnN0LmNsaWVudFkpO1xuXHRcdHRoaXMuX3NpbXVsYXRlRXZlbnQoJ21vdXNlbW92ZScsIGZpcnN0KTtcblx0fSxcblxuXHRfc2ltdWxhdGVFdmVudDogZnVuY3Rpb24gKHR5cGUsIGUpIHtcblx0XHR2YXIgc2ltdWxhdGVkRXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnTW91c2VFdmVudHMnKTtcblxuXHRcdHNpbXVsYXRlZEV2ZW50Ll9zaW11bGF0ZWQgPSB0cnVlO1xuXHRcdGUudGFyZ2V0Ll9zaW11bGF0ZWRDbGljayA9IHRydWU7XG5cblx0XHRzaW11bGF0ZWRFdmVudC5pbml0TW91c2VFdmVudChcblx0XHQgICAgICAgIHR5cGUsIHRydWUsIHRydWUsIHdpbmRvdywgMSxcblx0XHQgICAgICAgIGUuc2NyZWVuWCwgZS5zY3JlZW5ZLFxuXHRcdCAgICAgICAgZS5jbGllbnRYLCBlLmNsaWVudFksXG5cdFx0ICAgICAgICBmYWxzZSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgMCwgbnVsbCk7XG5cblx0XHRlLnRhcmdldC5kaXNwYXRjaEV2ZW50KHNpbXVsYXRlZEV2ZW50KTtcblx0fVxufSk7XG5cbi8vIEBzZWN0aW9uIEhhbmRsZXJzXG4vLyBAcHJvcGVydHkgdGFwOiBIYW5kbGVyXG4vLyBNb2JpbGUgdG91Y2ggaGFja3MgKHF1aWNrIHRhcCBhbmQgdG91Y2ggaG9sZCkgaGFuZGxlci5cbmlmICh0b3VjaCAmJiAhcG9pbnRlcikge1xuXHRNYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAndGFwJywgVGFwKTtcbn1cblxuLypcbiAqIEwuSGFuZGxlci5Ub3VjaFpvb20gaXMgdXNlZCBieSBMLk1hcCB0byBhZGQgcGluY2ggem9vbSBvbiBzdXBwb3J0ZWQgbW9iaWxlIGJyb3dzZXJzLlxuICovXG5cbi8vIEBuYW1lc3BhY2UgTWFwXG4vLyBAc2VjdGlvbiBJbnRlcmFjdGlvbiBPcHRpb25zXG5NYXAubWVyZ2VPcHRpb25zKHtcblx0Ly8gQHNlY3Rpb24gVG91Y2ggaW50ZXJhY3Rpb24gb3B0aW9uc1xuXHQvLyBAb3B0aW9uIHRvdWNoWm9vbTogQm9vbGVhbnxTdHJpbmcgPSAqXG5cdC8vIFdoZXRoZXIgdGhlIG1hcCBjYW4gYmUgem9vbWVkIGJ5IHRvdWNoLWRyYWdnaW5nIHdpdGggdHdvIGZpbmdlcnMuIElmXG5cdC8vIHBhc3NlZCBgJ2NlbnRlcidgLCBpdCB3aWxsIHpvb20gdG8gdGhlIGNlbnRlciBvZiB0aGUgdmlldyByZWdhcmRsZXNzIG9mXG5cdC8vIHdoZXJlIHRoZSB0b3VjaCBldmVudHMgKGZpbmdlcnMpIHdlcmUuIEVuYWJsZWQgZm9yIHRvdWNoLWNhcGFibGUgd2ViXG5cdC8vIGJyb3dzZXJzIGV4Y2VwdCBmb3Igb2xkIEFuZHJvaWRzLlxuXHR0b3VjaFpvb206IHRvdWNoICYmICFhbmRyb2lkMjMsXG5cblx0Ly8gQG9wdGlvbiBib3VuY2VBdFpvb21MaW1pdHM6IEJvb2xlYW4gPSB0cnVlXG5cdC8vIFNldCBpdCB0byBmYWxzZSBpZiB5b3UgZG9uJ3Qgd2FudCB0aGUgbWFwIHRvIHpvb20gYmV5b25kIG1pbi9tYXggem9vbVxuXHQvLyBhbmQgdGhlbiBib3VuY2UgYmFjayB3aGVuIHBpbmNoLXpvb21pbmcuXG5cdGJvdW5jZUF0Wm9vbUxpbWl0czogdHJ1ZVxufSk7XG5cbnZhciBUb3VjaFpvb20gPSBIYW5kbGVyLmV4dGVuZCh7XG5cdGFkZEhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0YWRkQ2xhc3ModGhpcy5fbWFwLl9jb250YWluZXIsICdsZWFmbGV0LXRvdWNoLXpvb20nKTtcblx0XHRvbih0aGlzLl9tYXAuX2NvbnRhaW5lciwgJ3RvdWNoc3RhcnQnLCB0aGlzLl9vblRvdWNoU3RhcnQsIHRoaXMpO1xuXHR9LFxuXG5cdHJlbW92ZUhvb2tzOiBmdW5jdGlvbiAoKSB7XG5cdFx0cmVtb3ZlQ2xhc3ModGhpcy5fbWFwLl9jb250YWluZXIsICdsZWFmbGV0LXRvdWNoLXpvb20nKTtcblx0XHRvZmYodGhpcy5fbWFwLl9jb250YWluZXIsICd0b3VjaHN0YXJ0JywgdGhpcy5fb25Ub3VjaFN0YXJ0LCB0aGlzKTtcblx0fSxcblxuXHRfb25Ub3VjaFN0YXJ0OiBmdW5jdGlvbiAoZSkge1xuXHRcdHZhciBtYXAgPSB0aGlzLl9tYXA7XG5cdFx0aWYgKCFlLnRvdWNoZXMgfHwgZS50b3VjaGVzLmxlbmd0aCAhPT0gMiB8fCBtYXAuX2FuaW1hdGluZ1pvb20gfHwgdGhpcy5fem9vbWluZykgeyByZXR1cm47IH1cblxuXHRcdHZhciBwMSA9IG1hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLnRvdWNoZXNbMF0pLFxuXHRcdCAgICBwMiA9IG1hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLnRvdWNoZXNbMV0pO1xuXG5cdFx0dGhpcy5fY2VudGVyUG9pbnQgPSBtYXAuZ2V0U2l6ZSgpLl9kaXZpZGVCeSgyKTtcblx0XHR0aGlzLl9zdGFydExhdExuZyA9IG1hcC5jb250YWluZXJQb2ludFRvTGF0TG5nKHRoaXMuX2NlbnRlclBvaW50KTtcblx0XHRpZiAobWFwLm9wdGlvbnMudG91Y2hab29tICE9PSAnY2VudGVyJykge1xuXHRcdFx0dGhpcy5fcGluY2hTdGFydExhdExuZyA9IG1hcC5jb250YWluZXJQb2ludFRvTGF0TG5nKHAxLmFkZChwMikuX2RpdmlkZUJ5KDIpKTtcblx0XHR9XG5cblx0XHR0aGlzLl9zdGFydERpc3QgPSBwMS5kaXN0YW5jZVRvKHAyKTtcblx0XHR0aGlzLl9zdGFydFpvb20gPSBtYXAuZ2V0Wm9vbSgpO1xuXG5cdFx0dGhpcy5fbW92ZWQgPSBmYWxzZTtcblx0XHR0aGlzLl96b29taW5nID0gdHJ1ZTtcblxuXHRcdG1hcC5fc3RvcCgpO1xuXG5cdFx0b24oZG9jdW1lbnQsICd0b3VjaG1vdmUnLCB0aGlzLl9vblRvdWNoTW92ZSwgdGhpcyk7XG5cdFx0b24oZG9jdW1lbnQsICd0b3VjaGVuZCcsIHRoaXMuX29uVG91Y2hFbmQsIHRoaXMpO1xuXG5cdFx0cHJldmVudERlZmF1bHQoZSk7XG5cdH0sXG5cblx0X29uVG91Y2hNb3ZlOiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmICghZS50b3VjaGVzIHx8IGUudG91Y2hlcy5sZW5ndGggIT09IDIgfHwgIXRoaXMuX3pvb21pbmcpIHsgcmV0dXJuOyB9XG5cblx0XHR2YXIgbWFwID0gdGhpcy5fbWFwLFxuXHRcdCAgICBwMSA9IG1hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLnRvdWNoZXNbMF0pLFxuXHRcdCAgICBwMiA9IG1hcC5tb3VzZUV2ZW50VG9Db250YWluZXJQb2ludChlLnRvdWNoZXNbMV0pLFxuXHRcdCAgICBzY2FsZSA9IHAxLmRpc3RhbmNlVG8ocDIpIC8gdGhpcy5fc3RhcnREaXN0O1xuXG5cdFx0dGhpcy5fem9vbSA9IG1hcC5nZXRTY2FsZVpvb20oc2NhbGUsIHRoaXMuX3N0YXJ0Wm9vbSk7XG5cblx0XHRpZiAoIW1hcC5vcHRpb25zLmJvdW5jZUF0Wm9vbUxpbWl0cyAmJiAoXG5cdFx0XHQodGhpcy5fem9vbSA8IG1hcC5nZXRNaW5ab29tKCkgJiYgc2NhbGUgPCAxKSB8fFxuXHRcdFx0KHRoaXMuX3pvb20gPiBtYXAuZ2V0TWF4Wm9vbSgpICYmIHNjYWxlID4gMSkpKSB7XG5cdFx0XHR0aGlzLl96b29tID0gbWFwLl9saW1pdFpvb20odGhpcy5fem9vbSk7XG5cdFx0fVxuXG5cdFx0aWYgKG1hcC5vcHRpb25zLnRvdWNoWm9vbSA9PT0gJ2NlbnRlcicpIHtcblx0XHRcdHRoaXMuX2NlbnRlciA9IHRoaXMuX3N0YXJ0TGF0TG5nO1xuXHRcdFx0aWYgKHNjYWxlID09PSAxKSB7IHJldHVybjsgfVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQvLyBHZXQgZGVsdGEgZnJvbSBwaW5jaCB0byBjZW50ZXIsIHNvIGNlbnRlckxhdExuZyBpcyBkZWx0YSBhcHBsaWVkIHRvIGluaXRpYWwgcGluY2hMYXRMbmdcblx0XHRcdHZhciBkZWx0YSA9IHAxLl9hZGQocDIpLl9kaXZpZGVCeSgyKS5fc3VidHJhY3QodGhpcy5fY2VudGVyUG9pbnQpO1xuXHRcdFx0aWYgKHNjYWxlID09PSAxICYmIGRlbHRhLnggPT09IDAgJiYgZGVsdGEueSA9PT0gMCkgeyByZXR1cm47IH1cblx0XHRcdHRoaXMuX2NlbnRlciA9IG1hcC51bnByb2plY3QobWFwLnByb2plY3QodGhpcy5fcGluY2hTdGFydExhdExuZywgdGhpcy5fem9vbSkuc3VidHJhY3QoZGVsdGEpLCB0aGlzLl96b29tKTtcblx0XHR9XG5cblx0XHRpZiAoIXRoaXMuX21vdmVkKSB7XG5cdFx0XHRtYXAuX21vdmVTdGFydCh0cnVlLCBmYWxzZSk7XG5cdFx0XHR0aGlzLl9tb3ZlZCA9IHRydWU7XG5cdFx0fVxuXG5cdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2FuaW1SZXF1ZXN0KTtcblxuXHRcdHZhciBtb3ZlRm4gPSBiaW5kKG1hcC5fbW92ZSwgbWFwLCB0aGlzLl9jZW50ZXIsIHRoaXMuX3pvb20sIHtwaW5jaDogdHJ1ZSwgcm91bmQ6IGZhbHNlfSk7XG5cdFx0dGhpcy5fYW5pbVJlcXVlc3QgPSByZXF1ZXN0QW5pbUZyYW1lKG1vdmVGbiwgdGhpcywgdHJ1ZSk7XG5cblx0XHRwcmV2ZW50RGVmYXVsdChlKTtcblx0fSxcblxuXHRfb25Ub3VjaEVuZDogZnVuY3Rpb24gKCkge1xuXHRcdGlmICghdGhpcy5fbW92ZWQgfHwgIXRoaXMuX3pvb21pbmcpIHtcblx0XHRcdHRoaXMuX3pvb21pbmcgPSBmYWxzZTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0aGlzLl96b29taW5nID0gZmFsc2U7XG5cdFx0Y2FuY2VsQW5pbUZyYW1lKHRoaXMuX2FuaW1SZXF1ZXN0KTtcblxuXHRcdG9mZihkb2N1bWVudCwgJ3RvdWNobW92ZScsIHRoaXMuX29uVG91Y2hNb3ZlKTtcblx0XHRvZmYoZG9jdW1lbnQsICd0b3VjaGVuZCcsIHRoaXMuX29uVG91Y2hFbmQpO1xuXG5cdFx0Ly8gUGluY2ggdXBkYXRlcyBHcmlkTGF5ZXJzJyBsZXZlbHMgb25seSB3aGVuIHpvb21TbmFwIGlzIG9mZiwgc28gem9vbVNuYXAgYmVjb21lcyBub1VwZGF0ZS5cblx0XHRpZiAodGhpcy5fbWFwLm9wdGlvbnMuem9vbUFuaW1hdGlvbikge1xuXHRcdFx0dGhpcy5fbWFwLl9hbmltYXRlWm9vbSh0aGlzLl9jZW50ZXIsIHRoaXMuX21hcC5fbGltaXRab29tKHRoaXMuX3pvb20pLCB0cnVlLCB0aGlzLl9tYXAub3B0aW9ucy56b29tU25hcCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuX21hcC5fcmVzZXRWaWV3KHRoaXMuX2NlbnRlciwgdGhpcy5fbWFwLl9saW1pdFpvb20odGhpcy5fem9vbSkpO1xuXHRcdH1cblx0fVxufSk7XG5cbi8vIEBzZWN0aW9uIEhhbmRsZXJzXG4vLyBAcHJvcGVydHkgdG91Y2hab29tOiBIYW5kbGVyXG4vLyBUb3VjaCB6b29tIGhhbmRsZXIuXG5NYXAuYWRkSW5pdEhvb2soJ2FkZEhhbmRsZXInLCAndG91Y2hab29tJywgVG91Y2hab29tKTtcblxuTWFwLkJveFpvb20gPSBCb3hab29tO1xuTWFwLkRvdWJsZUNsaWNrWm9vbSA9IERvdWJsZUNsaWNrWm9vbTtcbk1hcC5EcmFnID0gRHJhZztcbk1hcC5LZXlib2FyZCA9IEtleWJvYXJkO1xuTWFwLlNjcm9sbFdoZWVsWm9vbSA9IFNjcm9sbFdoZWVsWm9vbTtcbk1hcC5UYXAgPSBUYXA7XG5NYXAuVG91Y2hab29tID0gVG91Y2hab29tO1xuXG4vLyBtaXNjXHJcblxyXG52YXIgb2xkTCA9IHdpbmRvdy5MO1xyXG5mdW5jdGlvbiBub0NvbmZsaWN0KCkge1xyXG5cdHdpbmRvdy5MID0gb2xkTDtcclxuXHRyZXR1cm4gdGhpcztcclxufVxyXG5cclxuLy8gQWx3YXlzIGV4cG9ydCB1cyB0byB3aW5kb3cgZ2xvYmFsIChzZWUgIzIzNjQpXHJcbndpbmRvdy5MID0gZXhwb3J0cztcclxuXHJcbk9iamVjdC5mcmVlemUgPSBmcmVlemU7XG5cbmV4cG9ydHMudmVyc2lvbiA9IHZlcnNpb247XG5leHBvcnRzLm5vQ29uZmxpY3QgPSBub0NvbmZsaWN0O1xuZXhwb3J0cy5Db250cm9sID0gQ29udHJvbDtcbmV4cG9ydHMuY29udHJvbCA9IGNvbnRyb2w7XG5leHBvcnRzLkJyb3dzZXIgPSBCcm93c2VyO1xuZXhwb3J0cy5FdmVudGVkID0gRXZlbnRlZDtcbmV4cG9ydHMuTWl4aW4gPSBNaXhpbjtcbmV4cG9ydHMuVXRpbCA9IFV0aWw7XG5leHBvcnRzLkNsYXNzID0gQ2xhc3M7XG5leHBvcnRzLkhhbmRsZXIgPSBIYW5kbGVyO1xuZXhwb3J0cy5leHRlbmQgPSBleHRlbmQ7XG5leHBvcnRzLmJpbmQgPSBiaW5kO1xuZXhwb3J0cy5zdGFtcCA9IHN0YW1wO1xuZXhwb3J0cy5zZXRPcHRpb25zID0gc2V0T3B0aW9ucztcbmV4cG9ydHMuRG9tRXZlbnQgPSBEb21FdmVudDtcbmV4cG9ydHMuRG9tVXRpbCA9IERvbVV0aWw7XG5leHBvcnRzLlBvc0FuaW1hdGlvbiA9IFBvc0FuaW1hdGlvbjtcbmV4cG9ydHMuRHJhZ2dhYmxlID0gRHJhZ2dhYmxlO1xuZXhwb3J0cy5MaW5lVXRpbCA9IExpbmVVdGlsO1xuZXhwb3J0cy5Qb2x5VXRpbCA9IFBvbHlVdGlsO1xuZXhwb3J0cy5Qb2ludCA9IFBvaW50O1xuZXhwb3J0cy5wb2ludCA9IHRvUG9pbnQ7XG5leHBvcnRzLkJvdW5kcyA9IEJvdW5kcztcbmV4cG9ydHMuYm91bmRzID0gdG9Cb3VuZHM7XG5leHBvcnRzLlRyYW5zZm9ybWF0aW9uID0gVHJhbnNmb3JtYXRpb247XG5leHBvcnRzLnRyYW5zZm9ybWF0aW9uID0gdG9UcmFuc2Zvcm1hdGlvbjtcbmV4cG9ydHMuUHJvamVjdGlvbiA9IGluZGV4O1xuZXhwb3J0cy5MYXRMbmcgPSBMYXRMbmc7XG5leHBvcnRzLmxhdExuZyA9IHRvTGF0TG5nO1xuZXhwb3J0cy5MYXRMbmdCb3VuZHMgPSBMYXRMbmdCb3VuZHM7XG5leHBvcnRzLmxhdExuZ0JvdW5kcyA9IHRvTGF0TG5nQm91bmRzO1xuZXhwb3J0cy5DUlMgPSBDUlM7XG5leHBvcnRzLkdlb0pTT04gPSBHZW9KU09OO1xuZXhwb3J0cy5nZW9KU09OID0gZ2VvSlNPTjtcbmV4cG9ydHMuZ2VvSnNvbiA9IGdlb0pzb247XG5leHBvcnRzLkxheWVyID0gTGF5ZXI7XG5leHBvcnRzLkxheWVyR3JvdXAgPSBMYXllckdyb3VwO1xuZXhwb3J0cy5sYXllckdyb3VwID0gbGF5ZXJHcm91cDtcbmV4cG9ydHMuRmVhdHVyZUdyb3VwID0gRmVhdHVyZUdyb3VwO1xuZXhwb3J0cy5mZWF0dXJlR3JvdXAgPSBmZWF0dXJlR3JvdXA7XG5leHBvcnRzLkltYWdlT3ZlcmxheSA9IEltYWdlT3ZlcmxheTtcbmV4cG9ydHMuaW1hZ2VPdmVybGF5ID0gaW1hZ2VPdmVybGF5O1xuZXhwb3J0cy5WaWRlb092ZXJsYXkgPSBWaWRlb092ZXJsYXk7XG5leHBvcnRzLnZpZGVvT3ZlcmxheSA9IHZpZGVvT3ZlcmxheTtcbmV4cG9ydHMuRGl2T3ZlcmxheSA9IERpdk92ZXJsYXk7XG5leHBvcnRzLlBvcHVwID0gUG9wdXA7XG5leHBvcnRzLnBvcHVwID0gcG9wdXA7XG5leHBvcnRzLlRvb2x0aXAgPSBUb29sdGlwO1xuZXhwb3J0cy50b29sdGlwID0gdG9vbHRpcDtcbmV4cG9ydHMuSWNvbiA9IEljb247XG5leHBvcnRzLmljb24gPSBpY29uO1xuZXhwb3J0cy5EaXZJY29uID0gRGl2SWNvbjtcbmV4cG9ydHMuZGl2SWNvbiA9IGRpdkljb247XG5leHBvcnRzLk1hcmtlciA9IE1hcmtlcjtcbmV4cG9ydHMubWFya2VyID0gbWFya2VyO1xuZXhwb3J0cy5UaWxlTGF5ZXIgPSBUaWxlTGF5ZXI7XG5leHBvcnRzLnRpbGVMYXllciA9IHRpbGVMYXllcjtcbmV4cG9ydHMuR3JpZExheWVyID0gR3JpZExheWVyO1xuZXhwb3J0cy5ncmlkTGF5ZXIgPSBncmlkTGF5ZXI7XG5leHBvcnRzLlNWRyA9IFNWRztcbmV4cG9ydHMuc3ZnID0gc3ZnJDE7XG5leHBvcnRzLlJlbmRlcmVyID0gUmVuZGVyZXI7XG5leHBvcnRzLkNhbnZhcyA9IENhbnZhcztcbmV4cG9ydHMuY2FudmFzID0gY2FudmFzJDE7XG5leHBvcnRzLlBhdGggPSBQYXRoO1xuZXhwb3J0cy5DaXJjbGVNYXJrZXIgPSBDaXJjbGVNYXJrZXI7XG5leHBvcnRzLmNpcmNsZU1hcmtlciA9IGNpcmNsZU1hcmtlcjtcbmV4cG9ydHMuQ2lyY2xlID0gQ2lyY2xlO1xuZXhwb3J0cy5jaXJjbGUgPSBjaXJjbGU7XG5leHBvcnRzLlBvbHlsaW5lID0gUG9seWxpbmU7XG5leHBvcnRzLnBvbHlsaW5lID0gcG9seWxpbmU7XG5leHBvcnRzLlBvbHlnb24gPSBQb2x5Z29uO1xuZXhwb3J0cy5wb2x5Z29uID0gcG9seWdvbjtcbmV4cG9ydHMuUmVjdGFuZ2xlID0gUmVjdGFuZ2xlO1xuZXhwb3J0cy5yZWN0YW5nbGUgPSByZWN0YW5nbGU7XG5leHBvcnRzLk1hcCA9IE1hcDtcbmV4cG9ydHMubWFwID0gY3JlYXRlTWFwO1xuXG59KSkpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bGVhZmxldC1zcmMuanMubWFwXG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9sZWFmbGV0L2Rpc3QvbGVhZmxldC1zcmMuanNcbi8vIG1vZHVsZSBpZCA9IC4vbm9kZV9tb2R1bGVzL2xlYWZsZXQvZGlzdC9sZWFmbGV0LXNyYy5qc1xuLy8gbW9kdWxlIGNodW5rcyA9IDAgMSJdLCJzb3VyY2VSb290IjoiIn0=\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvcml2ZXRzL2Rpc3Qvcml2ZXRzLmpzP2ViMWIiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjhDQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixtQkFBbUIsZ0NBQWdDLEdBQUcsRUFBRTtBQUN0RjtBQUNBLGtCQUFrQjtBQUNsQix5Q0FBeUMsMEJBQTBCLDJEQUEyRCxFQUFFLGtCQUFrQiwwQkFBMEIsRUFBRSxtQ0FBbUMsOEJBQThCLG9DQUFvQyxjQUFjLEVBQUU7QUFDblMsOENBQThDLGlDQUFpQyxPQUFPLE9BQU8sNkNBQTZDLEVBQUUsV0FBVzs7QUFFdko7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsb0JBQW9CO0FBQ3BCLG9CQUFvQjtBQUNwQixrQkFBa0I7QUFDbEI7QUFDQSw2QkFBNkIsS0FBSztBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSx3Q0FBd0MsV0FBVztBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxXQUFXO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdDQUF3QyxZQUFZO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsV0FBVztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxXQUFXO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDLFdBQVc7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9EQUFvRCxXQUFXO0FBQy9EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0QsWUFBWTtBQUM1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYiw4Q0FBOEMsWUFBWTtBQUMxRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0EsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsV0FBVztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDLFlBQVk7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsV0FBVztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDLFdBQVc7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSwyQ0FBMkMsV0FBVztBQUN0RDtBQUNBLHlLQUF5SztBQUN6SztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsNENBQTRDLFdBQVc7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkNBQTZDLFdBQVc7QUFDeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0RBQWdELFlBQVk7QUFDNUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0QsV0FBVztBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxXQUFXO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsV0FBVztBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxXQUFXO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxXQUFXO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyxZQUFZO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyxXQUFXO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLHlDQUF5QyxXQUFXO0FBQ3BEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDLFdBQVc7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDLFdBQVc7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscURBQXFELFlBQVk7QUFDakU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQyxZQUFZO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVDQUF1QyxXQUFXO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLFdBQVc7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLFdBQVc7QUFDMUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdURBQXVELFdBQVc7QUFDbEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxLQUFLO0FBQUE7QUFDTCxHQUFHO0FBQ0g7QUFDQTs7QUFFQSxDQUFDIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL3JpdmV0cy9kaXN0L3JpdmV0cy5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFJpdmV0cy5qc1xuLy8gdmVyc2lvbjogMC45LjZcbi8vIGF1dGhvcjogTWljaGFlbCBSaWNoYXJkc1xuLy8gbGljZW5zZTogTUlUXG4oZnVuY3Rpb24oKSB7XG4gIHZhciBSaXZldHMsIGJpbmRNZXRob2QsIGpRdWVyeSwgdW5iaW5kTWV0aG9kLCBfcmVmLFxuICAgIF9fYmluZCA9IGZ1bmN0aW9uKGZuLCBtZSl7IHJldHVybiBmdW5jdGlvbigpeyByZXR1cm4gZm4uYXBwbHkobWUsIGFyZ3VtZW50cyk7IH07IH0sXG4gICAgX19zbGljZSA9IFtdLnNsaWNlLFxuICAgIF9faGFzUHJvcCA9IHt9Lmhhc093blByb3BlcnR5LFxuICAgIF9fZXh0ZW5kcyA9IGZ1bmN0aW9uKGNoaWxkLCBwYXJlbnQpIHsgZm9yICh2YXIga2V5IGluIHBhcmVudCkgeyBpZiAoX19oYXNQcm9wLmNhbGwocGFyZW50LCBrZXkpKSBjaGlsZFtrZXldID0gcGFyZW50W2tleV07IH0gZnVuY3Rpb24gY3RvcigpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGNoaWxkOyB9IGN0b3IucHJvdG90eXBlID0gcGFyZW50LnByb3RvdHlwZTsgY2hpbGQucHJvdG90eXBlID0gbmV3IGN0b3IoKTsgY2hpbGQuX19zdXBlcl9fID0gcGFyZW50LnByb3RvdHlwZTsgcmV0dXJuIGNoaWxkOyB9LFxuICAgIF9faW5kZXhPZiA9IFtdLmluZGV4T2YgfHwgZnVuY3Rpb24oaXRlbSkgeyBmb3IgKHZhciBpID0gMCwgbCA9IHRoaXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7IGlmIChpIGluIHRoaXMgJiYgdGhpc1tpXSA9PT0gaXRlbSkgcmV0dXJuIGk7IH0gcmV0dXJuIC0xOyB9O1xuXG4gIFJpdmV0cyA9IHtcbiAgICBvcHRpb25zOiBbJ3ByZWZpeCcsICd0ZW1wbGF0ZURlbGltaXRlcnMnLCAncm9vdEludGVyZmFjZScsICdwcmVsb2FkRGF0YScsICdoYW5kbGVyJywgJ2V4ZWN1dGVGdW5jdGlvbnMnXSxcbiAgICBleHRlbnNpb25zOiBbJ2JpbmRlcnMnLCAnZm9ybWF0dGVycycsICdjb21wb25lbnRzJywgJ2FkYXB0ZXJzJ10sXG4gICAgXCJwdWJsaWNcIjoge1xuICAgICAgYmluZGVyczoge30sXG4gICAgICBjb21wb25lbnRzOiB7fSxcbiAgICAgIGZvcm1hdHRlcnM6IHt9LFxuICAgICAgYWRhcHRlcnM6IHt9LFxuICAgICAgcHJlZml4OiAncnYnLFxuICAgICAgdGVtcGxhdGVEZWxpbWl0ZXJzOiBbJ3snLCAnfSddLFxuICAgICAgcm9vdEludGVyZmFjZTogJy4nLFxuICAgICAgcHJlbG9hZERhdGE6IHRydWUsXG4gICAgICBleGVjdXRlRnVuY3Rpb25zOiBmYWxzZSxcbiAgICAgIGl0ZXJhdGlvbkFsaWFzOiBmdW5jdGlvbihtb2RlbE5hbWUpIHtcbiAgICAgICAgcmV0dXJuICclJyArIG1vZGVsTmFtZSArICclJztcbiAgICAgIH0sXG4gICAgICBoYW5kbGVyOiBmdW5jdGlvbihjb250ZXh0LCBldiwgYmluZGluZykge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxsKGNvbnRleHQsIGV2LCBiaW5kaW5nLnZpZXcubW9kZWxzKTtcbiAgICAgIH0sXG4gICAgICBjb25maWd1cmU6IGZ1bmN0aW9uKG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIGRlc2NyaXB0b3IsIGtleSwgb3B0aW9uLCB2YWx1ZTtcbiAgICAgICAgaWYgKG9wdGlvbnMgPT0gbnVsbCkge1xuICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKG9wdGlvbiBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgdmFsdWUgPSBvcHRpb25zW29wdGlvbl07XG4gICAgICAgICAgaWYgKG9wdGlvbiA9PT0gJ2JpbmRlcnMnIHx8IG9wdGlvbiA9PT0gJ2NvbXBvbmVudHMnIHx8IG9wdGlvbiA9PT0gJ2Zvcm1hdHRlcnMnIHx8IG9wdGlvbiA9PT0gJ2FkYXB0ZXJzJykge1xuICAgICAgICAgICAgZm9yIChrZXkgaW4gdmFsdWUpIHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRvciA9IHZhbHVlW2tleV07XG4gICAgICAgICAgICAgIFJpdmV0c1tvcHRpb25dW2tleV0gPSBkZXNjcmlwdG9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBSaXZldHNbXCJwdWJsaWNcIl1bb3B0aW9uXSA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGJpbmQ6IGZ1bmN0aW9uKGVsLCBtb2RlbHMsIG9wdGlvbnMpIHtcbiAgICAgICAgdmFyIHZpZXc7XG4gICAgICAgIGlmIChtb2RlbHMgPT0gbnVsbCkge1xuICAgICAgICAgIG1vZGVscyA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zID09IG51bGwpIHtcbiAgICAgICAgICBvcHRpb25zID0ge307XG4gICAgICAgIH1cbiAgICAgICAgdmlldyA9IG5ldyBSaXZldHMuVmlldyhlbCwgbW9kZWxzLCBvcHRpb25zKTtcbiAgICAgICAgdmlldy5iaW5kKCk7XG4gICAgICAgIHJldHVybiB2aWV3O1xuICAgICAgfSxcbiAgICAgIGluaXQ6IGZ1bmN0aW9uKGNvbXBvbmVudCwgZWwsIGRhdGEpIHtcbiAgICAgICAgdmFyIHNjb3BlLCB0ZW1wbGF0ZSwgdmlldztcbiAgICAgICAgaWYgKGRhdGEgPT0gbnVsbCkge1xuICAgICAgICAgIGRhdGEgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZWwgPT0gbnVsbCkge1xuICAgICAgICAgIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIH1cbiAgICAgICAgY29tcG9uZW50ID0gUml2ZXRzW1wicHVibGljXCJdLmNvbXBvbmVudHNbY29tcG9uZW50XTtcbiAgICAgICAgdGVtcGxhdGUgPSBjb21wb25lbnQudGVtcGxhdGUuY2FsbCh0aGlzLCBlbCk7XG4gICAgICAgIGlmICh0ZW1wbGF0ZSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgICAgICAgd2hpbGUgKGVsLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICAgIGVsLnJlbW92ZUNoaWxkKGVsLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbC5hcHBlbmRDaGlsZCh0ZW1wbGF0ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZWwuaW5uZXJIVE1MID0gdGVtcGxhdGU7XG4gICAgICAgIH1cbiAgICAgICAgc2NvcGUgPSBjb21wb25lbnQuaW5pdGlhbGl6ZS5jYWxsKHRoaXMsIGVsLCBkYXRhKTtcbiAgICAgICAgdmlldyA9IG5ldyBSaXZldHMuVmlldyhlbCwgc2NvcGUpO1xuICAgICAgICB2aWV3LmJpbmQoKTtcbiAgICAgICAgcmV0dXJuIHZpZXc7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIGlmICh3aW5kb3dbJ2pRdWVyeSddIHx8IHdpbmRvd1snJCddKSB7XG4gICAgalF1ZXJ5ID0gd2luZG93WydqUXVlcnknXSB8fCB3aW5kb3dbJyQnXTtcbiAgICBfcmVmID0gJ29uJyBpbiBqUXVlcnkucHJvdG90eXBlID8gWydvbicsICdvZmYnXSA6IFsnYmluZCcsICd1bmJpbmQnXSwgYmluZE1ldGhvZCA9IF9yZWZbMF0sIHVuYmluZE1ldGhvZCA9IF9yZWZbMV07XG4gICAgUml2ZXRzLlV0aWwgPSB7XG4gICAgICBiaW5kRXZlbnQ6IGZ1bmN0aW9uKGVsLCBldmVudCwgaGFuZGxlcikge1xuICAgICAgICByZXR1cm4galF1ZXJ5KGVsKVtiaW5kTWV0aG9kXShldmVudCwgaGFuZGxlcik7XG4gICAgICB9LFxuICAgICAgdW5iaW5kRXZlbnQ6IGZ1bmN0aW9uKGVsLCBldmVudCwgaGFuZGxlcikge1xuICAgICAgICByZXR1cm4galF1ZXJ5KGVsKVt1bmJpbmRNZXRob2RdKGV2ZW50LCBoYW5kbGVyKTtcbiAgICAgIH0sXG4gICAgICBnZXRJbnB1dFZhbHVlOiBmdW5jdGlvbihlbCkge1xuICAgICAgICB2YXIgJGVsO1xuICAgICAgICAkZWwgPSBqUXVlcnkoZWwpO1xuICAgICAgICBpZiAoJGVsLmF0dHIoJ3R5cGUnKSA9PT0gJ2NoZWNrYm94Jykge1xuICAgICAgICAgIHJldHVybiAkZWwuaXMoJzpjaGVja2VkJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuICRlbC52YWwoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgUml2ZXRzLlV0aWwgPSB7XG4gICAgICBiaW5kRXZlbnQ6IChmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCdhZGRFdmVudExpc3RlbmVyJyBpbiB3aW5kb3cpIHtcbiAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oZWwsIGV2ZW50LCBoYW5kbGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gZWwuYWRkRXZlbnRMaXN0ZW5lcihldmVudCwgaGFuZGxlciwgZmFsc2UpO1xuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVsLCBldmVudCwgaGFuZGxlcikge1xuICAgICAgICAgIHJldHVybiBlbC5hdHRhY2hFdmVudCgnb24nICsgZXZlbnQsIGhhbmRsZXIpO1xuICAgICAgICB9O1xuICAgICAgfSkoKSxcbiAgICAgIHVuYmluZEV2ZW50OiAoZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICgncmVtb3ZlRXZlbnRMaXN0ZW5lcicgaW4gd2luZG93KSB7XG4gICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGVsLCBldmVudCwgaGFuZGxlcikge1xuICAgICAgICAgICAgcmV0dXJuIGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZXIsIGZhbHNlKTtcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihlbCwgZXZlbnQsIGhhbmRsZXIpIHtcbiAgICAgICAgICByZXR1cm4gZWwuZGV0YWNoRXZlbnQoJ29uJyArIGV2ZW50LCBoYW5kbGVyKTtcbiAgICAgICAgfTtcbiAgICAgIH0pKCksXG4gICAgICBnZXRJbnB1dFZhbHVlOiBmdW5jdGlvbihlbCkge1xuICAgICAgICB2YXIgbywgX2ksIF9sZW4sIF9yZXN1bHRzO1xuICAgICAgICBpZiAoZWwudHlwZSA9PT0gJ2NoZWNrYm94Jykge1xuICAgICAgICAgIHJldHVybiBlbC5jaGVja2VkO1xuICAgICAgICB9IGVsc2UgaWYgKGVsLnR5cGUgPT09ICdzZWxlY3QtbXVsdGlwbGUnKSB7XG4gICAgICAgICAgX3Jlc3VsdHMgPSBbXTtcbiAgICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IGVsLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgICBvID0gZWxbX2ldO1xuICAgICAgICAgICAgaWYgKG8uc2VsZWN0ZWQpIHtcbiAgICAgICAgICAgICAgX3Jlc3VsdHMucHVzaChvLnZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIF9yZXN1bHRzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBlbC52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gIH1cblxuICBSaXZldHMuVHlwZVBhcnNlciA9IChmdW5jdGlvbigpIHtcbiAgICBmdW5jdGlvbiBUeXBlUGFyc2VyKCkge31cblxuICAgIFR5cGVQYXJzZXIudHlwZXMgPSB7XG4gICAgICBwcmltaXRpdmU6IDAsXG4gICAgICBrZXlwYXRoOiAxXG4gICAgfTtcblxuICAgIFR5cGVQYXJzZXIucGFyc2UgPSBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgIGlmICgvXicuKickfF5cIi4qXCIkLy50ZXN0KHN0cmluZykpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiB0aGlzLnR5cGVzLnByaW1pdGl2ZSxcbiAgICAgICAgICB2YWx1ZTogc3RyaW5nLnNsaWNlKDEsIC0xKVxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmIChzdHJpbmcgPT09ICd0cnVlJykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IHRoaXMudHlwZXMucHJpbWl0aXZlLFxuICAgICAgICAgIHZhbHVlOiB0cnVlXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHN0cmluZyA9PT0gJ2ZhbHNlJykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IHRoaXMudHlwZXMucHJpbWl0aXZlLFxuICAgICAgICAgIHZhbHVlOiBmYWxzZVxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIGlmIChzdHJpbmcgPT09ICdudWxsJykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHR5cGU6IHRoaXMudHlwZXMucHJpbWl0aXZlLFxuICAgICAgICAgIHZhbHVlOiBudWxsXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHN0cmluZyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiB0aGlzLnR5cGVzLnByaW1pdGl2ZSxcbiAgICAgICAgICB2YWx1ZTogdm9pZCAwXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHN0cmluZyA9PT0gJycpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiB0aGlzLnR5cGVzLnByaW1pdGl2ZSxcbiAgICAgICAgICB2YWx1ZTogdm9pZCAwXG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKGlzTmFOKE51bWJlcihzdHJpbmcpKSA9PT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiB0aGlzLnR5cGVzLnByaW1pdGl2ZSxcbiAgICAgICAgICB2YWx1ZTogTnVtYmVyKHN0cmluZylcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogdGhpcy50eXBlcy5rZXlwYXRoLFxuICAgICAgICAgIHZhbHVlOiBzdHJpbmdcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIFR5cGVQYXJzZXI7XG5cbiAgfSkoKTtcblxuICBSaXZldHMuVGV4dFRlbXBsYXRlUGFyc2VyID0gKGZ1bmN0aW9uKCkge1xuICAgIGZ1bmN0aW9uIFRleHRUZW1wbGF0ZVBhcnNlcigpIHt9XG5cbiAgICBUZXh0VGVtcGxhdGVQYXJzZXIudHlwZXMgPSB7XG4gICAgICB0ZXh0OiAwLFxuICAgICAgYmluZGluZzogMVxuICAgIH07XG5cbiAgICBUZXh0VGVtcGxhdGVQYXJzZXIucGFyc2UgPSBmdW5jdGlvbih0ZW1wbGF0ZSwgZGVsaW1pdGVycykge1xuICAgICAgdmFyIGluZGV4LCBsYXN0SW5kZXgsIGxhc3RUb2tlbiwgbGVuZ3RoLCBzdWJzdHJpbmcsIHRva2VucywgdmFsdWU7XG4gICAgICB0b2tlbnMgPSBbXTtcbiAgICAgIGxlbmd0aCA9IHRlbXBsYXRlLmxlbmd0aDtcbiAgICAgIGluZGV4ID0gMDtcbiAgICAgIGxhc3RJbmRleCA9IDA7XG4gICAgICB3aGlsZSAobGFzdEluZGV4IDwgbGVuZ3RoKSB7XG4gICAgICAgIGluZGV4ID0gdGVtcGxhdGUuaW5kZXhPZihkZWxpbWl0ZXJzWzBdLCBsYXN0SW5kZXgpO1xuICAgICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgICAgdG9rZW5zLnB1c2goe1xuICAgICAgICAgICAgdHlwZTogdGhpcy50eXBlcy50ZXh0LFxuICAgICAgICAgICAgdmFsdWU6IHRlbXBsYXRlLnNsaWNlKGxhc3RJbmRleClcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZiAoaW5kZXggPiAwICYmIGxhc3RJbmRleCA8IGluZGV4KSB7XG4gICAgICAgICAgICB0b2tlbnMucHVzaCh7XG4gICAgICAgICAgICAgIHR5cGU6IHRoaXMudHlwZXMudGV4dCxcbiAgICAgICAgICAgICAgdmFsdWU6IHRlbXBsYXRlLnNsaWNlKGxhc3RJbmRleCwgaW5kZXgpXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbGFzdEluZGV4ID0gaW5kZXggKyBkZWxpbWl0ZXJzWzBdLmxlbmd0aDtcbiAgICAgICAgICBpbmRleCA9IHRlbXBsYXRlLmluZGV4T2YoZGVsaW1pdGVyc1sxXSwgbGFzdEluZGV4KTtcbiAgICAgICAgICBpZiAoaW5kZXggPCAwKSB7XG4gICAgICAgICAgICBzdWJzdHJpbmcgPSB0ZW1wbGF0ZS5zbGljZShsYXN0SW5kZXggLSBkZWxpbWl0ZXJzWzFdLmxlbmd0aCk7XG4gICAgICAgICAgICBsYXN0VG9rZW4gPSB0b2tlbnNbdG9rZW5zLmxlbmd0aCAtIDFdO1xuICAgICAgICAgICAgaWYgKChsYXN0VG9rZW4gIT0gbnVsbCA/IGxhc3RUb2tlbi50eXBlIDogdm9pZCAwKSA9PT0gdGhpcy50eXBlcy50ZXh0KSB7XG4gICAgICAgICAgICAgIGxhc3RUb2tlbi52YWx1ZSArPSBzdWJzdHJpbmc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0b2tlbnMucHVzaCh7XG4gICAgICAgICAgICAgICAgdHlwZTogdGhpcy50eXBlcy50ZXh0LFxuICAgICAgICAgICAgICAgIHZhbHVlOiBzdWJzdHJpbmdcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFsdWUgPSB0ZW1wbGF0ZS5zbGljZShsYXN0SW5kZXgsIGluZGV4KS50cmltKCk7XG4gICAgICAgICAgdG9rZW5zLnB1c2goe1xuICAgICAgICAgICAgdHlwZTogdGhpcy50eXBlcy5iaW5kaW5nLFxuICAgICAgICAgICAgdmFsdWU6IHZhbHVlXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgbGFzdEluZGV4ID0gaW5kZXggKyBkZWxpbWl0ZXJzWzFdLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRva2VucztcbiAgICB9O1xuXG4gICAgcmV0dXJuIFRleHRUZW1wbGF0ZVBhcnNlcjtcblxuICB9KSgpO1xuXG4gIFJpdmV0cy5WaWV3ID0gKGZ1bmN0aW9uKCkge1xuICAgIGZ1bmN0aW9uIFZpZXcoZWxzLCBtb2RlbHMsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBrLCBvcHRpb24sIHYsIF9iYXNlLCBfaSwgX2osIF9sZW4sIF9sZW4xLCBfcmVmMSwgX3JlZjIsIF9yZWYzLCBfcmVmNCwgX3JlZjU7XG4gICAgICB0aGlzLmVscyA9IGVscztcbiAgICAgIHRoaXMubW9kZWxzID0gbW9kZWxzO1xuICAgICAgaWYgKG9wdGlvbnMgPT0gbnVsbCkge1xuICAgICAgICBvcHRpb25zID0ge307XG4gICAgICB9XG4gICAgICB0aGlzLnVwZGF0ZSA9IF9fYmluZCh0aGlzLnVwZGF0ZSwgdGhpcyk7XG4gICAgICB0aGlzLnB1Ymxpc2ggPSBfX2JpbmQodGhpcy5wdWJsaXNoLCB0aGlzKTtcbiAgICAgIHRoaXMuc3luYyA9IF9fYmluZCh0aGlzLnN5bmMsIHRoaXMpO1xuICAgICAgdGhpcy51bmJpbmQgPSBfX2JpbmQodGhpcy51bmJpbmQsIHRoaXMpO1xuICAgICAgdGhpcy5iaW5kID0gX19iaW5kKHRoaXMuYmluZCwgdGhpcyk7XG4gICAgICB0aGlzLnNlbGVjdCA9IF9fYmluZCh0aGlzLnNlbGVjdCwgdGhpcyk7XG4gICAgICB0aGlzLnRyYXZlcnNlID0gX19iaW5kKHRoaXMudHJhdmVyc2UsIHRoaXMpO1xuICAgICAgdGhpcy5idWlsZCA9IF9fYmluZCh0aGlzLmJ1aWxkLCB0aGlzKTtcbiAgICAgIHRoaXMuYnVpbGRCaW5kaW5nID0gX19iaW5kKHRoaXMuYnVpbGRCaW5kaW5nLCB0aGlzKTtcbiAgICAgIHRoaXMuYmluZGluZ1JlZ0V4cCA9IF9fYmluZCh0aGlzLmJpbmRpbmdSZWdFeHAsIHRoaXMpO1xuICAgICAgdGhpcy5vcHRpb25zID0gX19iaW5kKHRoaXMub3B0aW9ucywgdGhpcyk7XG4gICAgICBpZiAoISh0aGlzLmVscy5qcXVlcnkgfHwgdGhpcy5lbHMgaW5zdGFuY2VvZiBBcnJheSkpIHtcbiAgICAgICAgdGhpcy5lbHMgPSBbdGhpcy5lbHNdO1xuICAgICAgfVxuICAgICAgX3JlZjEgPSBSaXZldHMuZXh0ZW5zaW9ucztcbiAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgb3B0aW9uID0gX3JlZjFbX2ldO1xuICAgICAgICB0aGlzW29wdGlvbl0gPSB7fTtcbiAgICAgICAgaWYgKG9wdGlvbnNbb3B0aW9uXSkge1xuICAgICAgICAgIF9yZWYyID0gb3B0aW9uc1tvcHRpb25dO1xuICAgICAgICAgIGZvciAoayBpbiBfcmVmMikge1xuICAgICAgICAgICAgdiA9IF9yZWYyW2tdO1xuICAgICAgICAgICAgdGhpc1tvcHRpb25dW2tdID0gdjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgX3JlZjMgPSBSaXZldHNbXCJwdWJsaWNcIl1bb3B0aW9uXTtcbiAgICAgICAgZm9yIChrIGluIF9yZWYzKSB7XG4gICAgICAgICAgdiA9IF9yZWYzW2tdO1xuICAgICAgICAgIGlmICgoX2Jhc2UgPSB0aGlzW29wdGlvbl0pW2tdID09IG51bGwpIHtcbiAgICAgICAgICAgIF9iYXNlW2tdID0gdjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIF9yZWY0ID0gUml2ZXRzLm9wdGlvbnM7XG4gICAgICBmb3IgKF9qID0gMCwgX2xlbjEgPSBfcmVmNC5sZW5ndGg7IF9qIDwgX2xlbjE7IF9qKyspIHtcbiAgICAgICAgb3B0aW9uID0gX3JlZjRbX2pdO1xuICAgICAgICB0aGlzW29wdGlvbl0gPSAoX3JlZjUgPSBvcHRpb25zW29wdGlvbl0pICE9IG51bGwgPyBfcmVmNSA6IFJpdmV0c1tcInB1YmxpY1wiXVtvcHRpb25dO1xuICAgICAgfVxuICAgICAgdGhpcy5idWlsZCgpO1xuICAgIH1cblxuICAgIFZpZXcucHJvdG90eXBlLm9wdGlvbnMgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBvcHRpb24sIG9wdGlvbnMsIF9pLCBfbGVuLCBfcmVmMTtcbiAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgIF9yZWYxID0gUml2ZXRzLmV4dGVuc2lvbnMuY29uY2F0KFJpdmV0cy5vcHRpb25zKTtcbiAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgb3B0aW9uID0gX3JlZjFbX2ldO1xuICAgICAgICBvcHRpb25zW29wdGlvbl0gPSB0aGlzW29wdGlvbl07XG4gICAgICB9XG4gICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9O1xuXG4gICAgVmlldy5wcm90b3R5cGUuYmluZGluZ1JlZ0V4cCA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIG5ldyBSZWdFeHAoXCJeXCIgKyB0aGlzLnByZWZpeCArIFwiLVwiKTtcbiAgICB9O1xuXG4gICAgVmlldy5wcm90b3R5cGUuYnVpbGRCaW5kaW5nID0gZnVuY3Rpb24oYmluZGluZywgbm9kZSwgdHlwZSwgZGVjbGFyYXRpb24pIHtcbiAgICAgIHZhciBjb250ZXh0LCBjdHgsIGRlcGVuZGVuY2llcywga2V5cGF0aCwgb3B0aW9ucywgcGlwZSwgcGlwZXM7XG4gICAgICBvcHRpb25zID0ge307XG4gICAgICBwaXBlcyA9IChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIF9pLCBfbGVuLCBfcmVmMSwgX3Jlc3VsdHM7XG4gICAgICAgIF9yZWYxID0gZGVjbGFyYXRpb24ubWF0Y2goLygoPzonW14nXSonKSooPzooPzpbXlxcfCddKig/OidbXiddKicpK1teXFx8J10qKSt8W15cXHxdKykpfF4kL2cpO1xuICAgICAgICBfcmVzdWx0cyA9IFtdO1xuICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgcGlwZSA9IF9yZWYxW19pXTtcbiAgICAgICAgICBfcmVzdWx0cy5wdXNoKHBpcGUudHJpbSgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gX3Jlc3VsdHM7XG4gICAgICB9KSgpO1xuICAgICAgY29udGV4dCA9IChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIF9pLCBfbGVuLCBfcmVmMSwgX3Jlc3VsdHM7XG4gICAgICAgIF9yZWYxID0gcGlwZXMuc2hpZnQoKS5zcGxpdCgnPCcpO1xuICAgICAgICBfcmVzdWx0cyA9IFtdO1xuICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgY3R4ID0gX3JlZjFbX2ldO1xuICAgICAgICAgIF9yZXN1bHRzLnB1c2goY3R4LnRyaW0oKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9yZXN1bHRzO1xuICAgICAgfSkoKTtcbiAgICAgIGtleXBhdGggPSBjb250ZXh0LnNoaWZ0KCk7XG4gICAgICBvcHRpb25zLmZvcm1hdHRlcnMgPSBwaXBlcztcbiAgICAgIGlmIChkZXBlbmRlbmNpZXMgPSBjb250ZXh0LnNoaWZ0KCkpIHtcbiAgICAgICAgb3B0aW9ucy5kZXBlbmRlbmNpZXMgPSBkZXBlbmRlbmNpZXMuc3BsaXQoL1xccysvKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLmJpbmRpbmdzLnB1c2gobmV3IFJpdmV0c1tiaW5kaW5nXSh0aGlzLCBub2RlLCB0eXBlLCBrZXlwYXRoLCBvcHRpb25zKSk7XG4gICAgfTtcblxuICAgIFZpZXcucHJvdG90eXBlLmJ1aWxkID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgZWwsIHBhcnNlLCBfaSwgX2xlbiwgX3JlZjE7XG4gICAgICB0aGlzLmJpbmRpbmdzID0gW107XG4gICAgICBwYXJzZSA9IChmdW5jdGlvbihfdGhpcykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24obm9kZSkge1xuICAgICAgICAgIHZhciBibG9jaywgY2hpbGROb2RlLCBkZWxpbWl0ZXJzLCBuLCBwYXJzZXIsIHRleHQsIHRva2VuLCB0b2tlbnMsIF9pLCBfaiwgX2xlbiwgX2xlbjEsIF9yZWYxO1xuICAgICAgICAgIGlmIChub2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICBwYXJzZXIgPSBSaXZldHMuVGV4dFRlbXBsYXRlUGFyc2VyO1xuICAgICAgICAgICAgaWYgKGRlbGltaXRlcnMgPSBfdGhpcy50ZW1wbGF0ZURlbGltaXRlcnMpIHtcbiAgICAgICAgICAgICAgaWYgKCh0b2tlbnMgPSBwYXJzZXIucGFyc2Uobm9kZS5kYXRhLCBkZWxpbWl0ZXJzKSkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodG9rZW5zLmxlbmd0aCA9PT0gMSAmJiB0b2tlbnNbMF0udHlwZSA9PT0gcGFyc2VyLnR5cGVzLnRleHQpKSB7XG4gICAgICAgICAgICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IHRva2Vucy5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICB0b2tlbiA9IHRva2Vuc1tfaV07XG4gICAgICAgICAgICAgICAgICAgIHRleHQgPSBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSh0b2tlbi52YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIG5vZGUucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGV4dCwgbm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0b2tlbi50eXBlID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgX3RoaXMuYnVpbGRCaW5kaW5nKCdUZXh0QmluZGluZycsIHRleHQsIG51bGwsIHRva2VuLnZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgbm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAobm9kZS5ub2RlVHlwZSA9PT0gMSkge1xuICAgICAgICAgICAgYmxvY2sgPSBfdGhpcy50cmF2ZXJzZShub2RlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFibG9jaykge1xuICAgICAgICAgICAgX3JlZjEgPSAoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIHZhciBfaywgX2xlbjEsIF9yZWYxLCBfcmVzdWx0cztcbiAgICAgICAgICAgICAgX3JlZjEgPSBub2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgIF9yZXN1bHRzID0gW107XG4gICAgICAgICAgICAgIGZvciAoX2sgPSAwLCBfbGVuMSA9IF9yZWYxLmxlbmd0aDsgX2sgPCBfbGVuMTsgX2srKykge1xuICAgICAgICAgICAgICAgIG4gPSBfcmVmMVtfa107XG4gICAgICAgICAgICAgICAgX3Jlc3VsdHMucHVzaChuKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXR1cm4gX3Jlc3VsdHM7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICAgICAgZm9yIChfaiA9IDAsIF9sZW4xID0gX3JlZjEubGVuZ3RoOyBfaiA8IF9sZW4xOyBfaisrKSB7XG4gICAgICAgICAgICAgIGNoaWxkTm9kZSA9IF9yZWYxW19qXTtcbiAgICAgICAgICAgICAgcGFyc2UoY2hpbGROb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICB9KSh0aGlzKTtcbiAgICAgIF9yZWYxID0gdGhpcy5lbHM7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGVsID0gX3JlZjFbX2ldO1xuICAgICAgICBwYXJzZShlbCk7XG4gICAgICB9XG4gICAgICB0aGlzLmJpbmRpbmdzLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgICB2YXIgX3JlZjIsIF9yZWYzO1xuICAgICAgICByZXR1cm4gKCgoX3JlZjIgPSBiLmJpbmRlcikgIT0gbnVsbCA/IF9yZWYyLnByaW9yaXR5IDogdm9pZCAwKSB8fCAwKSAtICgoKF9yZWYzID0gYS5iaW5kZXIpICE9IG51bGwgPyBfcmVmMy5wcmlvcml0eSA6IHZvaWQgMCkgfHwgMCk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgVmlldy5wcm90b3R5cGUudHJhdmVyc2UgPSBmdW5jdGlvbihub2RlKSB7XG4gICAgICB2YXIgYXR0cmlidXRlLCBhdHRyaWJ1dGVzLCBiaW5kZXIsIGJpbmRpbmdSZWdFeHAsIGJsb2NrLCBpZGVudGlmaWVyLCByZWdleHAsIHR5cGUsIHZhbHVlLCBfaSwgX2osIF9sZW4sIF9sZW4xLCBfcmVmMSwgX3JlZjIsIF9yZWYzO1xuICAgICAgYmluZGluZ1JlZ0V4cCA9IHRoaXMuYmluZGluZ1JlZ0V4cCgpO1xuICAgICAgYmxvY2sgPSBub2RlLm5vZGVOYW1lID09PSAnU0NSSVBUJyB8fCBub2RlLm5vZGVOYW1lID09PSAnU1RZTEUnO1xuICAgICAgX3JlZjEgPSBub2RlLmF0dHJpYnV0ZXM7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGF0dHJpYnV0ZSA9IF9yZWYxW19pXTtcbiAgICAgICAgaWYgKGJpbmRpbmdSZWdFeHAudGVzdChhdHRyaWJ1dGUubmFtZSkpIHtcbiAgICAgICAgICB0eXBlID0gYXR0cmlidXRlLm5hbWUucmVwbGFjZShiaW5kaW5nUmVnRXhwLCAnJyk7XG4gICAgICAgICAgaWYgKCEoYmluZGVyID0gdGhpcy5iaW5kZXJzW3R5cGVdKSkge1xuICAgICAgICAgICAgX3JlZjIgPSB0aGlzLmJpbmRlcnM7XG4gICAgICAgICAgICBmb3IgKGlkZW50aWZpZXIgaW4gX3JlZjIpIHtcbiAgICAgICAgICAgICAgdmFsdWUgPSBfcmVmMltpZGVudGlmaWVyXTtcbiAgICAgICAgICAgICAgaWYgKGlkZW50aWZpZXIgIT09ICcqJyAmJiBpZGVudGlmaWVyLmluZGV4T2YoJyonKSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZWdleHAgPSBuZXcgUmVnRXhwKFwiXlwiICsgKGlkZW50aWZpZXIucmVwbGFjZSgvXFwqL2csICcuKycpKSArIFwiJFwiKTtcbiAgICAgICAgICAgICAgICBpZiAocmVnZXhwLnRlc3QodHlwZSkpIHtcbiAgICAgICAgICAgICAgICAgIGJpbmRlciA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBiaW5kZXIgfHwgKGJpbmRlciA9IHRoaXMuYmluZGVyc1snKiddKTtcbiAgICAgICAgICBpZiAoYmluZGVyLmJsb2NrKSB7XG4gICAgICAgICAgICBibG9jayA9IHRydWU7XG4gICAgICAgICAgICBhdHRyaWJ1dGVzID0gW2F0dHJpYnV0ZV07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBfcmVmMyA9IGF0dHJpYnV0ZXMgfHwgbm9kZS5hdHRyaWJ1dGVzO1xuICAgICAgZm9yIChfaiA9IDAsIF9sZW4xID0gX3JlZjMubGVuZ3RoOyBfaiA8IF9sZW4xOyBfaisrKSB7XG4gICAgICAgIGF0dHJpYnV0ZSA9IF9yZWYzW19qXTtcbiAgICAgICAgaWYgKGJpbmRpbmdSZWdFeHAudGVzdChhdHRyaWJ1dGUubmFtZSkpIHtcbiAgICAgICAgICB0eXBlID0gYXR0cmlidXRlLm5hbWUucmVwbGFjZShiaW5kaW5nUmVnRXhwLCAnJyk7XG4gICAgICAgICAgdGhpcy5idWlsZEJpbmRpbmcoJ0JpbmRpbmcnLCBub2RlLCB0eXBlLCBhdHRyaWJ1dGUudmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoIWJsb2NrKSB7XG4gICAgICAgIHR5cGUgPSBub2RlLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIGlmICh0aGlzLmNvbXBvbmVudHNbdHlwZV0gJiYgIW5vZGUuX2JvdW5kKSB7XG4gICAgICAgICAgdGhpcy5iaW5kaW5ncy5wdXNoKG5ldyBSaXZldHMuQ29tcG9uZW50QmluZGluZyh0aGlzLCBub2RlLCB0eXBlKSk7XG4gICAgICAgICAgYmxvY2sgPSB0cnVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gYmxvY2s7XG4gICAgfTtcblxuICAgIFZpZXcucHJvdG90eXBlLnNlbGVjdCA9IGZ1bmN0aW9uKGZuKSB7XG4gICAgICB2YXIgYmluZGluZywgX2ksIF9sZW4sIF9yZWYxLCBfcmVzdWx0cztcbiAgICAgIF9yZWYxID0gdGhpcy5iaW5kaW5ncztcbiAgICAgIF9yZXN1bHRzID0gW107XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGJpbmRpbmcgPSBfcmVmMVtfaV07XG4gICAgICAgIGlmIChmbihiaW5kaW5nKSkge1xuICAgICAgICAgIF9yZXN1bHRzLnB1c2goYmluZGluZyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBfcmVzdWx0cztcbiAgICB9O1xuXG4gICAgVmlldy5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGJpbmRpbmcsIF9pLCBfbGVuLCBfcmVmMTtcbiAgICAgIF9yZWYxID0gdGhpcy5iaW5kaW5ncztcbiAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgYmluZGluZyA9IF9yZWYxW19pXTtcbiAgICAgICAgYmluZGluZy5iaW5kKCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIFZpZXcucHJvdG90eXBlLnVuYmluZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGJpbmRpbmcsIF9pLCBfbGVuLCBfcmVmMTtcbiAgICAgIF9yZWYxID0gdGhpcy5iaW5kaW5ncztcbiAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgYmluZGluZyA9IF9yZWYxW19pXTtcbiAgICAgICAgYmluZGluZy51bmJpbmQoKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgVmlldy5wcm90b3R5cGUuc3luYyA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGJpbmRpbmcsIF9pLCBfbGVuLCBfcmVmMTtcbiAgICAgIF9yZWYxID0gdGhpcy5iaW5kaW5ncztcbiAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgYmluZGluZyA9IF9yZWYxW19pXTtcbiAgICAgICAgaWYgKHR5cGVvZiBiaW5kaW5nLnN5bmMgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgIGJpbmRpbmcuc3luYygpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIFZpZXcucHJvdG90eXBlLnB1Ymxpc2ggPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBiaW5kaW5nLCBfaSwgX2xlbiwgX3JlZjE7XG4gICAgICBfcmVmMSA9IHRoaXMuc2VsZWN0KGZ1bmN0aW9uKGIpIHtcbiAgICAgICAgdmFyIF9yZWYxO1xuICAgICAgICByZXR1cm4gKF9yZWYxID0gYi5iaW5kZXIpICE9IG51bGwgPyBfcmVmMS5wdWJsaXNoZXMgOiB2b2lkIDA7XG4gICAgICB9KTtcbiAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgYmluZGluZyA9IF9yZWYxW19pXTtcbiAgICAgICAgYmluZGluZy5wdWJsaXNoKCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIFZpZXcucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uKG1vZGVscykge1xuICAgICAgdmFyIGJpbmRpbmcsIGtleSwgbW9kZWwsIF9pLCBfbGVuLCBfcmVmMTtcbiAgICAgIGlmIChtb2RlbHMgPT0gbnVsbCkge1xuICAgICAgICBtb2RlbHMgPSB7fTtcbiAgICAgIH1cbiAgICAgIGZvciAoa2V5IGluIG1vZGVscykge1xuICAgICAgICBtb2RlbCA9IG1vZGVsc1trZXldO1xuICAgICAgICB0aGlzLm1vZGVsc1trZXldID0gbW9kZWw7XG4gICAgICB9XG4gICAgICBfcmVmMSA9IHRoaXMuYmluZGluZ3M7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIGJpbmRpbmcgPSBfcmVmMVtfaV07XG4gICAgICAgIGlmICh0eXBlb2YgYmluZGluZy51cGRhdGUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgIGJpbmRpbmcudXBkYXRlKG1vZGVscyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIFZpZXc7XG5cbiAgfSkoKTtcblxuICBSaXZldHMuQmluZGluZyA9IChmdW5jdGlvbigpIHtcbiAgICBmdW5jdGlvbiBCaW5kaW5nKHZpZXcsIGVsLCB0eXBlLCBrZXlwYXRoLCBvcHRpb25zKSB7XG4gICAgICB0aGlzLnZpZXcgPSB2aWV3O1xuICAgICAgdGhpcy5lbCA9IGVsO1xuICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgIHRoaXMua2V5cGF0aCA9IGtleXBhdGg7XG4gICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zICE9IG51bGwgPyBvcHRpb25zIDoge307XG4gICAgICB0aGlzLmdldFZhbHVlID0gX19iaW5kKHRoaXMuZ2V0VmFsdWUsIHRoaXMpO1xuICAgICAgdGhpcy51cGRhdGUgPSBfX2JpbmQodGhpcy51cGRhdGUsIHRoaXMpO1xuICAgICAgdGhpcy51bmJpbmQgPSBfX2JpbmQodGhpcy51bmJpbmQsIHRoaXMpO1xuICAgICAgdGhpcy5iaW5kID0gX19iaW5kKHRoaXMuYmluZCwgdGhpcyk7XG4gICAgICB0aGlzLnB1Ymxpc2ggPSBfX2JpbmQodGhpcy5wdWJsaXNoLCB0aGlzKTtcbiAgICAgIHRoaXMuc3luYyA9IF9fYmluZCh0aGlzLnN5bmMsIHRoaXMpO1xuICAgICAgdGhpcy5zZXQgPSBfX2JpbmQodGhpcy5zZXQsIHRoaXMpO1xuICAgICAgdGhpcy5ldmVudEhhbmRsZXIgPSBfX2JpbmQodGhpcy5ldmVudEhhbmRsZXIsIHRoaXMpO1xuICAgICAgdGhpcy5mb3JtYXR0ZWRWYWx1ZSA9IF9fYmluZCh0aGlzLmZvcm1hdHRlZFZhbHVlLCB0aGlzKTtcbiAgICAgIHRoaXMucGFyc2VGb3JtYXR0ZXJBcmd1bWVudHMgPSBfX2JpbmQodGhpcy5wYXJzZUZvcm1hdHRlckFyZ3VtZW50cywgdGhpcyk7XG4gICAgICB0aGlzLnBhcnNlVGFyZ2V0ID0gX19iaW5kKHRoaXMucGFyc2VUYXJnZXQsIHRoaXMpO1xuICAgICAgdGhpcy5vYnNlcnZlID0gX19iaW5kKHRoaXMub2JzZXJ2ZSwgdGhpcyk7XG4gICAgICB0aGlzLnNldEJpbmRlciA9IF9fYmluZCh0aGlzLnNldEJpbmRlciwgdGhpcyk7XG4gICAgICB0aGlzLmZvcm1hdHRlcnMgPSB0aGlzLm9wdGlvbnMuZm9ybWF0dGVycyB8fCBbXTtcbiAgICAgIHRoaXMuZGVwZW5kZW5jaWVzID0gW107XG4gICAgICB0aGlzLmZvcm1hdHRlck9ic2VydmVycyA9IHt9O1xuICAgICAgdGhpcy5tb2RlbCA9IHZvaWQgMDtcbiAgICAgIHRoaXMuc2V0QmluZGVyKCk7XG4gICAgfVxuXG4gICAgQmluZGluZy5wcm90b3R5cGUuc2V0QmluZGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgaWRlbnRpZmllciwgcmVnZXhwLCB2YWx1ZSwgX3JlZjE7XG4gICAgICBpZiAoISh0aGlzLmJpbmRlciA9IHRoaXMudmlldy5iaW5kZXJzW3RoaXMudHlwZV0pKSB7XG4gICAgICAgIF9yZWYxID0gdGhpcy52aWV3LmJpbmRlcnM7XG4gICAgICAgIGZvciAoaWRlbnRpZmllciBpbiBfcmVmMSkge1xuICAgICAgICAgIHZhbHVlID0gX3JlZjFbaWRlbnRpZmllcl07XG4gICAgICAgICAgaWYgKGlkZW50aWZpZXIgIT09ICcqJyAmJiBpZGVudGlmaWVyLmluZGV4T2YoJyonKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHJlZ2V4cCA9IG5ldyBSZWdFeHAoXCJeXCIgKyAoaWRlbnRpZmllci5yZXBsYWNlKC9cXCovZywgJy4rJykpICsgXCIkXCIpO1xuICAgICAgICAgICAgaWYgKHJlZ2V4cC50ZXN0KHRoaXMudHlwZSkpIHtcbiAgICAgICAgICAgICAgdGhpcy5iaW5kZXIgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgdGhpcy5hcmdzID0gbmV3IFJlZ0V4cChcIl5cIiArIChpZGVudGlmaWVyLnJlcGxhY2UoL1xcKi9nLCAnKC4rKScpKSArIFwiJFwiKS5leGVjKHRoaXMudHlwZSk7XG4gICAgICAgICAgICAgIHRoaXMuYXJncy5zaGlmdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5iaW5kZXIgfHwgKHRoaXMuYmluZGVyID0gdGhpcy52aWV3LmJpbmRlcnNbJyonXSk7XG4gICAgICBpZiAodGhpcy5iaW5kZXIgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICByZXR1cm4gdGhpcy5iaW5kZXIgPSB7XG4gICAgICAgICAgcm91dGluZTogdGhpcy5iaW5kZXJcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgQmluZGluZy5wcm90b3R5cGUub2JzZXJ2ZSA9IGZ1bmN0aW9uKG9iaiwga2V5cGF0aCwgY2FsbGJhY2spIHtcbiAgICAgIHJldHVybiBSaXZldHMuc2lnaHRnbGFzcyhvYmosIGtleXBhdGgsIGNhbGxiYWNrLCB7XG4gICAgICAgIHJvb3Q6IHRoaXMudmlldy5yb290SW50ZXJmYWNlLFxuICAgICAgICBhZGFwdGVyczogdGhpcy52aWV3LmFkYXB0ZXJzXG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgQmluZGluZy5wcm90b3R5cGUucGFyc2VUYXJnZXQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB0b2tlbjtcbiAgICAgIHRva2VuID0gUml2ZXRzLlR5cGVQYXJzZXIucGFyc2UodGhpcy5rZXlwYXRoKTtcbiAgICAgIGlmICh0b2tlbi50eXBlID09PSBSaXZldHMuVHlwZVBhcnNlci50eXBlcy5wcmltaXRpdmUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsdWUgPSB0b2tlbi52YWx1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMub2JzZXJ2ZXIgPSB0aGlzLm9ic2VydmUodGhpcy52aWV3Lm1vZGVscywgdGhpcy5rZXlwYXRoLCB0aGlzLnN5bmMpO1xuICAgICAgICByZXR1cm4gdGhpcy5tb2RlbCA9IHRoaXMub2JzZXJ2ZXIudGFyZ2V0O1xuICAgICAgfVxuICAgIH07XG5cbiAgICBCaW5kaW5nLnByb3RvdHlwZS5wYXJzZUZvcm1hdHRlckFyZ3VtZW50cyA9IGZ1bmN0aW9uKGFyZ3MsIGZvcm1hdHRlckluZGV4KSB7XG4gICAgICB2YXIgYWksIGFyZywgb2JzZXJ2ZXIsIHByb2Nlc3NlZEFyZ3MsIF9iYXNlLCBfaSwgX2xlbjtcbiAgICAgIGFyZ3MgPSAoZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBfaSwgX2xlbiwgX3Jlc3VsdHM7XG4gICAgICAgIF9yZXN1bHRzID0gW107XG4gICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gYXJncy5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgIGFyZyA9IGFyZ3NbX2ldO1xuICAgICAgICAgIF9yZXN1bHRzLnB1c2goUml2ZXRzLlR5cGVQYXJzZXIucGFyc2UoYXJnKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9yZXN1bHRzO1xuICAgICAgfSkoKTtcbiAgICAgIHByb2Nlc3NlZEFyZ3MgPSBbXTtcbiAgICAgIGZvciAoYWkgPSBfaSA9IDAsIF9sZW4gPSBhcmdzLmxlbmd0aDsgX2kgPCBfbGVuOyBhaSA9ICsrX2kpIHtcbiAgICAgICAgYXJnID0gYXJnc1thaV07XG4gICAgICAgIHByb2Nlc3NlZEFyZ3MucHVzaChhcmcudHlwZSA9PT0gUml2ZXRzLlR5cGVQYXJzZXIudHlwZXMucHJpbWl0aXZlID8gYXJnLnZhbHVlIDogKChfYmFzZSA9IHRoaXMuZm9ybWF0dGVyT2JzZXJ2ZXJzKVtmb3JtYXR0ZXJJbmRleF0gfHwgKF9iYXNlW2Zvcm1hdHRlckluZGV4XSA9IHt9KSwgIShvYnNlcnZlciA9IHRoaXMuZm9ybWF0dGVyT2JzZXJ2ZXJzW2Zvcm1hdHRlckluZGV4XVthaV0pID8gKG9ic2VydmVyID0gdGhpcy5vYnNlcnZlKHRoaXMudmlldy5tb2RlbHMsIGFyZy52YWx1ZSwgdGhpcy5zeW5jKSwgdGhpcy5mb3JtYXR0ZXJPYnNlcnZlcnNbZm9ybWF0dGVySW5kZXhdW2FpXSA9IG9ic2VydmVyKSA6IHZvaWQgMCwgb2JzZXJ2ZXIudmFsdWUoKSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHByb2Nlc3NlZEFyZ3M7XG4gICAgfTtcblxuICAgIEJpbmRpbmcucHJvdG90eXBlLmZvcm1hdHRlZFZhbHVlID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHZhciBhcmdzLCBmaSwgZm9ybWF0dGVyLCBpZCwgcHJvY2Vzc2VkQXJncywgX2ksIF9sZW4sIF9yZWYxLCBfcmVmMjtcbiAgICAgIF9yZWYxID0gdGhpcy5mb3JtYXR0ZXJzO1xuICAgICAgZm9yIChmaSA9IF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBmaSA9ICsrX2kpIHtcbiAgICAgICAgZm9ybWF0dGVyID0gX3JlZjFbZmldO1xuICAgICAgICBhcmdzID0gZm9ybWF0dGVyLm1hdGNoKC9bXlxccyddK3wnKFteJ118J1teXFxzXSkqJ3xcIihbXlwiXXxcIlteXFxzXSkqXCIvZyk7XG4gICAgICAgIGlkID0gYXJncy5zaGlmdCgpO1xuICAgICAgICBmb3JtYXR0ZXIgPSB0aGlzLnZpZXcuZm9ybWF0dGVyc1tpZF07XG4gICAgICAgIHByb2Nlc3NlZEFyZ3MgPSB0aGlzLnBhcnNlRm9ybWF0dGVyQXJndW1lbnRzKGFyZ3MsIGZpKTtcbiAgICAgICAgaWYgKChmb3JtYXR0ZXIgIT0gbnVsbCA/IGZvcm1hdHRlci5yZWFkIDogdm9pZCAwKSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICAgICAgdmFsdWUgPSAoX3JlZjIgPSBmb3JtYXR0ZXIucmVhZCkuY2FsbC5hcHBseShfcmVmMiwgW3RoaXMubW9kZWwsIHZhbHVlXS5jb25jYXQoX19zbGljZS5jYWxsKHByb2Nlc3NlZEFyZ3MpKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoZm9ybWF0dGVyIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgICAgICB2YWx1ZSA9IGZvcm1hdHRlci5jYWxsLmFwcGx5KGZvcm1hdHRlciwgW3RoaXMubW9kZWwsIHZhbHVlXS5jb25jYXQoX19zbGljZS5jYWxsKHByb2Nlc3NlZEFyZ3MpKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9O1xuXG4gICAgQmluZGluZy5wcm90b3R5cGUuZXZlbnRIYW5kbGVyID0gZnVuY3Rpb24oZm4pIHtcbiAgICAgIHZhciBiaW5kaW5nLCBoYW5kbGVyO1xuICAgICAgaGFuZGxlciA9IChiaW5kaW5nID0gdGhpcykudmlldy5oYW5kbGVyO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKGV2KSB7XG4gICAgICAgIHJldHVybiBoYW5kbGVyLmNhbGwoZm4sIHRoaXMsIGV2LCBiaW5kaW5nKTtcbiAgICAgIH07XG4gICAgfTtcblxuICAgIEJpbmRpbmcucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICB2YXIgX3JlZjE7XG4gICAgICB2YWx1ZSA9IHZhbHVlIGluc3RhbmNlb2YgRnVuY3Rpb24gJiYgIXRoaXMuYmluZGVyW1wiZnVuY3Rpb25cIl0gJiYgUml2ZXRzW1wicHVibGljXCJdLmV4ZWN1dGVGdW5jdGlvbnMgPyB0aGlzLmZvcm1hdHRlZFZhbHVlKHZhbHVlLmNhbGwodGhpcy5tb2RlbCkpIDogdGhpcy5mb3JtYXR0ZWRWYWx1ZSh2YWx1ZSk7XG4gICAgICByZXR1cm4gKF9yZWYxID0gdGhpcy5iaW5kZXIucm91dGluZSkgIT0gbnVsbCA/IF9yZWYxLmNhbGwodGhpcywgdGhpcy5lbCwgdmFsdWUpIDogdm9pZCAwO1xuICAgIH07XG5cbiAgICBCaW5kaW5nLnByb3RvdHlwZS5zeW5jID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgZGVwZW5kZW5jeSwgb2JzZXJ2ZXI7XG4gICAgICByZXR1cm4gdGhpcy5zZXQoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgX2ksIF9qLCBfbGVuLCBfbGVuMSwgX3JlZjEsIF9yZWYyLCBfcmVmMztcbiAgICAgICAgaWYgKHRoaXMub2JzZXJ2ZXIpIHtcbiAgICAgICAgICBpZiAodGhpcy5tb2RlbCAhPT0gdGhpcy5vYnNlcnZlci50YXJnZXQpIHtcbiAgICAgICAgICAgIF9yZWYxID0gdGhpcy5kZXBlbmRlbmNpZXM7XG4gICAgICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgICAgIG9ic2VydmVyID0gX3JlZjFbX2ldO1xuICAgICAgICAgICAgICBvYnNlcnZlci51bm9ic2VydmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzID0gW107XG4gICAgICAgICAgICBpZiAoKCh0aGlzLm1vZGVsID0gdGhpcy5vYnNlcnZlci50YXJnZXQpICE9IG51bGwpICYmICgoX3JlZjIgPSB0aGlzLm9wdGlvbnMuZGVwZW5kZW5jaWVzKSAhPSBudWxsID8gX3JlZjIubGVuZ3RoIDogdm9pZCAwKSkge1xuICAgICAgICAgICAgICBfcmVmMyA9IHRoaXMub3B0aW9ucy5kZXBlbmRlbmNpZXM7XG4gICAgICAgICAgICAgIGZvciAoX2ogPSAwLCBfbGVuMSA9IF9yZWYzLmxlbmd0aDsgX2ogPCBfbGVuMTsgX2orKykge1xuICAgICAgICAgICAgICAgIGRlcGVuZGVuY3kgPSBfcmVmM1tfal07XG4gICAgICAgICAgICAgICAgb2JzZXJ2ZXIgPSB0aGlzLm9ic2VydmUodGhpcy5tb2RlbCwgZGVwZW5kZW5jeSwgdGhpcy5zeW5jKTtcbiAgICAgICAgICAgICAgICB0aGlzLmRlcGVuZGVuY2llcy5wdXNoKG9ic2VydmVyKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdGhpcy5vYnNlcnZlci52YWx1ZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgICAgICB9XG4gICAgICB9KS5jYWxsKHRoaXMpKTtcbiAgICB9O1xuXG4gICAgQmluZGluZy5wcm90b3R5cGUucHVibGlzaCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGFyZ3MsIGZpLCBmaVJldmVyc2VkLCBmb3JtYXR0ZXIsIGlkLCBsYXN0Zm9ybWF0dGVySW5kZXgsIHByb2Nlc3NlZEFyZ3MsIHZhbHVlLCBfaSwgX2xlbiwgX3JlZjEsIF9yZWYyLCBfcmVmMztcbiAgICAgIGlmICh0aGlzLm9ic2VydmVyKSB7XG4gICAgICAgIHZhbHVlID0gdGhpcy5nZXRWYWx1ZSh0aGlzLmVsKTtcbiAgICAgICAgbGFzdGZvcm1hdHRlckluZGV4ID0gdGhpcy5mb3JtYXR0ZXJzLmxlbmd0aCAtIDE7XG4gICAgICAgIF9yZWYxID0gdGhpcy5mb3JtYXR0ZXJzLnNsaWNlKDApLnJldmVyc2UoKTtcbiAgICAgICAgZm9yIChmaVJldmVyc2VkID0gX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IGZpUmV2ZXJzZWQgPSArK19pKSB7XG4gICAgICAgICAgZm9ybWF0dGVyID0gX3JlZjFbZmlSZXZlcnNlZF07XG4gICAgICAgICAgZmkgPSBsYXN0Zm9ybWF0dGVySW5kZXggLSBmaVJldmVyc2VkO1xuICAgICAgICAgIGFyZ3MgPSBmb3JtYXR0ZXIuc3BsaXQoL1xccysvKTtcbiAgICAgICAgICBpZCA9IGFyZ3Muc2hpZnQoKTtcbiAgICAgICAgICBwcm9jZXNzZWRBcmdzID0gdGhpcy5wYXJzZUZvcm1hdHRlckFyZ3VtZW50cyhhcmdzLCBmaSk7XG4gICAgICAgICAgaWYgKChfcmVmMiA9IHRoaXMudmlldy5mb3JtYXR0ZXJzW2lkXSkgIT0gbnVsbCA/IF9yZWYyLnB1Ymxpc2ggOiB2b2lkIDApIHtcbiAgICAgICAgICAgIHZhbHVlID0gKF9yZWYzID0gdGhpcy52aWV3LmZvcm1hdHRlcnNbaWRdKS5wdWJsaXNoLmFwcGx5KF9yZWYzLCBbdmFsdWVdLmNvbmNhdChfX3NsaWNlLmNhbGwocHJvY2Vzc2VkQXJncykpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMub2JzZXJ2ZXIuc2V0VmFsdWUodmFsdWUpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBCaW5kaW5nLnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgZGVwZW5kZW5jeSwgb2JzZXJ2ZXIsIF9pLCBfbGVuLCBfcmVmMSwgX3JlZjIsIF9yZWYzO1xuICAgICAgdGhpcy5wYXJzZVRhcmdldCgpO1xuICAgICAgaWYgKChfcmVmMSA9IHRoaXMuYmluZGVyLmJpbmQpICE9IG51bGwpIHtcbiAgICAgICAgX3JlZjEuY2FsbCh0aGlzLCB0aGlzLmVsKTtcbiAgICAgIH1cbiAgICAgIGlmICgodGhpcy5tb2RlbCAhPSBudWxsKSAmJiAoKF9yZWYyID0gdGhpcy5vcHRpb25zLmRlcGVuZGVuY2llcykgIT0gbnVsbCA/IF9yZWYyLmxlbmd0aCA6IHZvaWQgMCkpIHtcbiAgICAgICAgX3JlZjMgPSB0aGlzLm9wdGlvbnMuZGVwZW5kZW5jaWVzO1xuICAgICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYzLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgZGVwZW5kZW5jeSA9IF9yZWYzW19pXTtcbiAgICAgICAgICBvYnNlcnZlciA9IHRoaXMub2JzZXJ2ZSh0aGlzLm1vZGVsLCBkZXBlbmRlbmN5LCB0aGlzLnN5bmMpO1xuICAgICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzLnB1c2gob2JzZXJ2ZXIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodGhpcy52aWV3LnByZWxvYWREYXRhKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN5bmMoKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgQmluZGluZy5wcm90b3R5cGUudW5iaW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYWksIGFyZ3MsIGZpLCBvYnNlcnZlciwgX2ksIF9sZW4sIF9yZWYxLCBfcmVmMiwgX3JlZjMsIF9yZWY0O1xuICAgICAgaWYgKChfcmVmMSA9IHRoaXMuYmluZGVyLnVuYmluZCkgIT0gbnVsbCkge1xuICAgICAgICBfcmVmMS5jYWxsKHRoaXMsIHRoaXMuZWwpO1xuICAgICAgfVxuICAgICAgaWYgKChfcmVmMiA9IHRoaXMub2JzZXJ2ZXIpICE9IG51bGwpIHtcbiAgICAgICAgX3JlZjIudW5vYnNlcnZlKCk7XG4gICAgICB9XG4gICAgICBfcmVmMyA9IHRoaXMuZGVwZW5kZW5jaWVzO1xuICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMy5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICBvYnNlcnZlciA9IF9yZWYzW19pXTtcbiAgICAgICAgb2JzZXJ2ZXIudW5vYnNlcnZlKCk7XG4gICAgICB9XG4gICAgICB0aGlzLmRlcGVuZGVuY2llcyA9IFtdO1xuICAgICAgX3JlZjQgPSB0aGlzLmZvcm1hdHRlck9ic2VydmVycztcbiAgICAgIGZvciAoZmkgaW4gX3JlZjQpIHtcbiAgICAgICAgYXJncyA9IF9yZWY0W2ZpXTtcbiAgICAgICAgZm9yIChhaSBpbiBhcmdzKSB7XG4gICAgICAgICAgb2JzZXJ2ZXIgPSBhcmdzW2FpXTtcbiAgICAgICAgICBvYnNlcnZlci51bm9ic2VydmUoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0dGVyT2JzZXJ2ZXJzID0ge307XG4gICAgfTtcblxuICAgIEJpbmRpbmcucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uKG1vZGVscykge1xuICAgICAgdmFyIF9yZWYxLCBfcmVmMjtcbiAgICAgIGlmIChtb2RlbHMgPT0gbnVsbCkge1xuICAgICAgICBtb2RlbHMgPSB7fTtcbiAgICAgIH1cbiAgICAgIHRoaXMubW9kZWwgPSAoX3JlZjEgPSB0aGlzLm9ic2VydmVyKSAhPSBudWxsID8gX3JlZjEudGFyZ2V0IDogdm9pZCAwO1xuICAgICAgcmV0dXJuIChfcmVmMiA9IHRoaXMuYmluZGVyLnVwZGF0ZSkgIT0gbnVsbCA/IF9yZWYyLmNhbGwodGhpcywgbW9kZWxzKSA6IHZvaWQgMDtcbiAgICB9O1xuXG4gICAgQmluZGluZy5wcm90b3R5cGUuZ2V0VmFsdWUgPSBmdW5jdGlvbihlbCkge1xuICAgICAgaWYgKHRoaXMuYmluZGVyICYmICh0aGlzLmJpbmRlci5nZXRWYWx1ZSAhPSBudWxsKSkge1xuICAgICAgICByZXR1cm4gdGhpcy5iaW5kZXIuZ2V0VmFsdWUuY2FsbCh0aGlzLCBlbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gUml2ZXRzLlV0aWwuZ2V0SW5wdXRWYWx1ZShlbCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBCaW5kaW5nO1xuXG4gIH0pKCk7XG5cbiAgUml2ZXRzLkNvbXBvbmVudEJpbmRpbmcgPSAoZnVuY3Rpb24oX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKENvbXBvbmVudEJpbmRpbmcsIF9zdXBlcik7XG5cbiAgICBmdW5jdGlvbiBDb21wb25lbnRCaW5kaW5nKHZpZXcsIGVsLCB0eXBlKSB7XG4gICAgICB2YXIgYXR0cmlidXRlLCBiaW5kaW5nUmVnRXhwLCBwcm9wZXJ0eU5hbWUsIHRva2VuLCBfaSwgX2xlbiwgX3JlZjEsIF9yZWYyO1xuICAgICAgdGhpcy52aWV3ID0gdmlldztcbiAgICAgIHRoaXMuZWwgPSBlbDtcbiAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICB0aGlzLnVuYmluZCA9IF9fYmluZCh0aGlzLnVuYmluZCwgdGhpcyk7XG4gICAgICB0aGlzLmJpbmQgPSBfX2JpbmQodGhpcy5iaW5kLCB0aGlzKTtcbiAgICAgIHRoaXMubG9jYWxzID0gX19iaW5kKHRoaXMubG9jYWxzLCB0aGlzKTtcbiAgICAgIHRoaXMuY29tcG9uZW50ID0gdGhpcy52aWV3LmNvbXBvbmVudHNbdGhpcy50eXBlXTtcbiAgICAgIHRoaXNbXCJzdGF0aWNcIl0gPSB7fTtcbiAgICAgIHRoaXMub2JzZXJ2ZXJzID0ge307XG4gICAgICB0aGlzLnVwc3RyZWFtT2JzZXJ2ZXJzID0ge307XG4gICAgICBiaW5kaW5nUmVnRXhwID0gdmlldy5iaW5kaW5nUmVnRXhwKCk7XG4gICAgICBfcmVmMSA9IHRoaXMuZWwuYXR0cmlidXRlcyB8fCBbXTtcbiAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgYXR0cmlidXRlID0gX3JlZjFbX2ldO1xuICAgICAgICBpZiAoIWJpbmRpbmdSZWdFeHAudGVzdChhdHRyaWJ1dGUubmFtZSkpIHtcbiAgICAgICAgICBwcm9wZXJ0eU5hbWUgPSB0aGlzLmNhbWVsQ2FzZShhdHRyaWJ1dGUubmFtZSk7XG4gICAgICAgICAgdG9rZW4gPSBSaXZldHMuVHlwZVBhcnNlci5wYXJzZShhdHRyaWJ1dGUudmFsdWUpO1xuICAgICAgICAgIGlmIChfX2luZGV4T2YuY2FsbCgoX3JlZjIgPSB0aGlzLmNvbXBvbmVudFtcInN0YXRpY1wiXSkgIT0gbnVsbCA/IF9yZWYyIDogW10sIHByb3BlcnR5TmFtZSkgPj0gMCkge1xuICAgICAgICAgICAgdGhpc1tcInN0YXRpY1wiXVtwcm9wZXJ0eU5hbWVdID0gYXR0cmlidXRlLnZhbHVlO1xuICAgICAgICAgIH0gZWxzZSBpZiAodG9rZW4udHlwZSA9PT0gUml2ZXRzLlR5cGVQYXJzZXIudHlwZXMucHJpbWl0aXZlKSB7XG4gICAgICAgICAgICB0aGlzW1wic3RhdGljXCJdW3Byb3BlcnR5TmFtZV0gPSB0b2tlbi52YWx1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5vYnNlcnZlcnNbcHJvcGVydHlOYW1lXSA9IGF0dHJpYnV0ZS52YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBDb21wb25lbnRCaW5kaW5nLnByb3RvdHlwZS5zeW5jID0gZnVuY3Rpb24oKSB7fTtcblxuICAgIENvbXBvbmVudEJpbmRpbmcucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uKCkge307XG5cbiAgICBDb21wb25lbnRCaW5kaW5nLnByb3RvdHlwZS5wdWJsaXNoID0gZnVuY3Rpb24oKSB7fTtcblxuICAgIENvbXBvbmVudEJpbmRpbmcucHJvdG90eXBlLmxvY2FscyA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGtleSwgb2JzZXJ2ZXIsIHJlc3VsdCwgdmFsdWUsIF9yZWYxLCBfcmVmMjtcbiAgICAgIHJlc3VsdCA9IHt9O1xuICAgICAgX3JlZjEgPSB0aGlzW1wic3RhdGljXCJdO1xuICAgICAgZm9yIChrZXkgaW4gX3JlZjEpIHtcbiAgICAgICAgdmFsdWUgPSBfcmVmMVtrZXldO1xuICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgX3JlZjIgPSB0aGlzLm9ic2VydmVycztcbiAgICAgIGZvciAoa2V5IGluIF9yZWYyKSB7XG4gICAgICAgIG9ic2VydmVyID0gX3JlZjJba2V5XTtcbiAgICAgICAgcmVzdWx0W2tleV0gPSBvYnNlcnZlci52YWx1ZSgpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuXG4gICAgQ29tcG9uZW50QmluZGluZy5wcm90b3R5cGUuY2FtZWxDYXNlID0gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoLy0oW2Etel0pL2csIGZ1bmN0aW9uKGdyb3VwZWQpIHtcbiAgICAgICAgcmV0dXJuIGdyb3VwZWRbMV0udG9VcHBlckNhc2UoKTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBDb21wb25lbnRCaW5kaW5nLnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgaywga2V5LCBrZXlwYXRoLCBvYnNlcnZlciwgb3B0aW9uLCBvcHRpb25zLCBzY29wZSwgdiwgX2Jhc2UsIF9pLCBfaiwgX2xlbiwgX2xlbjEsIF9yZWYxLCBfcmVmMiwgX3JlZjMsIF9yZWY0LCBfcmVmNSwgX3JlZjYsIF9yZWY3O1xuICAgICAgaWYgKCF0aGlzLmJvdW5kKSB7XG4gICAgICAgIF9yZWYxID0gdGhpcy5vYnNlcnZlcnM7XG4gICAgICAgIGZvciAoa2V5IGluIF9yZWYxKSB7XG4gICAgICAgICAga2V5cGF0aCA9IF9yZWYxW2tleV07XG4gICAgICAgICAgdGhpcy5vYnNlcnZlcnNba2V5XSA9IHRoaXMub2JzZXJ2ZSh0aGlzLnZpZXcubW9kZWxzLCBrZXlwYXRoLCAoKGZ1bmN0aW9uKF90aGlzKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX3RoaXMuY29tcG9uZW50Vmlldy5tb2RlbHNba2V5XSA9IF90aGlzLm9ic2VydmVyc1trZXldLnZhbHVlKCk7XG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pKHRoaXMpKS5jYWxsKHRoaXMsIGtleSkpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYm91bmQgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuY29tcG9uZW50VmlldyAhPSBudWxsKSB7XG4gICAgICAgIHRoaXMuY29tcG9uZW50Vmlldy5iaW5kKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmVsLmlubmVySFRNTCA9IHRoaXMuY29tcG9uZW50LnRlbXBsYXRlLmNhbGwodGhpcyk7XG4gICAgICAgIHNjb3BlID0gdGhpcy5jb21wb25lbnQuaW5pdGlhbGl6ZS5jYWxsKHRoaXMsIHRoaXMuZWwsIHRoaXMubG9jYWxzKCkpO1xuICAgICAgICB0aGlzLmVsLl9ib3VuZCA9IHRydWU7XG4gICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgX3JlZjIgPSBSaXZldHMuZXh0ZW5zaW9ucztcbiAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMi5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgIG9wdGlvbiA9IF9yZWYyW19pXTtcbiAgICAgICAgICBvcHRpb25zW29wdGlvbl0gPSB7fTtcbiAgICAgICAgICBpZiAodGhpcy5jb21wb25lbnRbb3B0aW9uXSkge1xuICAgICAgICAgICAgX3JlZjMgPSB0aGlzLmNvbXBvbmVudFtvcHRpb25dO1xuICAgICAgICAgICAgZm9yIChrIGluIF9yZWYzKSB7XG4gICAgICAgICAgICAgIHYgPSBfcmVmM1trXTtcbiAgICAgICAgICAgICAgb3B0aW9uc1tvcHRpb25dW2tdID0gdjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgX3JlZjQgPSB0aGlzLnZpZXdbb3B0aW9uXTtcbiAgICAgICAgICBmb3IgKGsgaW4gX3JlZjQpIHtcbiAgICAgICAgICAgIHYgPSBfcmVmNFtrXTtcbiAgICAgICAgICAgIGlmICgoX2Jhc2UgPSBvcHRpb25zW29wdGlvbl0pW2tdID09IG51bGwpIHtcbiAgICAgICAgICAgICAgX2Jhc2Vba10gPSB2O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBfcmVmNSA9IFJpdmV0cy5vcHRpb25zO1xuICAgICAgICBmb3IgKF9qID0gMCwgX2xlbjEgPSBfcmVmNS5sZW5ndGg7IF9qIDwgX2xlbjE7IF9qKyspIHtcbiAgICAgICAgICBvcHRpb24gPSBfcmVmNVtfal07XG4gICAgICAgICAgb3B0aW9uc1tvcHRpb25dID0gKF9yZWY2ID0gdGhpcy5jb21wb25lbnRbb3B0aW9uXSkgIT0gbnVsbCA/IF9yZWY2IDogdGhpcy52aWV3W29wdGlvbl07XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jb21wb25lbnRWaWV3ID0gbmV3IFJpdmV0cy5WaWV3KEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMuZWwuY2hpbGROb2RlcyksIHNjb3BlLCBvcHRpb25zKTtcbiAgICAgICAgdGhpcy5jb21wb25lbnRWaWV3LmJpbmQoKTtcbiAgICAgICAgX3JlZjcgPSB0aGlzLm9ic2VydmVycztcbiAgICAgICAgZm9yIChrZXkgaW4gX3JlZjcpIHtcbiAgICAgICAgICBvYnNlcnZlciA9IF9yZWY3W2tleV07XG4gICAgICAgICAgdGhpcy51cHN0cmVhbU9ic2VydmVyc1trZXldID0gdGhpcy5vYnNlcnZlKHRoaXMuY29tcG9uZW50Vmlldy5tb2RlbHMsIGtleSwgKChmdW5jdGlvbihfdGhpcykge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKGtleSwgb2JzZXJ2ZXIpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvYnNlcnZlci5zZXRWYWx1ZShfdGhpcy5jb21wb25lbnRWaWV3Lm1vZGVsc1trZXldKTtcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSkodGhpcykpLmNhbGwodGhpcywga2V5LCBvYnNlcnZlcikpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIENvbXBvbmVudEJpbmRpbmcucHJvdG90eXBlLnVuYmluZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGtleSwgb2JzZXJ2ZXIsIF9yZWYxLCBfcmVmMiwgX3JlZjM7XG4gICAgICBfcmVmMSA9IHRoaXMudXBzdHJlYW1PYnNlcnZlcnM7XG4gICAgICBmb3IgKGtleSBpbiBfcmVmMSkge1xuICAgICAgICBvYnNlcnZlciA9IF9yZWYxW2tleV07XG4gICAgICAgIG9ic2VydmVyLnVub2JzZXJ2ZSgpO1xuICAgICAgfVxuICAgICAgX3JlZjIgPSB0aGlzLm9ic2VydmVycztcbiAgICAgIGZvciAoa2V5IGluIF9yZWYyKSB7XG4gICAgICAgIG9ic2VydmVyID0gX3JlZjJba2V5XTtcbiAgICAgICAgb2JzZXJ2ZXIudW5vYnNlcnZlKCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gKF9yZWYzID0gdGhpcy5jb21wb25lbnRWaWV3KSAhPSBudWxsID8gX3JlZjMudW5iaW5kLmNhbGwodGhpcykgOiB2b2lkIDA7XG4gICAgfTtcblxuICAgIHJldHVybiBDb21wb25lbnRCaW5kaW5nO1xuXG4gIH0pKFJpdmV0cy5CaW5kaW5nKTtcblxuICBSaXZldHMuVGV4dEJpbmRpbmcgPSAoZnVuY3Rpb24oX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFRleHRCaW5kaW5nLCBfc3VwZXIpO1xuXG4gICAgZnVuY3Rpb24gVGV4dEJpbmRpbmcodmlldywgZWwsIHR5cGUsIGtleXBhdGgsIG9wdGlvbnMpIHtcbiAgICAgIHRoaXMudmlldyA9IHZpZXc7XG4gICAgICB0aGlzLmVsID0gZWw7XG4gICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgdGhpcy5rZXlwYXRoID0ga2V5cGF0aDtcbiAgICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnMgIT0gbnVsbCA/IG9wdGlvbnMgOiB7fTtcbiAgICAgIHRoaXMuc3luYyA9IF9fYmluZCh0aGlzLnN5bmMsIHRoaXMpO1xuICAgICAgdGhpcy5mb3JtYXR0ZXJzID0gdGhpcy5vcHRpb25zLmZvcm1hdHRlcnMgfHwgW107XG4gICAgICB0aGlzLmRlcGVuZGVuY2llcyA9IFtdO1xuICAgICAgdGhpcy5mb3JtYXR0ZXJPYnNlcnZlcnMgPSB7fTtcbiAgICB9XG5cbiAgICBUZXh0QmluZGluZy5wcm90b3R5cGUuYmluZGVyID0ge1xuICAgICAgcm91dGluZTogZnVuY3Rpb24obm9kZSwgdmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIG5vZGUuZGF0YSA9IHZhbHVlICE9IG51bGwgPyB2YWx1ZSA6ICcnO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBUZXh0QmluZGluZy5wcm90b3R5cGUuc3luYyA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIFRleHRCaW5kaW5nLl9fc3VwZXJfXy5zeW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcblxuICAgIHJldHVybiBUZXh0QmluZGluZztcblxuICB9KShSaXZldHMuQmluZGluZyk7XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnMudGV4dCA9IGZ1bmN0aW9uKGVsLCB2YWx1ZSkge1xuICAgIGlmIChlbC50ZXh0Q29udGVudCAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gZWwudGV4dENvbnRlbnQgPSB2YWx1ZSAhPSBudWxsID8gdmFsdWUgOiAnJztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGVsLmlubmVyVGV4dCA9IHZhbHVlICE9IG51bGwgPyB2YWx1ZSA6ICcnO1xuICAgIH1cbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVycy5odG1sID0gZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGVsLmlubmVySFRNTCA9IHZhbHVlICE9IG51bGwgPyB2YWx1ZSA6ICcnO1xuICB9O1xuXG4gIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzLnNob3cgPSBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICByZXR1cm4gZWwuc3R5bGUuZGlzcGxheSA9IHZhbHVlID8gJycgOiAnbm9uZSc7XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnMuaGlkZSA9IGZ1bmN0aW9uKGVsLCB2YWx1ZSkge1xuICAgIHJldHVybiBlbC5zdHlsZS5kaXNwbGF5ID0gdmFsdWUgPyAnbm9uZScgOiAnJztcbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVycy5lbmFibGVkID0gZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGVsLmRpc2FibGVkID0gIXZhbHVlO1xuICB9O1xuXG4gIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzLmRpc2FibGVkID0gZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGVsLmRpc2FibGVkID0gISF2YWx1ZTtcbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVycy5jaGVja2VkID0ge1xuICAgIHB1Ymxpc2hlczogdHJ1ZSxcbiAgICBwcmlvcml0eTogMjAwMCxcbiAgICBiaW5kOiBmdW5jdGlvbihlbCkge1xuICAgICAgcmV0dXJuIFJpdmV0cy5VdGlsLmJpbmRFdmVudChlbCwgJ2NoYW5nZScsIHRoaXMucHVibGlzaCk7XG4gICAgfSxcbiAgICB1bmJpbmQ6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICByZXR1cm4gUml2ZXRzLlV0aWwudW5iaW5kRXZlbnQoZWwsICdjaGFuZ2UnLCB0aGlzLnB1Ymxpc2gpO1xuICAgIH0sXG4gICAgcm91dGluZTogZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgICB2YXIgX3JlZjE7XG4gICAgICBpZiAoZWwudHlwZSA9PT0gJ3JhZGlvJykge1xuICAgICAgICByZXR1cm4gZWwuY2hlY2tlZCA9ICgoX3JlZjEgPSBlbC52YWx1ZSkgIT0gbnVsbCA/IF9yZWYxLnRvU3RyaW5nKCkgOiB2b2lkIDApID09PSAodmFsdWUgIT0gbnVsbCA/IHZhbHVlLnRvU3RyaW5nKCkgOiB2b2lkIDApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGVsLmNoZWNrZWQgPSAhIXZhbHVlO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVycy51bmNoZWNrZWQgPSB7XG4gICAgcHVibGlzaGVzOiB0cnVlLFxuICAgIHByaW9yaXR5OiAyMDAwLFxuICAgIGJpbmQ6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICByZXR1cm4gUml2ZXRzLlV0aWwuYmluZEV2ZW50KGVsLCAnY2hhbmdlJywgdGhpcy5wdWJsaXNoKTtcbiAgICB9LFxuICAgIHVuYmluZDogZnVuY3Rpb24oZWwpIHtcbiAgICAgIHJldHVybiBSaXZldHMuVXRpbC51bmJpbmRFdmVudChlbCwgJ2NoYW5nZScsIHRoaXMucHVibGlzaCk7XG4gICAgfSxcbiAgICByb3V0aW5lOiBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICAgIHZhciBfcmVmMTtcbiAgICAgIGlmIChlbC50eXBlID09PSAncmFkaW8nKSB7XG4gICAgICAgIHJldHVybiBlbC5jaGVja2VkID0gKChfcmVmMSA9IGVsLnZhbHVlKSAhPSBudWxsID8gX3JlZjEudG9TdHJpbmcoKSA6IHZvaWQgMCkgIT09ICh2YWx1ZSAhPSBudWxsID8gdmFsdWUudG9TdHJpbmcoKSA6IHZvaWQgMCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZWwuY2hlY2tlZCA9ICF2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnMudmFsdWUgPSB7XG4gICAgcHVibGlzaGVzOiB0cnVlLFxuICAgIHByaW9yaXR5OiAzMDAwLFxuICAgIGJpbmQ6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICBpZiAoIShlbC50YWdOYW1lID09PSAnSU5QVVQnICYmIGVsLnR5cGUgPT09ICdyYWRpbycpKSB7XG4gICAgICAgIHRoaXMuZXZlbnQgPSBlbC50YWdOYW1lID09PSAnU0VMRUNUJyA/ICdjaGFuZ2UnIDogJ2lucHV0JztcbiAgICAgICAgcmV0dXJuIFJpdmV0cy5VdGlsLmJpbmRFdmVudChlbCwgdGhpcy5ldmVudCwgdGhpcy5wdWJsaXNoKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHVuYmluZDogZnVuY3Rpb24oZWwpIHtcbiAgICAgIGlmICghKGVsLnRhZ05hbWUgPT09ICdJTlBVVCcgJiYgZWwudHlwZSA9PT0gJ3JhZGlvJykpIHtcbiAgICAgICAgcmV0dXJuIFJpdmV0cy5VdGlsLnVuYmluZEV2ZW50KGVsLCB0aGlzLmV2ZW50LCB0aGlzLnB1Ymxpc2gpO1xuICAgICAgfVxuICAgIH0sXG4gICAgcm91dGluZTogZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgICB2YXIgbywgX2ksIF9sZW4sIF9yZWYxLCBfcmVmMiwgX3JlZjMsIF9yZXN1bHRzO1xuICAgICAgaWYgKGVsLnRhZ05hbWUgPT09ICdJTlBVVCcgJiYgZWwudHlwZSA9PT0gJ3JhZGlvJykge1xuICAgICAgICByZXR1cm4gZWwuc2V0QXR0cmlidXRlKCd2YWx1ZScsIHZhbHVlKTtcbiAgICAgIH0gZWxzZSBpZiAod2luZG93LmpRdWVyeSAhPSBudWxsKSB7XG4gICAgICAgIGVsID0galF1ZXJ5KGVsKTtcbiAgICAgICAgaWYgKCh2YWx1ZSAhPSBudWxsID8gdmFsdWUudG9TdHJpbmcoKSA6IHZvaWQgMCkgIT09ICgoX3JlZjEgPSBlbC52YWwoKSkgIT0gbnVsbCA/IF9yZWYxLnRvU3RyaW5nKCkgOiB2b2lkIDApKSB7XG4gICAgICAgICAgcmV0dXJuIGVsLnZhbCh2YWx1ZSAhPSBudWxsID8gdmFsdWUgOiAnJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChlbC50eXBlID09PSAnc2VsZWN0LW11bHRpcGxlJykge1xuICAgICAgICAgIGlmICh2YWx1ZSAhPSBudWxsKSB7XG4gICAgICAgICAgICBfcmVzdWx0cyA9IFtdO1xuICAgICAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBlbC5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgICAgICBvID0gZWxbX2ldO1xuICAgICAgICAgICAgICBfcmVzdWx0cy5wdXNoKG8uc2VsZWN0ZWQgPSAoX3JlZjIgPSBvLnZhbHVlLCBfX2luZGV4T2YuY2FsbCh2YWx1ZSwgX3JlZjIpID49IDApKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBfcmVzdWx0cztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoKHZhbHVlICE9IG51bGwgPyB2YWx1ZS50b1N0cmluZygpIDogdm9pZCAwKSAhPT0gKChfcmVmMyA9IGVsLnZhbHVlKSAhPSBudWxsID8gX3JlZjMudG9TdHJpbmcoKSA6IHZvaWQgMCkpIHtcbiAgICAgICAgICByZXR1cm4gZWwudmFsdWUgPSB2YWx1ZSAhPSBudWxsID8gdmFsdWUgOiAnJztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVyc1tcImlmXCJdID0ge1xuICAgIGJsb2NrOiB0cnVlLFxuICAgIHByaW9yaXR5OiA0MDAwLFxuICAgIGJpbmQ6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICB2YXIgYXR0ciwgZGVjbGFyYXRpb247XG4gICAgICBpZiAodGhpcy5tYXJrZXIgPT0gbnVsbCkge1xuICAgICAgICBhdHRyID0gW3RoaXMudmlldy5wcmVmaXgsIHRoaXMudHlwZV0uam9pbignLScpLnJlcGxhY2UoJy0tJywgJy0nKTtcbiAgICAgICAgZGVjbGFyYXRpb24gPSBlbC5nZXRBdHRyaWJ1dGUoYXR0cik7XG4gICAgICAgIHRoaXMubWFya2VyID0gZG9jdW1lbnQuY3JlYXRlQ29tbWVudChcIiByaXZldHM6IFwiICsgdGhpcy50eXBlICsgXCIgXCIgKyBkZWNsYXJhdGlvbiArIFwiIFwiKTtcbiAgICAgICAgdGhpcy5ib3VuZCA9IGZhbHNlO1xuICAgICAgICBlbC5yZW1vdmVBdHRyaWJ1dGUoYXR0cik7XG4gICAgICAgIGVsLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMubWFya2VyLCBlbCk7XG4gICAgICAgIHJldHVybiBlbC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGVsKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHVuYmluZDogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAodGhpcy5uZXN0ZWQpIHtcbiAgICAgICAgdGhpcy5uZXN0ZWQudW5iaW5kKCk7XG4gICAgICAgIHJldHVybiB0aGlzLmJvdW5kID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSxcbiAgICByb3V0aW5lOiBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICAgIHZhciBrZXksIG1vZGVsLCBtb2RlbHMsIF9yZWYxO1xuICAgICAgaWYgKCEhdmFsdWUgPT09ICF0aGlzLmJvdW5kKSB7XG4gICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgIG1vZGVscyA9IHt9O1xuICAgICAgICAgIF9yZWYxID0gdGhpcy52aWV3Lm1vZGVscztcbiAgICAgICAgICBmb3IgKGtleSBpbiBfcmVmMSkge1xuICAgICAgICAgICAgbW9kZWwgPSBfcmVmMVtrZXldO1xuICAgICAgICAgICAgbW9kZWxzW2tleV0gPSBtb2RlbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgKHRoaXMubmVzdGVkIHx8ICh0aGlzLm5lc3RlZCA9IG5ldyBSaXZldHMuVmlldyhlbCwgbW9kZWxzLCB0aGlzLnZpZXcub3B0aW9ucygpKSkpLmJpbmQoKTtcbiAgICAgICAgICB0aGlzLm1hcmtlci5wYXJlbnROb2RlLmluc2VydEJlZm9yZShlbCwgdGhpcy5tYXJrZXIubmV4dFNpYmxpbmcpO1xuICAgICAgICAgIHJldHVybiB0aGlzLmJvdW5kID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBlbC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGVsKTtcbiAgICAgICAgICB0aGlzLm5lc3RlZC51bmJpbmQoKTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5ib3VuZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICB1cGRhdGU6IGZ1bmN0aW9uKG1vZGVscykge1xuICAgICAgdmFyIF9yZWYxO1xuICAgICAgcmV0dXJuIChfcmVmMSA9IHRoaXMubmVzdGVkKSAhPSBudWxsID8gX3JlZjEudXBkYXRlKG1vZGVscykgOiB2b2lkIDA7XG4gICAgfVxuICB9O1xuXG4gIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzLnVubGVzcyA9IHtcbiAgICBibG9jazogdHJ1ZSxcbiAgICBwcmlvcml0eTogNDAwMCxcbiAgICBiaW5kOiBmdW5jdGlvbihlbCkge1xuICAgICAgcmV0dXJuIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzW1wiaWZcIl0uYmluZC5jYWxsKHRoaXMsIGVsKTtcbiAgICB9LFxuICAgIHVuYmluZDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnNbXCJpZlwiXS51bmJpbmQuY2FsbCh0aGlzKTtcbiAgICB9LFxuICAgIHJvdXRpbmU6IGZ1bmN0aW9uKGVsLCB2YWx1ZSkge1xuICAgICAgcmV0dXJuIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzW1wiaWZcIl0ucm91dGluZS5jYWxsKHRoaXMsIGVsLCAhdmFsdWUpO1xuICAgIH0sXG4gICAgdXBkYXRlOiBmdW5jdGlvbihtb2RlbHMpIHtcbiAgICAgIHJldHVybiBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVyc1tcImlmXCJdLnVwZGF0ZS5jYWxsKHRoaXMsIG1vZGVscyk7XG4gICAgfVxuICB9O1xuXG4gIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzWydvbi0qJ10gPSB7XG4gICAgXCJmdW5jdGlvblwiOiB0cnVlLFxuICAgIHByaW9yaXR5OiAxMDAwLFxuICAgIHVuYmluZDogZnVuY3Rpb24oZWwpIHtcbiAgICAgIGlmICh0aGlzLmhhbmRsZXIpIHtcbiAgICAgICAgcmV0dXJuIFJpdmV0cy5VdGlsLnVuYmluZEV2ZW50KGVsLCB0aGlzLmFyZ3NbMF0sIHRoaXMuaGFuZGxlcik7XG4gICAgICB9XG4gICAgfSxcbiAgICByb3V0aW5lOiBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICAgIGlmICh0aGlzLmhhbmRsZXIpIHtcbiAgICAgICAgUml2ZXRzLlV0aWwudW5iaW5kRXZlbnQoZWwsIHRoaXMuYXJnc1swXSwgdGhpcy5oYW5kbGVyKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBSaXZldHMuVXRpbC5iaW5kRXZlbnQoZWwsIHRoaXMuYXJnc1swXSwgdGhpcy5oYW5kbGVyID0gdGhpcy5ldmVudEhhbmRsZXIodmFsdWUpKTtcbiAgICB9XG4gIH07XG5cbiAgUml2ZXRzW1wicHVibGljXCJdLmJpbmRlcnNbJ2VhY2gtKiddID0ge1xuICAgIGJsb2NrOiB0cnVlLFxuICAgIHByaW9yaXR5OiA0MDAwLFxuICAgIGJpbmQ6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICB2YXIgYXR0ciwgdmlldywgX2ksIF9sZW4sIF9yZWYxO1xuICAgICAgaWYgKHRoaXMubWFya2VyID09IG51bGwpIHtcbiAgICAgICAgYXR0ciA9IFt0aGlzLnZpZXcucHJlZml4LCB0aGlzLnR5cGVdLmpvaW4oJy0nKS5yZXBsYWNlKCctLScsICctJyk7XG4gICAgICAgIHRoaXMubWFya2VyID0gZG9jdW1lbnQuY3JlYXRlQ29tbWVudChcIiByaXZldHM6IFwiICsgdGhpcy50eXBlICsgXCIgXCIpO1xuICAgICAgICB0aGlzLml0ZXJhdGVkID0gW107XG4gICAgICAgIGVsLnJlbW92ZUF0dHJpYnV0ZShhdHRyKTtcbiAgICAgICAgZWwucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGhpcy5tYXJrZXIsIGVsKTtcbiAgICAgICAgZWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChlbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBfcmVmMSA9IHRoaXMuaXRlcmF0ZWQ7XG4gICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgICB2aWV3ID0gX3JlZjFbX2ldO1xuICAgICAgICAgIHZpZXcuYmluZCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICB1bmJpbmQ6IGZ1bmN0aW9uKGVsKSB7XG4gICAgICB2YXIgdmlldywgX2ksIF9sZW4sIF9yZWYxO1xuICAgICAgaWYgKHRoaXMuaXRlcmF0ZWQgIT0gbnVsbCkge1xuICAgICAgICBfcmVmMSA9IHRoaXMuaXRlcmF0ZWQ7XG4gICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgICB2aWV3ID0gX3JlZjFbX2ldO1xuICAgICAgICAgIHZpZXcudW5iaW5kKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIHJvdXRpbmU6IGZ1bmN0aW9uKGVsLCBjb2xsZWN0aW9uKSB7XG4gICAgICB2YXIgYmluZGluZywgZGF0YSwgaSwgaW5kZXgsIGtleSwgbW9kZWwsIG1vZGVsTmFtZSwgb3B0aW9ucywgcHJldmlvdXMsIHRlbXBsYXRlLCB2aWV3LCBfaSwgX2osIF9rLCBfbGVuLCBfbGVuMSwgX2xlbjIsIF9yZWYxLCBfcmVmMiwgX3JlZjM7XG4gICAgICBtb2RlbE5hbWUgPSB0aGlzLmFyZ3NbMF07XG4gICAgICBjb2xsZWN0aW9uID0gY29sbGVjdGlvbiB8fCBbXTtcbiAgICAgIGlmICh0aGlzLml0ZXJhdGVkLmxlbmd0aCA+IGNvbGxlY3Rpb24ubGVuZ3RoKSB7XG4gICAgICAgIF9yZWYxID0gQXJyYXkodGhpcy5pdGVyYXRlZC5sZW5ndGggLSBjb2xsZWN0aW9uLmxlbmd0aCk7XG4gICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjEubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgICBpID0gX3JlZjFbX2ldO1xuICAgICAgICAgIHZpZXcgPSB0aGlzLml0ZXJhdGVkLnBvcCgpO1xuICAgICAgICAgIHZpZXcudW5iaW5kKCk7XG4gICAgICAgICAgdGhpcy5tYXJrZXIucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh2aWV3LmVsc1swXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGZvciAoaW5kZXggPSBfaiA9IDAsIF9sZW4xID0gY29sbGVjdGlvbi5sZW5ndGg7IF9qIDwgX2xlbjE7IGluZGV4ID0gKytfaikge1xuICAgICAgICBtb2RlbCA9IGNvbGxlY3Rpb25baW5kZXhdO1xuICAgICAgICBkYXRhID0ge1xuICAgICAgICAgIGluZGV4OiBpbmRleFxuICAgICAgICB9O1xuICAgICAgICBkYXRhW1JpdmV0c1tcInB1YmxpY1wiXS5pdGVyYXRpb25BbGlhcyhtb2RlbE5hbWUpXSA9IGluZGV4O1xuICAgICAgICBkYXRhW21vZGVsTmFtZV0gPSBtb2RlbDtcbiAgICAgICAgaWYgKHRoaXMuaXRlcmF0ZWRbaW5kZXhdID09IG51bGwpIHtcbiAgICAgICAgICBfcmVmMiA9IHRoaXMudmlldy5tb2RlbHM7XG4gICAgICAgICAgZm9yIChrZXkgaW4gX3JlZjIpIHtcbiAgICAgICAgICAgIG1vZGVsID0gX3JlZjJba2V5XTtcbiAgICAgICAgICAgIGlmIChkYXRhW2tleV0gPT0gbnVsbCkge1xuICAgICAgICAgICAgICBkYXRhW2tleV0gPSBtb2RlbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcHJldmlvdXMgPSB0aGlzLml0ZXJhdGVkLmxlbmd0aCA/IHRoaXMuaXRlcmF0ZWRbdGhpcy5pdGVyYXRlZC5sZW5ndGggLSAxXS5lbHNbMF0gOiB0aGlzLm1hcmtlcjtcbiAgICAgICAgICBvcHRpb25zID0gdGhpcy52aWV3Lm9wdGlvbnMoKTtcbiAgICAgICAgICBvcHRpb25zLnByZWxvYWREYXRhID0gdHJ1ZTtcbiAgICAgICAgICB0ZW1wbGF0ZSA9IGVsLmNsb25lTm9kZSh0cnVlKTtcbiAgICAgICAgICB2aWV3ID0gbmV3IFJpdmV0cy5WaWV3KHRlbXBsYXRlLCBkYXRhLCBvcHRpb25zKTtcbiAgICAgICAgICB2aWV3LmJpbmQoKTtcbiAgICAgICAgICB0aGlzLml0ZXJhdGVkLnB1c2godmlldyk7XG4gICAgICAgICAgdGhpcy5tYXJrZXIucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGVtcGxhdGUsIHByZXZpb3VzLm5leHRTaWJsaW5nKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLml0ZXJhdGVkW2luZGV4XS5tb2RlbHNbbW9kZWxOYW1lXSAhPT0gbW9kZWwpIHtcbiAgICAgICAgICB0aGlzLml0ZXJhdGVkW2luZGV4XS51cGRhdGUoZGF0YSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChlbC5ub2RlTmFtZSA9PT0gJ09QVElPTicpIHtcbiAgICAgICAgX3JlZjMgPSB0aGlzLnZpZXcuYmluZGluZ3M7XG4gICAgICAgIGZvciAoX2sgPSAwLCBfbGVuMiA9IF9yZWYzLmxlbmd0aDsgX2sgPCBfbGVuMjsgX2srKykge1xuICAgICAgICAgIGJpbmRpbmcgPSBfcmVmM1tfa107XG4gICAgICAgICAgaWYgKGJpbmRpbmcuZWwgPT09IHRoaXMubWFya2VyLnBhcmVudE5vZGUgJiYgYmluZGluZy50eXBlID09PSAndmFsdWUnKSB7XG4gICAgICAgICAgICBiaW5kaW5nLnN5bmMoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIHVwZGF0ZTogZnVuY3Rpb24obW9kZWxzKSB7XG4gICAgICB2YXIgZGF0YSwga2V5LCBtb2RlbCwgdmlldywgX2ksIF9sZW4sIF9yZWYxO1xuICAgICAgZGF0YSA9IHt9O1xuICAgICAgZm9yIChrZXkgaW4gbW9kZWxzKSB7XG4gICAgICAgIG1vZGVsID0gbW9kZWxzW2tleV07XG4gICAgICAgIGlmIChrZXkgIT09IHRoaXMuYXJnc1swXSkge1xuICAgICAgICAgIGRhdGFba2V5XSA9IG1vZGVsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBfcmVmMSA9IHRoaXMuaXRlcmF0ZWQ7XG4gICAgICBmb3IgKF9pID0gMCwgX2xlbiA9IF9yZWYxLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgIHZpZXcgPSBfcmVmMVtfaV07XG4gICAgICAgIHZpZXcudXBkYXRlKGRhdGEpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYmluZGVyc1snY2xhc3MtKiddID0gZnVuY3Rpb24oZWwsIHZhbHVlKSB7XG4gICAgdmFyIGVsQ2xhc3M7XG4gICAgZWxDbGFzcyA9IFwiIFwiICsgZWwuY2xhc3NOYW1lICsgXCIgXCI7XG4gICAgaWYgKCF2YWx1ZSA9PT0gKGVsQ2xhc3MuaW5kZXhPZihcIiBcIiArIHRoaXMuYXJnc1swXSArIFwiIFwiKSAhPT0gLTEpKSB7XG4gICAgICByZXR1cm4gZWwuY2xhc3NOYW1lID0gdmFsdWUgPyBcIlwiICsgZWwuY2xhc3NOYW1lICsgXCIgXCIgKyB0aGlzLmFyZ3NbMF0gOiBlbENsYXNzLnJlcGxhY2UoXCIgXCIgKyB0aGlzLmFyZ3NbMF0gKyBcIiBcIiwgJyAnKS50cmltKCk7XG4gICAgfVxuICB9O1xuXG4gIFJpdmV0c1tcInB1YmxpY1wiXS5iaW5kZXJzWycqJ10gPSBmdW5jdGlvbihlbCwgdmFsdWUpIHtcbiAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGVsLnNldEF0dHJpYnV0ZSh0aGlzLnR5cGUsIHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGVsLnJlbW92ZUF0dHJpYnV0ZSh0aGlzLnR5cGUpO1xuICAgIH1cbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uZm9ybWF0dGVyc1snY2FsbCddID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGFyZ3MsIHZhbHVlO1xuICAgIHZhbHVlID0gYXJndW1lbnRzWzBdLCBhcmdzID0gMiA8PSBhcmd1bWVudHMubGVuZ3RoID8gX19zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkgOiBbXTtcbiAgICByZXR1cm4gdmFsdWUuY2FsbC5hcHBseSh2YWx1ZSwgW3RoaXNdLmNvbmNhdChfX3NsaWNlLmNhbGwoYXJncykpKTtcbiAgfTtcblxuICBSaXZldHNbXCJwdWJsaWNcIl0uYWRhcHRlcnNbJy4nXSA9IHtcbiAgICBpZDogJ19ydicsXG4gICAgY291bnRlcjogMCxcbiAgICB3ZWFrbWFwOiB7fSxcbiAgICB3ZWFrUmVmZXJlbmNlOiBmdW5jdGlvbihvYmopIHtcbiAgICAgIHZhciBpZCwgX2Jhc2UsIF9uYW1lO1xuICAgICAgaWYgKCFvYmouaGFzT3duUHJvcGVydHkodGhpcy5pZCkpIHtcbiAgICAgICAgaWQgPSB0aGlzLmNvdW50ZXIrKztcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgdGhpcy5pZCwge1xuICAgICAgICAgIHZhbHVlOiBpZFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAoX2Jhc2UgPSB0aGlzLndlYWttYXApW19uYW1lID0gb2JqW3RoaXMuaWRdXSB8fCAoX2Jhc2VbX25hbWVdID0ge1xuICAgICAgICBjYWxsYmFja3M6IHt9XG4gICAgICB9KTtcbiAgICB9LFxuICAgIGNsZWFudXBXZWFrUmVmZXJlbmNlOiBmdW5jdGlvbihyZWYsIGlkKSB7XG4gICAgICBpZiAoIU9iamVjdC5rZXlzKHJlZi5jYWxsYmFja3MpLmxlbmd0aCkge1xuICAgICAgICBpZiAoIShyZWYucG9pbnRlcnMgJiYgT2JqZWN0LmtleXMocmVmLnBvaW50ZXJzKS5sZW5ndGgpKSB7XG4gICAgICAgICAgcmV0dXJuIGRlbGV0ZSB0aGlzLndlYWttYXBbaWRdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBzdHViRnVuY3Rpb246IGZ1bmN0aW9uKG9iaiwgZm4pIHtcbiAgICAgIHZhciBtYXAsIG9yaWdpbmFsLCB3ZWFrbWFwO1xuICAgICAgb3JpZ2luYWwgPSBvYmpbZm5dO1xuICAgICAgbWFwID0gdGhpcy53ZWFrUmVmZXJlbmNlKG9iaik7XG4gICAgICB3ZWFrbWFwID0gdGhpcy53ZWFrbWFwO1xuICAgICAgcmV0dXJuIG9ialtmbl0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNhbGxiYWNrLCBrLCByLCByZXNwb25zZSwgX2ksIF9sZW4sIF9yZWYxLCBfcmVmMiwgX3JlZjMsIF9yZWY0O1xuICAgICAgICByZXNwb25zZSA9IG9yaWdpbmFsLmFwcGx5KG9iaiwgYXJndW1lbnRzKTtcbiAgICAgICAgX3JlZjEgPSBtYXAucG9pbnRlcnM7XG4gICAgICAgIGZvciAociBpbiBfcmVmMSkge1xuICAgICAgICAgIGsgPSBfcmVmMVtyXTtcbiAgICAgICAgICBfcmVmNCA9IChfcmVmMiA9IChfcmVmMyA9IHdlYWttYXBbcl0pICE9IG51bGwgPyBfcmVmMy5jYWxsYmFja3Nba10gOiB2b2lkIDApICE9IG51bGwgPyBfcmVmMiA6IFtdO1xuICAgICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gX3JlZjQubGVuZ3RoOyBfaSA8IF9sZW47IF9pKyspIHtcbiAgICAgICAgICAgIGNhbGxiYWNrID0gX3JlZjRbX2ldO1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgICAgfTtcbiAgICB9LFxuICAgIG9ic2VydmVNdXRhdGlvbnM6IGZ1bmN0aW9uKG9iaiwgcmVmLCBrZXlwYXRoKSB7XG4gICAgICB2YXIgZm4sIGZ1bmN0aW9ucywgbWFwLCBfYmFzZSwgX2ksIF9sZW47XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgICAgIG1hcCA9IHRoaXMud2Vha1JlZmVyZW5jZShvYmopO1xuICAgICAgICBpZiAobWFwLnBvaW50ZXJzID09IG51bGwpIHtcbiAgICAgICAgICBtYXAucG9pbnRlcnMgPSB7fTtcbiAgICAgICAgICBmdW5jdGlvbnMgPSBbJ3B1c2gnLCAncG9wJywgJ3NoaWZ0JywgJ3Vuc2hpZnQnLCAnc29ydCcsICdyZXZlcnNlJywgJ3NwbGljZSddO1xuICAgICAgICAgIGZvciAoX2kgPSAwLCBfbGVuID0gZnVuY3Rpb25zLmxlbmd0aDsgX2kgPCBfbGVuOyBfaSsrKSB7XG4gICAgICAgICAgICBmbiA9IGZ1bmN0aW9uc1tfaV07XG4gICAgICAgICAgICB0aGlzLnN0dWJGdW5jdGlvbihvYmosIGZuKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChfYmFzZSA9IG1hcC5wb2ludGVycylbcmVmXSA9PSBudWxsKSB7XG4gICAgICAgICAgX2Jhc2VbcmVmXSA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChfX2luZGV4T2YuY2FsbChtYXAucG9pbnRlcnNbcmVmXSwga2V5cGF0aCkgPCAwKSB7XG4gICAgICAgICAgcmV0dXJuIG1hcC5wb2ludGVyc1tyZWZdLnB1c2goa2V5cGF0aCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIHVub2JzZXJ2ZU11dGF0aW9uczogZnVuY3Rpb24ob2JqLCByZWYsIGtleXBhdGgpIHtcbiAgICAgIHZhciBpZHgsIG1hcCwgcG9pbnRlcnM7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopICYmIChvYmpbdGhpcy5pZF0gIT0gbnVsbCkpIHtcbiAgICAgICAgaWYgKG1hcCA9IHRoaXMud2Vha21hcFtvYmpbdGhpcy5pZF1dKSB7XG4gICAgICAgICAgaWYgKHBvaW50ZXJzID0gbWFwLnBvaW50ZXJzW3JlZl0pIHtcbiAgICAgICAgICAgIGlmICgoaWR4ID0gcG9pbnRlcnMuaW5kZXhPZihrZXlwYXRoKSkgPj0gMCkge1xuICAgICAgICAgICAgICBwb2ludGVycy5zcGxpY2UoaWR4LCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghcG9pbnRlcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIGRlbGV0ZSBtYXAucG9pbnRlcnNbcmVmXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNsZWFudXBXZWFrUmVmZXJlbmNlKG1hcCwgb2JqW3RoaXMuaWRdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIG9ic2VydmU6IGZ1bmN0aW9uKG9iaiwga2V5cGF0aCwgY2FsbGJhY2spIHtcbiAgICAgIHZhciBjYWxsYmFja3MsIGRlc2MsIHZhbHVlO1xuICAgICAgY2FsbGJhY2tzID0gdGhpcy53ZWFrUmVmZXJlbmNlKG9iaikuY2FsbGJhY2tzO1xuICAgICAgaWYgKGNhbGxiYWNrc1trZXlwYXRoXSA9PSBudWxsKSB7XG4gICAgICAgIGNhbGxiYWNrc1trZXlwYXRoXSA9IFtdO1xuICAgICAgICBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmosIGtleXBhdGgpO1xuICAgICAgICBpZiAoISgoZGVzYyAhPSBudWxsID8gZGVzYy5nZXQgOiB2b2lkIDApIHx8IChkZXNjICE9IG51bGwgPyBkZXNjLnNldCA6IHZvaWQgMCkpKSB7XG4gICAgICAgICAgdmFsdWUgPSBvYmpba2V5cGF0aF07XG4gICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5cGF0aCwge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXQ6IChmdW5jdGlvbihfdGhpcykge1xuICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24obmV3VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2IsIG1hcCwgX2ksIF9sZW4sIF9yZWYxO1xuICAgICAgICAgICAgICAgIGlmIChuZXdWYWx1ZSAhPT0gdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgIF90aGlzLnVub2JzZXJ2ZU11dGF0aW9ucyh2YWx1ZSwgb2JqW190aGlzLmlkXSwga2V5cGF0aCk7XG4gICAgICAgICAgICAgICAgICB2YWx1ZSA9IG5ld1ZhbHVlO1xuICAgICAgICAgICAgICAgICAgaWYgKG1hcCA9IF90aGlzLndlYWttYXBbb2JqW190aGlzLmlkXV0pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2tzID0gbWFwLmNhbGxiYWNrcztcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGxiYWNrc1trZXlwYXRoXSkge1xuICAgICAgICAgICAgICAgICAgICAgIF9yZWYxID0gY2FsbGJhY2tzW2tleXBhdGhdLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgZm9yIChfaSA9IDAsIF9sZW4gPSBfcmVmMS5sZW5ndGg7IF9pIDwgX2xlbjsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2IgPSBfcmVmMVtfaV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoX19pbmRleE9mLmNhbGwoY2FsbGJhY2tzW2tleXBhdGhdLCBjYikgPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBjYigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gX3RoaXMub2JzZXJ2ZU11dGF0aW9ucyhuZXdWYWx1ZSwgb2JqW190aGlzLmlkXSwga2V5cGF0aCk7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSkodGhpcylcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKF9faW5kZXhPZi5jYWxsKGNhbGxiYWNrc1trZXlwYXRoXSwgY2FsbGJhY2spIDwgMCkge1xuICAgICAgICBjYWxsYmFja3Nba2V5cGF0aF0ucHVzaChjYWxsYmFjayk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5vYnNlcnZlTXV0YXRpb25zKG9ialtrZXlwYXRoXSwgb2JqW3RoaXMuaWRdLCBrZXlwYXRoKTtcbiAgICB9LFxuICAgIHVub2JzZXJ2ZTogZnVuY3Rpb24ob2JqLCBrZXlwYXRoLCBjYWxsYmFjaykge1xuICAgICAgdmFyIGNhbGxiYWNrcywgaWR4LCBtYXA7XG4gICAgICBpZiAobWFwID0gdGhpcy53ZWFrbWFwW29ialt0aGlzLmlkXV0pIHtcbiAgICAgICAgaWYgKGNhbGxiYWNrcyA9IG1hcC5jYWxsYmFja3Nba2V5cGF0aF0pIHtcbiAgICAgICAgICBpZiAoKGlkeCA9IGNhbGxiYWNrcy5pbmRleE9mKGNhbGxiYWNrKSkgPj0gMCkge1xuICAgICAgICAgICAgY2FsbGJhY2tzLnNwbGljZShpZHgsIDEpO1xuICAgICAgICAgICAgaWYgKCFjYWxsYmFja3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgIGRlbGV0ZSBtYXAuY2FsbGJhY2tzW2tleXBhdGhdO1xuICAgICAgICAgICAgICB0aGlzLnVub2JzZXJ2ZU11dGF0aW9ucyhvYmpba2V5cGF0aF0sIG9ialt0aGlzLmlkXSwga2V5cGF0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0aGlzLmNsZWFudXBXZWFrUmVmZXJlbmNlKG1hcCwgb2JqW3RoaXMuaWRdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgZ2V0OiBmdW5jdGlvbihvYmosIGtleXBhdGgpIHtcbiAgICAgIHJldHVybiBvYmpba2V5cGF0aF07XG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKG9iaiwga2V5cGF0aCwgdmFsdWUpIHtcbiAgICAgIHJldHVybiBvYmpba2V5cGF0aF0gPSB2YWx1ZTtcbiAgICB9XG4gIH07XG5cbiAgUml2ZXRzLmZhY3RvcnkgPSBmdW5jdGlvbihzaWdodGdsYXNzKSB7XG4gICAgUml2ZXRzLnNpZ2h0Z2xhc3MgPSBzaWdodGdsYXNzO1xuICAgIFJpdmV0c1tcInB1YmxpY1wiXS5fID0gUml2ZXRzO1xuICAgIHJldHVybiBSaXZldHNbXCJwdWJsaWNcIl07XG4gIH07XG5cbiAgaWYgKHR5cGVvZiAodHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUgIT09IG51bGwgPyBtb2R1bGUuZXhwb3J0cyA6IHZvaWQgMCkgPT09ICdvYmplY3QnKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBSaXZldHMuZmFjdG9yeShyZXF1aXJlKCdzaWdodGdsYXNzJykpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgIGRlZmluZShbJ3NpZ2h0Z2xhc3MnXSwgZnVuY3Rpb24oc2lnaHRnbGFzcykge1xuICAgICAgcmV0dXJuIHRoaXMucml2ZXRzID0gUml2ZXRzLmZhY3Rvcnkoc2lnaHRnbGFzcyk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5yaXZldHMgPSBSaXZldHMuZmFjdG9yeShzaWdodGdsYXNzKTtcbiAgfVxuXG59KS5jYWxsKHRoaXMpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvcml2ZXRzL2Rpc3Qvcml2ZXRzLmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9yaXZldHMvZGlzdC9yaXZldHMuanNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIDEgMiJdLCJzb3VyY2VSb290IjoiIn0=\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvc2lnaHRnbGFzcy9pbmRleC5qcz85NjA1Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjtBQUNuQjs7QUFFQSxtQkFBbUIsd0JBQXdCO0FBQzNDOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkIsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsS0FBSztBQUFBO0FBQ0wsR0FBRztBQUNIO0FBQ0E7QUFDQSxDQUFDIiwiZmlsZSI6Ii4vbm9kZV9tb2R1bGVzL3NpZ2h0Z2xhc3MvaW5kZXguanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oKSB7XG4gIC8vIFB1YmxpYyBzaWdodGdsYXNzIGludGVyZmFjZS5cbiAgZnVuY3Rpb24gc2lnaHRnbGFzcyhvYmosIGtleXBhdGgsIGNhbGxiYWNrLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIG5ldyBPYnNlcnZlcihvYmosIGtleXBhdGgsIGNhbGxiYWNrLCBvcHRpb25zKVxuICB9XG5cbiAgLy8gQmF0dGVyaWVzIG5vdCBpbmNsdWRlZC5cbiAgc2lnaHRnbGFzcy5hZGFwdGVycyA9IHt9XG5cbiAgLy8gQ29uc3RydWN0cyBhIG5ldyBrZXlwYXRoIG9ic2VydmVyIGFuZCBraWNrcyB0aGluZ3Mgb2ZmLlxuICBmdW5jdGlvbiBPYnNlcnZlcihvYmosIGtleXBhdGgsIGNhbGxiYWNrLCBvcHRpb25zKSB7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICAgIHRoaXMub3B0aW9ucy5hZGFwdGVycyA9IHRoaXMub3B0aW9ucy5hZGFwdGVycyB8fCB7fVxuICAgIHRoaXMub2JqID0gb2JqXG4gICAgdGhpcy5rZXlwYXRoID0ga2V5cGF0aFxuICAgIHRoaXMuY2FsbGJhY2sgPSBjYWxsYmFja1xuICAgIHRoaXMub2JqZWN0UGF0aCA9IFtdXG4gICAgdGhpcy51cGRhdGUgPSB0aGlzLnVwZGF0ZS5iaW5kKHRoaXMpXG4gICAgdGhpcy5wYXJzZSgpXG5cbiAgICBpZiAoaXNPYmplY3QodGhpcy50YXJnZXQgPSB0aGlzLnJlYWxpemUoKSkpIHtcbiAgICAgIHRoaXMuc2V0KHRydWUsIHRoaXMua2V5LCB0aGlzLnRhcmdldCwgdGhpcy5jYWxsYmFjaylcbiAgICB9XG4gIH1cblxuICAvLyBUb2tlbml6ZXMgdGhlIHByb3ZpZGVkIGtleXBhdGggc3RyaW5nIGludG8gaW50ZXJmYWNlICsgcGF0aCB0b2tlbnMgZm9yIHRoZVxuICAvLyBvYnNlcnZlciB0byB3b3JrIHdpdGguXG4gIE9ic2VydmVyLnRva2VuaXplID0gZnVuY3Rpb24oa2V5cGF0aCwgaW50ZXJmYWNlcywgcm9vdCkge1xuICAgIHZhciB0b2tlbnMgPSBbXVxuICAgIHZhciBjdXJyZW50ID0ge2k6IHJvb3QsIHBhdGg6ICcnfVxuICAgIHZhciBpbmRleCwgY2hyXG5cbiAgICBmb3IgKGluZGV4ID0gMDsgaW5kZXggPCBrZXlwYXRoLmxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgY2hyID0ga2V5cGF0aC5jaGFyQXQoaW5kZXgpXG5cbiAgICAgIGlmICghIX5pbnRlcmZhY2VzLmluZGV4T2YoY2hyKSkge1xuICAgICAgICB0b2tlbnMucHVzaChjdXJyZW50KVxuICAgICAgICBjdXJyZW50ID0ge2k6IGNociwgcGF0aDogJyd9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjdXJyZW50LnBhdGggKz0gY2hyXG4gICAgICB9XG4gICAgfVxuXG4gICAgdG9rZW5zLnB1c2goY3VycmVudClcbiAgICByZXR1cm4gdG9rZW5zXG4gIH1cblxuICAvLyBQYXJzZXMgdGhlIGtleXBhdGggdXNpbmcgdGhlIGludGVyZmFjZXMgZGVmaW5lZCBvbiB0aGUgdmlldy4gU2V0cyB2YXJpYWJsZXNcbiAgLy8gZm9yIHRoZSB0b2tlbml6ZWQga2V5cGF0aCBhcyB3ZWxsIGFzIHRoZSBlbmQga2V5LlxuICBPYnNlcnZlci5wcm90b3R5cGUucGFyc2UgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgaW50ZXJmYWNlcyA9IHRoaXMuaW50ZXJmYWNlcygpXG4gICAgdmFyIHJvb3QsIHBhdGhcblxuICAgIGlmICghaW50ZXJmYWNlcy5sZW5ndGgpIHtcbiAgICAgIGVycm9yKCdNdXN0IGRlZmluZSBhdCBsZWFzdCBvbmUgYWRhcHRlciBpbnRlcmZhY2UuJylcbiAgICB9XG5cbiAgICBpZiAoISF+aW50ZXJmYWNlcy5pbmRleE9mKHRoaXMua2V5cGF0aFswXSkpIHtcbiAgICAgIHJvb3QgPSB0aGlzLmtleXBhdGhbMF1cbiAgICAgIHBhdGggPSB0aGlzLmtleXBhdGguc3Vic3RyKDEpXG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0eXBlb2YgKHJvb3QgPSB0aGlzLm9wdGlvbnMucm9vdCB8fCBzaWdodGdsYXNzLnJvb3QpID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICBlcnJvcignTXVzdCBkZWZpbmUgYSBkZWZhdWx0IHJvb3QgYWRhcHRlci4nKVxuICAgICAgfVxuXG4gICAgICBwYXRoID0gdGhpcy5rZXlwYXRoXG4gICAgfVxuXG4gICAgdGhpcy50b2tlbnMgPSBPYnNlcnZlci50b2tlbml6ZShwYXRoLCBpbnRlcmZhY2VzLCByb290KVxuICAgIHRoaXMua2V5ID0gdGhpcy50b2tlbnMucG9wKClcbiAgfVxuXG4gIC8vIFJlYWxpemVzIHRoZSBmdWxsIGtleXBhdGgsIGF0dGFjaGluZyBvYnNlcnZlcnMgZm9yIGV2ZXJ5IGtleSBhbmQgY29ycmVjdGluZ1xuICAvLyBvbGQgb2JzZXJ2ZXJzIHRvIGFueSBjaGFuZ2VkIG9iamVjdHMgaW4gdGhlIGtleXBhdGguXG4gIE9ic2VydmVyLnByb3RvdHlwZS5yZWFsaXplID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGN1cnJlbnQgPSB0aGlzLm9ialxuICAgIHZhciB1bnJlYWNoZWQgPSBmYWxzZVxuICAgIHZhciBwcmV2XG5cbiAgICB0aGlzLnRva2Vucy5mb3JFYWNoKGZ1bmN0aW9uKHRva2VuLCBpbmRleCkge1xuICAgICAgaWYgKGlzT2JqZWN0KGN1cnJlbnQpKSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5vYmplY3RQYXRoW2luZGV4XSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBpZiAoY3VycmVudCAhPT0gKHByZXYgPSB0aGlzLm9iamVjdFBhdGhbaW5kZXhdKSkge1xuICAgICAgICAgICAgdGhpcy5zZXQoZmFsc2UsIHRva2VuLCBwcmV2LCB0aGlzLnVwZGF0ZSlcbiAgICAgICAgICAgIHRoaXMuc2V0KHRydWUsIHRva2VuLCBjdXJyZW50LCB0aGlzLnVwZGF0ZSlcbiAgICAgICAgICAgIHRoaXMub2JqZWN0UGF0aFtpbmRleF0gPSBjdXJyZW50XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuc2V0KHRydWUsIHRva2VuLCBjdXJyZW50LCB0aGlzLnVwZGF0ZSlcbiAgICAgICAgICB0aGlzLm9iamVjdFBhdGhbaW5kZXhdID0gY3VycmVudFxuICAgICAgICB9XG5cbiAgICAgICAgY3VycmVudCA9IHRoaXMuZ2V0KHRva2VuLCBjdXJyZW50KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHVucmVhY2hlZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICB1bnJlYWNoZWQgPSBpbmRleFxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHByZXYgPSB0aGlzLm9iamVjdFBhdGhbaW5kZXhdKSB7XG4gICAgICAgICAgdGhpcy5zZXQoZmFsc2UsIHRva2VuLCBwcmV2LCB0aGlzLnVwZGF0ZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIHRoaXMpXG5cbiAgICBpZiAodW5yZWFjaGVkICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy5vYmplY3RQYXRoLnNwbGljZSh1bnJlYWNoZWQpXG4gICAgfVxuXG4gICAgcmV0dXJuIGN1cnJlbnRcbiAgfVxuXG4gIC8vIFVwZGF0ZXMgdGhlIGtleXBhdGguIFRoaXMgaXMgY2FsbGVkIHdoZW4gYW55IGludGVybWVkaWFyeSBrZXkgaXMgY2hhbmdlZC5cbiAgT2JzZXJ2ZXIucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBuZXh0LCBvbGRWYWx1ZVxuXG4gICAgaWYgKChuZXh0ID0gdGhpcy5yZWFsaXplKCkpICE9PSB0aGlzLnRhcmdldCkge1xuICAgICAgaWYgKGlzT2JqZWN0KHRoaXMudGFyZ2V0KSkge1xuICAgICAgICB0aGlzLnNldChmYWxzZSwgdGhpcy5rZXksIHRoaXMudGFyZ2V0LCB0aGlzLmNhbGxiYWNrKVxuICAgICAgfVxuXG4gICAgICBpZiAoaXNPYmplY3QobmV4dCkpIHtcbiAgICAgICAgdGhpcy5zZXQodHJ1ZSwgdGhpcy5rZXksIG5leHQsIHRoaXMuY2FsbGJhY2spXG4gICAgICB9XG5cbiAgICAgIG9sZFZhbHVlID0gdGhpcy52YWx1ZSgpXG4gICAgICB0aGlzLnRhcmdldCA9IG5leHRcblxuICAgICAgLy8gQWx3YXlzIGNhbGwgY2FsbGJhY2sgaWYgdmFsdWUgaXMgYSBmdW5jdGlvbi4gSWYgbm90IGEgZnVuY3Rpb24sIGNhbGwgY2FsbGJhY2sgb25seSBpZiB2YWx1ZSBjaGFuZ2VkXG4gICAgICBpZiAodGhpcy52YWx1ZSgpIGluc3RhbmNlb2YgRnVuY3Rpb24gfHwgdGhpcy52YWx1ZSgpICE9PSBvbGRWYWx1ZSkgdGhpcy5jYWxsYmFjaygpXG4gICAgfVxuICB9XG5cbiAgLy8gUmVhZHMgdGhlIGN1cnJlbnQgZW5kIHZhbHVlIG9mIHRoZSBvYnNlcnZlZCBrZXlwYXRoLiBSZXR1cm5zIHVuZGVmaW5lZCBpZlxuICAvLyB0aGUgZnVsbCBrZXlwYXRoIGlzIHVucmVhY2hhYmxlLlxuICBPYnNlcnZlci5wcm90b3R5cGUudmFsdWUgPSBmdW5jdGlvbigpIHtcbiAgICBpZiAoaXNPYmplY3QodGhpcy50YXJnZXQpKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXQodGhpcy5rZXksIHRoaXMudGFyZ2V0KVxuICAgIH1cbiAgfVxuXG4gIC8vIFNldHMgdGhlIGN1cnJlbnQgZW5kIHZhbHVlIG9mIHRoZSBvYnNlcnZlZCBrZXlwYXRoLiBDYWxsaW5nIHNldFZhbHVlIHdoZW5cbiAgLy8gdGhlIGZ1bGwga2V5cGF0aCBpcyB1bnJlYWNoYWJsZSBpcyBhIG5vLW9wLlxuICBPYnNlcnZlci5wcm90b3R5cGUuc2V0VmFsdWUgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIGlmIChpc09iamVjdCh0aGlzLnRhcmdldCkpIHtcbiAgICAgIHRoaXMuYWRhcHRlcih0aGlzLmtleSkuc2V0KHRoaXMudGFyZ2V0LCB0aGlzLmtleS5wYXRoLCB2YWx1ZSlcbiAgICB9XG4gIH1cblxuICAvLyBHZXRzIHRoZSBwcm92aWRlZCBrZXkgb24gYW4gb2JqZWN0LlxuICBPYnNlcnZlci5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24oa2V5LCBvYmopIHtcbiAgICByZXR1cm4gdGhpcy5hZGFwdGVyKGtleSkuZ2V0KG9iaiwga2V5LnBhdGgpXG4gIH1cblxuICAvLyBPYnNlcnZlcyBvciB1bm9ic2VydmVzIGEgY2FsbGJhY2sgb24gdGhlIG9iamVjdCB1c2luZyB0aGUgcHJvdmlkZWQga2V5LlxuICBPYnNlcnZlci5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24oYWN0aXZlLCBrZXksIG9iaiwgY2FsbGJhY2spIHtcbiAgICB2YXIgYWN0aW9uID0gYWN0aXZlID8gJ29ic2VydmUnIDogJ3Vub2JzZXJ2ZSdcbiAgICB0aGlzLmFkYXB0ZXIoa2V5KVthY3Rpb25dKG9iaiwga2V5LnBhdGgsIGNhbGxiYWNrKVxuICB9XG5cbiAgLy8gUmV0dXJucyBhbiBhcnJheSBvZiBhbGwgdW5pcXVlIGFkYXB0ZXIgaW50ZXJmYWNlcyBhdmFpbGFibGUuXG4gIE9ic2VydmVyLnByb3RvdHlwZS5pbnRlcmZhY2VzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGludGVyZmFjZXMgPSBPYmplY3Qua2V5cyh0aGlzLm9wdGlvbnMuYWRhcHRlcnMpXG5cbiAgICBPYmplY3Qua2V5cyhzaWdodGdsYXNzLmFkYXB0ZXJzKS5mb3JFYWNoKGZ1bmN0aW9uKGkpIHtcbiAgICAgIGlmICghfmludGVyZmFjZXMuaW5kZXhPZihpKSkge1xuICAgICAgICBpbnRlcmZhY2VzLnB1c2goaSlcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgcmV0dXJuIGludGVyZmFjZXNcbiAgfVxuXG4gIC8vIENvbnZlbmllbmNlIGZ1bmN0aW9uIHRvIGdyYWIgdGhlIGFkYXB0ZXIgZm9yIGEgc3BlY2lmaWMga2V5LlxuICBPYnNlcnZlci5wcm90b3R5cGUuYWRhcHRlciA9IGZ1bmN0aW9uKGtleSkge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMuYWRhcHRlcnNba2V5LmldIHx8XG4gICAgICBzaWdodGdsYXNzLmFkYXB0ZXJzW2tleS5pXVxuICB9XG5cbiAgLy8gVW5vYnNlcnZlcyB0aGUgZW50aXJlIGtleXBhdGguXG4gIE9ic2VydmVyLnByb3RvdHlwZS51bm9ic2VydmUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgb2JqXG5cbiAgICB0aGlzLnRva2Vucy5mb3JFYWNoKGZ1bmN0aW9uKHRva2VuLCBpbmRleCkge1xuICAgICAgaWYgKG9iaiA9IHRoaXMub2JqZWN0UGF0aFtpbmRleF0pIHtcbiAgICAgICAgdGhpcy5zZXQoZmFsc2UsIHRva2VuLCBvYmosIHRoaXMudXBkYXRlKVxuICAgICAgfVxuICAgIH0sIHRoaXMpXG5cbiAgICBpZiAoaXNPYmplY3QodGhpcy50YXJnZXQpKSB7XG4gICAgICB0aGlzLnNldChmYWxzZSwgdGhpcy5rZXksIHRoaXMudGFyZ2V0LCB0aGlzLmNhbGxiYWNrKVxuICAgIH1cbiAgfVxuXG4gIC8vIENoZWNrIGlmIGEgdmFsdWUgaXMgYW4gb2JqZWN0IHRoYW4gY2FuIGJlIG9ic2VydmVkLlxuICBmdW5jdGlvbiBpc09iamVjdChvYmopIHtcbiAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgb2JqICE9PSBudWxsXG4gIH1cblxuICAvLyBFcnJvciB0aHJvd2VyLlxuICBmdW5jdGlvbiBlcnJvcihtZXNzYWdlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdbc2lnaHRnbGFzc10gJyArIG1lc3NhZ2UpXG4gIH1cblxuICAvLyBFeHBvcnQgbW9kdWxlIGZvciBOb2RlIGFuZCB0aGUgYnJvd3Nlci5cbiAgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBzaWdodGdsYXNzXG4gIH0gZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgZGVmaW5lKFtdLCBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB0aGlzLnNpZ2h0Z2xhc3MgPSBzaWdodGdsYXNzXG4gICAgfSlcbiAgfSBlbHNlIHtcbiAgICB0aGlzLnNpZ2h0Z2xhc3MgPSBzaWdodGdsYXNzXG4gIH1cbn0pLmNhbGwodGhpcyk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9zaWdodGdsYXNzL2luZGV4LmpzXG4vLyBtb2R1bGUgaWQgPSAuL25vZGVfbW9kdWxlcy9zaWdodGdsYXNzL2luZGV4LmpzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCAxIDIiXSwic291cmNlUm9vdCI6IiJ9\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvYm9vdHN0cmFwLmpzPzBlNTgiXSwibmFtZXMiOlsid2luZG93IiwiYXhpb3MiLCJyZXF1aXJlIiwicGhwdm1zIiwiYmFzZV91cmwiLCJkb2N1bWVudCIsImhlYWQiLCJxdWVyeVNlbGVjdG9yIiwiZGVmYXVsdCIsImJhc2VVUkwiLCJkZWZhdWx0cyIsImhlYWRlcnMiLCJjb21tb24iLCJ0b2tlbiIsImNvbnRlbnQiLCJjb25zb2xlIiwiZXJyb3IiLCJhcGlfa2V5IiwiUEhQVk1TX1VTRVJfQVBJX0tFWSJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7QUFJQUEsT0FBT0MsS0FBUCxHQUFlLG1CQUFBQyxDQUFRLCtCQUFSLENBQWY7O0FBRUE7OztBQUdBRixPQUFPRyxNQUFQLEdBQWdCLEVBQWhCOztBQUVBOzs7O0FBSUEsSUFBTUMsV0FBV0MsU0FBU0MsSUFBVCxDQUFjQyxhQUFkLENBQTRCLHVCQUE1QixDQUFqQjtBQUNBLElBQUdILFFBQUgsRUFBYTtBQUNYSixTQUFPQyxLQUFQLENBQWFPLE9BQWIsQ0FBcUJDLE9BQXJCLEdBQStCTCxRQUEvQjtBQUNEOztBQUVESixPQUFPQyxLQUFQLENBQWFTLFFBQWIsQ0FBc0JDLE9BQXRCLENBQThCQyxNQUE5QixDQUFxQyxrQkFBckMsSUFBMkQsZ0JBQTNEO0FBQ0EsSUFBTUMsUUFBUVIsU0FBU0MsSUFBVCxDQUFjQyxhQUFkLENBQTRCLHlCQUE1QixDQUFkOztBQUVBLElBQUlNLEtBQUosRUFBVztBQUNUYixTQUFPQyxLQUFQLENBQWFTLFFBQWIsQ0FBc0JDLE9BQXRCLENBQThCQyxNQUE5QixDQUFxQyxjQUFyQyxJQUF1REMsTUFBTUMsT0FBN0Q7QUFDQTs7O0FBR0QsQ0FMRCxNQUtPO0FBQ0xDLFVBQVFDLEtBQVIsQ0FBYyx1RUFBZDtBQUNEOztBQUVELElBQU1DLFVBQVVaLFNBQVNDLElBQVQsQ0FBY0MsYUFBZCxDQUE0QixzQkFBNUIsQ0FBaEI7QUFDQSxJQUFJVSxPQUFKLEVBQWE7QUFDWGpCLFNBQU9DLEtBQVAsQ0FBYVMsUUFBYixDQUFzQkMsT0FBdEIsQ0FBOEJDLE1BQTlCLENBQXFDLFdBQXJDLElBQW9ESyxRQUFRSCxPQUE1RDtBQUNBZCxTQUFPa0IsbUJBQVAsR0FBNkJELFFBQVFILE9BQXJDO0FBQ0QsQ0FIRCxNQUdPO0FBQ0xkLFNBQU9rQixtQkFBUCxHQUE2QixLQUE3QjtBQUNBSCxVQUFRQyxLQUFSLENBQWMsb0JBQWQ7QUFDRDs7QUFFRCxtQkFBQWQsQ0FBUSwwQkFBUiIsImZpbGUiOiIuL3Jlc291cmNlcy9qcy9ib290c3RyYXAuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEJvb3RzdHJhcCBhbnkgSmF2YXNjcmlwdCBsaWJyYXJpZXMgcmVxdWlyZWRcbiAqL1xuXG53aW5kb3cuYXhpb3MgPSByZXF1aXJlKCdheGlvcycpO1xuXG4vKipcbiAqIENvbnRhaW5lciBmb3IgcGhwVk1TIHNwZWNpZmljIGZ1bmN0aW9uc1xuICovXG53aW5kb3cucGhwdm1zID0ge307XG5cbi8qKlxuICogQ29uZmlndXJlIEF4aW9zIHdpdGggYm90aCB0aGUgY3NyZiB0b2tlbiBhbmQgdGhlIEFQSSBrZXlcbiAqL1xuXG5jb25zdCBiYXNlX3VybCA9IGRvY3VtZW50LmhlYWQucXVlcnlTZWxlY3RvcignbWV0YVtuYW1lPVwiYmFzZS11cmxcIl0nKTtcbmlmKGJhc2VfdXJsKSB7XG4gIHdpbmRvdy5heGlvcy5kZWZhdWx0LmJhc2VVUkwgPSBiYXNlX3VybDtcbn1cblxud2luZG93LmF4aW9zLmRlZmF1bHRzLmhlYWRlcnMuY29tbW9uWydYLVJlcXVlc3RlZC1XaXRoJ10gPSAnWE1MSHR0cFJlcXVlc3QnO1xuY29uc3QgdG9rZW4gPSBkb2N1bWVudC5oZWFkLnF1ZXJ5U2VsZWN0b3IoJ21ldGFbbmFtZT1cImNzcmYtdG9rZW5cIl0nKTtcblxuaWYgKHRva2VuKSB7XG4gIHdpbmRvdy5heGlvcy5kZWZhdWx0cy5oZWFkZXJzLmNvbW1vblsnWC1DU1JGLVRPS0VOJ10gPSB0b2tlbi5jb250ZW50XG4gIC8qd2luZG93LmpxdWVyeS5hamF4U2V0dXAoe1xuICAgICdYLUNTUkYtVE9LRU4nOiB0b2tlbi5jb250ZW50XG4gIH0pKi9cbn0gZWxzZSB7XG4gIGNvbnNvbGUuZXJyb3IoJ0NTUkYgdG9rZW4gbm90IGZvdW5kOiBodHRwczovL2xhcmF2ZWwuY29tL2RvY3MvY3NyZiNjc3JmLXgtY3NyZi10b2tlbicpXG59XG5cbmNvbnN0IGFwaV9rZXkgPSBkb2N1bWVudC5oZWFkLnF1ZXJ5U2VsZWN0b3IoJ21ldGFbbmFtZT1cImFwaS1rZXlcIl0nKTtcbmlmIChhcGlfa2V5KSB7XG4gIHdpbmRvdy5heGlvcy5kZWZhdWx0cy5oZWFkZXJzLmNvbW1vblsneC1hcGkta2V5J10gPSBhcGlfa2V5LmNvbnRlbnQ7XG4gIHdpbmRvdy5QSFBWTVNfVVNFUl9BUElfS0VZID0gYXBpX2tleS5jb250ZW50XG59IGVsc2Uge1xuICB3aW5kb3cuUEhQVk1TX1VTRVJfQVBJX0tFWSA9IGZhbHNlO1xuICBjb25zb2xlLmVycm9yKCdBUEkgS2V5IG5vdCBmb3VuZCEnKVxufVxuXG5yZXF1aXJlKCcuL2NvbW1vbicpO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vcmVzb3VyY2VzL2pzL2Jvb3RzdHJhcC5qcyJdLCJzb3VyY2VSb290IjoiIn0=\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvY29tbW9uLmpzPzVmZDUiXSwibmFtZXMiOlsicml2ZXRzIiwicmVxdWlyZSIsImZvcm1hdHRlcnMiLCJwcmVwZW5kIiwidmFsdWUiLCJ0aW1lX2htIiwiaG91cnMiLCJNYXRoIiwiZmxvb3IiLCJtaW5zIiwiZ3QiLCJsZW4iLCJsZW5ndGgiLCJsdCIsImVxIl0sIm1hcHBpbmdzIjoiQUFBQTs7OztBQUlBLElBQU1BLFNBQVMsbUJBQUFDLENBQVEsc0NBQVIsQ0FBZjs7QUFFQTs7Ozs7O0FBTUFELE9BQU9FLFVBQVAsQ0FBa0JDLE9BQWxCLEdBQTRCLFVBQVVDLEtBQVYsRUFBaUJELE9BQWpCLEVBQTBCO0FBQ2xELFNBQU9BLFVBQVVDLEtBQWpCO0FBQ0gsQ0FGRDs7QUFJQTs7Ozs7QUFLQUosT0FBT0UsVUFBUCxDQUFrQkcsT0FBbEIsR0FBNEIsVUFBU0QsS0FBVCxFQUFnQjtBQUN4QyxNQUFNRSxRQUFRQyxLQUFLQyxLQUFMLENBQVdKLFFBQVEsRUFBbkIsQ0FBZDtBQUNBLE1BQU1LLE9BQU9MLFFBQVEsRUFBckI7QUFDQSxTQUFPRSxRQUFRLElBQVIsR0FBZUcsSUFBZixHQUFzQixHQUE3QjtBQUNILENBSkQ7O0FBTUE7Ozs7OztBQU1BVCxPQUFPRSxVQUFQLENBQWtCUSxFQUFsQixHQUF1QixVQUFDTixLQUFELEVBQVFPLEdBQVIsRUFBZ0I7QUFDbkMsU0FBT1AsTUFBTVEsTUFBTixHQUFlRCxHQUF0QjtBQUNILENBRkQ7O0FBSUE7Ozs7OztBQU1BWCxPQUFPRSxVQUFQLENBQWtCVyxFQUFsQixHQUF1QixVQUFDVCxLQUFELEVBQVFPLEdBQVIsRUFBZ0I7QUFDbkMsU0FBT1AsTUFBTVEsTUFBTixHQUFlRCxHQUF0QjtBQUNILENBRkQ7O0FBSUE7Ozs7OztBQU1BWCxPQUFPRSxVQUFQLENBQWtCWSxFQUFsQixHQUF1QixVQUFDVixLQUFELEVBQVFPLEdBQVIsRUFBZ0I7QUFDbkMsU0FBT1AsTUFBTVEsTUFBTixHQUFlRCxHQUF0QjtBQUNILENBRkQiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvY29tbW9uLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKlxuICovXG5cbmNvbnN0IHJpdmV0cyA9IHJlcXVpcmUoJ3JpdmV0cycpO1xuXG4vKipcbiAqIEdlbmVyaWMgZm9ybWF0dGVyIHRvIHByZXBlbmRcbiAqIEBwYXJhbSB2YWx1ZVxuICogQHBhcmFtIHByZXBlbmRcbiAqIEByZXR1cm5zIHsqfVxuICovXG5yaXZldHMuZm9ybWF0dGVycy5wcmVwZW5kID0gZnVuY3Rpb24gKHZhbHVlLCBwcmVwZW5kKSB7XG4gICAgcmV0dXJuIHByZXBlbmQgKyB2YWx1ZVxufTtcblxuLyoqXG4gKiBGb3JtYXQgbWludXRlcyBpbnRvIEhIaCBNTW1cbiAqIEBwYXJhbSB2YWx1ZVxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xucml2ZXRzLmZvcm1hdHRlcnMudGltZV9obSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgY29uc3QgaG91cnMgPSBNYXRoLmZsb29yKHZhbHVlIC8gNjApO1xuICAgIGNvbnN0IG1pbnMgPSB2YWx1ZSAlIDYwO1xuICAgIHJldHVybiBob3VycyArICdoICcgKyBtaW5zICsgJ20nO1xufTtcblxuLyoqXG4gKlxuICogQHBhcmFtIHZhbHVlXG4gKiBAcGFyYW0gbGVuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xucml2ZXRzLmZvcm1hdHRlcnMuZ3QgPSAodmFsdWUsIGxlbikgPT4ge1xuICAgIHJldHVybiB2YWx1ZS5sZW5ndGggPiBsZW47XG59O1xuXG4vKipcbiAqXG4gKiBAcGFyYW0gdmFsdWVcbiAqIEBwYXJhbSBsZW5cbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5yaXZldHMuZm9ybWF0dGVycy5sdCA9ICh2YWx1ZSwgbGVuKSA9PiB7XG4gICAgcmV0dXJuIHZhbHVlLmxlbmd0aCA8IGxlbjtcbn07XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB2YWx1ZVxuICogQHBhcmFtIGxlblxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbnJpdmV0cy5mb3JtYXR0ZXJzLmVxID0gKHZhbHVlLCBsZW4pID0+IHtcbiAgICByZXR1cm4gdmFsdWUubGVuZ3RoID4gbGVuO1xufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3Jlc291cmNlcy9qcy9jb21tb24uanMiXSwic291cmNlUm9vdCI6IiJ9\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvZnJvbnRlbmQvYXBwLmpzPzYwZTgiXSwibmFtZXMiOlsicmVxdWlyZSIsIndpbmRvdyIsInBocHZtcyIsIm1hcCJdLCJtYXBwaW5ncyI6IjtBQUNBLG1CQUFBQSxDQUFRLDZCQUFSOztBQUVBO0FBQ0FDLE9BQU9DLE1BQVAsQ0FBY0MsR0FBZCxHQUFvQixtQkFBQUgsQ0FBUSw4QkFBUixDQUFwQiIsImZpbGUiOiIuL3Jlc291cmNlcy9qcy9mcm9udGVuZC9hcHAuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJcbnJlcXVpcmUoJy4vLi4vYm9vdHN0cmFwJyk7XG5cbi8vIEltcG9ydCB0aGUgbWFwcGluZyBmdW5jdGlvblxud2luZG93LnBocHZtcy5tYXAgPSByZXF1aXJlKCcuLi9tYXBzL2luZGV4Jyk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9yZXNvdXJjZXMvanMvZnJvbnRlbmQvYXBwLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\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/NGZiMCJdLCJuYW1lcyI6WyJsZWFmbGV0IiwicmVxdWlyZSIsIm9wdHMiLCJPYmplY3QiLCJhc3NpZ24iLCJyZW5kZXJfZWxlbSIsIm92ZXJsYXlfZWxlbSIsImxhdCIsImxvbiIsInpvb20iLCJsYXllcnMiLCJzZXRfbWFya2VyIiwibWFya2VyX3BvcHVwIiwibWV0YXJfd21zIiwidXJsIiwicGFyYW1zIiwibWFwIiwiZHJhd19iYXNlX21hcCIsImNvb3JkcyIsImNvbnNvbGUiLCJsb2ciLCJzZXRWaWV3IiwibWFya2VyIiwiYWRkVG8iLCJiaW5kUG9wdXAiLCJhZGRXTVNMYXllciJdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsSUFBTUEsVUFBVSxtQkFBQUMsQ0FBUSw0Q0FBUixDQUFoQjs7QUFFQTtBQUNBOztBQUVBOzs7OztBQUtBLHlEQUFlLFVBQUNDLElBQUQsRUFBVTtBQUN2QkEsU0FBT0MsT0FBT0MsTUFBUCxDQUFjO0FBQ25CQyxpQkFBYSxLQURNO0FBRW5CQyxrQkFBYyxFQUZLO0FBR25CQyxTQUFLLENBSGM7QUFJbkJDLFNBQUssQ0FKYztBQUtuQkMsVUFBTSxFQUxhO0FBTW5CQyxZQUFRLEVBTlc7QUFPbkJDLGdCQUFZLElBUE87QUFRbkJDLGtCQUFjLEVBUks7O0FBVW5CO0FBQ0FDLGVBQVc7QUFDUEMsV0FBSyxFQURFO0FBRVBDLGNBQVE7QUFGRDtBQVhRLEdBQWQsRUFlSmIsSUFmSSxDQUFQOztBQWlCQSxNQUFJYyxNQUFNLGtFQUFBQyxDQUFjZixJQUFkLENBQVY7QUFDQSxNQUFNZ0IsU0FBUyxDQUFDaEIsS0FBS0ssR0FBTixFQUFXTCxLQUFLTSxHQUFoQixDQUFmO0FBQ0FXLFVBQVFDLEdBQVIsQ0FBWSxpQkFBWixFQUErQkYsTUFBL0I7O0FBRUFGLE1BQUlLLE9BQUosQ0FBWUgsTUFBWixFQUFvQmhCLEtBQUtPLElBQXpCO0FBQ0EsTUFBSVAsS0FBS1MsVUFBTCxLQUFvQixJQUF4QixFQUE4QjtBQUM1QlgsWUFBUXNCLE1BQVIsQ0FBZUosTUFBZixFQUF1QkssS0FBdkIsQ0FBNkJQLEdBQTdCLEVBQWtDUSxTQUFsQyxDQUE0Q3RCLEtBQUtVLFlBQWpEO0FBQ0Q7O0FBRUQsTUFBR1YsS0FBS1csU0FBTCxDQUFlQyxHQUFmLEtBQXVCLEVBQTFCLEVBQThCO0FBQzFCVyxJQUFBLHFFQUFBQSxDQUFZVCxHQUFaLEVBQWlCZCxLQUFLVyxTQUF0QjtBQUNIOztBQUVELFNBQU9HLEdBQVA7QUFDRCxDQWhDRCIsImZpbGUiOiIuL3Jlc291cmNlcy9qcy9tYXBzL2FpcnNwYWNlX21hcC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIlxuY29uc3QgbGVhZmxldCA9IHJlcXVpcmUoJ2xlYWZsZXQnKTtcblxuaW1wb3J0IGRyYXdfYmFzZV9tYXAgZnJvbSAnLi9iYXNlX21hcCdcbmltcG9ydCB7IGFkZFdNU0xheWVyIH0gZnJvbSAnLi9oZWxwZXJzJztcblxuLyoqXG4gKiBSZW5kZXIgYSBtYXAgd2l0aCB0aGUgYWlyc3BhY2UsIGV0YyBhcm91bmQgYSBnaXZlbiBzZXQgb2YgY29vcmRzXG4gKiBlLmcsIHRoZSBhaXJwb3J0IG1hcFxuICogQHBhcmFtIG9wdHNcbiAqL1xuZXhwb3J0IGRlZmF1bHQgKG9wdHMpID0+IHtcbiAgb3B0cyA9IE9iamVjdC5hc3NpZ24oe1xuICAgIHJlbmRlcl9lbGVtOiAnbWFwJyxcbiAgICBvdmVybGF5X2VsZW06ICcnLFxuICAgIGxhdDogMCxcbiAgICBsb246IDAsXG4gICAgem9vbTogMTIsXG4gICAgbGF5ZXJzOiBbXSxcbiAgICBzZXRfbWFya2VyOiB0cnVlLFxuICAgIG1hcmtlcl9wb3B1cDogJycsXG5cbiAgICAvLyBQYXNzZWQgZnJvbSB0aGUgY29uZmlnL21hcHMucGhwIGZpbGVcbiAgICBtZXRhcl93bXM6IHtcbiAgICAgICAgdXJsOiAnJyxcbiAgICAgICAgcGFyYW1zOiB7fVxuICAgIH0sXG4gIH0sIG9wdHMpO1xuXG4gIGxldCBtYXAgPSBkcmF3X2Jhc2VfbWFwKG9wdHMpO1xuICBjb25zdCBjb29yZHMgPSBbb3B0cy5sYXQsIG9wdHMubG9uXTtcbiAgY29uc29sZS5sb2coJ0FwcGx5aW5nIGNvb3JkcycsIGNvb3Jkcyk7XG5cbiAgbWFwLnNldFZpZXcoY29vcmRzLCBvcHRzLnpvb20pO1xuICBpZiAob3B0cy5zZXRfbWFya2VyID09PSB0cnVlKSB7XG4gICAgbGVhZmxldC5tYXJrZXIoY29vcmRzKS5hZGRUbyhtYXApLmJpbmRQb3B1cChvcHRzLm1hcmtlcl9wb3B1cCk7XG4gIH1cblxuICBpZihvcHRzLm1ldGFyX3dtcy51cmwgIT09ICcnKSB7XG4gICAgICBhZGRXTVNMYXllcihtYXAsIG9wdHMubWV0YXJfd21zKTtcbiAgfVxuXG4gIHJldHVybiBtYXA7XG59O1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vcmVzb3VyY2VzL2pzL21hcHMvYWlyc3BhY2VfbWFwLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\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("var leaflet = __webpack_require__(\"./node_modules/leaflet/dist/leaflet-src.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 }, opts);\n\n var feature_groups = [];\n /*var 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 var opencyclemap_phys_osm = new leaflet.TileLayer('http://{s}.tile.thunderforest.com/landscape/{z}/{x}/{y}.png?apikey=f09a38fa87514de4890fc96e7fe8ecb1', {\n maxZoom: 14,\n minZoom: 4,\n format: 'image/png',\n transparent: true\n });\n\n feature_groups.push(opencyclemap_phys_osm);\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 openaip_basemap_phys_osm = leaflet.featureGroup(feature_groups);\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 var attrib = leaflet.control.attribution({ position: 'bottomleft' });\n attrib.addAttribution('<a href=\"https://www.thunderforest.com\" target=\"_blank\" style=\"\">Thunderforest</a>');\n attrib.addAttribution('<a href=\"https://www.openaip.net\" target=\"_blank\" style=\"\">openAIP</a>');\n attrib.addAttribution('<a href=\"https://www.openstreetmap.org/copyright\" target=\"_blank\" style=\"\">OpenStreetMap</a> contributors');\n attrib.addAttribution('<a href=\"https://www.openweathermap.org\" target=\"_blank\" style=\"\">OpenWeatherMap</a>');\n\n attrib.addTo(map);\n\n return map;\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9iYXNlX21hcC5qcz80MzA3Il0sIm5hbWVzIjpbImxlYWZsZXQiLCJyZXF1aXJlIiwib3B0cyIsIk9iamVjdCIsImFzc2lnbiIsInJlbmRlcl9lbGVtIiwiY2VudGVyIiwiem9vbSIsIm1heFpvb20iLCJsYXllcnMiLCJzZXRfbWFya2VyIiwiZmVhdHVyZV9ncm91cHMiLCJvcGVuY3ljbGVtYXBfcGh5c19vc20iLCJUaWxlTGF5ZXIiLCJtaW5ab29tIiwiZm9ybWF0IiwidHJhbnNwYXJlbnQiLCJwdXNoIiwib3BlbmFpcF9iYXNlbWFwX3BoeXNfb3NtIiwiZmVhdHVyZUdyb3VwIiwibWFwIiwic2Nyb2xsV2hlZWxab29tIiwiYXR0cmliIiwiY29udHJvbCIsImF0dHJpYnV0aW9uIiwicG9zaXRpb24iLCJhZGRBdHRyaWJ1dGlvbiIsImFkZFRvIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxVQUFVLG1CQUFBQyxDQUFRLDRDQUFSLENBQWhCOztBQUVBLHlEQUFlLFVBQUNDLElBQUQsRUFBVTs7QUFFckJBLFdBQU9DLE9BQU9DLE1BQVAsQ0FBYztBQUNqQkMscUJBQWEsS0FESTtBQUVqQkMsZ0JBQVEsQ0FBQyxRQUFELEVBQVcsQ0FBQyxRQUFaLENBRlM7QUFHakJDLGNBQU0sQ0FIVztBQUlqQkMsaUJBQVMsRUFKUTtBQUtqQkMsZ0JBQVEsRUFMUztBQU1qQkMsb0JBQVk7QUFOSyxLQUFkLEVBT0pSLElBUEksQ0FBUDs7QUFTQSxRQUFJUyxpQkFBaUIsRUFBckI7QUFDQTs7Ozs7Ozs7Ozs7OztBQWNBLFFBQU1DLHdCQUF3QixJQUFJWixRQUFRYSxTQUFaLENBQzFCLHFHQUQwQixFQUM2RTtBQUNuR0wsaUJBQVMsRUFEMEY7QUFFbkdNLGlCQUFTLENBRjBGO0FBR25HQyxnQkFBUSxXQUgyRjtBQUluR0MscUJBQWE7QUFKc0YsS0FEN0UsQ0FBOUI7O0FBUUFMLG1CQUFlTSxJQUFmLENBQW9CTCxxQkFBcEI7O0FBRUE7Ozs7Ozs7Ozs7OztBQWFBLFFBQU1NLDJCQUEyQmxCLFFBQVFtQixZQUFSLENBQXFCUixjQUFyQixDQUFqQzs7QUFFQSxRQUFJUyxNQUFNcEIsUUFBUW9CLEdBQVIsQ0FBWSxLQUFaLEVBQW1CO0FBQ3pCWCxnQkFBUSxDQUFDUyx3QkFBRCxDQURpQjtBQUV6QlosZ0JBQVFKLEtBQUtJLE1BRlk7QUFHekJDLGNBQU1MLEtBQUtLLElBSGM7QUFJekJjLHlCQUFpQjtBQUpRLEtBQW5CLENBQVY7O0FBT0EsUUFBTUMsU0FBU3RCLFFBQVF1QixPQUFSLENBQWdCQyxXQUFoQixDQUE0QixFQUFDQyxVQUFVLFlBQVgsRUFBNUIsQ0FBZjtBQUNBSCxXQUFPSSxjQUFQLENBQXNCLG9GQUF0QjtBQUNBSixXQUFPSSxjQUFQLENBQXNCLHdFQUF0QjtBQUNBSixXQUFPSSxjQUFQLENBQXNCLDJHQUF0QjtBQUNBSixXQUFPSSxjQUFQLENBQXNCLHNGQUF0Qjs7QUFFQUosV0FBT0ssS0FBUCxDQUFhUCxHQUFiOztBQUVBLFdBQU9BLEdBQVA7QUFDSCxDQW5FRCIsImZpbGUiOiIuL3Jlc291cmNlcy9qcy9tYXBzL2Jhc2VfbWFwLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiY29uc3QgbGVhZmxldCA9IHJlcXVpcmUoJ2xlYWZsZXQnKTtcblxuZXhwb3J0IGRlZmF1bHQgKG9wdHMpID0+IHtcblxuICAgIG9wdHMgPSBPYmplY3QuYXNzaWduKHtcbiAgICAgICAgcmVuZGVyX2VsZW06ICdtYXAnLFxuICAgICAgICBjZW50ZXI6IFsyOS45ODEzOSwgLTk1LjMzMzc0XSxcbiAgICAgICAgem9vbTogNSxcbiAgICAgICAgbWF4Wm9vbTogMTAsXG4gICAgICAgIGxheWVyczogW10sXG4gICAgICAgIHNldF9tYXJrZXI6IGZhbHNlLFxuICAgIH0sIG9wdHMpO1xuXG4gICAgbGV0IGZlYXR1cmVfZ3JvdXBzID0gW107XG4gICAgLyp2YXIgb3BlbmFpcF9haXJzcGFjZV9sYWJlbHMgPSBuZXcgbGVhZmxldC5UaWxlTGF5ZXIuV01TKFxuICAgICAgICBcImh0dHA6Ly97c30udGlsZS5tYXBzLm9wZW5haXAubmV0L2dlb3dlYmNhY2hlL3NlcnZpY2Uvd21zXCIsIHtcbiAgICAgICAgICAgIG1heFpvb206IDE0LFxuICAgICAgICAgICAgbWluWm9vbTogMTIsXG4gICAgICAgICAgICBsYXllcnM6ICdvcGVuYWlwX2FwcHJvdmVkX2FpcnNwYWNlc19sYWJlbHMnLFxuICAgICAgICAgICAgdGlsZVNpemU6IDEwMjQsXG4gICAgICAgICAgICBkZXRlY3RSZXRpbmE6IHRydWUsXG4gICAgICAgICAgICBzdWJkb21haW5zOiAnMTInLFxuICAgICAgICAgICAgZm9ybWF0OiAnaW1hZ2UvcG5nJyxcbiAgICAgICAgICAgIHRyYW5zcGFyZW50OiB0cnVlXG4gICAgICAgIH0pO1xuXG4gICAgb3BlbmFpcF9haXJzcGFjZV9sYWJlbHMuYWRkVG8obWFwKTsqL1xuXG4gICAgY29uc3Qgb3BlbmN5Y2xlbWFwX3BoeXNfb3NtID0gbmV3IGxlYWZsZXQuVGlsZUxheWVyKFxuICAgICAgICAnaHR0cDovL3tzfS50aWxlLnRodW5kZXJmb3Jlc3QuY29tL2xhbmRzY2FwZS97en0ve3h9L3t5fS5wbmc/YXBpa2V5PWYwOWEzOGZhODc1MTRkZTQ4OTBmYzk2ZTdmZThlY2IxJywge1xuICAgICAgICAgICAgbWF4Wm9vbTogMTQsXG4gICAgICAgICAgICBtaW5ab29tOiA0LFxuICAgICAgICAgICAgZm9ybWF0OiAnaW1hZ2UvcG5nJyxcbiAgICAgICAgICAgIHRyYW5zcGFyZW50OiB0cnVlXG4gICAgICAgIH0pXG5cbiAgICBmZWF0dXJlX2dyb3Vwcy5wdXNoKG9wZW5jeWNsZW1hcF9waHlzX29zbSlcblxuICAgIC8qY29uc3Qgb3BlbmFpcF9jYWNoZWRfYmFzZW1hcCA9IG5ldyBsZWFmbGV0LlRpbGVMYXllcihcImh0dHA6Ly97c30udGlsZS5tYXBzLm9wZW5haXAubmV0L2dlb3dlYmNhY2hlL3NlcnZpY2UvdG1zLzEuMC4wL29wZW5haXBfYmFzZW1hcEBFUFNHJTNBOTAwOTEzQHBuZy97en0ve3h9L3t5fS5wbmdcIiwge1xuICAgICAgICBtYXhab29tOiAxNCxcbiAgICAgICAgbWluWm9vbTogNCxcbiAgICAgICAgdG1zOiB0cnVlLFxuICAgICAgICBkZXRlY3RSZXRpbmE6IHRydWUsXG4gICAgICAgIHN1YmRvbWFpbnM6ICcxMicsXG4gICAgICAgIGZvcm1hdDogJ2ltYWdlL3BuZycsXG4gICAgICAgIHRyYW5zcGFyZW50OiB0cnVlXG4gICAgfSk7XG5cbiAgICBmZWF0dXJlX2dyb3Vwcy5wdXNoKG9wZW5haXBfY2FjaGVkX2Jhc2VtYXApO1xuICAgICovXG5cbiAgICBjb25zdCBvcGVuYWlwX2Jhc2VtYXBfcGh5c19vc20gPSBsZWFmbGV0LmZlYXR1cmVHcm91cChmZWF0dXJlX2dyb3Vwcyk7XG5cbiAgICBsZXQgbWFwID0gbGVhZmxldC5tYXAoJ21hcCcsIHtcbiAgICAgICAgbGF5ZXJzOiBbb3BlbmFpcF9iYXNlbWFwX3BoeXNfb3NtXSxcbiAgICAgICAgY2VudGVyOiBvcHRzLmNlbnRlcixcbiAgICAgICAgem9vbTogb3B0cy56b29tLFxuICAgICAgICBzY3JvbGxXaGVlbFpvb206IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgY29uc3QgYXR0cmliID0gbGVhZmxldC5jb250cm9sLmF0dHJpYnV0aW9uKHtwb3NpdGlvbjogJ2JvdHRvbWxlZnQnfSlcbiAgICBhdHRyaWIuYWRkQXR0cmlidXRpb24oJzxhIGhyZWY9XCJodHRwczovL3d3dy50aHVuZGVyZm9yZXN0LmNvbVwiIHRhcmdldD1cIl9ibGFua1wiIHN0eWxlPVwiXCI+VGh1bmRlcmZvcmVzdDwvYT4nKVxuICAgIGF0dHJpYi5hZGRBdHRyaWJ1dGlvbignPGEgaHJlZj1cImh0dHBzOi8vd3d3Lm9wZW5haXAubmV0XCIgdGFyZ2V0PVwiX2JsYW5rXCIgc3R5bGU9XCJcIj5vcGVuQUlQPC9hPicpXG4gICAgYXR0cmliLmFkZEF0dHJpYnV0aW9uKCc8YSBocmVmPVwiaHR0cHM6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvY29weXJpZ2h0XCIgdGFyZ2V0PVwiX2JsYW5rXCIgc3R5bGU9XCJcIj5PcGVuU3RyZWV0TWFwPC9hPiBjb250cmlidXRvcnMnKVxuICAgIGF0dHJpYi5hZGRBdHRyaWJ1dGlvbignPGEgaHJlZj1cImh0dHBzOi8vd3d3Lm9wZW53ZWF0aGVybWFwLm9yZ1wiIHRhcmdldD1cIl9ibGFua1wiIHN0eWxlPVwiXCI+T3BlbldlYXRoZXJNYXA8L2E+JylcblxuICAgIGF0dHJpYi5hZGRUbyhtYXApO1xuXG4gICAgcmV0dXJuIG1hcFxufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3Jlc291cmNlcy9qcy9tYXBzL2Jhc2VfbWFwLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\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/NzdmNyJdLCJuYW1lcyI6WyJQTEFOX1JPVVRFX0NPTE9SIiwiQUNUVUFMX1JPVVRFX0NPTE9SIiwiQ0lSQ0xFX0NPTE9SIl0sIm1hcHBpbmdzIjoiOzs7QUFBTyxJQUNIQSxtQkFBbUIsU0FEaEI7QUFBQSxJQUVIQyxxQkFBcUIsU0FGbEI7QUFBQSxJQUdIQyxlQUFlLFNBSFoiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvbWFwcy9jb25maWcuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgbGV0XG4gICAgUExBTl9ST1VURV9DT0xPUiA9ICcjMDQzNzU4JyxcbiAgICBBQ1RVQUxfUk9VVEVfQ09MT1IgPSAnIzA2N2VjMScsXG4gICAgQ0lSQ0xFX0NPTE9SID0gJyMwNTYwOTMnO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vcmVzb3VyY2VzL2pzL21hcHMvY29uZmlnLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9oZWxwZXJzLmpzPzNjZDUiXSwibmFtZXMiOlsibGVhZmxldCIsInJlcXVpcmUiLCJhZGRXTVNMYXllciIsIm1hcCIsIm9wdHMiLCJ1cmwiLCJwYXJhbXMiLCJPYmplY3QiLCJhc3NpZ24iLCJmb3JtYXQiLCJ0cmFuc3BhcmVudCIsIm1heFpvb20iLCJtaW5ab29tIiwibWxheWVyIiwidGlsZUxheWVyIiwid21zIiwiYWRkVG8iLCJzaG93RmVhdHVyZVBvcHVwIiwiZmVhdHVyZSIsImxheWVyIiwicG9wdXBfaHRtbCIsInByb3BlcnRpZXMiLCJwb3B1cCIsImJpbmRQb3B1cCJdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EsSUFBTUEsVUFBVSxtQkFBQUMsQ0FBUSw0Q0FBUixDQUFoQjs7QUFFQTs7Ozs7Ozs7O0FBU08sU0FBU0MsV0FBVCxDQUFxQkMsR0FBckIsRUFBMEJDLElBQTFCLEVBQWdDOztBQUVuQyxRQUFHQSxLQUFLQyxHQUFMLEtBQWEsRUFBaEIsRUFBb0I7QUFDaEI7QUFDSDs7QUFFREQsU0FBS0UsTUFBTCxHQUFjQyxPQUFPQyxNQUFQLENBQWM7QUFDeEJDLGdCQUFRLFdBRGdCO0FBRXhCQyxxQkFBYSxJQUZXO0FBR3hCQyxpQkFBUyxFQUhlO0FBSXhCQyxpQkFBUztBQUplLEtBQWQsRUFLWFIsS0FBS0UsTUFMTSxDQUFkOztBQU9BLFFBQU1PLFNBQVNiLFFBQVFjLFNBQVIsQ0FBa0JDLEdBQWxCLENBQ1hYLEtBQUtDLEdBRE0sRUFDREQsS0FBS0UsTUFESixDQUFmOztBQUlBTyxXQUFPRyxLQUFQLENBQWFiLEdBQWI7O0FBRUEsV0FBT1UsTUFBUDtBQUNIOztBQUVEOzs7OztBQUtPLFNBQVNJLGdCQUFULENBQTBCQyxPQUExQixFQUFtQ0MsS0FBbkMsRUFBMEM7QUFDN0MsUUFBSUMsYUFBYSxFQUFqQjtBQUNBLFFBQUlGLFFBQVFHLFVBQVIsSUFBc0JILFFBQVFHLFVBQVIsQ0FBbUJDLEtBQTdDLEVBQW9EO0FBQ2hERixzQkFBY0YsUUFBUUcsVUFBUixDQUFtQkMsS0FBakM7QUFDSDs7QUFFREgsVUFBTUksU0FBTixDQUFnQkgsVUFBaEI7QUFDSCIsImZpbGUiOiIuL3Jlc291cmNlcy9qcy9tYXBzL2hlbHBlcnMuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJcbmNvbnN0IGxlYWZsZXQgPSByZXF1aXJlKCdsZWFmbGV0Jyk7XG5cbi8qKlxuICogQWRkIGEgV01TIGxheWVyIHRvIGEgbWFwLiBvcHRzIG11c3QgYmU6XG4gKiB7XG4gKiAgdXJsOiAnJyxcbiAqICBwYXJhbXM6IHt9XG4gKiAgfVxuICogQHBhcmFtIG1hcFxuICogQHBhcmFtIG9wdHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkZFdNU0xheWVyKG1hcCwgb3B0cykge1xuXG4gICAgaWYob3B0cy51cmwgPT09ICcnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBvcHRzLnBhcmFtcyA9IE9iamVjdC5hc3NpZ24oe1xuICAgICAgICBmb3JtYXQ6ICdpbWFnZS9wbmcnLFxuICAgICAgICB0cmFuc3BhcmVudDogdHJ1ZSxcbiAgICAgICAgbWF4Wm9vbTogMTQsXG4gICAgICAgIG1pblpvb206IDQsXG4gICAgfSwgb3B0cy5wYXJhbXMpO1xuXG4gICAgY29uc3QgbWxheWVyID0gbGVhZmxldC50aWxlTGF5ZXIud21zKFxuICAgICAgICBvcHRzLnVybCwgb3B0cy5wYXJhbXNcbiAgICApO1xuXG4gICAgbWxheWVyLmFkZFRvKG1hcCk7XG5cbiAgICByZXR1cm4gbWxheWVyO1xufVxuXG4vKipcbiAqIFNob3cgYSBwb3B1cFxuICogQHBhcmFtIGZlYXR1cmVcbiAqIEBwYXJhbSBsYXllclxuICovXG5leHBvcnQgZnVuY3Rpb24gc2hvd0ZlYXR1cmVQb3B1cChmZWF0dXJlLCBsYXllcikge1xuICAgIGxldCBwb3B1cF9odG1sID0gJyc7XG4gICAgaWYgKGZlYXR1cmUucHJvcGVydGllcyAmJiBmZWF0dXJlLnByb3BlcnRpZXMucG9wdXApIHtcbiAgICAgICAgcG9wdXBfaHRtbCArPSBmZWF0dXJlLnByb3BlcnRpZXMucG9wdXBcbiAgICB9XG5cbiAgICBsYXllci5iaW5kUG9wdXAocG9wdXBfaHRtbClcbn1cblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3Jlc291cmNlcy9qcy9tYXBzL2hlbHBlcnMuanMiXSwic291cmNlUm9vdCI6IiJ9\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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9pbmRleC5qcz85MmYwIl0sIm5hbWVzIjpbIndpbmRvdyIsIkwiLCJyZXF1aXJlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQTtBQUFBOzs7O0FBSUFBLE9BQU9DLENBQVAsR0FBVyxtQkFBQUMsQ0FBUSw0Q0FBUixDQUFYO0FBQ0EsbUJBQUFBLENBQVEscURBQVI7QUFDQSxtQkFBQUEsQ0FBUSwrREFBUjs7QUFFQTtBQUNBO0FBQ0EiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvbWFwcy9pbmRleC5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQWxsIG9mIHRoZSBmdW5jdGlvbmFsaXR5IHJlcXVpcmVkIGZvciBtYXBzXG4gKi9cblxud2luZG93LkwgPSByZXF1aXJlKCdsZWFmbGV0Jyk7XG5yZXF1aXJlKCdMZWFmbGV0Lkdlb2Rlc2ljJyk7XG5yZXF1aXJlKCdsZWFmbGV0LXJvdGF0ZWRtYXJrZXInKTtcblxuaW1wb3J0IHJlbmRlcl9haXJzcGFjZV9tYXAgZnJvbSAnLi9haXJzcGFjZV9tYXAnXG5pbXBvcnQgcmVuZGVyX2xpdmVfbWFwIGZyb20gJy4vbGl2ZV9tYXAnXG5pbXBvcnQgcmVuZGVyX3JvdXRlX21hcCBmcm9tICcuL3JvdXRlX21hcCdcblxuZXhwb3J0IHtcbiAgcmVuZGVyX2FpcnNwYWNlX21hcCxcbiAgcmVuZGVyX2xpdmVfbWFwLFxuICByZW5kZXJfcm91dGVfbWFwLFxufVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vcmVzb3VyY2VzL2pzL21hcHMvaW5kZXguanMiXSwic291cmNlUm9vdCI6IiJ9\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 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvbWFwcy9saXZlX21hcC5qcz9lN2Y2Il0sIm5hbWVzIjpbImdlb2xpYiIsInJlcXVpcmUiLCJsZWFmbGV0Iiwicml2ZXRzIiwib3B0cyIsIk9iamVjdCIsImFzc2lnbiIsInVwZGF0ZV91cmkiLCJwaXJlcF91cmkiLCJwaXJlcF9saW5rX3VyaSIsInBvc2l0aW9ucyIsInJlbmRlcl9lbGVtIiwiYWlyY3JhZnRfaWNvbiIsInVuaXRzIiwibWFwIiwiZHJhd19iYXNlX21hcCIsImFpcmNyYWZ0SWNvbiIsImljb24iLCJpY29uVXJsIiwiaWNvblNpemUiLCJpY29uQW5jaG9yIiwibWFya2Vyc19saXN0IiwicGFubmVkVG9DZW50ZXIiLCJsYXllckZsaWdodHMiLCJsYXllclNlbEZsaWdodCIsImxheWVyU2VsRmxpZ2h0RmVhdHVyZSIsImxheWVyU2VsRmxpZ2h0TGF5ZXIiLCJsYXllclNlbEFyciIsImxheWVyU2VsRGVwIiwibWFwQ29udHJvbGxlciIsImZvY3VzTWFya2VyIiwiZSIsIm1vZGVsIiwicGlyZXAiLCJpZCIsImNvbnNvbGUiLCJsb2ciLCJtYXJrZXIiLCJvbkZsaWdodENsaWNrIiwicl9tYXBfdmlldyIsImJpbmQiLCIkIiwiY29udHJvbGxlciIsInJfdGFibGVfdmlldyIsInBpcmVwcyIsImZlYXR1cmUiLCJsYXllciIsInJlcGxhY2UiLCJwcm9wZXJ0aWVzIiwicGlyZXBfaWQiLCJnZW9qc29uX3VyaSIsInBpcmVwX2luZm8iLCJhamF4IiwidXJsIiwiZGF0YVR5cGUiLCJlcnJvciIsImZsaWdodF9yb3V0ZSIsIndoZW4iLCJkb25lIiwicnRlIiwicmVtb3ZlTGF5ZXIiLCJnZW9kZXNpYyIsIndlaWdodCIsIm9wYWNpdHkiLCJjb2xvciIsIndyYXAiLCJhZGRUbyIsImdlb0pzb24iLCJsaW5lIiwiYyIsImdldENlbnRlciIsImxhdGl0dWRlIiwiYWlycG9ydHMiLCJhIiwibGF0IiwibG9uZ2l0dWRlIiwibG9uIiwiZCIsInBhblRvIiwicG9zaXRpb24iLCJsbmciLCJ1cGRhdGUiLCJkYXRhIiwic2hvdyIsInVwZGF0ZU1hcCIsImZsaWdodHMiLCJjbGVhckxheWVycyIsImdlb0pTT04iLCJmbGlnaHRHZW9Kc29uIiwib25FYWNoRmVhdHVyZSIsIm9uIiwiY2xpY2siLCJwb3B1cF9odG1sIiwicG9wdXAiLCJ1bmRlZmluZWQiLCJiaW5kUG9wdXAiLCJwb2ludFRvTGF5ZXIiLCJsYXRsb24iLCJyb3RhdGlvbkFuZ2xlIiwiaGVhZGluZyIsImhhc19kYXRhIiwibGVuZ3RoIiwic2V0SW50ZXJ2YWwiXSwibWFwcGluZ3MiOiI7QUFBQTtBQUFBOztBQUVBLElBQU1BLFNBQVMsbUJBQUFDLENBQVEsc0NBQVIsQ0FBZjtBQUNBLElBQU1DLFVBQVUsbUJBQUFELENBQVEsNENBQVIsQ0FBaEI7QUFDQSxJQUFNRSxTQUFTLG1CQUFBRixDQUFRLHNDQUFSLENBQWY7O0FBRUE7QUFDQTs7QUFFQTs7Ozs7QUFLQSx5REFBZSxVQUFDRyxJQUFELEVBQVU7O0FBRXJCQSxXQUFPQyxPQUFPQyxNQUFQLENBQWM7QUFDakJDLG9CQUFZLFlBREs7QUFFakJDLG1CQUFXLGtCQUZNO0FBR2pCQyx3QkFBZ0IsY0FIQztBQUlqQkMsbUJBQVcsSUFKTTtBQUtqQkMscUJBQWEsS0FMSTtBQU1qQkMsdUJBQWUsZ0NBTkU7QUFPakJDLGVBQU87QUFQVSxLQUFkLEVBUUpULElBUkksQ0FBUDs7QUFVQSxRQUFNVSxNQUFNLGtFQUFBQyxDQUFjWCxJQUFkLENBQVo7QUFDQSxRQUFNWSxlQUFlZCxRQUFRZSxJQUFSLENBQWE7QUFDOUJDLGlCQUFTZCxLQUFLUSxhQURnQjtBQUU5Qk8sa0JBQVUsQ0FBQyxFQUFELEVBQUssRUFBTCxDQUZvQjtBQUc5QkMsb0JBQVksQ0FBQyxFQUFELEVBQUssRUFBTDtBQUhrQixLQUFiLENBQXJCOztBQU1BOzs7O0FBSUEsUUFBSUMsZUFBZSxFQUFuQjs7QUFFQSxRQUFJQyxpQkFBaUIsS0FBckI7O0FBRUEsUUFBSUMsZUFBZSxJQUFuQjtBQUNBLFFBQUlDLGlCQUFpQixJQUFyQjtBQUNBLFFBQUlDLHdCQUF3QixJQUE1QjtBQUNBLFFBQUlDLHNCQUFzQixJQUExQjtBQUNBLFFBQUlDLGNBQWMsSUFBbEI7QUFDQSxRQUFJQyxjQUFjLElBQWxCOztBQUVBOzs7O0FBSUEsUUFBTUMsZ0JBQWdCO0FBQ2xCOzs7OztBQUtBQyxxQkFBYSxxQkFBQ0MsQ0FBRCxFQUFJQyxLQUFKLEVBQWM7QUFDdkIsZ0JBQUcsRUFBRUEsTUFBTUMsS0FBTixDQUFZQyxFQUFaLElBQWtCYixZQUFwQixDQUFILEVBQXNDO0FBQ2xDYyx3QkFBUUMsR0FBUixDQUFZLDBCQUFaO0FBQ0E7QUFDSDs7QUFFRCxnQkFBTUMsU0FBU2hCLGFBQWFXLE1BQU1DLEtBQU4sQ0FBWUMsRUFBekIsQ0FBZjtBQUNBSSwwQkFBY0QsT0FBTyxDQUFQLENBQWQsRUFBeUJBLE9BQU8sQ0FBUCxDQUF6QjtBQUNIO0FBZGlCLEtBQXRCOztBQWlCQSxRQUFNRSxhQUFhcEMsT0FBT3FDLElBQVAsQ0FBWUMsRUFBRSxlQUFGLENBQVosRUFBZ0MsRUFBQ1IsT0FBTyxFQUFSLEVBQVlTLFlBQVliLGFBQXhCLEVBQWhDLENBQW5CO0FBQ0EsUUFBTWMsZUFBZXhDLE9BQU9xQyxJQUFQLENBQVlDLEVBQUUsZUFBRixDQUFaLEVBQWdDLEVBQUNHLFFBQVEsRUFBVCxFQUFhRixZQUFZYixhQUF6QixFQUFoQyxDQUFyQjs7QUFFQTs7Ozs7QUFLQSxRQUFNUyxnQkFBZ0IsU0FBaEJBLGFBQWdCLENBQUNPLE9BQUQsRUFBVUMsS0FBVixFQUFvQjs7QUFFdEMsWUFBTXRDLFlBQVlKLEtBQUtJLFNBQUwsQ0FBZXVDLE9BQWYsQ0FBdUIsTUFBdkIsRUFBK0JGLFFBQVFHLFVBQVIsQ0FBbUJDLFFBQWxELENBQWxCO0FBQ0EsWUFBTUMsY0FBYzlDLEtBQUtJLFNBQUwsQ0FBZXVDLE9BQWYsQ0FBdUIsTUFBdkIsRUFBK0JGLFFBQVFHLFVBQVIsQ0FBbUJDLFFBQWxELElBQThELGdCQUFsRjs7QUFFQSxZQUFNRSxhQUFhVixFQUFFVyxJQUFGLENBQU87QUFDdEJDLGlCQUFLN0MsU0FEaUI7QUFFdEI4QyxzQkFBVSxNQUZZO0FBR3RCQyxtQkFBT3BCLFFBQVFDO0FBSE8sU0FBUCxDQUFuQjs7QUFNQSxZQUFNb0IsZUFBZWYsRUFBRVcsSUFBRixDQUFPO0FBQ3hCQyxpQkFBS0gsV0FEbUI7QUFFeEJJLHNCQUFVLE1BRmM7QUFHeEJDLG1CQUFPcEIsUUFBUUM7QUFIUyxTQUFQLENBQXJCOztBQU1BO0FBQ0FLLFVBQUVnQixJQUFGLENBQU9ELFlBQVAsRUFBcUJFLElBQXJCLENBQTBCLFVBQUNDLEdBQUQsRUFBUztBQUMvQixnQkFBSW5DLG1CQUFtQixJQUF2QixFQUE2QjtBQUN6QlYsb0JBQUk4QyxXQUFKLENBQWdCcEMsY0FBaEI7QUFDQTtBQUNBO0FBQ0g7O0FBRURBLDZCQUFpQnRCLFFBQVEyRCxRQUFSLENBQWlCLEVBQWpCLEVBQXFCO0FBQ2xDQyx3QkFBUSxDQUQwQjtBQUVsQ0MseUJBQVMsR0FGeUI7QUFHbENDLHVCQUFPLG1FQUgyQjtBQUlsQ0Msc0JBQU07QUFKNEIsYUFBckIsRUFLZEMsS0FMYyxDQUtScEQsR0FMUSxDQUFqQjs7QUFPQVUsMkJBQWUyQyxPQUFmLENBQXVCUixJQUFJUyxJQUEzQjtBQUNBM0Msb0NBQXdCb0IsT0FBeEI7QUFDQW5CLGtDQUFzQm9CLEtBQXRCOztBQUVBOzs7Ozs7QUFPQTtBQUNBLGdCQUFHLENBQUN4QixjQUFKLEVBQW9CO0FBQ2hCO0FBQ0Esb0JBQU0rQyxJQUFJckUsT0FBT3NFLFNBQVAsQ0FBaUIsQ0FDdkIsRUFBQ0MsVUFBVVosSUFBSWEsUUFBSixDQUFhQyxDQUFiLENBQWVDLEdBQTFCLEVBQStCQyxXQUFXaEIsSUFBSWEsUUFBSixDQUFhQyxDQUFiLENBQWVHLEdBQXpELEVBRHVCLEVBRXZCLEVBQUNMLFVBQVVaLElBQUlhLFFBQUosQ0FBYUssQ0FBYixDQUFlSCxHQUExQixFQUErQkMsV0FBV2hCLElBQUlhLFFBQUosQ0FBYUssQ0FBYixDQUFlRCxHQUF6RCxFQUZ1QixDQUFqQixDQUFWOztBQUtBO0FBQ0E5RCxvQkFBSWdFLEtBQUosQ0FBVSxFQUFDSixLQUFLZixJQUFJb0IsUUFBSixDQUFhTCxHQUFuQixFQUF3Qk0sS0FBS3JCLElBQUlvQixRQUFKLENBQWFILEdBQTFDLEVBQVY7QUFDQXRELGlDQUFpQixJQUFqQjtBQUNIO0FBQ0osU0FyQ0Q7O0FBdUNBO0FBQ0E7QUFDQTtBQUNBbUIsVUFBRWdCLElBQUYsQ0FBT04sVUFBUCxFQUFtQk8sSUFBbkIsQ0FBd0IsaUJBQVM7QUFDN0JuQix1QkFBVzBDLE1BQVgsQ0FBa0IsRUFBQ2hELE9BQU1BLE1BQU1pRCxJQUFiLEVBQWxCO0FBQ0F6QyxjQUFFLGVBQUYsRUFBbUIwQyxJQUFuQjtBQUNILFNBSEQ7QUFJSCxLQWhFRDs7QUFrRUEsUUFBTUMsWUFBWSxTQUFaQSxTQUFZLEdBQU07O0FBRXBCakQsZ0JBQVFDLEdBQVIsQ0FBWSxpQ0FBWjs7QUFFQTs7O0FBR0EsWUFBTTVCLFlBQVlKLEtBQUtJLFNBQUwsQ0FBZXVDLE9BQWYsQ0FBdUIsTUFBdkIsRUFBK0IsRUFBL0IsQ0FBbEI7QUFDQSxZQUFJSCxTQUFTSCxFQUFFVyxJQUFGLENBQU87QUFDaEJDLGlCQUFLN0MsU0FEVztBQUVoQjhDLHNCQUFVLE1BRk07QUFHaEJDLG1CQUFPcEIsUUFBUUM7QUFIQyxTQUFQLENBQWI7O0FBTUEsWUFBSWlELFVBQVU1QyxFQUFFVyxJQUFGLENBQU87QUFDakJDLGlCQUFLakQsS0FBS0csVUFETztBQUVqQitDLHNCQUFVLE1BRk87QUFHakJDLG1CQUFPcEIsUUFBUUM7QUFIRSxTQUFQLENBQWQ7O0FBTUFLLFVBQUVnQixJQUFGLENBQU80QixPQUFQLEVBQWdCM0IsSUFBaEIsQ0FBcUIseUJBQWlCOztBQUVsQyxnQkFBSW5DLGlCQUFpQixJQUFyQixFQUEyQjtBQUN2QkEsNkJBQWErRCxXQUFiO0FBQ0g7O0FBRUQvRCwyQkFBZXJCLFFBQVFxRixPQUFSLENBQWdCQyxhQUFoQixFQUErQjtBQUMxQ0MsK0JBQWUsdUJBQUM1QyxPQUFELEVBQVVDLEtBQVYsRUFBb0I7QUFDL0JBLDBCQUFNNEMsRUFBTixDQUFTO0FBQ0xDLCtCQUFPLGVBQUM1RCxDQUFELEVBQU87QUFDVlQsNkNBQWlCLEtBQWpCO0FBQ0FnQiwwQ0FBY08sT0FBZCxFQUF1QkMsS0FBdkI7QUFDSDtBQUpJLHFCQUFUOztBQU9BLHdCQUFJOEMsYUFBYSxFQUFqQjtBQUNBLHdCQUFJL0MsUUFBUUcsVUFBUixJQUF1QkgsUUFBUUcsVUFBUixDQUFtQjZDLEtBQW5CLEtBQTZCLEVBQTdCLElBQW1DaEQsUUFBUUcsVUFBUixDQUFtQjZDLEtBQW5CLEtBQTZCQyxTQUEzRixFQUF1RztBQUNuR0Ysc0NBQWMvQyxRQUFRRyxVQUFSLENBQW1CNkMsS0FBakM7QUFDQS9DLDhCQUFNaUQsU0FBTixDQUFnQkgsVUFBaEI7QUFDSDs7QUFFRDtBQUNBdkUsaUNBQWF3QixRQUFRRyxVQUFSLENBQW1CQyxRQUFoQyxJQUE0QyxDQUFDSixPQUFELEVBQVVDLEtBQVYsQ0FBNUM7QUFDSCxpQkFqQnlDO0FBa0IxQ2tELDhCQUFjLHNCQUFVbkQsT0FBVixFQUFtQm9ELE1BQW5CLEVBQTJCO0FBQ3JDLDJCQUFPL0YsUUFBUW1DLE1BQVIsQ0FBZTRELE1BQWYsRUFBdUI7QUFDMUJoRiw4QkFBTUQsWUFEb0I7QUFFMUJrRix1Q0FBZXJELFFBQVFHLFVBQVIsQ0FBbUJtRDtBQUZSLHFCQUF2QixDQUFQO0FBSUg7QUF2QnlDLGFBQS9CLENBQWY7O0FBMEJBNUUseUJBQWEyQyxLQUFiLENBQW1CcEQsR0FBbkI7O0FBRUE7QUFDQSxnQkFBSVUsbUJBQW1CLElBQXZCLEVBQTZCO0FBQ3pCYyw4QkFBY2IscUJBQWQsRUFBcUNDLG1CQUFyQztBQUNIO0FBQ0osU0F0Q0Q7O0FBd0NBZSxVQUFFZ0IsSUFBRixDQUFPYixNQUFQLEVBQWVjLElBQWYsQ0FBb0Isa0JBQVU7QUFDMUJmLHlCQUFhc0MsTUFBYixDQUFvQjtBQUNoQnJDLHdCQUFRQSxPQUFPc0MsSUFEQztBQUVoQmtCLDBCQUFXeEQsT0FBT3NDLElBQVAsQ0FBWW1CLE1BQVosR0FBcUI7QUFGaEIsYUFBcEI7QUFJSCxTQUxEO0FBTUgsS0FsRUQ7O0FBb0VBakI7QUFDQWtCLGdCQUFZbEIsU0FBWixFQUF1QixLQUF2QjtBQUNILENBdk1EIiwiZmlsZSI6Ii4vcmVzb3VyY2VzL2pzL21hcHMvbGl2ZV9tYXAuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvL1xuXG5jb25zdCBnZW9saWIgPSByZXF1aXJlKCdnZW9saWInKTtcbmNvbnN0IGxlYWZsZXQgPSByZXF1aXJlKCdsZWFmbGV0Jyk7XG5jb25zdCByaXZldHMgPSByZXF1aXJlKCdyaXZldHMnKTtcblxuaW1wb3J0IGRyYXdfYmFzZV9tYXAgZnJvbSAnLi9iYXNlX21hcCdcbmltcG9ydCB7IEFDVFVBTF9ST1VURV9DT0xPUiB9IGZyb20gJy4vY29uZmlnJ1xuXG4vKipcbiAqIFJlbmRlciB0aGUgbGl2ZSBtYXBcbiAqIEBwYXJhbSBvcHRzXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgZGVmYXVsdCAob3B0cykgPT4ge1xuXG4gICAgb3B0cyA9IE9iamVjdC5hc3NpZ24oe1xuICAgICAgICB1cGRhdGVfdXJpOiAnL2FwaS9hY2FycycsXG4gICAgICAgIHBpcmVwX3VyaTogJy9hcGkvcGlyZXBzL3tpZH0nLFxuICAgICAgICBwaXJlcF9saW5rX3VyaTogJy9waXJlcHMve2lkfScsXG4gICAgICAgIHBvc2l0aW9uczogbnVsbCxcbiAgICAgICAgcmVuZGVyX2VsZW06ICdtYXAnLFxuICAgICAgICBhaXJjcmFmdF9pY29uOiAnL2Fzc2V0cy9pbWcvYWNhcnMvYWlyY3JhZnQucG5nJyxcbiAgICAgICAgdW5pdHM6ICdubWknLFxuICAgIH0sIG9wdHMpO1xuXG4gICAgY29uc3QgbWFwID0gZHJhd19iYXNlX21hcChvcHRzKTtcbiAgICBjb25zdCBhaXJjcmFmdEljb24gPSBsZWFmbGV0Lmljb24oe1xuICAgICAgICBpY29uVXJsOiBvcHRzLmFpcmNyYWZ0X2ljb24sXG4gICAgICAgIGljb25TaXplOiBbNDIsIDQyXSxcbiAgICAgICAgaWNvbkFuY2hvcjogWzIxLCAyMV0sXG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBIb2xkIHRoZSBtYXJrZXJzXG4gICAgICogQHR5cGUge3t9fVxuICAgICAqL1xuICAgIGxldCBtYXJrZXJzX2xpc3QgPSB7fTtcblxuICAgIGxldCBwYW5uZWRUb0NlbnRlciA9IGZhbHNlO1xuXG4gICAgbGV0IGxheWVyRmxpZ2h0cyA9IG51bGw7XG4gICAgbGV0IGxheWVyU2VsRmxpZ2h0ID0gbnVsbDtcbiAgICBsZXQgbGF5ZXJTZWxGbGlnaHRGZWF0dXJlID0gbnVsbDtcbiAgICBsZXQgbGF5ZXJTZWxGbGlnaHRMYXllciA9IG51bGw7XG4gICAgbGV0IGxheWVyU2VsQXJyID0gbnVsbDtcbiAgICBsZXQgbGF5ZXJTZWxEZXAgPSBudWxsO1xuXG4gICAgLyoqXG4gICAgICogQ29udHJvbGxlciBmb3IgdHdvLXdheSBiaW5kaW5nc1xuICAgICAqIEB0eXBlIHt7Zm9jdXNNYXJrZXI6IGZvY3VzTWFya2VyfX1cbiAgICAgKi9cbiAgICBjb25zdCBtYXBDb250cm9sbGVyID0ge1xuICAgICAgICAvKipcbiAgICAgICAgICogRm9jdXMgb24gYSBzcGVjaWZpYyBtYXJrZXJcbiAgICAgICAgICogQHBhcmFtIGVcbiAgICAgICAgICogQHBhcmFtIG1vZGVsXG4gICAgICAgICAqL1xuICAgICAgICBmb2N1c01hcmtlcjogKGUsIG1vZGVsKSA9PiB7XG4gICAgICAgICAgICBpZighKG1vZGVsLnBpcmVwLmlkIGluIG1hcmtlcnNfbGlzdCkpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnbWFya2VyIG5vdCBmb3VuZCBpbiBsaXN0Jyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBtYXJrZXIgPSBtYXJrZXJzX2xpc3RbbW9kZWwucGlyZXAuaWRdO1xuICAgICAgICAgICAgb25GbGlnaHRDbGljayhtYXJrZXJbMF0sIG1hcmtlclsxXSk7XG4gICAgICAgIH0sXG4gICAgfTtcblxuICAgIGNvbnN0IHJfbWFwX3ZpZXcgPSByaXZldHMuYmluZCgkKCcjbWFwLWluZm8tYm94JyksIHtwaXJlcDoge30sIGNvbnRyb2xsZXI6IG1hcENvbnRyb2xsZXJ9KTtcbiAgICBjb25zdCByX3RhYmxlX3ZpZXcgPSByaXZldHMuYmluZCgkKCcjbGl2ZV9mbGlnaHRzJyksIHtwaXJlcHM6IFtdLCBjb250cm9sbGVyOiBtYXBDb250cm9sbGVyfSk7XG5cbiAgICAvKipcbiAgICAgKiBXaGVuIGEgZmxpZ2h0IGlzIGNsaWNrZWQgb24sIHNob3cgdGhlIHBhdGgsIGV0YyBmb3IgdGhhdCBmbGlnaHRcbiAgICAgKiBAcGFyYW0gZmVhdHVyZVxuICAgICAqIEBwYXJhbSBsYXllclxuICAgICAqL1xuICAgIGNvbnN0IG9uRmxpZ2h0Q2xpY2sgPSAoZmVhdHVyZSwgbGF5ZXIpID0+IHtcblxuICAgICAgICBjb25zdCBwaXJlcF91cmkgPSBvcHRzLnBpcmVwX3VyaS5yZXBsYWNlKCd7aWR9JywgZmVhdHVyZS5wcm9wZXJ0aWVzLnBpcmVwX2lkKTtcbiAgICAgICAgY29uc3QgZ2VvanNvbl91cmkgPSBvcHRzLnBpcmVwX3VyaS5yZXBsYWNlKCd7aWR9JywgZmVhdHVyZS5wcm9wZXJ0aWVzLnBpcmVwX2lkKSArIFwiL2FjYXJzL2dlb2pzb25cIjtcblxuICAgICAgICBjb25zdCBwaXJlcF9pbmZvID0gJC5hamF4KHtcbiAgICAgICAgICAgIHVybDogcGlyZXBfdXJpLFxuICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgIGVycm9yOiBjb25zb2xlLmxvZ1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBmbGlnaHRfcm91dGUgPSAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBnZW9qc29uX3VyaSxcbiAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICBlcnJvcjogY29uc29sZS5sb2dcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gTG9hZCB1cCB0aGUgUElSRVAgaW5mb1xuICAgICAgICAkLndoZW4oZmxpZ2h0X3JvdXRlKS5kb25lKChydGUpID0+IHtcbiAgICAgICAgICAgIGlmIChsYXllclNlbEZsaWdodCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG1hcC5yZW1vdmVMYXllcihsYXllclNlbEZsaWdodCk7XG4gICAgICAgICAgICAgICAgLy9tYXAucmVtb3ZlTGF5ZXIobGF5ZXJTZWxBcnIpO1xuICAgICAgICAgICAgICAgIC8vbWFwLnJlbW92ZUxheWVyKGxheWVyU2VsRGVwKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGF5ZXJTZWxGbGlnaHQgPSBsZWFmbGV0Lmdlb2Rlc2ljKFtdLCB7XG4gICAgICAgICAgICAgICAgd2VpZ2h0OiA1LFxuICAgICAgICAgICAgICAgIG9wYWNpdHk6IDAuOSxcbiAgICAgICAgICAgICAgICBjb2xvcjogQUNUVUFMX1JPVVRFX0NPTE9SLFxuICAgICAgICAgICAgICAgIHdyYXA6IGZhbHNlLFxuICAgICAgICAgICAgfSkuYWRkVG8obWFwKTtcblxuICAgICAgICAgICAgbGF5ZXJTZWxGbGlnaHQuZ2VvSnNvbihydGUubGluZSk7XG4gICAgICAgICAgICBsYXllclNlbEZsaWdodEZlYXR1cmUgPSBmZWF0dXJlO1xuICAgICAgICAgICAgbGF5ZXJTZWxGbGlnaHRMYXllciA9IGxheWVyO1xuXG4gICAgICAgICAgICAvKmNvbnN0IGRwdEljb24gPSBsZWFmbGV0LmRpdkljb24oe1xuICAgICAgICAgICAgICAgIGh0bWw6ICc8ZGl2IGNsYXNzPVwibWFwLWluZm8tbGFiZWxcIj48aDU+JyArIHJ0ZS5haXJwb3J0cy5kLmljYW8gKyAnPC9oNT48L2Rpdj4nXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgbGF5ZXJTZWxEZXAgPSBsZWFmbGV0Lm1hcmtlcihbcnRlLmFpcnBvcnRzLmQubGF0LCBydGUuYWlycG9ydHMuZC5sb25dLCB7aWNvbjpkcHRJY29ufSkuYWRkVG8obWFwKTtcbiAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8vIENlbnRlciBvbiBpdCwgYnV0IG9ubHkgZG8gaXQgb25jZSwgaW4gY2FzZSB0aGUgbWFwIGlzIG1vdmVkXG4gICAgICAgICAgICBpZighcGFubmVkVG9DZW50ZXIpIHtcbiAgICAgICAgICAgICAgICAvLyBmaW5kIGNlbnRlclxuICAgICAgICAgICAgICAgIGNvbnN0IGMgPSBnZW9saWIuZ2V0Q2VudGVyKFtcbiAgICAgICAgICAgICAgICAgICAge2xhdGl0dWRlOiBydGUuYWlycG9ydHMuYS5sYXQsIGxvbmdpdHVkZTogcnRlLmFpcnBvcnRzLmEubG9ufSxcbiAgICAgICAgICAgICAgICAgICAge2xhdGl0dWRlOiBydGUuYWlycG9ydHMuZC5sYXQsIGxvbmdpdHVkZTogcnRlLmFpcnBvcnRzLmQubG9ufSxcbiAgICAgICAgICAgICAgICBdKTtcblxuICAgICAgICAgICAgICAgIC8vbWFwLnBhblRvKHtsYXQ6IGMubGF0aXR1ZGUsIGxuZzogYy5sb25naXR1ZGV9KTtcbiAgICAgICAgICAgICAgICBtYXAucGFuVG8oe2xhdDogcnRlLnBvc2l0aW9uLmxhdCwgbG5nOiBydGUucG9zaXRpb24ubG9ufSk7XG4gICAgICAgICAgICAgICAgcGFubmVkVG9DZW50ZXIgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICAvL1xuICAgICAgICAvLyBXaGVuIHRoZSBQSVJFUCBpbmZvIGlzIGRvbmUgbG9hZGluZywgc2hvdyB0aGUgYm90dG9tIGJhclxuICAgICAgICAvL1xuICAgICAgICAkLndoZW4ocGlyZXBfaW5mbykuZG9uZShwaXJlcCA9PiB7XG4gICAgICAgICAgICByX21hcF92aWV3LnVwZGF0ZSh7cGlyZXA6cGlyZXAuZGF0YX0pO1xuICAgICAgICAgICAgJCgnI21hcC1pbmZvLWJveCcpLnNob3coKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIGNvbnN0IHVwZGF0ZU1hcCA9ICgpID0+IHtcblxuICAgICAgICBjb25zb2xlLmxvZygncmVsb2FkaW5nIGZsaWdodHMgZnJvbSBhY2Fycy4uLicpO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBSkFYIFVQREFURVxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3QgcGlyZXBfdXJpID0gb3B0cy5waXJlcF91cmkucmVwbGFjZSgne2lkfScsICcnKTtcbiAgICAgICAgbGV0IHBpcmVwcyA9ICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IHBpcmVwX3VyaSxcbiAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICBlcnJvcjogY29uc29sZS5sb2dcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IGZsaWdodHMgPSAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBvcHRzLnVwZGF0ZV91cmksXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgZXJyb3I6IGNvbnNvbGUubG9nXG4gICAgICAgIH0pO1xuXG4gICAgICAgICQud2hlbihmbGlnaHRzKS5kb25lKGZsaWdodEdlb0pzb24gPT4ge1xuXG4gICAgICAgICAgICBpZiAobGF5ZXJGbGlnaHRzICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgbGF5ZXJGbGlnaHRzLmNsZWFyTGF5ZXJzKClcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGF5ZXJGbGlnaHRzID0gbGVhZmxldC5nZW9KU09OKGZsaWdodEdlb0pzb24sIHtcbiAgICAgICAgICAgICAgICBvbkVhY2hGZWF0dXJlOiAoZmVhdHVyZSwgbGF5ZXIpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgbGF5ZXIub24oe1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xpY2s6IChlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFubmVkVG9DZW50ZXIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkZsaWdodENsaWNrKGZlYXR1cmUsIGxheWVyKVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBsZXQgcG9wdXBfaHRtbCA9ICcnO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmVhdHVyZS5wcm9wZXJ0aWVzICYmIChmZWF0dXJlLnByb3BlcnRpZXMucG9wdXAgIT09ICcnICYmIGZlYXR1cmUucHJvcGVydGllcy5wb3B1cCAhPT0gdW5kZWZpbmVkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9wdXBfaHRtbCArPSBmZWF0dXJlLnByb3BlcnRpZXMucG9wdXA7XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXllci5iaW5kUG9wdXAocG9wdXBfaHRtbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBhZGQgdG8gdGhlIGxpc3RcbiAgICAgICAgICAgICAgICAgICAgbWFya2Vyc19saXN0W2ZlYXR1cmUucHJvcGVydGllcy5waXJlcF9pZF0gPSBbZmVhdHVyZSwgbGF5ZXJdO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcG9pbnRUb0xheWVyOiBmdW5jdGlvbiAoZmVhdHVyZSwgbGF0bG9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBsZWFmbGV0Lm1hcmtlcihsYXRsb24sIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGljb246IGFpcmNyYWZ0SWNvbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvdGF0aW9uQW5nbGU6IGZlYXR1cmUucHJvcGVydGllcy5oZWFkaW5nXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGxheWVyRmxpZ2h0cy5hZGRUbyhtYXApO1xuXG4gICAgICAgICAgICAvLyBSZWxvYWQgdGhlIGNsaWNrZWQtZmxpZ2h0IGluZm9ybWF0aW9uXG4gICAgICAgICAgICBpZiAobGF5ZXJTZWxGbGlnaHQgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBvbkZsaWdodENsaWNrKGxheWVyU2VsRmxpZ2h0RmVhdHVyZSwgbGF5ZXJTZWxGbGlnaHRMYXllcilcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgJC53aGVuKHBpcmVwcykuZG9uZShwaXJlcHMgPT4ge1xuICAgICAgICAgICAgcl90YWJsZV92aWV3LnVwZGF0ZSh7XG4gICAgICAgICAgICAgICAgcGlyZXBzOiBwaXJlcHMuZGF0YSxcbiAgICAgICAgICAgICAgICBoYXNfZGF0YTogKHBpcmVwcy5kYXRhLmxlbmd0aCA+IDApLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICB1cGRhdGVNYXAoKTtcbiAgICBzZXRJbnRlcnZhbCh1cGRhdGVNYXAsIDEwMDAwKVxufTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3Jlc291cmNlcy9qcy9tYXBzL2xpdmVfbWFwLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==\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/YTc0NSJdLCJuYW1lcyI6WyJsZWFmbGV0IiwicmVxdWlyZSIsIm9uRmVhdHVyZVBvaW50Q2xpY2siLCJmZWF0dXJlIiwibGF5ZXIiLCJwb3B1cF9odG1sIiwicHJvcGVydGllcyIsInBvcHVwIiwiYmluZFBvcHVwIiwicG9pbnRUb0xheWVyIiwibGF0bG5nIiwiY2lyY2xlTWFya2VyIiwicmFkaXVzIiwiZmlsbENvbG9yIiwiY29sb3IiLCJ3ZWlnaHQiLCJvcGFjaXR5IiwiZmlsbE9wYWNpdHkiLCJvcHRzIiwiT2JqZWN0IiwiYXNzaWduIiwicm91dGVfcG9pbnRzIiwicGxhbm5lZF9yb3V0ZV9saW5lIiwiYWN0dWFsX3JvdXRlX3BvaW50cyIsImFjdHVhbF9yb3V0ZV9saW5lIiwicmVuZGVyX2VsZW0iLCJsaXZlX21hcCIsImFpcmNyYWZ0X2ljb24iLCJtZXRhcl93bXMiLCJ1cmwiLCJwYXJhbXMiLCJhaXJjcmFmdEljb24iLCJpY29uIiwiaWNvblVybCIsImljb25TaXplIiwiaWNvbkFuY2hvciIsIm1hcCIsImRyYXdfYmFzZV9tYXAiLCJsYXllckxpdmVGbGlnaHQiLCJhZGRXTVNMYXllciIsImdlb2Rlc2ljTGF5ZXIiLCJnZW9kZXNpYyIsInN0ZXBzIiwid3JhcCIsImFkZFRvIiwiZ2VvSnNvbiIsImZpdEJvdW5kcyIsImdldEJvdW5kcyIsImUiLCJjb25zb2xlIiwibG9nIiwiZ2VvSlNPTiIsIm9uRWFjaEZlYXR1cmUiLCJzdHlsZSIsImZlYXR1cmVzIiwibGVuZ3RoIiwibGl2ZUZsaWdodCIsInVyaSIsInBpcmVwX3VyaSIsImxpdmVfcm91dGUiLCIkIiwiYWpheCIsImRhdGFUeXBlIiwiZXJyb3IiLCJ3aGVuIiwiZG9uZSIsInJvdXRlSnNvbiIsImxhdGxvbiIsIm1hcmtlciIsInJvdGF0aW9uQW5nbGUiLCJoZWFkaW5nIiwic2V0SW50ZXJ2YWwiXSwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUFBLElBQU1BLFVBQVUsbUJBQUFDLENBQVEsNENBQVIsQ0FBaEI7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7Ozs7QUFLTyxJQUFNQyxzQkFBc0IsU0FBdEJBLG1CQUFzQixDQUFDQyxPQUFELEVBQVVDLEtBQVYsRUFBb0I7QUFDbkQsUUFBSUMsYUFBYSxFQUFqQjtBQUNBLFFBQUlGLFFBQVFHLFVBQVIsSUFBc0JILFFBQVFHLFVBQVIsQ0FBbUJDLEtBQTdDLEVBQW9EO0FBQ2hERixzQkFBY0YsUUFBUUcsVUFBUixDQUFtQkMsS0FBakM7QUFDSDs7QUFFREgsVUFBTUksU0FBTixDQUFnQkgsVUFBaEI7QUFDSCxDQVBNOztBQVNQOzs7Ozs7QUFNTyxJQUFNSSxlQUFlLFNBQWZBLFlBQWUsQ0FBQ04sT0FBRCxFQUFVTyxNQUFWLEVBQXFCO0FBQzdDLFdBQU9WLFFBQVFXLFlBQVIsQ0FBcUJELE1BQXJCLEVBQTZCO0FBQ2hDRSxnQkFBUSxDQUR3QjtBQUVoQ0MsbUJBQVcsNkRBRnFCO0FBR2hDQyxlQUFPLE1BSHlCO0FBSWhDQyxnQkFBUSxDQUp3QjtBQUtoQ0MsaUJBQVMsQ0FMdUI7QUFNaENDLHFCQUFhO0FBTm1CLEtBQTdCLENBQVA7QUFRSCxDQVRNOztBQVdQOzs7Ozt5REFLZSxVQUFDQyxJQUFELEVBQVU7O0FBRXJCQSxXQUFPQyxPQUFPQyxNQUFQLENBQWM7O0FBRWpCQyxzQkFBYyxJQUZHO0FBR2pCQyw0QkFBb0IsSUFISDtBQUlqQkMsNkJBQXFCLElBSko7QUFLakJDLDJCQUFtQixJQUxGO0FBTWpCQyxxQkFBYSxLQU5JO0FBT2pCQyxrQkFBVSxLQVBPO0FBUWpCQyx1QkFBZSxnQ0FSRTtBQVNqQkMsbUJBQVc7QUFDUEMsaUJBQUssRUFERTtBQUVQQyxvQkFBUTtBQUZEO0FBVE0sS0FBZCxFQWFKWixJQWJJLENBQVA7O0FBZUEsUUFBTWEsZUFBZS9CLFFBQVFnQyxJQUFSLENBQWE7QUFDOUJDLGlCQUFTZixLQUFLUyxhQURnQjtBQUU5Qk8sa0JBQVUsQ0FBQyxFQUFELEVBQUssRUFBTCxDQUZvQjtBQUc5QkMsb0JBQVksQ0FBQyxFQUFELEVBQUssRUFBTDtBQUhrQixLQUFiLENBQXJCOztBQU1BLFFBQUlDLE1BQU0sa0VBQUFDLENBQWNuQixJQUFkLENBQVY7QUFDQSxRQUFJb0Isd0JBQUo7O0FBRUEsUUFBSXBCLEtBQUtVLFNBQUwsQ0FBZUMsR0FBZixLQUF1QixFQUEzQixFQUErQjtBQUMzQlUsUUFBQSxxRUFBQUEsQ0FBWUgsR0FBWixFQUFpQmxCLEtBQUtVLFNBQXRCO0FBQ0g7O0FBRUQsUUFBSVksZ0JBQWdCeEMsUUFBUXlDLFFBQVIsQ0FBaUIsRUFBakIsRUFBcUI7QUFDckMxQixnQkFBUSxDQUQ2QjtBQUVyQ0MsaUJBQVMsR0FGNEI7QUFHckNGLGVBQU8saUVBSDhCO0FBSXJDNEIsZUFBTyxFQUo4QjtBQUtyQ0MsY0FBTTtBQUwrQixLQUFyQixFQU1qQkMsS0FOaUIsQ0FNWFIsR0FOVyxDQUFwQjs7QUFRQUksa0JBQWNLLE9BQWQsQ0FBc0IzQixLQUFLSSxrQkFBM0I7O0FBRUEsUUFBSTtBQUNBYyxZQUFJVSxTQUFKLENBQWNOLGNBQWNPLFNBQWQsRUFBZDtBQUNILEtBRkQsQ0FFRSxPQUFPQyxDQUFQLEVBQVU7QUFDUkMsZ0JBQVFDLEdBQVIsQ0FBWUYsQ0FBWjtBQUNIOztBQUVEO0FBQ0EsUUFBSTlCLEtBQUtHLFlBQUwsS0FBc0IsSUFBMUIsRUFBZ0M7QUFDNUIsWUFBSUEsZUFBZXJCLFFBQVFtRCxPQUFSLENBQWdCakMsS0FBS0csWUFBckIsRUFBbUM7QUFDbEQrQiwyQkFBZWxELG1CQURtQztBQUVsRE8sMEJBQWNBLFlBRm9DO0FBR2xENEMsbUJBQU87QUFDSCx5QkFBUyxpRUFETjtBQUVILDBCQUFVLENBRlA7QUFHSCwyQkFBVztBQUhSO0FBSDJDLFNBQW5DLENBQW5COztBQVVBaEMscUJBQWF1QixLQUFiLENBQW1CUixHQUFuQjtBQUNIOztBQUVEOzs7O0FBSUEsUUFBSWxCLEtBQUtNLGlCQUFMLEtBQTJCLElBQTNCLElBQW1DTixLQUFLTSxpQkFBTCxDQUF1QjhCLFFBQXZCLENBQWdDQyxNQUFoQyxHQUF5QyxDQUFoRixFQUFtRjtBQUMvRSxZQUFJZixpQkFBZ0J4QyxRQUFReUMsUUFBUixDQUFpQixFQUFqQixFQUFxQjtBQUNyQzFCLG9CQUFRLENBRDZCO0FBRXJDQyxxQkFBUyxHQUY0QjtBQUdyQ0YsbUJBQU8sbUVBSDhCO0FBSXJDNEIsbUJBQU8sRUFKOEI7QUFLckNDLGtCQUFNO0FBTCtCLFNBQXJCLEVBTWpCQyxLQU5pQixDQU1YUixHQU5XLENBQXBCOztBQVFBSSx1QkFBY0ssT0FBZCxDQUFzQjNCLEtBQUtNLGlCQUEzQjs7QUFFQSxZQUFJO0FBQ0FZLGdCQUFJVSxTQUFKLENBQWNOLGVBQWNPLFNBQWQsRUFBZDtBQUNILFNBRkQsQ0FFRSxPQUFPQyxDQUFQLEVBQVU7QUFDUkMsb0JBQVFDLEdBQVIsQ0FBWUYsQ0FBWjtBQUNIO0FBQ0o7O0FBRUQsUUFBSTlCLEtBQUtLLG1CQUFMLEtBQTZCLElBQTdCLElBQXFDTCxLQUFLSyxtQkFBTCxDQUF5QitCLFFBQXpCLENBQWtDQyxNQUFsQyxHQUEyQyxDQUFwRixFQUF1RjtBQUNuRixZQUFJbEMsZ0JBQWVyQixRQUFRbUQsT0FBUixDQUFnQmpDLEtBQUtLLG1CQUFyQixFQUEwQztBQUN6RDZCLDJCQUFlbEQsbUJBRDBDO0FBRXpETywwQkFBY0EsWUFGMkM7QUFHekQ0QyxtQkFBTztBQUNILHlCQUFTLG1FQUROO0FBRUgsMEJBQVUsQ0FGUDtBQUdILDJCQUFXO0FBSFI7QUFIa0QsU0FBMUMsQ0FBbkI7O0FBVUFoQyxzQkFBYXVCLEtBQWIsQ0FBbUJSLEdBQW5CO0FBQ0g7O0FBRUQ7OztBQUdBLFFBQU1vQixhQUFhLFNBQWJBLFVBQWEsR0FBTTtBQUNyQixZQUFNQyxNQUFNdkMsS0FBS3dDLFNBQWpCO0FBQ0EsWUFBTUMsYUFBYUMsRUFBRUMsSUFBRixDQUFPO0FBQ3RCaEMsaUJBQUs0QixHQURpQjtBQUV0Qkssc0JBQVUsTUFGWTtBQUd0QkMsbUJBQU9kLFFBQVFDO0FBSE8sU0FBUCxDQUFuQjs7QUFNQVUsVUFBRUksSUFBRixDQUFPTCxVQUFQLEVBQW1CTSxJQUFuQixDQUF3QixVQUFDQyxTQUFELEVBQWU7QUFDbkM1Qiw4QkFBa0J0QyxRQUFRbUQsT0FBUixDQUFnQmUsU0FBaEIsRUFBMkI7QUFDekN6RCw4QkFBYyxzQkFBVU4sT0FBVixFQUFtQmdFLE1BQW5CLEVBQTJCO0FBQ3JDLDJCQUFPbkUsUUFBUW9FLE1BQVIsQ0FBZUQsTUFBZixFQUF1QjtBQUMxQm5DLDhCQUFNRCxZQURvQjtBQUUxQnNDLHVDQUFlbEUsUUFBUUcsVUFBUixDQUFtQmdFO0FBRlIscUJBQXZCLENBQVA7QUFJSDtBQU53QyxhQUEzQixDQUFsQjs7QUFTQWhDLDRCQUFnQk0sS0FBaEIsQ0FBc0JSLEdBQXRCO0FBQ0gsU0FYRDtBQVlILEtBcEJEOztBQXNCQW1DLGdCQUFZZixVQUFaLEVBQXdCLEtBQXhCO0FBQ0gsQ0EzSEQiLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvbWFwcy9yb3V0ZV9tYXAuanMuanMiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBsZWFmbGV0ID0gcmVxdWlyZSgnbGVhZmxldCcpO1xuXG5pbXBvcnQgZHJhd19iYXNlX21hcCBmcm9tICcuL2Jhc2VfbWFwJ1xuaW1wb3J0IHthZGRXTVNMYXllcn0gZnJvbSAnLi9oZWxwZXJzJztcblxuaW1wb3J0IHtBQ1RVQUxfUk9VVEVfQ09MT1IsIENJUkNMRV9DT0xPUiwgUExBTl9ST1VURV9DT0xPUn0gZnJvbSAnLi9jb25maWcnXG5cbi8qKlxuICogU2hvdyBzb21lIHBvcHVwIHRleHQgd2hlbiBhIGZlYXR1cmUgaXMgY2xpY2tlZCBvblxuICogQHBhcmFtIGZlYXR1cmVcbiAqIEBwYXJhbSBsYXllclxuICovXG5leHBvcnQgY29uc3Qgb25GZWF0dXJlUG9pbnRDbGljayA9IChmZWF0dXJlLCBsYXllcikgPT4ge1xuICAgIGxldCBwb3B1cF9odG1sID0gJyc7XG4gICAgaWYgKGZlYXR1cmUucHJvcGVydGllcyAmJiBmZWF0dXJlLnByb3BlcnRpZXMucG9wdXApIHtcbiAgICAgICAgcG9wdXBfaHRtbCArPSBmZWF0dXJlLnByb3BlcnRpZXMucG9wdXBcbiAgICB9XG5cbiAgICBsYXllci5iaW5kUG9wdXAocG9wdXBfaHRtbClcbn07XG5cbi8qKlxuICogU2hvdyBlYWNoIHBvaW50IGFzIGEgbWFya2VyXG4gKiBAcGFyYW0gZmVhdHVyZVxuICogQHBhcmFtIGxhdGxuZ1xuICogQHJldHVybnMgeyp9XG4gKi9cbmV4cG9ydCBjb25zdCBwb2ludFRvTGF5ZXIgPSAoZmVhdHVyZSwgbGF0bG5nKSA9PiB7XG4gICAgcmV0dXJuIGxlYWZsZXQuY2lyY2xlTWFya2VyKGxhdGxuZywge1xuICAgICAgICByYWRpdXM6IDUsXG4gICAgICAgIGZpbGxDb2xvcjogQ0lSQ0xFX0NPTE9SLFxuICAgICAgICBjb2xvcjogJyMwMDAnLFxuICAgICAgICB3ZWlnaHQ6IDEsXG4gICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgIGZpbGxPcGFjaXR5OiAwLjhcbiAgICB9KVxufVxuXG4vKipcbiAqXG4gKiBAcGFyYW0gb3B0c1xuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGRlZmF1bHQgKG9wdHMpID0+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");
/***/ })
/******/ });