/* onsenui v2.10.10 - 2019-07-29 */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.ons = factory()); }(this, (function () { 'use strict'; var onsElements = {}; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Add vendor prefix. * * @param {String} name * @return {String} */ var prefix = function () { var styles = window.getComputedStyle(document.documentElement, ''); var prefix = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1]; return function (name) { return '-' + prefix + '-' + util$1.hyphenate(name); }; }(); /** * Minimal utility library for manipulating element's style. * Set element's style. * * @param {Element} element * @param {Object} styles * @return {Element} */ var styler = function styler(element, style) { Object.keys(style).forEach(function (key) { if (key in element.style) { element.style[key] = style[key]; } else if (prefix(key) in element.style) { element.style[prefix(key)] = style[key]; } else { util$1.warn('No such style property: ' + key); } }); return element; }; /** * @param {Element} element * @param {String} styles Space-separated CSS properties to remove */ styler.clear = function (element) { var styles = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var clearlist = styles.split(/\s+/).reduce(function (r, s) { return r.concat([util$1.hyphenate(s), prefix(s)]); }, []), keys = []; var _loop = function _loop(i) { var key = element.style[i]; if (clearlist.length === 0 || clearlist.some(function (s) { return key.indexOf(s) === 0; })) { keys.push(key); // Store the key to fix Safari style indexes } }; for (var i = element.style.length - 1; i >= 0; i--) { _loop(i); } keys.forEach(function (key) { return element.style[key] = ''; }); element.getAttribute('style') === '' && element.removeAttribute('style'); }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var objectWithoutProperties = function (obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Save HTMLElement object before Custom Elements polyfill patch global HTMLElement. var NativeHTMLElement = window.HTMLElement; /** * @object ons.platform * @category util * @description * [en]Utility methods to detect current platform.[/en] * [ja]現在実行されているプラットフォームを検知するためのユーティリティメソッドを収めたオブジェクトです。[/ja] */ var Platform = function () { /** * All elements will be rendered as if the app was running on this platform. * @type {String} */ function Platform() { classCallCheck(this, Platform); this._selectedPlatform = null; this._ignorePlatformSelect = false; } /** * @method select * @signature select(platform) * @param {string} platform Name of the platform. * [en]Possible values are: "opera", "firefox", "safari", "chrome", "ie", "android", "blackberry", "ios" or "wp".[/en] * [ja]"opera", "firefox", "safari", "chrome", "ie", "android", "blackberry", "ios", "wp"のいずれかを指定します。[/ja] * @description * [en]Sets the platform used to render the elements. Useful for testing.[/en] * [ja]要素を描画するために利用するプラットフォーム名を設定します。テストに便利です。[/ja] */ createClass(Platform, [{ key: 'select', value: function select(platform) { if (typeof platform === 'string') { this._selectedPlatform = platform.trim().toLowerCase(); } } }, { key: '_getSelectedPlatform', value: function _getSelectedPlatform() { return this._ignorePlatformSelect ? null : this._selectedPlatform; } }, { key: '_runOnActualPlatform', value: function _runOnActualPlatform(fn) { this._ignorePlatformSelect = true; var result = fn(); this._ignorePlatformSelect = false; return result; } //---------------- // General //---------------- /** * @method isWebView * @signature isWebView() * @description * [en]Returns whether app is running in Cordova.[/en] * [ja]Cordova内で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isWebView', value: function isWebView() { if (document.readyState === 'loading' || document.readyState == 'uninitialized') { throw new Error('isWebView() method is available after dom contents loaded.'); } return !!(window.cordova || window.phonegap || window.PhoneGap); } //---------------- // iOS devices //---------------- /** * @method isIPhone * @signature isIPhone() * @description * [en]Returns whether the device is iPhone.[/en] * [ja]iPhone上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIPhone', value: function isIPhone() { return (/iPhone/i.test(navigator.userAgent) ); } /** * @method isIPhoneX * @signature isIPhoneX() * @description * [en]Returns whether the device is iPhone X, XS, XS Max, or XR.[/en] * [ja]iPhone X や XS、XS Max、または XR 上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIPhoneX', value: function isIPhoneX() { // iOS WebViews on the same iOS version have the same user agent. // We cannot avoid using window.screen. // We also cannot use cordova-plugin-device since its behavior is different between simulators and real devices. // This works well both in iOS Safari and (UI|WK)WebView of iPhone X. return this.isIPhone() && (window.screen.width === 375 && window.screen.height === 812 || // X, XS portrait window.screen.width === 812 && window.screen.height === 375 || // X, XS landscape window.screen.width === 414 && window.screen.height === 896 || // XS Max, XR portrait window.screen.width === 896 && window.screen.height === 414); // XS Max, XR landscape } /** * @method isIPad * @signature isIPad() * @description * [en]Returns whether the device is iPad.[/en] * [ja]iPad上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIPad', value: function isIPad() { return (/iPad/i.test(navigator.userAgent) ); } /** * @return {Boolean} */ }, { key: 'isIPod', value: function isIPod() { return (/iPod/i.test(navigator.userAgent) ); } //---------------- // iOS versions //---------------- /** * @method isIOS * @signature isIOS([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the OS is iOS. By default will return manually selected platform if it is set.[/en] * [ja]iOS上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIOS', value: function isIOS(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'ios'; } if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) { return (/iOS/i.test(device.platform) ); } else { return (/iPhone|iPad|iPod/i.test(navigator.userAgent) ); } } /** * @method isIOS7above * @signature isIOS7above() * @description * [en]Returns whether the iOS version is 7 or above.[/en] * [ja]iOS7以上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIOS7above', value: function isIOS7above() { if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) { return (/iOS/i.test(device.platform) && parseInt(device.version.split('.')[0]) >= 7 ); } else if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) { var ver = (navigator.userAgent.match(/\b[0-9]+_[0-9]+(?:_[0-9]+)?\b/) || [''])[0].replace(/_/g, '.'); return parseInt(ver.split('.')[0]) >= 7; } return false; } //---------------- // iOS browsers //---------------- /** * @method isIOSSafari * @signature isIOSSafari() * @description * [en]Returns whether app is running in iOS Safari.[/en] * [ja]iOS Safariで実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIOSSafari', value: function isIOSSafari() { var navigator = window.navigator; var ua = navigator.userAgent; return !!(this.isIOS() && ua.indexOf('Safari') !== -1 && ua.indexOf('Version') !== -1 && !navigator.standalone); } /** * @method isWKWebView * @signature isWKWebView() * @description * [en]Returns whether app is running in WKWebView.[/en] * [ja]WKWebViewで実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isWKWebView', value: function isWKWebView() { var lte9 = /constructor/i.test(NativeHTMLElement); return !!(this.isIOS() && window.webkit && window.webkit.messageHandlers && window.indexedDB && !lte9); } /** * @method isUIWebView * @signature isUIWebView() * @description * [en]Returns whether app is running in UIWebView.[/en] * [ja]UIWebViewで実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isUIWebView', value: function isUIWebView() { return !!(this.isIOS() && !this.isIOSSafari() && !this.isWKWebView()); } //---------------- // Android devices //---------------- /** * @method isAndroidPhone * @signature isAndroidPhone() * @description * [en]Returns whether the device is Android phone.[/en] * [ja]Android携帯上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isAndroidPhone', value: function isAndroidPhone() { return (/Android/i.test(navigator.userAgent) && /Mobile/i.test(navigator.userAgent) ); } /** * @method isAndroidTablet * @signature isAndroidTablet() * @description * [en]Returns whether the device is Android tablet.[/en] * [ja]Androidタブレット上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isAndroidTablet', value: function isAndroidTablet() { return (/Android/i.test(navigator.userAgent) && !/Mobile/i.test(navigator.userAgent) ); } //---------------- // Android versions //---------------- /** * @method isAndroid * @signature isAndroid([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the OS is Android. By default will return manually selected platform if it is set.[/en] * [ja]Android上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isAndroid', value: function isAndroid(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'android'; } if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) { return (/Android/i.test(device.platform) ); } else { return (/Android/i.test(navigator.userAgent) ); } } //---------------- // Other devices //---------------- /** * @method isWP * @signature isWP([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the OS is Windows phone. By default will return manually selected platform if it is set.[/en] * [ja][/ja] * @return {Boolean} */ }, { key: 'isWP', value: function isWP(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'wp'; } if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) { return (/Win32NT|WinCE/i.test(device.platform) ); } else { return (/Windows Phone|IEMobile|WPDesktop/i.test(navigator.userAgent) ); } } /** * @method isBlackBerry * @signature isBlackBerry([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the device is BlackBerry. By default will return manually selected platform if it is set.[/en] * [ja]BlackBerry上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isBlackBerry', value: function isBlackBerry(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'blackberry'; } if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) { return (/BlackBerry/i.test(device.platform) ); } else { return (/BlackBerry|RIM Tablet OS|BB10/i.test(navigator.userAgent) ); } } //---------------- // Other browsers //---------------- /** * @method isOpera * @signature isOpera([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Opera. By default will return manually selected platform if it is set.[/en] * [ja]Opera上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isOpera', value: function isOpera(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'opera'; } return !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; } /** * @method isFirefox * @signature isFirefox([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Firefox. By default will return manually selected platform if it is set.[/en] * [ja]Firefox上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isFirefox', value: function isFirefox(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'firefox'; } return typeof InstallTrigger !== 'undefined'; } /** * @method isSafari * @signature isSafari([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Safari. By default will return manually selected platform if it is set.[/en] * [ja]Safari上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isSafari', value: function isSafari(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'safari'; } return Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 || function (p) { return p.toString() === '[object SafariRemoteNotification]'; }(!window['safari'] || safari.pushNotification); } /** * @method isChrome * @signature isChrome([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Chrome. By default will return manually selected platform if it is set.[/en] * [ja]Chrome上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isChrome', value: function isChrome(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'chrome'; } return !!window.chrome && !(!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) && !(navigator.userAgent.indexOf(' Edge/') >= 0); } /** * @method isIE * @signature isIE([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Internet Explorer. By default will return manually selected platform if it is set.[/en] * [ja]Internet Explorer上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIE', value: function isIE(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'ie'; } return false || !!document.documentMode; } /** * @method isEdge * @signature isEdge([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Edge. By default will return manually selected platform if it is set.[/en] * [ja]Edge上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isEdge', value: function isEdge(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'edge'; } return navigator.userAgent.indexOf(' Edge/') >= 0; } //---------------- // Utility functions //---------------- /** * @return {String} */ }, { key: 'getMobileOS', value: function getMobileOS() { if (this.isAndroid()) { return 'android'; } else if (this.isIOS()) { return 'ios'; } else if (this.isWP()) { return 'wp'; } else { return 'other'; } } /** * @return {String} */ }, { key: 'getIOSDevice', value: function getIOSDevice() { if (this.isIPhone()) { return 'iphone'; } else if (this.isIPad()) { return 'ipad'; } else if (this.isIPod()) { return 'ipod'; } else { return 'na'; } } }]); return Platform; }(); var platform = new Platform(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var error = function error(message) { return util$1.throw('In PageAttributeExpression: ' + message); }; var pageAttributeExpression = { _variables: {}, /** * Define a variable. * * @param {String} name Name of the variable * @param {String|Function} value Value of the variable. Can be a string or a function. The function must return a string. * @param {Boolean} overwrite If this value is false, an error will be thrown when trying to define a variable that has already been defined. */ defineVariable: function defineVariable(name, value) { var overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (typeof name !== 'string') { error('Variable name must be a string'); } else if (typeof value !== 'string' && typeof value !== 'function') { error('Variable value must be a string or a function'); } else if (this._variables.hasOwnProperty(name) && !overwrite) { error('"' + name + '" is already defined'); } this._variables[name] = value; }, /** * Get a variable. * * @param {String} name Name of the variable. * @return {String|Function|null} */ getVariable: function getVariable(name) { if (!this._variables.hasOwnProperty(name)) { return null; } return this._variables[name]; }, /** * Remove a variable. * * @param {String} name Name of the varaible. */ removeVariable: function removeVariable(name) { delete this._variables[name]; }, /** * Get all variables. * * @return {Object} */ getAllVariables: function getAllVariables() { return this._variables; }, _parsePart: function _parsePart(part) { var c = void 0, inInterpolation = false, currentIndex = 0; var tokens = []; if (part.length === 0) { error('Unable to parse empty string'); } for (var i = 0; i < part.length; i++) { c = part.charAt(i); if (c === '$' && part.charAt(i + 1) === '{') { if (inInterpolation) { error('Nested interpolation not supported'); } var token = part.substring(currentIndex, i); if (token.length > 0) { tokens.push(part.substring(currentIndex, i)); } currentIndex = i; inInterpolation = true; } else if (c === '}') { if (!inInterpolation) { error('} must be preceeded by ${'); } var _token = part.substring(currentIndex, i + 1); if (_token.length > 0) { tokens.push(part.substring(currentIndex, i + 1)); } currentIndex = i + 1; inInterpolation = false; } } if (inInterpolation) { error('Unterminated interpolation'); } tokens.push(part.substring(currentIndex, part.length)); return tokens; }, _replaceToken: function _replaceToken(token) { var re = /^\${(.*?)}$/, match = token.match(re); if (match) { var name = match[1].trim(); var variable = this.getVariable(name); if (variable === null) { error('Variable "' + name + '" does not exist'); } else if (typeof variable === 'string') { return variable; } else { var rv = variable(); if (typeof rv !== 'string') { error('Must return a string'); } return rv; } } else { return token; } }, _replaceTokens: function _replaceTokens(tokens) { return tokens.map(this._replaceToken.bind(this)); }, _parseExpression: function _parseExpression(expression) { return expression.split(',').map(function (part) { return part.trim(); }).map(this._parsePart.bind(this)).map(this._replaceTokens.bind(this)).map(function (part) { return part.join(''); }); }, /** * Evaluate an expression. * * @param {String} expression An page attribute expression. * @return {Array} */ evaluate: function evaluate(expression) { if (!expression) { return []; } return this._parseExpression(expression); } }; // Define default variables. pageAttributeExpression.defineVariable('mobileOS', platform.getMobileOS()); pageAttributeExpression.defineVariable('iOSDevice', platform.getIOSDevice()); pageAttributeExpression.defineVariable('runtime', function () { return platform.isWebView() ? 'cordova' : 'browser'; }); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var internal$1 = {}; internal$1.config = { autoStatusBarFill: true, animationsDisabled: false, warningsDisabled: false }; internal$1.nullElement = window.document.createElement('div'); /** * @return {Boolean} */ internal$1.isEnabledAutoStatusBarFill = function () { return !!internal$1.config.autoStatusBarFill; }; /** * @param {String} html * @return {String} */ internal$1.normalizePageHTML = function (html) { return ('' + html).trim(); }; internal$1.waitDOMContentLoaded = function (callback) { if (window.document.readyState === 'loading' || window.document.readyState == 'uninitialized') { var wrappedCallback = function wrappedCallback() { callback(); window.document.removeEventListener('DOMContentLoaded', wrappedCallback); }; window.document.addEventListener('DOMContentLoaded', wrappedCallback); } else { setImmediate(callback); } }; internal$1.autoStatusBarFill = function (action) { var onReady = function onReady() { if (internal$1.shouldFillStatusBar()) { action(); } document.removeEventListener('deviceready', onReady); }; if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object') { document.addEventListener('deviceready', onReady); } else if (['complete', 'interactive'].indexOf(document.readyState) === -1) { internal$1.waitDOMContentLoaded(onReady); } else { onReady(); } }; internal$1.shouldFillStatusBar = function () { return internal$1.isEnabledAutoStatusBarFill() && (platform.isWebView() && platform.isIOS7above() && !platform.isIPhoneX() || document.body.querySelector('.ons-status-bar-mock.ios')); }; internal$1.templateStore = { _storage: {}, /** * @param {String} key * @return {String/null} template */ get: function get$$1(key) { return internal$1.templateStore._storage[key] || null; }, /** * @param {String} key * @param {String} template */ set: function set$$1(key, template) { internal$1.templateStore._storage[key] = template; } }; window.document.addEventListener('_templateloaded', function (e) { if (e.target.nodeName.toLowerCase() === 'ons-template') { internal$1.templateStore.set(e.templateId, e.template); } }, false); internal$1.waitDOMContentLoaded(function () { register('script[type="text/ons-template"]'); register('script[type="text/template"]'); register('script[type="text/ng-template"]'); register('template'); function register(query) { var templates = window.document.querySelectorAll(query); for (var i = 0; i < templates.length; i++) { internal$1.templateStore.set(templates[i].getAttribute('id'), templates[i].textContent || templates[i].content); } } }); /** * @param {String} page * @return {Promise} */ internal$1.getTemplateHTMLAsync = function (page) { return new Promise(function (resolve, reject) { internal$1.waitDOMContentLoaded(function () { var cache = internal$1.templateStore.get(page); if (cache) { if (cache instanceof DocumentFragment) { return resolve(cache); } var html = typeof cache === 'string' ? cache : cache[1]; return resolve(internal$1.normalizePageHTML(html)); } var local = window.document.getElementById(page); if (local) { var _html = local.textContent || local.content; return resolve(_html); } var xhr = new XMLHttpRequest(); xhr.open('GET', page, true); xhr.onload = function () { var html = xhr.responseText; if (xhr.status >= 400 && xhr.status < 600) { reject(html); } else { // Refresh script tags var fragment = util$1.createFragment(html); util$1.arrayFrom(fragment.querySelectorAll('script')).forEach(function (el) { var script = document.createElement('script'); script.type = el.type || 'text/javascript'; script.appendChild(document.createTextNode(el.text || el.textContent || el.innerHTML)); el.parentNode.replaceChild(script, el); }); internal$1.templateStore.set(page, fragment); resolve(fragment); } }; xhr.onerror = function () { util$1.throw('Page template not found: ' + page); }; xhr.send(null); }); }); }; /** * @param {String} page * @return {Promise} */ internal$1.getPageHTMLAsync = function (page) { var pages = pageAttributeExpression.evaluate(page); var getPage = function getPage(page) { if (typeof page !== 'string') { return Promise.reject('Must specify a page.'); } return internal$1.getTemplateHTMLAsync(page).catch(function (error) { if (pages.length === 0) { return Promise.reject(error); } return getPage(pages.shift()); }); }; return getPage(pages.shift()); }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var AnimatorFactory = function () { /** * @param {Object} opts * @param {Object} opts.animators The dictionary for animator classes * @param {Function} opts.baseClass The base class of animators * @param {String} [opts.baseClassName] The name of the base class of animators * @param {String} [opts.defaultAnimation] The default animation name * @param {Object} [opts.defaultAnimationOptions] The default animation options */ function AnimatorFactory(opts) { classCallCheck(this, AnimatorFactory); this._animators = opts.animators; this._baseClass = opts.baseClass; this._baseClassName = opts.baseClassName || opts.baseClass.name; this._animation = opts.defaultAnimation || 'default'; this._animationOptions = opts.defaultAnimationOptions || {}; if (!this._animators[this._animation]) { util$1.throw('No such animation: ' + this._animation); } } /** * @param {String} jsonString * @return {Object/null} */ createClass(AnimatorFactory, [{ key: 'setAnimationOptions', /** * @param {Object} options */ value: function setAnimationOptions(options) { this._animationOptions = options; } /** * @param {Object} options * @param {String} [options.animation] The animation name * @param {Object} [options.animationOptions] The animation options * @param {Object} defaultAnimator The default animator instance * @return {Object} An animator instance */ }, { key: 'newAnimator', value: function newAnimator() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var defaultAnimator = arguments[1]; var animator = null; if (options.animation instanceof this._baseClass) { return options.animation; } var Animator = null; if (typeof options.animation === 'string') { Animator = this._animators[options.animation]; } if (!Animator && defaultAnimator) { animator = defaultAnimator; } else { Animator = Animator || this._animators[this._animation]; var animationOpts = util$1.extend({}, this._animationOptions, options.animationOptions || {}, internal$1.config.animationsDisabled ? { duration: 0, delay: 0 } : {}); animator = new Animator(animationOpts); if (typeof animator === 'function') { animator = new animator(animationOpts); // eslint-disable-line new-cap } } if (!(animator instanceof this._baseClass)) { util$1.throw('"animator" is not an instance of ' + this._baseClassName); } return animator; } }], [{ key: 'parseAnimationOptionsString', value: function parseAnimationOptionsString(jsonString) { try { if (typeof jsonString === 'string') { var result = util$1.animationOptionsParse(jsonString); if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && result !== null) { return result; } else { console.error('"animation-options" attribute must be a JSON object string: ' + jsonString); } } return {}; } catch (e) { console.error('"animation-options" attribute must be a JSON object string: ' + jsonString); return {}; } } }]); return AnimatorFactory; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var autoStyleEnabled = true; // Modifiers var modifiersMap = { 'quiet': 'material--flat', 'light': 'material--flat', 'outline': 'material--flat', 'cta': '', 'large--quiet': 'material--flat large', 'large--cta': 'large', 'noborder': '', 'tappable': '' }; var platforms = {}; platforms.android = function (element) { var elementName = element.tagName.toLowerCase(); if (!util$1.hasModifier(element, 'material')) { var oldModifier = element.getAttribute('modifier') || ''; var newModifier = oldModifier.trim().split(/\s+/).map(function (e) { return modifiersMap.hasOwnProperty(e) ? modifiersMap[e] : e; }); newModifier.unshift('material'); element.setAttribute('modifier', newModifier.join(' ').trim()); } var elements = ['ons-alert-dialog-button', 'ons-toolbar-button', 'ons-back-button', 'ons-button', 'ons-list-item', 'ons-fab', 'ons-speed-dial', 'ons-speed-dial-item', 'ons-tab']; // Effects if (elements.indexOf(elementName) !== -1 && !element.hasAttribute('ripple') && !element.querySelector('ons-ripple')) { if (elementName === 'ons-list-item') { if (element.hasAttribute('tappable')) { element.setAttribute('ripple', ''); element.removeAttribute('tappable'); } } else { element.setAttribute('ripple', ''); } } }; platforms.ios = function (element) { // Modifiers if (util$1.removeModifier(element, 'material')) { if (util$1.removeModifier(element, 'material--flat')) { util$1.addModifier(element, util$1.removeModifier(element, 'large') ? 'large--quiet' : 'quiet'); } if (!element.getAttribute('modifier')) { element.removeAttribute('modifier'); } } // Effects if (element.hasAttribute('ripple')) { if (element.tagName.toLowerCase() === 'ons-list-item') { element.setAttribute('tappable', ''); } element.removeAttribute('ripple'); } }; var unlocked = { android: true }; var getPlatform = function getPlatform(element, force) { if (autoStyleEnabled && !element.hasAttribute('disable-auto-styling')) { var mobileOS = platform.getMobileOS(); if (platforms.hasOwnProperty(mobileOS) && (unlocked.hasOwnProperty(mobileOS) || force)) { return mobileOS; } } return null; }; var prepare = function prepare(element, force) { var p = getPlatform(element, force); p && platforms[p](element); }; var mapModifier = function mapModifier(modifier, element, force) { if (getPlatform(element, force)) { return modifier.split(/\s+/).map(function (m) { return modifiersMap.hasOwnProperty(m) ? modifiersMap[m] : m; }).join(' '); } return modifier; }; var restoreModifier = function restoreModifier(element) { if (getPlatform(element) === 'android') { var modifier = element.getAttribute('modifier') || ''; var newModifier = mapModifier(modifier, element); if (!/(^|\s+)material($|\s+)/i.test(modifier)) { newModifier = 'material ' + newModifier; } if (newModifier !== modifier) { element.setAttribute('modifier', newModifier.trim()); return true; } } return false; }; var autoStyle = { isEnabled: function isEnabled() { return autoStyleEnabled; }, enable: function enable() { return autoStyleEnabled = true; }, disable: function disable() { return autoStyleEnabled = false; }, prepare: prepare, mapModifier: mapModifier, getPlatform: getPlatform, restoreModifier: restoreModifier }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var ModifierUtil = function () { function ModifierUtil() { classCallCheck(this, ModifierUtil); } createClass(ModifierUtil, null, [{ key: 'diff', /** * @param {String} last * @param {String} current */ value: function diff(last, current) { last = makeDict(('' + last).trim()); current = makeDict(('' + current).trim()); var removed = Object.keys(last).reduce(function (result, token) { if (!current[token]) { result.push(token); } return result; }, []); var added = Object.keys(current).reduce(function (result, token) { if (!last[token]) { result.push(token); } return result; }, []); return { added: added, removed: removed }; function makeDict(modifier) { var dict = {}; ModifierUtil.split(modifier).forEach(function (token) { return dict[token] = token; }); return dict; } } /** * @param {Object} diff * @param {Array} diff.removed * @param {Array} diff.added * @param {Object} classList * @param {String} template */ }, { key: 'applyDiffToClassList', value: function applyDiffToClassList(diff, classList, template) { diff.added.map(function (modifier) { return template.replace(/\*/g, modifier); }).forEach(function (klass) { return klass.split(/\s+/).forEach(function (k) { return classList.add(k); }); }); diff.removed.map(function (modifier) { return template.replace(/\*/g, modifier); }).forEach(function (klass) { return klass.split(/\s+/).forEach(function (k) { return classList.remove(k); }); }); } /** * @param {Object} diff * @param {Array} diff.removed * @param {Array} diff.added * @param {HTMLElement} element * @param {Object} scheme */ }, { key: 'applyDiffToElement', value: function applyDiffToElement(diff, element, scheme) { Object.keys(scheme).forEach(function (selector) { var targetElements = !selector || util$1.match(element, selector) ? [element] : Array.prototype.filter.call(element.querySelectorAll(selector), function (targetElement) { return !util$1.findParent(targetElement, element.tagName, function (parent) { return parent === element; }); }); for (var i = 0; i < targetElements.length; i++) { ModifierUtil.applyDiffToClassList(diff, targetElements[i].classList, scheme[selector]); } }); } /** * @param {String} last * @param {String} current * @param {HTMLElement} element * @param {Object} scheme */ }, { key: 'onModifierChanged', value: function onModifierChanged(last, current, element, scheme) { ModifierUtil.applyDiffToElement(ModifierUtil.diff(last, current), element, scheme); autoStyle.restoreModifier(element); } }, { key: 'refresh', value: function refresh(element, scheme) { ModifierUtil.applyDiffToElement(ModifierUtil.diff('', element.getAttribute('modifier') || ''), element, scheme); } /** * @param {HTMLElement} element * @param {Object} scheme */ }, { key: 'initModifier', value: function initModifier(element, scheme) { var modifier = element.getAttribute('modifier'); if (typeof modifier !== 'string') { return; } ModifierUtil.applyDiffToElement({ removed: [], added: ModifierUtil.split(modifier) }, element, scheme); } }, { key: 'split', value: function split(modifier) { if (typeof modifier !== 'string') { return []; } return modifier.trim().split(/ +/).filter(function (token) { return token !== ''; }); } /** * Add modifier token to an element. */ }, { key: 'addModifier', value: function addModifier(element, modifierToken) { if (!element.hasAttribute('modifier')) { element.setAttribute('modifier', modifierToken); } else { var tokens = ModifierUtil.split(element.getAttribute('modifier')); if (tokens.indexOf(modifierToken) == -1) { tokens.push(modifierToken); element.setAttribute('modifier', tokens.join(' ')); } } } /** * Remove modifier token from an element. */ }, { key: 'removeModifier', value: function removeModifier(element, modifierToken) { if (element.hasAttribute('modifier')) { var tokens = ModifierUtil.split(element.getAttribute('modifier')); var index = tokens.indexOf(modifierToken); if (index !== -1) { tokens.splice(index, 1); element.setAttribute('modifier', tokens.join(' ')); } } } }]); return ModifierUtil; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var util$3 = { _ready: false, _domContentLoaded: false, _onDOMContentLoaded: function _onDOMContentLoaded() { util$3._domContentLoaded = true; if (platform.isWebView()) { window.document.addEventListener('deviceready', function () { util$3._ready = true; }, false); } else { util$3._ready = true; } }, addBackButtonListener: function addBackButtonListener(fn) { if (!this._domContentLoaded) { throw new Error('This method is available after DOMContentLoaded'); } if (this._ready) { window.document.addEventListener('backbutton', fn, false); } else { window.document.addEventListener('deviceready', function () { window.document.addEventListener('backbutton', fn, false); }); } }, removeBackButtonListener: function removeBackButtonListener(fn) { if (!this._domContentLoaded) { throw new Error('This method is available after DOMContentLoaded'); } if (this._ready) { window.document.removeEventListener('backbutton', fn, false); } else { window.document.addEventListener('deviceready', function () { window.document.removeEventListener('backbutton', fn, false); }); } } }; window.addEventListener('DOMContentLoaded', function () { return util$3._onDOMContentLoaded(); }, false); var HandlerRepository = { _store: {}, _genId: function () { var i = 0; return function () { return i++; }; }(), set: function set$$1(element, handler) { if (element.dataset.deviceBackButtonHandlerId) { this.remove(element); } var id = element.dataset.deviceBackButtonHandlerId = HandlerRepository._genId(); this._store[id] = handler; }, remove: function remove(element) { if (element.dataset.deviceBackButtonHandlerId) { delete this._store[element.dataset.deviceBackButtonHandlerId]; delete element.dataset.deviceBackButtonHandlerId; } }, get: function get$$1(element) { if (!element.dataset.deviceBackButtonHandlerId) { return undefined; } var id = element.dataset.deviceBackButtonHandlerId; if (!this._store[id]) { throw new Error(); } return this._store[id]; }, has: function has(element) { if (!element.dataset) { return false; } var id = element.dataset.deviceBackButtonHandlerId; return !!this._store[id]; } }; var DeviceBackButtonDispatcher = function () { function DeviceBackButtonDispatcher() { classCallCheck(this, DeviceBackButtonDispatcher); this._isEnabled = false; this._boundCallback = this._callback.bind(this); } /** * Enable to handle 'backbutton' events. */ createClass(DeviceBackButtonDispatcher, [{ key: 'enable', value: function enable() { if (!this._isEnabled) { util$3.addBackButtonListener(this._boundCallback); this._isEnabled = true; } } /** * Disable to handle 'backbutton' events. */ }, { key: 'disable', value: function disable() { if (this._isEnabled) { util$3.removeBackButtonListener(this._boundCallback); this._isEnabled = false; } } /** * Fire a 'backbutton' event manually. */ }, { key: 'fireDeviceBackButtonEvent', value: function fireDeviceBackButtonEvent() { var event = document.createEvent('Event'); event.initEvent('backbutton', true, true); document.dispatchEvent(event); } }, { key: '_callback', value: function _callback() { this._dispatchDeviceBackButtonEvent(); } /** * @param {HTMLElement} element * @param {Function} callback */ }, { key: 'createHandler', value: function createHandler(element, callback) { if (!(element instanceof HTMLElement)) { throw new Error('element must be an instance of HTMLElement'); } if (!(callback instanceof Function)) { throw new Error('callback must be an instance of Function'); } var handler = { _callback: callback, _element: element, disable: function disable() { HandlerRepository.remove(element); }, setListener: function setListener(callback) { this._callback = callback; }, enable: function enable() { HandlerRepository.set(element, this); }, isEnabled: function isEnabled() { return HandlerRepository.get(element) === this; }, destroy: function destroy() { HandlerRepository.remove(element); this._callback = this._element = null; } }; handler.enable(); return handler; } }, { key: '_dispatchDeviceBackButtonEvent', value: function _dispatchDeviceBackButtonEvent() { var tree = this._captureTree(); var element = this._findHandlerLeafElement(tree); var handler = HandlerRepository.get(element); handler._callback(createEvent(element)); function createEvent(element) { return { _element: element, callParentHandler: function callParentHandler() { var parent = this._element.parentNode; while (parent) { handler = HandlerRepository.get(parent); if (handler) { return handler._callback(createEvent(parent)); } parent = parent.parentNode; } } }; } } /** * @return {Object} */ }, { key: '_captureTree', value: function _captureTree() { return createTree(document.body); function createTree(element) { var tree = { element: element, children: Array.prototype.concat.apply([], arrayOf(element.children).map(function (childElement) { if (childElement.style.display === 'none' || childElement._isShown === false) { return []; } if (childElement.children.length === 0 && !HandlerRepository.has(childElement)) { return []; } var result = createTree(childElement); if (result.children.length === 0 && !HandlerRepository.has(result.element)) { return []; } return [result]; })) }; if (!HandlerRepository.has(tree.element)) { for (var i = 0; i < tree.children.length; i++) { var subTree = tree.children[i]; if (HandlerRepository.has(subTree.element)) { return subTree; } } } return tree; } function arrayOf(target) { var result = []; for (var i = 0; i < target.length; i++) { result.push(target[i]); } return result; } } /** * @param {Object} tree * @return {HTMLElement} */ }, { key: '_findHandlerLeafElement', value: function _findHandlerLeafElement(tree) { return find(tree); function find(node) { if (node.children.length === 0) { return node.element; } if (node.children.length === 1) { return find(node.children[0]); } return node.children.map(function (childNode) { return childNode.element; }).reduce(function (left, right) { if (!left) { return right; } var leftZ = parseInt(window.getComputedStyle(left, '').zIndex, 10); var rightZ = parseInt(window.getComputedStyle(right, '').zIndex, 10); if (!isNaN(leftZ) && !isNaN(rightZ)) { return leftZ > rightZ ? left : right; } throw new Error('Capturing backbutton-handler is failure.'); }, null); } } }]); return DeviceBackButtonDispatcher; }(); var deviceBackButtonDispatcher = new DeviceBackButtonDispatcher(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ internal$1.AnimatorFactory = AnimatorFactory; internal$1.ModifierUtil = ModifierUtil; internal$1.dbbDispatcher = deviceBackButtonDispatcher; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var startsWith = function startsWith(s, c) { return s.substr(0, c.length) === c; }; var endsWith = function endsWith(s, c) { return s.substr(s.length - c.length, c.length) === c; }; var unwrap = function unwrap(s) { return s.slice(1, -1); }; var isObjectString = function isObjectString(s) { return startsWith(s, '{') && endsWith(s, '}'); }; var isArrayString = function isArrayString(s) { return startsWith(s, '[') && endsWith(s, ']'); }; var isQuotedString = function isQuotedString(s) { return startsWith(s, '\'') && endsWith(s, '\'') || startsWith(s, '"') && endsWith(s, '"'); }; var error$1 = function error(token, string, originalString) { throw new Error('Unexpected token \'' + token + '\' at position ' + (originalString.length - string.length - 1) + ' in string: \'' + originalString + '\''); }; var processToken = function processToken(token, string, originalString) { if (token === 'true' || token === 'false') { return token === 'true'; } else if (isQuotedString(token)) { return unwrap(token); } else if (!isNaN(token)) { return +token; } else if (isObjectString(token)) { return parseObject(unwrap(token)); } else if (isArrayString(token)) { return parseArray(unwrap(token)); } else { error$1(token, string, originalString); } }; var nextToken = function nextToken(string) { string = string.trim(); var limit = string.length; if (string[0] === ':' || string[0] === ',') { limit = 1; } else if (string[0] === '{' || string[0] === '[') { var c = string.charCodeAt(0); var nestedObject = 1; for (var i = 1; i < string.length; i++) { if (string.charCodeAt(i) === c) { nestedObject++; } else if (string.charCodeAt(i) === c + 2) { nestedObject--; if (nestedObject === 0) { limit = i + 1; break; } } } } else if (string[0] === '\'' || string[0] === '"') { for (var _i = 1; _i < string.length; _i++) { if (string[_i] === string[0]) { limit = _i + 1; break; } } } else { for (var _i2 = 1; _i2 < string.length; _i2++) { if ([' ', ',', ':'].indexOf(string[_i2]) !== -1) { limit = _i2; break; } } } return string.slice(0, limit); }; var parseObject = function parseObject(string) { var isValidKey = function isValidKey(key) { return (/^[A-Z_$][A-Z0-9_$]*$/i.test(key) ); }; string = string.trim(); var originalString = string; var object = {}; var readingKey = true, key = void 0, previousToken = void 0, token = void 0; while (string.length > 0) { previousToken = token; token = nextToken(string); string = string.slice(token.length, string.length).trim(); if (token === ':' && (!readingKey || !previousToken || previousToken === ',') || token === ',' && readingKey || token !== ':' && token !== ',' && previousToken && previousToken !== ',' && previousToken !== ':') { error$1(token, string, originalString); } else if (token === ':' && readingKey && previousToken) { previousToken = isQuotedString(previousToken) ? unwrap(previousToken) : previousToken; if (isValidKey(previousToken)) { key = previousToken; readingKey = false; } else { throw new Error('Invalid key token \'' + previousToken + '\' at position 0 in string: \'' + originalString + '\''); } } else if (token === ',' && !readingKey && previousToken) { object[key] = processToken(previousToken, string, originalString); readingKey = true; } } if (token) { object[key] = processToken(token, string, originalString); } return object; }; var parseArray = function parseArray(string) { string = string.trim(); var originalString = string; var array = []; var previousToken = void 0, token = void 0; while (string.length > 0) { previousToken = token; token = nextToken(string); string = string.slice(token.length, string.length).trim(); if (token === ',' && (!previousToken || previousToken === ',')) { error$1(token, string, originalString); } else if (token === ',') { array.push(processToken(previousToken, string, originalString)); } } if (token) { if (token !== ',') { array.push(processToken(token, string, originalString)); } else { error$1(token, string, originalString); } } return array; }; var parse = function parse(string) { string = string.trim(); if (isObjectString(string)) { return parseObject(unwrap(string)); } else if (isArrayString(string)) { return parseArray(unwrap(string)); } else { throw new Error('Provided string must be object or array like: ' + string); } }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var util$1 = {}; var errorPrefix = '[Onsen UI]'; util$1.globals = { fabOffset: 0, errorPrefix: errorPrefix, supportsPassive: false }; platform._runOnActualPlatform(function () { util$1.globals.actualMobileOS = platform.getMobileOS(); util$1.globals.isUIWebView = platform.isUIWebView(); util$1.globals.isWKWebView = platform.isWKWebView(); }); try { var opts = Object.defineProperty({}, 'passive', { get: function get$$1() { util$1.globals.supportsPassive = true; } }); window.addEventListener('testPassive', null, opts); window.removeEventListener('testPassive', null, opts); } catch (e) { } /** * @param {Element} el Target * @param {String} name Event name * @param {Function} handler Event handler * @param {Object} [opt] Event options (passive, capture...) * @param {Boolean} [isGD] If comes from GestureDetector. Just for testing. */ util$1.addEventListener = function (el, name, handler, opt, isGD) { el.addEventListener(name, handler, util$1.globals.supportsPassive ? opt : (opt || {}).capture); }; util$1.removeEventListener = function (el, name, handler, opt, isGD) { el.removeEventListener(name, handler, util$1.globals.supportsPassive ? opt : (opt || {}).capture); }; /** * @param {String/Function} query dot class name or node name or matcher function. * @return {Function} */ util$1.prepareQuery = function (query) { return query instanceof Function ? query : function (element) { return util$1.match(element, query); }; }; /** * @param {Element} e * @param {String/Function} s CSS Selector. * @return {Boolean} */ util$1.match = function (e, s) { return (e.matches || e.webkitMatchesSelector || e.mozMatchesSelector || e.msMatchesSelector).call(e, s); }; /** * @param {Element} element * @param {String/Function} query dot class name or node name or matcher function. * @return {HTMLElement/null} */ util$1.findChild = function (element, query) { var match = util$1.prepareQuery(query); // Caution: `element.children` is `undefined` in some environments if `element` is `svg` for (var i = 0; i < element.childNodes.length; i++) { var node = element.childNodes[i]; if (node.nodeType !== Node.ELEMENT_NODE) { // process only element nodes continue; } if (match(node)) { return node; } } return null; }; /** * @param {Element} element * @param {String/Function} query dot class name or node name or matcher function. * @return {HTMLElement/null} */ util$1.findParent = function (element, query, until) { var match = util$1.prepareQuery(query); var parent = element.parentNode; for (;;) { if (!parent || parent === document || parent instanceof DocumentFragment || until && until(parent)) { return null; } else if (match(parent)) { return parent; } parent = parent.parentNode; } }; /** * @param {Element} element * @return {boolean} */ util$1.isAttached = function (element) { return document.body.contains(element); }; /** * @param {Element} element * @return {boolean} */ util$1.hasAnyComponentAsParent = function (element) { while (element && document.documentElement !== element) { element = element.parentNode; if (element && element.nodeName.toLowerCase().match(/(ons-navigator|ons-tabbar|ons-modal)/)) { return true; } } return false; }; /** * @param {Object} element * @return {Array} */ util$1.getAllChildNodes = function (element) { var _ref; return (_ref = [element]).concat.apply(_ref, toConsumableArray(Array.from(element.children).map(function (childEl) { return util$1.getAllChildNodes(childEl); }))); }; /** * @param {Element} element * @return {boolean} */ util$1.isPageControl = function (element) { return element.nodeName.match(/^ons-(navigator|splitter|tabbar|page)$/i); }; /** * @param {Element} element * @param {String} action to propagate */ util$1.propagateAction = function (element, action) { for (var i = 0; i < element.childNodes.length; i++) { var child = element.childNodes[i]; if (child[action] instanceof Function) { child[action](); } else { util$1.propagateAction(child, action); } } }; /** * @param {String} string - string to be camelized * @return {String} Camelized string */ util$1.camelize = function (string) { return string.toLowerCase().replace(/-([a-z])/g, function (m, l) { return l.toUpperCase(); }); }; /** * @param {String} string - string to be hyphenated * @return {String} Hyphenated string */ util$1.hyphenate = function (string) { return string.replace(/([a-zA-Z])([A-Z])/g, '$1-$2').toLowerCase(); }; /** * @param {String} selector - tag and class only * @param {Object} style * @param {Element} */ util$1.create = function () { var selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var style = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var classList = selector.split('.'); var element = document.createElement(classList.shift() || 'div'); if (classList.length) { element.className = classList.join(' '); } styler(element, style); return element; }; /** * @param {String} html * @return {Element} */ util$1.createElement = function (html) { var wrapper = document.createElement('div'); if (html instanceof DocumentFragment) { wrapper.appendChild(document.importNode(html, true)); } else { wrapper.innerHTML = html.trim(); } if (wrapper.children.length > 1) { util$1.throw('HTML template must contain a single root element'); } var element = wrapper.children[0]; wrapper.children[0].remove(); return element; }; /** * @param {String} html * @return {HTMLFragment} */ util$1.createFragment = function (html) { var template = document.createElement('template'); template.innerHTML = html; return document.importNode(template.content, true); }; /* * @param {Object} dst Destination object. * @param {...Object} src Source object(s). * @returns {Object} Reference to `dst`. */ util$1.extend = function (dst) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } for (var i = 0; i < args.length; i++) { if (args[i]) { var keys = Object.keys(args[i]); for (var j = 0; j < keys.length; j++) { var key = keys[j]; dst[key] = args[i][key]; } } } return dst; }; /** * @param {Object} arrayLike * @return {Array} */ util$1.arrayFrom = function (arrayLike) { return Array.prototype.slice.apply(arrayLike); }; /** * @param {String} jsonString * @param {Object} [failSafe] * @return {Object} */ util$1.parseJSONObjectSafely = function (jsonString) { var failSafe = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; try { var result = JSON.parse('' + jsonString); if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && result !== null) { return result; } } catch (e) { return failSafe; } return failSafe; }; /** * @param {String} path - path such as 'myApp.controllers.data.loadData' * @return {Any} - whatever is located at that path */ util$1.findFromPath = function (path) { path = path.split('.'); var el = window, key; while (key = path.shift()) { // eslint-disable-line no-cond-assign el = el[key]; } return el; }; /** * @param {HTMLElement} container - Page or page-container that implements 'topPage' * @return {HTMLElement|null} - Visible page element or null if not found. */ util$1.getTopPage = function (container) { return container && (container.tagName.toLowerCase() === 'ons-page' ? container : container.topPage) || null; }; /** * @param {HTMLElement} container - Element where the search begins * @return {HTMLElement|null} - Page element that contains the visible toolbar or null. */ util$1.findToolbarPage = function (container) { var page = util$1.getTopPage(container); if (page) { if (page._canAnimateToolbar()) { return page; } for (var i = 0; i < page._contentElement.children.length; i++) { var nextPage = util$1.getTopPage(page._contentElement.children[i]); if (nextPage && !/ons-tabbar/i.test(page._contentElement.children[i].tagName)) { return util$1.findToolbarPage(nextPage); } } } return null; }; /** * @param {Element} element * @param {String} eventName * @param {Object} [detail] * @return {CustomEvent} */ util$1.triggerElementEvent = function (target, eventName) { var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var event = new CustomEvent(eventName, { bubbles: true, cancelable: true, detail: detail }); Object.keys(detail).forEach(function (key) { event[key] = detail[key]; }); target.dispatchEvent(event); return event; }; /** * @param {Element} target * @param {String} modifierName * @return {Boolean} */ util$1.hasModifier = function (target, modifierName) { if (!target.hasAttribute('modifier')) { return false; } return RegExp('(^|\\s+)' + modifierName + '($|\\s+)', 'i').test(target.getAttribute('modifier')); }; /** * @param {Element} target * @param {String} modifierName * @param {Object} options.autoStyle Maps the modifierName to the corresponding styled modifier. * @param {Object} options.forceAutoStyle Ignores platform limitation. * @return {Boolean} Whether it was added or not. */ util$1.addModifier = function (target, modifierName) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (options.autoStyle) { modifierName = autoStyle.mapModifier(modifierName, target, options.forceAutoStyle); } if (util$1.hasModifier(target, modifierName)) { return false; } target.setAttribute('modifier', ((target.getAttribute('modifier') || '') + ' ' + modifierName).trim()); return true; }; /** * @param {Element} target * @param {String} modifierName * @param {Object} options.autoStyle Maps the modifierName to the corresponding styled modifier. * @param {Object} options.forceAutoStyle Ignores platform limitation. * @return {Boolean} Whether it was found or not. */ util$1.removeModifier = function (target, modifierName) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (options.autoStyle) { modifierName = autoStyle.mapModifier(modifierName, target, options.forceAutoStyle); } if (!target.getAttribute('modifier') || !util$1.hasModifier(target, modifierName)) { return false; } var newModifiers = target.getAttribute('modifier').split(/\s+/).filter(function (m) { return m && m !== modifierName; }); newModifiers.length ? target.setAttribute('modifier', newModifiers.join(' ')) : target.removeAttribute('modifier'); return true; }; /** * @param {Element} target * @param {String} modifierName * @param {Boolean} options.force Forces modifier to be added or removed. * @param {Object} options.autoStyle Maps the modifierName to the corresponding styled modifier. * @param {Boolean} options.forceAutoStyle Ignores platform limitation. * @return {Boolean} Whether it was found or not. */ util$1.toggleModifier = function () { var options = arguments.length > 2 ? arguments.length <= 2 ? undefined : arguments[2] : {}; var force = typeof options === 'boolean' ? options : options.force; var toggle = typeof force === 'boolean' ? force : !util$1.hasModifier.apply(util$1, arguments); toggle ? util$1.addModifier.apply(util$1, arguments) : util$1.removeModifier.apply(util$1, arguments); }; /** * @param {Element} el * @param {String} defaultClass * @param {Object} scheme */ util$1.restoreClass = function (el, defaultClass, scheme) { defaultClass.split(/\s+/).forEach(function (c) { return c !== '' && !el.classList.contains(c) && el.classList.add(c); }); el.hasAttribute('modifier') && ModifierUtil.refresh(el, scheme); }; // TODO: FIX util$1.updateParentPosition = function (el) { if (!el._parentUpdated && el.parentElement) { if (window.getComputedStyle(el.parentElement).getPropertyValue('position') === 'static') { el.parentElement.style.position = 'relative'; } el._parentUpdated = true; } }; util$1.toggleAttribute = function (element, name, value) { if (value) { element.setAttribute(name, typeof value === 'boolean' ? '' : value); } else { element.removeAttribute(name); } }; util$1.bindListeners = function (element, listenerNames) { listenerNames.forEach(function (name) { var boundName = name.replace(/^_[a-z]/, '_bound' + name[1].toUpperCase()); element[boundName] = element[boundName] || element[name].bind(element); }); }; util$1.each = function (obj, f) { return Object.keys(obj).forEach(function (key) { return f(key, obj[key]); }); }; /** * @param {Element} target * @param {boolean} hasRipple * @param {Object} attrs */ util$1.updateRipple = function (target, hasRipple) { var attrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (hasRipple === undefined) { hasRipple = target.hasAttribute('ripple'); } var rippleElement = util$1.findChild(target, 'ons-ripple'); if (hasRipple) { if (!rippleElement) { var element = document.createElement('ons-ripple'); Object.keys(attrs).forEach(function (key) { return element.setAttribute(key, attrs[key]); }); target.insertBefore(element, target.firstChild); } } else if (rippleElement) { rippleElement.remove(); } }; /** * @param {String} * @return {Object} */ util$1.animationOptionsParse = parse; /** * @param {*} value */ util$1.isInteger = function (value) { return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; }; /** * @return {Object} Deferred promise. */ util$1.defer = function () { var deferred = {}; deferred.promise = new Promise(function (resolve, reject) { deferred.resolve = resolve; deferred.reject = reject; }); return deferred; }; /** * Show warnings when they are enabled. * * @param {*} arguments to console.warn */ util$1.warn = function () { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } if (!internal$1.config.warningsDisabled) { var _console; (_console = console).warn.apply(_console, [errorPrefix].concat(args)); } }; util$1.throw = function (message) { throw new Error(errorPrefix + ' ' + message); }; util$1.throwAbstract = function () { return util$1.throw('Cannot instantiate abstract class'); }; util$1.throwMember = function () { return util$1.throw('Class member must be implemented'); }; util$1.throwPageLoader = function () { return util$1.throw('First parameter should be an instance of PageLoader'); }; util$1.throwAnimator = function (el) { return util$1.throw('"Animator" param must inherit ' + el + 'Animator'); }; var prevent = function prevent(e) { return e.cancelable && e.preventDefault(); }; /** * Prevent scrolling while draging horizontally on iOS. * * @param {gd} GestureDetector instance */ util$1.iosPreventScroll = function (gd) { if (util$1.globals.actualMobileOS === 'ios') { var clean = function clean(e) { gd.off('touchmove', prevent); gd.off('dragend', clean); }; gd.on('touchmove', prevent); gd.on('dragend', clean); } }; /** * Prevents scroll in underlying pages on iOS. See #2220 #2274 #1949 * * @param {el} HTMLElement that prevents the events * @param {add} Boolean Add or remove event listeners */ util$1.iosPageScrollFix = function (add) { // Full fix - May cause issues with UIWebView's momentum scroll if (util$1.globals.actualMobileOS === 'ios') { document.body.classList.toggle('ons-ios-scroll', add); // Allows custom and localized fixes (#2274) if (!util$1.globals.isUIWebView || internal$1.config.forceUIWebViewScrollFix) { document.body.classList.toggle('ons-ios-scroll-fix', add); } } }; util$1.iosMaskScrollFix = function (el, add) { // Half fix - only prevents scroll on masks if (util$1.globals.isUIWebView) { var action = (add ? 'add' : 'remove') + 'EventListener'; el[action]('touchmove', prevent, false); } }; /** * Distance and deltaTime filter some weird dragstart events that are not fired immediately. * * @param {event} */ util$1.isValidGesture = function (event) { return event.gesture !== undefined && (event.gesture.distance <= 15 || event.gesture.deltaTime <= 100); }; util$1.checkMissingImport = function () { for (var _len3 = arguments.length, elementNames = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { elementNames[_key3] = arguments[_key3]; } elementNames.forEach(function (name) { if (!onsElements[name]) { util$1.throw('Ons' + name + ' is required but was not imported (Custom Elements)'); } }); }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Minimal animation library for managing css transition on mobile browsers. */ var TIMEOUT_RATIO = 1.4; var util$4 = {}; // capitalize string util$4.capitalize = function (str) { return str.charAt(0).toUpperCase() + str.slice(1); }; /** * @param {Object} params * @param {String} params.property * @param {Float} params.duration * @param {String} params.timing */ util$4.buildTransitionValue = function (params) { params.property = params.property || 'all'; params.duration = params.duration || 0.4; params.timing = params.timing || 'linear'; var props = params.property.split(/ +/); return props.map(function (prop) { return prop + ' ' + params.duration + 's ' + params.timing; }).join(', '); }; /** * Add an event handler on "transitionend" event. */ util$4.onceOnTransitionEnd = function (element, callback) { if (!element) { return function () {}; } var fn = function fn(event) { if (element == event.target) { event.stopPropagation(); removeListeners(); callback(); } }; var removeListeners = function removeListeners() { util$4._transitionEndEvents.forEach(function (eventName) { element.removeEventListener(eventName, fn, false); }); }; util$4._transitionEndEvents.forEach(function (eventName) { element.addEventListener(eventName, fn, false); }); return removeListeners; }; util$4._transitionEndEvents = function () { if ('ontransitionend' in window) { return ['transitionend']; } if ('onwebkittransitionend' in window) { return ['webkitTransitionEnd']; } if (util$4.vendorPrefix === 'webkit' || util$4.vendorPrefix === 'o' || util$4.vendorPrefix === 'moz' || util$4.vendorPrefix === 'ms') { return [util$4.vendorPrefix + 'TransitionEnd', 'transitionend']; } return []; }(); util$4._cssPropertyDict = function () { var styles = window.getComputedStyle(document.documentElement, ''); var dict = {}; var a = 'A'.charCodeAt(0); var z = 'z'.charCodeAt(0); var upper = function upper(s) { return s.substr(1).toUpperCase(); }; for (var i = 0; i < styles.length; i++) { var key = styles[i].replace(/^[-]+/, '').replace(/[-][a-z]/g, upper).replace(/^moz/, 'Moz'); if (a <= key.charCodeAt(0) && z >= key.charCodeAt(0)) { if (key !== 'cssText' && key !== 'parentText') { dict[key] = true; } } } return dict; }(); util$4.hasCssProperty = function (name) { return name in util$4._cssPropertyDict; }; /** * Vendor prefix for css property. */ util$4.vendorPrefix = function () { var styles = window.getComputedStyle(document.documentElement, ''), pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1]; return pre; }(); util$4.forceLayoutAtOnce = function (elements, callback) { this.batchImmediate(function () { elements.forEach(function (element) { // force layout element.offsetHeight; }); callback(); }); }; util$4.batchImmediate = function () { var callbacks = []; return function (callback) { if (callbacks.length === 0) { setImmediate(function () { var concreateCallbacks = callbacks.slice(0); callbacks = []; concreateCallbacks.forEach(function (callback) { callback(); }); }); } callbacks.push(callback); }; }(); util$4.batchAnimationFrame = function () { var callbacks = []; var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { setTimeout(callback, 1000 / 60); }; return function (callback) { if (callbacks.length === 0) { raf(function () { var concreateCallbacks = callbacks.slice(0); callbacks = []; concreateCallbacks.forEach(function (callback) { callback(); }); }); } callbacks.push(callback); }; }(); util$4.transitionPropertyName = function () { if (util$4.hasCssProperty('transitionDuration')) { return 'transition'; } if (util$4.hasCssProperty(util$4.vendorPrefix + 'TransitionDuration')) { return util$4.vendorPrefix + 'Transition'; } throw new Error('Invalid state'); }(); /** * @param {HTMLElement} element */ var Animit = function Animit(element, defaults) { if (!(this instanceof Animit)) { return new Animit(element, defaults); } if (element instanceof HTMLElement) { this.elements = [element]; } else if (Object.prototype.toString.call(element) === '[object Array]') { this.elements = element; } else { throw new Error('First argument must be an array or an instance of HTMLElement.'); } this.defaults = defaults; this.transitionQueue = []; this.lastStyleAttributeDict = []; }; Animit.prototype = { /** * @property {Array} */ transitionQueue: undefined, /** * @property {Array} */ elements: undefined, /** * @property {Object} */ defaults: undefined, /** * Start animation sequence with passed animations. * * @param {Function} callback */ play: function play(callback) { if (typeof callback === 'function') { this.transitionQueue.push(function (done) { callback(); done(); }); } this.startAnimation(); return this; }, /** * Most of the animations follow this default process. * * @param {from} css or options object containing css * @param {to} css or options object containing css * @param {delay} delay to wait */ default: function _default(from, to, delay) { function step(params, duration, timing) { if (params.duration !== undefined) { duration = params.duration; } if (params.timing !== undefined) { timing = params.timing; } return { css: params.css || params, duration: duration, timing: timing }; } return this.saveStyle().queue(step(from, 0, this.defaults.timing)).wait(delay === undefined ? this.defaults.delay : delay).queue(step(to, this.defaults.duration, this.defaults.timing)).restoreStyle(); }, /** * Queue transition animations or other function. * * e.g. animit(elt).queue({color: 'red'}) * e.g. animit(elt).queue({color: 'red'}, {duration: 0.4}) * e.g. animit(elt).queue({css: {color: 'red'}, duration: 0.2}) * * @param {Object|Animit.Transition|Function} transition * @param {Object} [options] */ queue: function queue(transition, options) { var queue = this.transitionQueue; if (transition && options) { options.css = transition; transition = new Animit.Transition(options); } if (!(transition instanceof Function || transition instanceof Animit.Transition)) { if (transition.css) { transition = new Animit.Transition(transition); } else { transition = new Animit.Transition({ css: transition }); } } if (transition instanceof Function) { queue.push(transition); } else if (transition instanceof Animit.Transition) { queue.push(transition.build()); } else { throw new Error('Invalid arguments'); } return this; }, /** * Queue transition animations. * * @param {Float} seconds */ wait: function wait(seconds) { if (seconds > 0) { this.transitionQueue.push(function (done) { setTimeout(done, 1000 * seconds); }); } return this; }, saveStyle: function saveStyle() { this.transitionQueue.push(function (done) { this.elements.forEach(function (element, index) { var css = this.lastStyleAttributeDict[index] = {}; for (var i = 0; i < element.style.length; i++) { css[element.style[i]] = element.style[element.style[i]]; } }.bind(this)); done(); }.bind(this)); return this; }, /** * Restore element's style. * * @param {Object} [options] * @param {Float} [options.duration] * @param {String} [options.timing] * @param {String} [options.transition] */ restoreStyle: function restoreStyle(options) { options = options || {}; var self = this; if (options.transition && !options.duration) { throw new Error('"options.duration" is required when "options.transition" is enabled.'); } var transitionName = util$4.transitionPropertyName; if (options.transition || options.duration && options.duration > 0) { var transitionValue = options.transition || 'all ' + options.duration + 's ' + (options.timing || 'linear'); this.transitionQueue.push(function (done) { var elements = this.elements; var timeoutId; var clearTransition = function clearTransition() { elements.forEach(function (element) { element.style[transitionName] = ''; }); }; // add "transitionend" event handler var removeListeners = util$4.onceOnTransitionEnd(elements[0], function () { clearTimeout(timeoutId); clearTransition(); done(); }); // for fail safe. timeoutId = setTimeout(function () { removeListeners(); clearTransition(); done(); }, options.duration * 1000 * TIMEOUT_RATIO); // transition and style settings elements.forEach(function (element, index) { var css = self.lastStyleAttributeDict[index]; if (!css) { throw new Error('restoreStyle(): The style is not saved. Invoke saveStyle() before.'); } self.lastStyleAttributeDict[index] = undefined; var name; for (var i = 0, len = element.style.length; i < len; i++) { name = element.style[i]; if (css[name] === undefined) { css[name] = ''; } } element.style[transitionName] = transitionValue; Object.keys(css).forEach(function (key) { if (key !== transitionName) { element.style[key] = css[key]; } }); element.style[transitionName] = transitionValue; }); }); } else { this.transitionQueue.push(function (done) { reset(); done(); }); } return this; function reset() { // Clear transition animation settings. self.elements.forEach(function (element, index) { element.style[transitionName] = 'none'; var css = self.lastStyleAttributeDict[index]; if (!css) { throw new Error('restoreStyle(): The style is not saved. Invoke saveStyle() before.'); } self.lastStyleAttributeDict[index] = undefined; for (var i = 0, name = ''; i < element.style.length; i++) { name = element.style[i]; if (typeof css[element.style[i]] === 'undefined') { css[element.style[i]] = ''; } } Object.keys(css).forEach(function (key) { element.style[key] = css[key]; }); }); } }, /** * Start animation sequence. */ startAnimation: function startAnimation() { this._dequeueTransition(); return this; }, _dequeueTransition: function _dequeueTransition() { var transition = this.transitionQueue.shift(); if (this._currentTransition) { throw new Error('Current transition exists.'); } this._currentTransition = transition; var self = this; var called = false; var done = function done() { if (!called) { called = true; self._currentTransition = undefined; self._dequeueTransition(); } else { throw new Error('Invalid state: This callback is called twice.'); } }; if (transition) { transition.call(this, done); } } }; /** * @param {Animit} arguments */ Animit.runAll = function () /* arguments... */{ for (var i = 0; i < arguments.length; i++) { arguments[i].play(); } }; /** * @param {Object} options * @param {Float} [options.duration] * @param {String} [options.property] * @param {String} [options.timing] */ Animit.Transition = function (options) { this.options = options || {}; this.options.duration = this.options.duration || 0; this.options.timing = this.options.timing || 'linear'; this.options.css = this.options.css || {}; this.options.property = this.options.property || 'all'; }; Animit.Transition.prototype = { /** * @param {HTMLElement} element * @return {Function} */ build: function build() { if (Object.keys(this.options.css).length === 0) { throw new Error('options.css is required.'); } var css = createActualCssProps(this.options.css); if (this.options.duration > 0) { var transitionValue = util$4.buildTransitionValue(this.options); var self = this; return function (callback) { var elements = this.elements; var timeout = self.options.duration * 1000 * TIMEOUT_RATIO; var timeoutId; var removeListeners = util$4.onceOnTransitionEnd(elements[0], function () { clearTimeout(timeoutId); callback(); }); timeoutId = setTimeout(function () { removeListeners(); callback(); }, timeout); elements.forEach(function (element) { element.style[util$4.transitionPropertyName] = transitionValue; Object.keys(css).forEach(function (name) { element.style[name] = css[name]; }); }); }; } if (this.options.duration <= 0) { return function (callback) { var elements = this.elements; elements.forEach(function (element) { element.style[util$4.transitionPropertyName] = ''; Object.keys(css).forEach(function (name) { element.style[name] = css[name]; }); }); if (elements.length > 0) { util$4.forceLayoutAtOnce(elements, function () { util$4.batchAnimationFrame(callback); }); } else { util$4.batchAnimationFrame(callback); } }; } function createActualCssProps(css) { var result = {}; Object.keys(css).forEach(function (name) { var value = css[name]; if (util$4.hasCssProperty(name)) { result[name] = value; return; } var prefixed = util$4.vendorPrefix + util$4.capitalize(name); if (util$4.hasCssProperty(prefixed)) { result[prefixed] = value; } else { result[prefixed] = value; result[name] = value; } }); return result; } } }; /* * Gesture detector library that forked from github.com/EightMedia/hammer.js. */ var Event$1; var Utils; var Detection; var PointerEvent; /** * @object ons.GestureDetector * @category gesture * @description * [en]Utility class for gesture detection.[/en] * [ja]ジェスチャを検知するためのユーティリティクラスです。[/ja] */ /** * @method constructor * @signature constructor(element[, options]) * @description * [en]Create a new GestureDetector instance.[/en] * [ja]GestureDetectorのインスタンスを生成します。[/ja] * @param {Element} element * [en]Name of the event.[/en] * [ja]ジェスチャを検知するDOM要素を指定します。[/ja] * @param {Object} [options] * [en]Options object.[/en] * [ja]オプションを指定します。[/ja] * @return {ons.GestureDetector.Instance} */ var GestureDetector = function GestureDetector(element, options) { return new GestureDetector.Instance(element, options || {}); }; /** * default settings. * more settings are defined per gesture at `/gestures`. Each gesture can be disabled/enabled * by setting it's name (like `swipe`) to false. * You can set the defaults for all instances by changing this object before creating an instance. * @example * ```` * GestureDetector.defaults.drag = false; * GestureDetector.defaults.behavior.touchAction = 'pan-y'; * delete GestureDetector.defaults.behavior.userSelect; * ```` * @property defaults * @type {Object} */ GestureDetector.defaults = { behavior: { // userSelect: 'none', // Also disables selection in `input` children touchAction: 'pan-y', touchCallout: 'none', contentZooming: 'none', userDrag: 'none', tapHighlightColor: 'rgba(0,0,0,0)' } }; /** * GestureDetector document where the base events are added at * @property DOCUMENT * @type {HTMLElement} * @default window.document */ GestureDetector.DOCUMENT = document; /** * detect support for pointer events * @property HAS_POINTEREVENTS * @type {Boolean} */ GestureDetector.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled; /** * detect support for touch events * @property HAS_TOUCHEVENTS * @type {Boolean} */ GestureDetector.HAS_TOUCHEVENTS = 'ontouchstart' in window; /** * detect mobile browsers * @property IS_MOBILE * @type {Boolean} */ GestureDetector.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent); /** * detect if we want to support mouseevents at all * @property NO_MOUSEEVENTS * @type {Boolean} */ GestureDetector.NO_MOUSEEVENTS = GestureDetector.HAS_TOUCHEVENTS && GestureDetector.IS_MOBILE || GestureDetector.HAS_POINTEREVENTS; /** * interval in which GestureDetector recalculates current velocity/direction/angle in ms * @property CALCULATE_INTERVAL * @type {Number} * @default 25 */ GestureDetector.CALCULATE_INTERVAL = 25; /** * eventtypes per touchevent (start, move, end) are filled by `Event.determineEventTypes` on `setup` * the object contains the DOM event names per type (`EVENT_START`, `EVENT_MOVE`, `EVENT_END`) * @property EVENT_TYPES * @private * @writeOnce * @type {Object} */ var EVENT_TYPES = {}; /** * direction strings, for safe comparisons * @property DIRECTION_DOWN|LEFT|UP|RIGHT * @final * @type {String} * @default 'down' 'left' 'up' 'right' */ var DIRECTION_DOWN = GestureDetector.DIRECTION_DOWN = 'down'; var DIRECTION_LEFT = GestureDetector.DIRECTION_LEFT = 'left'; var DIRECTION_UP = GestureDetector.DIRECTION_UP = 'up'; var DIRECTION_RIGHT = GestureDetector.DIRECTION_RIGHT = 'right'; /** * pointertype strings, for safe comparisons * @property POINTER_MOUSE|TOUCH|PEN * @final * @type {String} * @default 'mouse' 'touch' 'pen' */ var POINTER_MOUSE = GestureDetector.POINTER_MOUSE = 'mouse'; var POINTER_TOUCH = GestureDetector.POINTER_TOUCH = 'touch'; var POINTER_PEN = GestureDetector.POINTER_PEN = 'pen'; /** * eventtypes * @property EVENT_START|MOVE|END|RELEASE|TOUCH * @final * @type {String} * @default 'start' 'change' 'move' 'end' 'release' 'touch' */ var EVENT_START = GestureDetector.EVENT_START = 'start'; var EVENT_MOVE = GestureDetector.EVENT_MOVE = 'move'; var EVENT_END = GestureDetector.EVENT_END = 'end'; var EVENT_RELEASE = GestureDetector.EVENT_RELEASE = 'release'; var EVENT_TOUCH = GestureDetector.EVENT_TOUCH = 'touch'; /** * if the window events are set... * @property READY * @writeOnce * @type {Boolean} * @default false */ GestureDetector.READY = false; /** * plugins namespace * @property plugins * @type {Object} */ GestureDetector.plugins = GestureDetector.plugins || {}; /** * gestures namespace * see `/gestures` for the definitions * @property gestures * @type {Object} */ GestureDetector.gestures = GestureDetector.gestures || {}; /** * setup events to detect gestures on the document * this function is called when creating an new instance * @private */ function setup(opts) { if (GestureDetector.READY) { return; } // find what eventtypes we add listeners to Event$1.determineEventTypes(); // Register all gestures inside GestureDetector.gestures Utils.each(GestureDetector.gestures, function (gesture) { Detection.register(gesture); }); // Add touch events on the document Event$1.onTouch(GestureDetector.DOCUMENT, EVENT_MOVE, Detection.detect, opts); Event$1.onTouch(GestureDetector.DOCUMENT, EVENT_END, Detection.detect, opts); // GestureDetector is ready...! GestureDetector.READY = true; } /** * @module GestureDetector * * @class Utils * @static */ Utils = GestureDetector.utils = { /** * extend method, could also be used for cloning when `dest` is an empty object. * changes the dest object * @param {Object} dest * @param {Object} src * @param {Boolean} [merge=false] do a merge * @return {Object} dest */ extend: function extend(dest, src, merge) { for (var key in src) { if (src.hasOwnProperty(key) && (dest[key] === undefined || !merge)) { dest[key] = src[key]; } } return dest; }, /** * simple addEventListener wrapper * @param {HTMLElement} element * @param {String} type * @param {Function} handler */ on: function on(element, type, handler, opt) { util$1.addEventListener(element, type, handler, opt, true); }, /** * simple removeEventListener wrapper * @param {HTMLElement} element * @param {String} type * @param {Function} handler */ off: function off(element, type, handler, opt) { util$1.removeEventListener(element, type, handler, opt, true); }, /** * forEach over arrays and objects * @param {Object|Array} obj * @param {Function} iterator * @param {any} iterator.item * @param {Number} iterator.index * @param {Object|Array} iterator.obj the source object * @param {Object} context value to use as `this` in the iterator */ each: function each(obj, iterator, context) { var i, len; // native forEach on arrays if ('forEach' in obj) { obj.forEach(iterator, context); // arrays } else if (obj.length !== undefined) { for (i = 0, len = obj.length; i < len; i++) { if (iterator.call(context, obj[i], i, obj) === false) { return; } } // objects } else { for (i in obj) { if (obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj) === false) { return; } } } }, /** * find if a string contains the string using indexOf * @param {String} src * @param {String} find * @return {Boolean} found */ inStr: function inStr(src, find) { return src.indexOf(find) > -1; }, /** * find if a array contains the object using indexOf or a simple polyfill * @param {String} src * @param {String} find * @return {Boolean|Number} false when not found, or the index */ inArray: function inArray(src, find, deep) { if (deep) { for (var i = 0, len = src.length; i < len; i++) { // Array.findIndex if (Object.keys(find).every(function (key) { return src[i][key] === find[key]; })) { return i; } } return -1; } if (src.indexOf) { return src.indexOf(find); } else { for (var i = 0, len = src.length; i < len; i++) { if (src[i] === find) { return i; } } return -1; } }, /** * convert an array-like object (`arguments`, `touchlist`) to an array * @param {Object} obj * @return {Array} */ toArray: function toArray(obj) { return Array.prototype.slice.call(obj, 0); }, /** * find if a node is in the given parent * @param {HTMLElement} node * @param {HTMLElement} parent * @return {Boolean} found */ hasParent: function hasParent(node, parent) { while (node) { if (node == parent) { return true; } node = node.parentNode; } return false; }, /** * get the center of all the touches * @param {Array} touches * @return {Object} center contains `pageX`, `pageY`, `clientX` and `clientY` properties */ getCenter: function getCenter(touches) { var pageX = [], pageY = [], clientX = [], clientY = [], min = Math.min, max = Math.max; // no need to loop when only one touch if (touches.length === 1) { return { pageX: touches[0].pageX, pageY: touches[0].pageY, clientX: touches[0].clientX, clientY: touches[0].clientY }; } Utils.each(touches, function (touch) { pageX.push(touch.pageX); pageY.push(touch.pageY); clientX.push(touch.clientX); clientY.push(touch.clientY); }); return { pageX: (min.apply(Math, pageX) + max.apply(Math, pageX)) / 2, pageY: (min.apply(Math, pageY) + max.apply(Math, pageY)) / 2, clientX: (min.apply(Math, clientX) + max.apply(Math, clientX)) / 2, clientY: (min.apply(Math, clientY) + max.apply(Math, clientY)) / 2 }; }, /** * calculate the velocity between two points. unit is in px per ms. * @param {Number} deltaTime * @param {Number} deltaX * @param {Number} deltaY * @return {Object} velocity `x` and `y` */ getVelocity: function getVelocity(deltaTime, deltaX, deltaY) { return { x: Math.abs(deltaX / deltaTime) || 0, y: Math.abs(deltaY / deltaTime) || 0 }; }, /** * calculate the angle between two coordinates * @param {Touch} touch1 * @param {Touch} touch2 * @return {Number} angle */ getAngle: function getAngle(touch1, touch2) { var x = touch2.clientX - touch1.clientX, y = touch2.clientY - touch1.clientY; return Math.atan2(y, x) * 180 / Math.PI; }, /** * do a small comparison to get the direction between two touches. * @param {Touch} touch1 * @param {Touch} touch2 * @return {String} direction matches `DIRECTION_LEFT|RIGHT|UP|DOWN` */ getDirection: function getDirection(touch1, touch2) { var x = Math.abs(touch1.clientX - touch2.clientX), y = Math.abs(touch1.clientY - touch2.clientY); if (x >= y) { return touch1.clientX - touch2.clientX > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; } return touch1.clientY - touch2.clientY > 0 ? DIRECTION_UP : DIRECTION_DOWN; }, /** * calculate the distance between two touches * @param {Touch}touch1 * @param {Touch} touch2 * @return {Number} distance */ getDistance: function getDistance(touch1, touch2) { var x = touch2.clientX - touch1.clientX, y = touch2.clientY - touch1.clientY; return Math.sqrt(x * x + y * y); }, /** * calculate the scale factor between two touchLists * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out * @param {Array} start array of touches * @param {Array} end array of touches * @return {Number} scale */ getScale: function getScale(start, end) { // need two fingers... if (start.length >= 2 && end.length >= 2) { return this.getDistance(end[0], end[1]) / this.getDistance(start[0], start[1]); } return 1; }, /** * calculate the rotation degrees between two touchLists * @param {Array} start array of touches * @param {Array} end array of touches * @return {Number} rotation */ getRotation: function getRotation(start, end) { // need two fingers if (start.length >= 2 && end.length >= 2) { return this.getAngle(end[1], end[0]) - this.getAngle(start[1], start[0]); } return 0; }, /** * find out if the direction is vertical * * @param {String} direction matches `DIRECTION_UP|DOWN` * @return {Boolean} is_vertical */ isVertical: function isVertical(direction) { return direction == DIRECTION_UP || direction == DIRECTION_DOWN; }, /** * set css properties with their prefixes * @param {HTMLElement} element * @param {String} prop * @param {String} value * @param {Boolean} [toggle=true] * @return {Boolean} */ setPrefixedCss: function setPrefixedCss(element, prop, value, toggle) { var prefixes = ['', 'Webkit', 'Moz', 'O', 'ms']; prop = Utils.toCamelCase(prop); for (var i = 0; i < prefixes.length; i++) { var p = prop; // prefixes if (prefixes[i]) { p = prefixes[i] + p.slice(0, 1).toUpperCase() + p.slice(1); } // test the style if (p in element.style) { element.style[p] = (toggle === null || toggle) && value || ''; break; } } }, /** * toggle browser default behavior by setting css properties. * `userSelect='none'` also sets `element.onselectstart` to false * `userDrag='none'` also sets `element.ondragstart` to false * * @param {HtmlElement} element * @param {Object} props * @param {Boolean} [toggle=true] */ toggleBehavior: function toggleBehavior(element, props, toggle) { if (!props || !element || !element.style) { return; } // set the css properties Utils.each(props, function (value, prop) { Utils.setPrefixedCss(element, prop, value, toggle); }); var falseFn = toggle && function () { return false; }; // also the disable onselectstart if (props.userSelect == 'none') { element.onselectstart = falseFn; } // and disable ondragstart if (props.userDrag == 'none') { element.ondragstart = falseFn; } }, /** * convert a string with underscores to camelCase * so prevent_default becomes preventDefault * @param {String} str * @return {String} camelCaseStr */ toCamelCase: function toCamelCase(str) { return str.replace(/[_-]([a-z])/g, function (s) { return s[1].toUpperCase(); }); } }; /** * @module GestureDetector */ /** * @class Event * @static */ Event$1 = GestureDetector.event = { /** * when touch events have been fired, this is true * this is used to stop mouse events * @property prevent_mouseevents * @private * @type {Boolean} */ preventMouseEvents: false, /** * if EVENT_START has been fired * @property started * @private * @type {Boolean} */ started: false, /** * when the mouse is hold down, this is true * @property should_detect * @private * @type {Boolean} */ shouldDetect: false, /** * simple event binder with a hook and support for multiple types * @param {HTMLElement} element * @param {String} type * @param {Function} handler * @param {Object} [opt] * @param {Function} [hook] * @param {Object} hook.type */ on: function on(element, type, handler, opt, hook) { var types = type.split(' '); Utils.each(types, function (type) { Utils.on(element, type, handler, opt); hook && hook(type); }); }, /** * simple event unbinder with a hook and support for multiple types * @param {HTMLElement} element * @param {String} type * @param {Function} handler * @param {Object} [opt] * @param {Function} [hook] * @param {Object} hook.type */ off: function off(element, type, handler, opt, hook) { var types = type.split(' '); Utils.each(types, function (type) { Utils.off(element, type, handler, opt); hook && hook(type); }); }, /** * the core touch event handler. * this finds out if we should to detect gestures * @param {HTMLElement} element * @param {String} eventType matches `EVENT_START|MOVE|END` * @param {Function} handler * @return onTouchHandler {Function} the core event handler */ onTouch: function onTouch(element, eventType, handler, opt) { var self = this; var onTouchHandler = function onTouchHandler(ev) { var srcType = ev.type.toLowerCase(), isPointer = GestureDetector.HAS_POINTEREVENTS, isMouse = Utils.inStr(srcType, 'mouse'), triggerType; // if we are in a mouseevent, but there has been a touchevent triggered in this session // we want to do nothing. simply break out of the event. if (isMouse && self.preventMouseEvents) { return; // mousebutton must be down } else if (isMouse && eventType == EVENT_START && ev.button === 0) { self.preventMouseEvents = false; self.shouldDetect = true; } else if (isPointer && eventType == EVENT_START) { self.shouldDetect = ev.buttons === 1 || PointerEvent.matchType(POINTER_TOUCH, ev); // just a valid start event, but no mouse } else if (!isMouse && eventType == EVENT_START) { self.preventMouseEvents = true; self.shouldDetect = true; } // update the pointer event before entering the detection if (isPointer && eventType != EVENT_END) { PointerEvent.updatePointer(eventType, ev); } // we are in a touch/down state, so allowed detection of gestures if (self.shouldDetect) { triggerType = self.doDetect.call(self, ev, eventType, element, handler); } // ...and we are done with the detection // so reset everything to start each detection totally fresh if (triggerType == EVENT_END) { self.preventMouseEvents = false; self.shouldDetect = false; PointerEvent.reset(); // update the pointerevent object after the detection } if (isPointer && eventType == EVENT_END) { PointerEvent.updatePointer(eventType, ev); } }; this.on(element, EVENT_TYPES[eventType], onTouchHandler, opt); return onTouchHandler; }, /** * the core detection method * this finds out what GestureDetector-touch-events to trigger * @param {Object} ev * @param {String} eventType matches `EVENT_START|MOVE|END` * @param {HTMLElement} element * @param {Function} handler * @return {String} triggerType matches `EVENT_START|MOVE|END` */ doDetect: function doDetect(ev, eventType, element, handler) { var touchList = this.getTouchList(ev, eventType); var touchListLength = touchList.length; var triggerType = eventType; var triggerChange = touchList.trigger; // used by fakeMultitouch plugin var changedLength = touchListLength; // at each touchstart-like event we want also want to trigger a TOUCH event... if (eventType == EVENT_START) { triggerChange = EVENT_TOUCH; // ...the same for a touchend-like event } else if (eventType == EVENT_END) { triggerChange = EVENT_RELEASE; // keep track of how many touches have been removed changedLength = touchList.length - (ev.changedTouches ? ev.changedTouches.length : 1); } // after there are still touches on the screen, // we just want to trigger a MOVE event. so change the START or END to a MOVE // but only after detection has been started, the first time we actually want a START if (changedLength > 0 && this.started) { triggerType = EVENT_MOVE; } // detection has been started, we keep track of this, see above this.started = true; // generate some event data, some basic information var evData = this.collectEventData(element, triggerType, touchList, ev); // trigger the triggerType event before the change (TOUCH, RELEASE) events // but the END event should be at last if (eventType != EVENT_END) { handler.call(Detection, evData); } // trigger a change (TOUCH, RELEASE) event, this means the length of the touches changed if (triggerChange) { evData.changedLength = changedLength; evData.eventType = triggerChange; handler.call(Detection, evData); evData.eventType = triggerType; delete evData.changedLength; } // trigger the END event if (triggerType == EVENT_END) { handler.call(Detection, evData); // ...and we are done with the detection // so reset everything to start each detection totally fresh this.started = false; } return triggerType; }, /** * we have different events for each device/browser * determine what we need and set them in the EVENT_TYPES constant * the `onTouch` method is bind to these properties. * @return {Object} events */ determineEventTypes: function determineEventTypes() { var types; if (GestureDetector.HAS_POINTEREVENTS) { if (window.PointerEvent) { types = ['pointerdown', 'pointermove', 'pointerup pointercancel lostpointercapture']; } else { types = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp MSPointerCancel MSLostPointerCapture']; } } else if (GestureDetector.NO_MOUSEEVENTS) { types = ['touchstart', 'touchmove', 'touchend touchcancel']; } else { types = ['touchstart mousedown', 'touchmove mousemove', 'touchend touchcancel mouseup']; } EVENT_TYPES[EVENT_START] = types[0]; EVENT_TYPES[EVENT_MOVE] = types[1]; EVENT_TYPES[EVENT_END] = types[2]; return EVENT_TYPES; }, /** * create touchList depending on the event * @param {Object} ev * @param {String} eventType * @return {Array} touches */ getTouchList: function getTouchList(ev, eventType) { // get the fake pointerEvent touchlist if (GestureDetector.HAS_POINTEREVENTS) { return PointerEvent.getTouchList(); } // get the touchlist if (ev.touches) { if (eventType == EVENT_MOVE) { return ev.touches; } var identifiers = []; var concat = [].concat(Utils.toArray(ev.touches), Utils.toArray(ev.changedTouches)); var touchList = []; Utils.each(concat, function (touch) { if (Utils.inArray(identifiers, touch.identifier) === -1) { touchList.push(touch); } identifiers.push(touch.identifier); }); return touchList; } // make fake touchList from mouse position ev.identifier = 1; return [ev]; }, /** * collect basic event data * @param {HTMLElement} element * @param {String} eventType matches `EVENT_START|MOVE|END` * @param {Array} touches * @param {Object} ev * @return {Object} ev */ collectEventData: function collectEventData(element, eventType, touches, ev) { // find out pointerType var pointerType = POINTER_TOUCH; if (Utils.inStr(ev.type, 'mouse') || PointerEvent.matchType(POINTER_MOUSE, ev)) { pointerType = POINTER_MOUSE; } else if (PointerEvent.matchType(POINTER_PEN, ev)) { pointerType = POINTER_PEN; } return { center: Utils.getCenter(touches), timeStamp: Date.now(), target: ev.target, touches: touches, eventType: eventType, pointerType: pointerType, srcEvent: ev, /** * prevent the browser default actions * mostly used to disable scrolling of the browser */ preventDefault: function preventDefault() { var srcEvent = this.srcEvent; srcEvent.preventManipulation && srcEvent.preventManipulation(); srcEvent.preventDefault && srcEvent.preventDefault(); }, /** * stop bubbling the event up to its parents */ stopPropagation: function stopPropagation() { this.srcEvent.stopPropagation(); }, /** * immediately stop gesture detection * might be useful after a swipe was detected * @return {*} */ stopDetect: function stopDetect() { return Detection.stopDetect(); } }; } }; /** * @module GestureDetector * * @class PointerEvent * @static */ PointerEvent = GestureDetector.PointerEvent = { /** * holds all pointers, by `identifier` * @property pointers * @type {Object} */ pointers: {}, /** * get the pointers as an array * @return {Array} touchlist */ getTouchList: function getTouchList() { var touchlist = []; // we can use forEach since pointerEvents only is in IE10 Utils.each(this.pointers, function (pointer) { touchlist.push(pointer); }); return touchlist; }, /** * update the position of a pointer * @param {String} eventType matches `EVENT_START|MOVE|END` * @param {Object} pointerEvent */ updatePointer: function updatePointer(eventType, pointerEvent) { if (eventType == EVENT_END || eventType != EVENT_END && pointerEvent.buttons !== 1) { delete this.pointers[pointerEvent.pointerId]; } else { pointerEvent.identifier = pointerEvent.pointerId; this.pointers[pointerEvent.pointerId] = pointerEvent; } }, /** * check if ev matches pointertype * @param {String} pointerType matches `POINTER_MOUSE|TOUCH|PEN` * @param {PointerEvent} ev */ matchType: function matchType(pointerType, ev) { if (!ev.pointerType) { return false; } var pt = ev.pointerType, types = {}; types[POINTER_MOUSE] = pt === (ev.MSPOINTER_TYPE_MOUSE || POINTER_MOUSE); types[POINTER_TOUCH] = pt === (ev.MSPOINTER_TYPE_TOUCH || POINTER_TOUCH); types[POINTER_PEN] = pt === (ev.MSPOINTER_TYPE_PEN || POINTER_PEN); return types[pointerType]; }, /** * reset the stored pointers */ reset: function resetList() { this.pointers = {}; } }; /** * @module GestureDetector * * @class Detection * @static */ Detection = GestureDetector.detection = { // contains all registered GestureDetector.gestures in the correct order gestures: [], // data of the current GestureDetector.gesture detection session current: null, // the previous GestureDetector.gesture session data // is a full clone of the previous gesture.current object previous: null, // when this becomes true, no gestures are fired stopped: false, /** * start GestureDetector.gesture detection * @param {GestureDetector.Instance} inst * @param {Object} eventData */ startDetect: function startDetect(inst, eventData) { // already busy with a GestureDetector.gesture detection on an element if (this.current) { return; } this.stopped = false; // holds current session this.current = { inst: inst, // reference to GestureDetectorInstance we're working for startEvent: Utils.extend({}, eventData), // start eventData for distances, timing etc lastEvent: false, // last eventData lastCalcEvent: false, // last eventData for calculations. futureCalcEvent: false, // last eventData for calculations. lastCalcData: {}, // last lastCalcData name: '' // current gesture we're in/detected, can be 'tap', 'hold' etc }; this.detect(eventData); }, /** * GestureDetector.gesture detection * @param {Object} eventData * @return {any} */ detect: function detect(eventData) { if (!this.current || this.stopped) { return; } // extend event data with calculations about scale, distance etc eventData = this.extendEventData(eventData); // GestureDetector instance and instance options var inst = this.current.inst, instOptions = inst.options; // call GestureDetector.gesture handlers Utils.each(this.gestures, function triggerGesture(gesture) { // only when the instance options have enabled this gesture if (!this.stopped && inst.enabled && instOptions[gesture.name]) { gesture.handler.call(gesture, eventData, inst); } }, this); // store as previous event event if (this.current) { this.current.lastEvent = eventData; } if (eventData.eventType == EVENT_END) { this.stopDetect(); } return eventData; // eslint-disable-line consistent-return }, /** * clear the GestureDetector.gesture vars * this is called on endDetect, but can also be used when a final GestureDetector.gesture has been detected * to stop other GestureDetector.gestures from being fired */ stopDetect: function stopDetect() { // clone current data to the store as the previous gesture // used for the double tap gesture, since this is an other gesture detect session this.previous = Utils.extend({}, this.current); // reset the current this.current = null; this.stopped = true; }, /** * calculate velocity, angle and direction * @param {Object} ev * @param {Object} center * @param {Number} deltaTime * @param {Number} deltaX * @param {Number} deltaY */ getCalculatedData: function getCalculatedData(ev, center, deltaTime, deltaX, deltaY) { var cur = this.current, recalc = false, calcEv = cur.lastCalcEvent, calcData = cur.lastCalcData; if (calcEv && ev.timeStamp - calcEv.timeStamp > GestureDetector.CALCULATE_INTERVAL) { center = calcEv.center; deltaTime = ev.timeStamp - calcEv.timeStamp; deltaX = ev.center.clientX - calcEv.center.clientX; deltaY = ev.center.clientY - calcEv.center.clientY; recalc = true; } if (ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { cur.futureCalcEvent = ev; } if (!cur.lastCalcEvent || recalc) { calcData.velocity = Utils.getVelocity(deltaTime, deltaX, deltaY); calcData.angle = Utils.getAngle(center, ev.center); calcData.direction = Utils.getDirection(center, ev.center); cur.lastCalcEvent = cur.futureCalcEvent || ev; cur.futureCalcEvent = ev; } ev.velocityX = calcData.velocity.x; ev.velocityY = calcData.velocity.y; ev.interimAngle = calcData.angle; ev.interimDirection = calcData.direction; }, /** * extend eventData for GestureDetector.gestures * @param {Object} ev * @return {Object} ev */ extendEventData: function extendEventData(ev) { var cur = this.current, startEv = cur.startEvent, lastEv = cur.lastEvent || startEv; // update the start touchlist to calculate the scale/rotation if (ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { startEv.touches = []; Utils.each(ev.touches, function (touch) { startEv.touches.push({ clientX: touch.clientX, clientY: touch.clientY }); }); } var deltaTime = ev.timeStamp - startEv.timeStamp, deltaX = ev.center.clientX - startEv.center.clientX, deltaY = ev.center.clientY - startEv.center.clientY; this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY); Utils.extend(ev, { startEvent: startEv, deltaTime: deltaTime, deltaX: deltaX, deltaY: deltaY, distance: Utils.getDistance(startEv.center, ev.center), angle: Utils.getAngle(startEv.center, ev.center), direction: Utils.getDirection(startEv.center, ev.center), scale: Utils.getScale(startEv.touches, ev.touches), rotation: Utils.getRotation(startEv.touches, ev.touches) }); return ev; }, /** * register new gesture * @param {Object} gesture object, see `gestures/` for documentation * @return {Array} gestures */ register: function register(gesture) { // add an enable gesture options if there is no given var options = gesture.defaults || {}; if (options[gesture.name] === undefined) { options[gesture.name] = true; } // extend GestureDetector default options with the GestureDetector.gesture options Utils.extend(GestureDetector.defaults, options, true); // set its index gesture.index = gesture.index || 1000; // add GestureDetector.gesture to the list this.gestures.push(gesture); // sort the list by index this.gestures.sort(function (a, b) { if (a.index < b.index) { return -1; } if (a.index > b.index) { return 1; } return 0; }); return this.gestures; } }; /** * @module GestureDetector */ /** * create new GestureDetector instance * all methods should return the instance itself, so it is chainable. * * @class Instance * @constructor * @param {HTMLElement} element * @param {Object} [options={}] options are merged with `GestureDetector.defaults` * @return {GestureDetector.Instance} */ GestureDetector.Instance = function (element, options) { var self = this; var listenerOptions = options && options.passive ? { passive: true } : undefined; // setup GestureDetectorJS window events and register all gestures // this also sets up the default options setup(listenerOptions); /** * @property element * @type {HTMLElement} */ this.element = element; /** * @property enabled * @type {Boolean} * @protected */ this.enabled = true; /** * options, merged with the defaults * options with an _ are converted to camelCase * @property options * @type {Object} */ Utils.each(options, function (value, name) { delete options[name]; options[Utils.toCamelCase(name)] = value; }); this.options = Utils.extend(Utils.extend({}, GestureDetector.defaults), options || {}); this.options.listenerOptions = listenerOptions; // add some css to the element to prevent the browser from doing its native behavior if (this.options.behavior) { Utils.toggleBehavior(this.element, this.options.behavior, true); } /** * event start handler on the element to start the detection * @property eventStartHandler * @type {Object} */ this.eventStartHandler = Event$1.onTouch(element, EVENT_START, function (ev) { if (self.enabled && ev.eventType == EVENT_START) { Detection.startDetect(self, ev); } else if (ev.eventType == EVENT_TOUCH) { Detection.detect(ev); } }, listenerOptions); /** * keep a list of user event handlers which needs to be removed when calling 'dispose' * @property eventHandlers * @type {Array} */ this.eventHandlers = []; }; GestureDetector.Instance.prototype = { /** * @method on * @signature on(gestures, handler) * @description * [en]Adds an event handler for a gesture. Available gestures are: drag, dragleft, dragright, dragup, dragdown, hold, release, swipe, swipeleft, swiperight, swipeup, swipedown, tap, doubletap, touch, transform, pinch, pinchin, pinchout and rotate. [/en] * [ja]ジェスチャに対するイベントハンドラを追加します。指定できるジェスチャ名は、drag dragleft dragright dragup dragdown hold release swipe swipeleft swiperight swipeup swipedown tap doubletap touch transform pinch pinchin pinchout rotate です。[/ja] * @param {String} gestures * [en]A space separated list of gestures.[/en] * [ja]検知するジェスチャ名を指定します。スペースで複数指定することができます。[/ja] * @param {Function} handler * [en]An event handling function.[/en] * [ja]イベントハンドラとなる関数オブジェクトを指定します。[/ja] */ on: function onEvent(gestures, handler, opt) { var self = this; Event$1.on(self.element, gestures, handler, util$1.extend({}, self.options.listenerOptions, opt), function (type) { self.eventHandlers.push({ gesture: type, handler: handler }); }); return self; }, /** * @method off * @signature off(gestures, handler) * @description * [en]Remove an event listener.[/en] * [ja]イベントリスナーを削除します。[/ja] * @param {String} gestures * [en]A space separated list of gestures.[/en] * [ja]ジェスチャ名を指定します。スペースで複数指定することができます。[/ja] * @param {Function} handler * [en]An event handling function.[/en] * [ja]イベントハンドラとなる関数オブジェクトを指定します。[/ja] */ off: function offEvent(gestures, handler, opt) { var self = this; Event$1.off(self.element, gestures, handler, util$1.extend({}, self.options.listenerOptions, opt), function (type) { var index = Utils.inArray(self.eventHandlers, { gesture: type, handler: handler }, true); if (index >= 0) { self.eventHandlers.splice(index, 1); } }); return self; }, /** * trigger gesture event * @method trigger * @signature trigger(gesture, eventData) * @param {String} gesture * @param {Object} [eventData] */ trigger: function triggerEvent(gesture, eventData) { // optional if (!eventData) { eventData = {}; } // create DOM event var event = GestureDetector.DOCUMENT.createEvent('Event'); event.initEvent(gesture, true, true); event.gesture = eventData; // trigger on the target if it is in the instance element, // this is for event delegation tricks var element = this.element; if (Utils.hasParent(eventData.target, element)) { element = eventData.target; } element.dispatchEvent(event); return this; }, /** * @method enable * @signature enable(state) * @description * [en]Enable or disable gesture detection.[/en] * [ja]ジェスチャ検知を有効化/無効化します。[/ja] * @param {Boolean} state * [en]Specify if it should be enabled or not.[/en] * [ja]有効にするかどうかを指定します。[/ja] */ enable: function enable(state) { this.enabled = state; return this; }, /** * @method dispose * @signature dispose() * @description * [en]Remove and destroy all event handlers for this instance.[/en] * [ja]このインスタンスでのジェスチャの検知や、イベントハンドラを全て解除して廃棄します。[/ja] */ dispose: function dispose() { var i, eh; // undo all changes made by stop_browser_behavior Utils.toggleBehavior(this.element, this.options.behavior, false); // unbind all custom event handlers for (i = -1; eh = this.eventHandlers[++i];) { // eslint-disable-line no-cond-assign Utils.off(this.element, eh.gesture, eh.handler); } this.eventHandlers = []; // unbind the start event listener Event$1.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler); return null; } }; /** * @module gestures */ /** * Move with x fingers (default 1) around on the page. * Preventing the default browser behavior is a good way to improve feel and working. * ```` * GestureDetectortime.on("drag", function(ev) { * console.log(ev); * ev.gesture.preventDefault(); * }); * ```` * * @class Drag * @static */ /** * @event drag * @param {Object} ev */ /** * @event dragstart * @param {Object} ev */ /** * @event dragend * @param {Object} ev */ /** * @event drapleft * @param {Object} ev */ /** * @event dragright * @param {Object} ev */ /** * @event dragup * @param {Object} ev */ /** * @event dragdown * @param {Object} ev */ /** * @param {String} name */ (function (name) { var triggered = false; function dragGesture(ev, inst) { var cur = Detection.current; // max touches if (inst.options.dragMaxTouches > 0 && ev.touches.length > inst.options.dragMaxTouches) { return; } switch (ev.eventType) { case EVENT_START: triggered = false; break; case EVENT_MOVE: // when the distance we moved is too small we skip this gesture // or we can be already in dragging if (ev.distance < inst.options.dragMinDistance && cur.name != name) { return; } var startCenter = cur.startEvent.center; // we are dragging! if (cur.name != name) { cur.name = name; if (inst.options.dragDistanceCorrection && ev.distance > 0) { // When a drag is triggered, set the event center to dragMinDistance pixels from the original event center. // Without this correction, the dragged distance would jumpstart at dragMinDistance pixels instead of at 0. // It might be useful to save the original start point somewhere var factor = Math.abs(inst.options.dragMinDistance / ev.distance); startCenter.pageX += ev.deltaX * factor; startCenter.pageY += ev.deltaY * factor; startCenter.clientX += ev.deltaX * factor; startCenter.clientY += ev.deltaY * factor; // recalculate event data using new start point ev = Detection.extendEventData(ev); } } // lock drag to axis? if (cur.lastEvent.dragLockToAxis || inst.options.dragLockToAxis && inst.options.dragLockMinDistance <= ev.distance) { ev.dragLockToAxis = true; } // keep direction on the axis that the drag gesture started on var lastDirection = cur.lastEvent.direction; if (ev.dragLockToAxis && lastDirection !== ev.direction) { if (Utils.isVertical(lastDirection)) { ev.direction = ev.deltaY < 0 ? DIRECTION_UP : DIRECTION_DOWN; } else { ev.direction = ev.deltaX < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; } } // first time, trigger dragstart event if (!triggered) { inst.trigger(name + 'start', ev); triggered = true; } // trigger events inst.trigger(name, ev); inst.trigger(name + ev.direction, ev); var isVertical = Utils.isVertical(ev.direction); // block the browser events if (inst.options.dragBlockVertical && isVertical || inst.options.dragBlockHorizontal && !isVertical) { ev.preventDefault(); } break; case EVENT_RELEASE: if (triggered && ev.changedLength <= inst.options.dragMaxTouches) { inst.trigger(name + 'end', ev); triggered = false; } break; case EVENT_END: triggered = false; break; } } GestureDetector.gestures.Drag = { name: name, index: 50, handler: dragGesture, defaults: { /** * minimal movement that have to be made before the drag event gets triggered * @property dragMinDistance * @type {Number} * @default 10 */ dragMinDistance: 10, /** * Set dragDistanceCorrection to true to make the starting point of the drag * be calculated from where the drag was triggered, not from where the touch started. * Useful to avoid a jerk-starting drag, which can make fine-adjustments * through dragging difficult, and be visually unappealing. * @property dragDistanceCorrection * @type {Boolean} * @default true */ dragDistanceCorrection: true, /** * set 0 for unlimited, but this can conflict with transform * @property dragMaxTouches * @type {Number} * @default 1 */ dragMaxTouches: 1, /** * prevent default browser behavior when dragging occurs * be careful with it, it makes the element a blocking element * when you are using the drag gesture, it is a good practice to set this true * @property dragBlockHorizontal * @type {Boolean} * @default false */ dragBlockHorizontal: false, /** * same as `dragBlockHorizontal`, but for vertical movement * @property dragBlockVertical * @type {Boolean} * @default false */ dragBlockVertical: false, /** * dragLockToAxis keeps the drag gesture on the axis that it started on, * It disallows vertical directions if the initial direction was horizontal, and vice versa. * @property dragLockToAxis * @type {Boolean} * @default false */ dragLockToAxis: false, /** * drag lock only kicks in when distance > dragLockMinDistance * This way, locking occurs only when the distance has become large enough to reliably determine the direction * @property dragLockMinDistance * @type {Number} * @default 25 */ dragLockMinDistance: 25 } }; })('drag'); /** * @module gestures */ /** * trigger a simple gesture event, so you can do anything in your handler. * only usable if you know what your doing... * * @class Gesture * @static */ /** * @event gesture * @param {Object} ev */ GestureDetector.gestures.Gesture = { name: 'gesture', index: 1337, handler: function releaseGesture(ev, inst) { inst.trigger(this.name, ev); } }; /** * @module gestures */ /** * Touch stays at the same place for x time * * @class Hold * @static */ /** * @event hold * @param {Object} ev */ /** * @param {String} name */ (function (name) { var timer; function holdGesture(ev, inst) { var options = inst.options, current = Detection.current; switch (ev.eventType) { case EVENT_START: clearTimeout(timer); // set the gesture so we can check in the timeout if it still is current.name = name; // set timer and if after the timeout it still is hold, // we trigger the hold event timer = setTimeout(function () { if (current && current.name == name) { inst.trigger(name, ev); } }, options.holdTimeout); break; case EVENT_MOVE: if (ev.distance > options.holdThreshold) { clearTimeout(timer); } break; case EVENT_RELEASE: clearTimeout(timer); break; } } GestureDetector.gestures.Hold = { name: name, index: 10, defaults: { /** * @property holdTimeout * @type {Number} * @default 500 */ holdTimeout: 500, /** * movement allowed while holding * @property holdThreshold * @type {Number} * @default 2 */ holdThreshold: 2 }, handler: holdGesture }; })('hold'); /** * @module gestures */ /** * when a touch is being released from the page * * @class Release * @static */ /** * @event release * @param {Object} ev */ GestureDetector.gestures.Release = { name: 'release', index: Infinity, handler: function releaseGesture(ev, inst) { if (ev.eventType == EVENT_RELEASE) { inst.trigger(this.name, ev); } } }; /** * @module gestures */ /** * triggers swipe events when the end velocity is above the threshold * for best usage, set `preventDefault` (on the drag gesture) to `true` * ```` * GestureDetectortime.on("dragleft swipeleft", function(ev) { * console.log(ev); * ev.gesture.preventDefault(); * }); * ```` * * @class Swipe * @static */ /** * @event swipe * @param {Object} ev */ /** * @event swipeleft * @param {Object} ev */ /** * @event swiperight * @param {Object} ev */ /** * @event swipeup * @param {Object} ev */ /** * @event swipedown * @param {Object} ev */ GestureDetector.gestures.Swipe = { name: 'swipe', index: 40, defaults: { /** * @property swipeMinTouches * @type {Number} * @default 1 */ swipeMinTouches: 1, /** * @property swipeMaxTouches * @type {Number} * @default 1 */ swipeMaxTouches: 1, /** * horizontal swipe velocity * @property swipeVelocityX * @type {Number} * @default 0.6 */ swipeVelocityX: 0.6, /** * vertical swipe velocity * @property swipeVelocityY * @type {Number} * @default 0.6 */ swipeVelocityY: 0.6 }, handler: function swipeGesture(ev, inst) { if (ev.eventType == EVENT_RELEASE) { var touches = ev.touches.length, options = inst.options; // max touches if (touches < options.swipeMinTouches || touches > options.swipeMaxTouches) { return; } // when the distance we moved is too small we skip this gesture // or we can be already in dragging if (ev.velocityX > options.swipeVelocityX || ev.velocityY > options.swipeVelocityY) { // trigger swipe events inst.trigger(this.name, ev); inst.trigger(this.name + ev.direction, ev); } } } }; /** * @module gestures */ /** * Single tap and a double tap on a place * * @class Tap * @static */ /** * @event tap * @param {Object} ev */ /** * @event doubletap * @param {Object} ev */ /** * @param {String} name */ (function (name) { var hasMoved = false; function tapGesture(ev, inst) { var options = inst.options, current = Detection.current, prev = Detection.previous, sincePrev, didDoubleTap; switch (ev.eventType) { case EVENT_START: hasMoved = false; break; case EVENT_MOVE: hasMoved = hasMoved || ev.distance > options.tapMaxDistance; break; case EVENT_END: if (!Utils.inStr(ev.srcEvent.type, 'cancel') && ev.deltaTime < options.tapMaxTime && !hasMoved) { // previous gesture, for the double tap since these are two different gesture detections sincePrev = prev && prev.lastEvent && ev.timeStamp - prev.lastEvent.timeStamp; didDoubleTap = false; // check if double tap if (prev && prev.name == name && sincePrev && sincePrev < options.doubleTapInterval && ev.distance < options.doubleTapDistance) { inst.trigger('doubletap', ev); didDoubleTap = true; } // do a single tap if (!didDoubleTap || options.tapAlways) { current.name = name; inst.trigger(current.name, ev); } } break; } } GestureDetector.gestures.Tap = { name: name, index: 100, handler: tapGesture, defaults: { /** * max time of a tap, this is for the slow tappers * @property tapMaxTime * @type {Number} * @default 250 */ tapMaxTime: 250, /** * max distance of movement of a tap, this is for the slow tappers * @property tapMaxDistance * @type {Number} * @default 10 */ tapMaxDistance: 10, /** * always trigger the `tap` event, even while double-tapping * @property tapAlways * @type {Boolean} * @default true */ tapAlways: true, /** * max distance between two taps * @property doubleTapDistance * @type {Number} * @default 20 */ doubleTapDistance: 20, /** * max time between two taps * @property doubleTapInterval * @type {Number} * @default 300 */ doubleTapInterval: 300 } }; })('tap'); /** * @module gestures */ /** * when a touch is being touched at the page * * @class Touch * @static */ /** * @event touch * @param {Object} ev */ GestureDetector.gestures.Touch = { name: 'touch', index: -Infinity, defaults: { /** * call preventDefault at touchstart, and makes the element blocking by disabling the scrolling of the page, * but it improves gestures like transforming and dragging. * be careful with using this, it can be very annoying for users to be stuck on the page * @property preventDefault * @type {Boolean} * @default false */ preventDefault: false, /** * disable mouse events, so only touch (or pen!) input triggers events * @property preventMouse * @type {Boolean} * @default false */ preventMouse: false }, handler: function touchGesture(ev, inst) { if (inst.options.preventMouse && ev.pointerType == POINTER_MOUSE) { ev.stopDetect(); return; } if (inst.options.preventDefault) { ev.preventDefault(); } if (ev.eventType == EVENT_TOUCH) { inst.trigger('touch', ev); } } }; /** * @module gestures */ /** * User want to scale or rotate with 2 fingers * Preventing the default browser behavior is a good way to improve feel and working. This can be done with the * `preventDefault` option. * * @class Transform * @static */ /** * @event transform * @param {Object} ev */ /** * @event transformstart * @param {Object} ev */ /** * @event transformend * @param {Object} ev */ /** * @event pinchin * @param {Object} ev */ /** * @event pinchout * @param {Object} ev */ /** * @event rotate * @param {Object} ev */ /** * @param {String} name */ (function (name) { var triggered = false; function transformGesture(ev, inst) { switch (ev.eventType) { case EVENT_START: triggered = false; break; case EVENT_MOVE: // at least multitouch if (ev.touches.length < 2) { return; } var scaleThreshold = Math.abs(1 - ev.scale); var rotationThreshold = Math.abs(ev.rotation); // when the distance we moved is too small we skip this gesture // or we can be already in dragging if (scaleThreshold < inst.options.transformMinScale && rotationThreshold < inst.options.transformMinRotation) { return; } // we are transforming! Detection.current.name = name; // first time, trigger dragstart event if (!triggered) { inst.trigger(name + 'start', ev); triggered = true; } inst.trigger(name, ev); // basic transform event // trigger rotate event if (rotationThreshold > inst.options.transformMinRotation) { inst.trigger('rotate', ev); } // trigger pinch event if (scaleThreshold > inst.options.transformMinScale) { inst.trigger('pinch', ev); inst.trigger('pinch' + (ev.scale < 1 ? 'in' : 'out'), ev); } break; case EVENT_RELEASE: if (triggered && ev.changedLength < 2) { inst.trigger(name + 'end', ev); triggered = false; } break; } } GestureDetector.gestures.Transform = { name: name, index: 45, defaults: { /** * minimal scale factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1 * @property transformMinScale * @type {Number} * @default 0.01 */ transformMinScale: 0.01, /** * rotation in degrees * @property transformMinRotation * @type {Number} * @default 1 */ transformMinRotation: 1 }, handler: transformGesture }; })('transform'); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var readyMap = void 0; var queueMap = void 0; function isContentReady(element) { if (element.childNodes.length > 0) { setContentReady(element); } return readyMap.has(element); } function setContentReady(element) { readyMap.set(element, true); } function addCallback(element, fn) { if (!queueMap.has(element)) { queueMap.set(element, []); } queueMap.get(element).push(fn); } function consumeQueue(element) { var callbacks = queueMap.get(element, []) || []; queueMap.delete(element); callbacks.forEach(function (callback) { return callback(); }); } function contentReady(element) { var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; if (readyMap === undefined) { readyMap = new WeakMap(); queueMap = new WeakMap(); } addCallback(element, fn); if (isContentReady(element)) { consumeQueue(element); return; } var observer = new MutationObserver(function (changes) { setContentReady(element); consumeQueue(element); }); observer.observe(element, { childList: true, characterData: true }); // failback for elements has empty content. setImmediate(function () { setContentReady(element); consumeQueue(element); }); } /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var ToastQueue = function () { function ToastQueue() { classCallCheck(this, ToastQueue); this.queue = []; } createClass(ToastQueue, [{ key: "add", value: function add(fn, promise) { var _this = this; this.queue.push(fn); if (this.queue.length === 1) { setImmediate(this.queue[0]); } promise.then(function () { _this.queue.shift(); if (_this.queue.length > 0) { setTimeout(_this.queue[0], 1000 / 30); // Apply some visual delay } }); } }]); return ToastQueue; }(); var ToastQueue$1 = new ToastQueue(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var _setAttributes = function _setAttributes(element, options) { ['id', 'class', 'animation'].forEach(function (a) { return options.hasOwnProperty(a) && element.setAttribute(a, options[a]); }); if (options.modifier) { util$1.addModifier(element, options.modifier); } }; var _normalizeArguments = function _normalizeArguments(message) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var defaults$$1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; options = _extends({}, options); typeof message === 'string' ? options.message = message : options = message; if (!options || !options.message && !options.messageHTML) { util$1.throw('Notifications must contain a message'); } if (options.hasOwnProperty('buttonLabels') || options.hasOwnProperty('buttonLabel')) { options.buttonLabels = options.buttonLabels || options.buttonLabel; if (!Array.isArray(options.buttonLabels)) { options.buttonLabels = [options.buttonLabels || '']; } } return util$1.extend({ compile: function compile(param) { return param; }, callback: function callback(param) { return param; }, animation: 'default', cancelable: false, primaryButtonIndex: (options.buttonLabels || defaults$$1.buttonLabels || []).length - 1 }, defaults$$1, options); }; /** * @object ons.notification * @category dialog * @tutorial vanilla/Reference/notification * @description * [en] * Utility methods to create different kinds of notifications. There are three methods available: * * * `ons.notification.alert()` * * `ons.notification.confirm()` * * `ons.notification.prompt()` * * `ons.notification.toast()` * * It will automatically display a Material Design dialog on Android devices. * [/en] * [ja]いくつかの種類のアラートダイアログを作成するためのユーティリティメソッドを収めたオブジェクトです。[/ja] * @example * ons.notification.alert('Hello, world!'); * * ons.notification.confirm('Are you ready?') * .then( * function(answer) { * if (answer === 1) { * ons.notification.alert('Let\'s go!'); * } * } * ); * * ons.notification.prompt('How old are ?') * .then( * function(age) { * ons.notification.alert('You are ' + age + ' years old.'); * } * ); */ var notification = {}; notification._createAlertDialog = function () { for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) { params[_key] = arguments[_key]; } return new Promise(function (resolve) { var options = _normalizeArguments.apply(undefined, params); util$1.checkMissingImport('AlertDialog', 'AlertDialogButton'); // Prompt input string var inputString = ''; if (options.isPrompt) { inputString = '\n <input\n class="text-input text-input--underbar"\n type="' + (options.inputType || 'text') + '"\n placeholder="' + (options.placeholder || '') + '"\n value="' + (options.defaultValue || '') + '"\n style="width: 100%; margin-top: 10px;"\n />\n '; } // Buttons string var buttons = ''; options.buttonLabels.forEach(function (label, index) { buttons += '\n <ons-alert-dialog-button\n class="\n ' + (index === options.primaryButtonIndex ? ' alert-dialog-button--primal' : '') + '\n ' + (options.buttonLabels.length <= 2 ? ' alert-dialog-button--rowfooter' : '') + '\n "\n style="position: relative;">\n ' + label + '\n </ons-alert-dialog-button>\n '; }); // Dialog Element var el = {}; var _destroyDialog = function _destroyDialog() { if (el.dialog.onDialogCancel) { el.dialog.removeEventListener('dialog-cancel', el.dialog.onDialogCancel); } Object.keys(el).forEach(function (key) { return delete el[key]; }); el = null; if (options.destroy instanceof Function) { options.destroy(); } }; el.dialog = document.createElement('ons-alert-dialog'); el.dialog.innerHTML = '\n <div class="alert-dialog-mask"\n style="\n ' + (options.maskColor ? 'background-color: ' + options.maskColor : '') + '\n "></div>\n <div class="alert-dialog">\n <div class="alert-dialog-container">\n <div class="alert-dialog-title">\n ' + (options.title || '') + '\n </div>\n <div class="alert-dialog-content">\n ' + (options.message || options.messageHTML) + '\n ' + inputString + '\n </div>\n <div class="\n alert-dialog-footer\n ' + (options.buttonLabels.length <= 2 ? ' alert-dialog-footer--rowfooter' : '') + '\n ">\n ' + buttons + '\n </div>\n </div>\n </div>\n '; contentReady(el.dialog); // Set attributes _setAttributes(el.dialog, options); // Prompt events if (options.isPrompt && options.submitOnEnter) { el.input = el.dialog.querySelector('.text-input'); el.input.onkeypress = function (event) { if (event.keyCode === 13) { el.dialog.hide().then(function () { if (el) { var resolveValue = el.input.value; _destroyDialog(); options.callback(resolveValue); resolve(resolveValue); } }); } }; } // Button events el.footer = el.dialog.querySelector('.alert-dialog-footer'); util$1.arrayFrom(el.dialog.querySelectorAll('.alert-dialog-button')).forEach(function (buttonElement, index) { buttonElement.onclick = function () { el.dialog.hide().then(function () { if (el) { var resolveValue = index; if (options.isPrompt) { resolveValue = index === options.primaryButtonIndex ? el.input.value : null; } el.dialog.remove(); _destroyDialog(); options.callback(resolveValue); resolve(resolveValue); } }); }; el.footer.appendChild(buttonElement); }); // Cancel events if (options.cancelable) { el.dialog.cancelable = true; el.dialog.onDialogCancel = function () { setImmediate(function () { el.dialog.remove(); _destroyDialog(); }); var resolveValue = options.isPrompt ? null : -1; options.callback(resolveValue); resolve(resolveValue); }; el.dialog.addEventListener('dialog-cancel', el.dialog.onDialogCancel, false); } // Show dialog document.body.appendChild(el.dialog); options.compile(el.dialog); setImmediate(function () { el.dialog.show().then(function () { if (el.input && options.isPrompt && options.autofocus) { var strLength = el.input.value.length; el.input.focus(); el.input.setSelectionRange(strLength, strLength); } }); }); }); }; /** * @method alert * @signature alert(message [, options] | options) * @return {Promise} * [en]Will resolve to the index of the button that was pressed or `-1` when canceled.[/en] * [ja][/ja] * @param {String} message * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en] * [ja][/ja] * @param {Object} options * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクトです。[/ja] * @param {String} [options.message] * [en]Notification message.[/en] * [ja]アラートダイアログに表示する文字列を指定します。[/ja] * @param {String} [options.messageHTML] * [en]Notification message in HTML.[/en] * [ja]アラートダイアログに表示するHTMLを指定します。[/ja] * @param {String | Array} [options.buttonLabels] * [en]Labels for the buttons. Default is `"OK"`.[/en] * [ja]確認ボタンのラベルを指定します。"OK"がデフォルトです。[/ja] * @param {Number} [options.primaryButtonIndex] * [en]Index of primary button. Default is the last one.[/en] * [ja]プライマリボタンのインデックスを指定します。デフォルトは 0 です。[/ja] * @param {Boolean} [options.cancelable] * [en]Whether the dialog is cancelable or not. Default is `false`. If the dialog is cancelable it can be closed by clicking the background or pressing the Android back button.[/en] * [ja]ダイアログがキャンセル可能かどうかを指定します。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `none` and `fade`. Default is `fade`.[/en] * [ja]アラートダイアログを表示する際のアニメーション名を指定します。"none", "fade"のいずれかを指定できます。[/ja] * @param {String} [options.id] * [en]The `<ons-alert-dialog>` element's ID.[/en] * [ja]ons-alert-dialog要素のID。[/ja] * @param {String} [options.class] * [en]The `<ons-alert-dialog>` element's class.[/en] * [ja]ons-alert-dialog要素のclass。[/ja] * @param {String} [options.title] * [en]Dialog title. Default is `"Alert"`.[/en] * [ja]アラートダイアログの上部に表示するタイトルを指定します。"Alert"がデフォルトです。[/ja] * @param {String} [options.modifier] * [en]Modifier for the dialog.[/en] * [ja]アラートダイアログのmodifier属性の値を指定します。[/ja] * @param {String} [options.maskColor] * [en]Color of the background mask. Default is "rgba(0, 0, 0, 0.2)" ("rgba(0, 0, 0, 0.3)" for Material).[/en] * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja] * @param {Function} [options.callback] * [en]Function that executes after dialog has been closed.[/en] * [ja]アラートダイアログが閉じられた時に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en] * Display an alert dialog to show the user a message. * * The content of the message can be either simple text or HTML. * * It can be called in the following ways: * * ``` * ons.notification.alert(message, options); * ons.notification.alert(options); * ``` * * Must specify either `message` or `messageHTML`. * [/en] * [ja] * ユーザーへメッセージを見せるためのアラートダイアログを表示します。 * 表示するメッセージは、テキストかもしくはHTMLを指定できます。 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。 * [/ja] */ notification.alert = function (message, options) { return notification._createAlertDialog(message, options, { buttonLabels: ['OK'], title: 'Alert' }); }; /** * @method confirm * @signature confirm(message [, options] | options) * @return {Promise} * [en]Will resolve to the index of the button that was pressed or `-1` when canceled.[/en] * [ja][/ja] * @param {String} message * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en] * [ja][/ja] * @param {Object} options * [en]Parameter object.[/en] * @param {Array} [options.buttonLabels] * [en]Labels for the buttons. Default is `["Cancel", "OK"]`.[/en] * [ja]ボタンのラベルの配列を指定します。["Cancel", "OK"]がデフォルトです。[/ja] * @param {Number} [options.primaryButtonIndex] * [en]Index of primary button. Default is the last one.[/en] * [ja]プライマリボタンのインデックスを指定します。デフォルトは 1 です。[/ja] * @description * [en] * Display a dialog to ask the user for confirmation. Extends `alert()` parameters. * The default button labels are `"Cancel"` and `"OK"` but they can be customized. * * It can be called in the following ways: * * ``` * ons.notification.confirm(message, options); * ons.notification.confirm(options); * ``` * * Must specify either `message` or `messageHTML`. * [/en] * [ja] * ユーザに確認を促すダイアログを表示します。 * デオルとのボタンラベルは、"Cancel"と"OK"ですが、これはこのメソッドの引数でカスタマイズできます。 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。 * [/ja] */ notification.confirm = function (message, options) { return notification._createAlertDialog(message, options, { buttonLabels: ['Cancel', 'OK'], title: 'Confirm' }); }; /** * @method prompt * @signature prompt(message [, options] | options) * @param {String} message * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en] * [ja][/ja] * @return {Promise} * [en]Will resolve to the input value when the dialog is closed or `null` when canceled.[/en] * [ja][/ja] * @param {Object} options * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクトです。[/ja] * @param {String | Array} [options.buttonLabels] * [en]Labels for the buttons. Default is `"OK"`.[/en] * [ja]確認ボタンのラベルを指定します。"OK"がデフォルトです。[/ja] * @param {Number} [options.primaryButtonIndex] * [en]Index of primary button. Default is the last one.[/en] * [ja]プライマリボタンのインデックスを指定します。デフォルトは 0 です。[/ja] * @param {String} [options.placeholder] * [en]Placeholder for the text input.[/en] * [ja]テキスト欄のプレースホルダに表示するテキストを指定します。[/ja] * @param {String} [options.defaultValue] * [en]Default value for the text input.[/en] * [ja]テキスト欄のデフォルトの値を指定します。[/ja] * @param {String} [options.inputType] * [en]Type of the input element (`password`, `date`...). Default is `text`.[/en] * [ja][/ja] * @param {Boolean} [options.autofocus] * [en]Autofocus the input element. Default is `true`. In Cordova, `KeyboardDisplayRequiresUserAction` in `config.xml` must be `false` to activate this feature.[/en] * [ja]input要素に自動的にフォーカスするかどうかを指定します。デフォルトはtrueです。Cordova環境では、この機能を有効にするためには `config.xml` で `KeyboardDisplayRequiresUserAction` を `false` に設定する必要があります。[/ja] * @param {Boolean} [options.submitOnEnter] * [en]Submit automatically when enter is pressed. Default is `true`.[/en] * [ja]Enterが押された際にそのformをsubmitするかどうかを指定します。デフォルトはtrueです。[/ja] * @description * [en] * Display a dialog with a prompt to ask the user a question. Extends `alert()` parameters. * * It can be called in the following ways: * * ``` * ons.notification.prompt(message, options); * ons.notification.prompt(options); * ``` * * Must specify either `message` or `messageHTML`. * [/en] * [ja] * ユーザーに入力を促すダイアログを表示します。 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。 * [/ja] */ notification.prompt = function (message, options) { return notification._createAlertDialog(message, options, { buttonLabels: ['OK'], title: 'Alert', isPrompt: true, autofocus: true, submitOnEnter: true }); }; /** * @method toast * @signature toast(message [, options] | options) * @return {Promise} * [en]Will resolve when the toast is hidden.[/en] * [ja][/ja] * @param {String} message * [en]Toast message. This argument is optional but if it's not defined then `options.message` must be defined instead.[/en] * [ja][/ja] * @param {Object} options * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクトです。[/ja] * @param {String} [options.message] * [en]Notification message.[/en] * [ja]トーストに表示する文字列を指定します。[/ja] * @param {String} [options.buttonLabel] * [en]Label for the button.[/en] * [ja]確認ボタンのラベルを指定します。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `none`, `fade`, `ascend`, `lift` and `fall`. Default is `ascend` for Android and `lift` for iOS.[/en] * [ja]トーストを表示する際のアニメーション名を指定します。"none", "fade", "ascend", "lift", "fall"のいずれかを指定できます。[/ja] * @param {Number} [options.timeout] * [en]Number of miliseconds where the toast is visible before hiding automatically.[/en] * [ja][/ja] * @param {Boolean} [options.force] * [en]If `true`, the toast skips the notification queue and is shown immediately. Defaults to `false`.[/en] * [ja][/ja] * @param {String} [options.id] * [en]The `<ons-toast>` element's ID.[/en] * [ja]ons-toast要素のID。[/ja] * @param {String} [options.class] * [en]The `<ons-toast>` element's class.[/en] * [ja]ons-toast要素のclass。[/ja] * @param {String} [options.modifier] * [en]Modifier for the element.[/en] * [ja]トーストのmodifier属性の値を指定します。[/ja] * @param {Function} [options.callback] * [en]Function that executes after toast has been hidden.[/en] * [ja]トーストが閉じられた時に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en] * Display a simple notification toast with an optional button that can be used for simple actions. * * It can be called in the following ways: * * ``` * ons.notification.toast(message, options); * ons.notification.toast(options); * ``` * [/en] * [ja][/ja] */ notification.toast = function (message, options) { var promise = new Promise(function (resolve) { util$1.checkMissingImport('Toast'); // Throws error, must be inside promise options = _normalizeArguments(message, options, { timeout: 0, force: false }); var toast = util$1.createElement('\n <ons-toast>\n ' + options.message + '\n ' + (options.buttonLabels ? '<button>' + options.buttonLabels[0] + '</button>' : '') + '\n </ons-toast>\n '); _setAttributes(toast, options); var finish = function finish(value) { if (toast) { toast.hide().then(function () { if (toast) { toast.remove(); toast = null; options.callback(value); resolve(value); } }); } }; if (options.buttonLabels) { util$1.findChild(toast._toast, 'button').onclick = function () { return finish(0); }; } document.body.appendChild(toast); options.compile(toast); var show = function show() { toast.parentElement && toast.show(options).then(function () { if (options.timeout) { setTimeout(function () { return finish(-1); }, options.timeout); } }); }; setImmediate(function () { return options.force ? show() : ToastQueue$1.add(show, promise); }); }); return promise; }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Validate parameters var checkOptions = function checkOptions(options) { var err = function err(prop) { var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Function'; return util$1.throw('"options.' + prop + '" must be an instance of ' + type); }; var hasOwnProperty = function hasOwnProperty(prop) { return Object.hasOwnProperty.call(options, prop); }; var instanceOf = function instanceOf(prop) { var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Function; return options[prop] instanceof type; }; var b = 'buttons', cb = 'callback', c = 'compile', d = 'destroy'; (!hasOwnProperty(b) || !instanceOf(b, Array)) && err(b, 'Array'); hasOwnProperty(cb) && !instanceOf(cb) && err(cb); hasOwnProperty(c) && !instanceOf(c) && err(c); hasOwnProperty(d) && !instanceOf(d) && err(d); }; // Action Sheet var actionSheet = (function () { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return new Promise(function (resolve) { util$1.checkMissingImport('ActionSheet'); checkOptions(options); // Main component var actionSheet = util$1.createElement('\n <ons-action-sheet\n ' + (options.title ? 'title="' + options.title + '"' : '') + '\n ' + (options.cancelable ? 'cancelable' : '') + '\n ' + (options.modifier ? 'modifier="' + options.modifier + '"' : '') + '\n ' + (options.maskColor ? 'mask-color="' + options.maskColor + '"' : '') + '\n ' + (options.id ? 'id="' + options.id + '"' : '') + '\n ' + (options.class ? 'class="' + options.class + '"' : '') + '\n >\n <div class="action-sheet"></div>\n </ons-action-sheet>\n '); // Resolve action and clean up var finish = function finish(event) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; if (actionSheet) { options.destroy && options.destroy(actionSheet); actionSheet.removeEventListener('dialog-cancel', finish, false); actionSheet.remove(); actionSheet = null; options.callback && options.callback(index); resolve(index); } }; // Link cancel handler actionSheet.addEventListener('dialog-cancel', finish, false); // Create buttons and link action handler var buttons = document.createDocumentFragment(); options.buttons.forEach(function (item, index) { var buttonOptions = typeof item === 'string' ? { label: item } : _extends({}, item); if (options.destructive === index) { buttonOptions.modifier = (buttonOptions.modifier || '') + ' destructive'; } var button = util$1.createElement('\n <ons-action-sheet-button\n ' + (buttonOptions.icon ? 'icon="' + buttonOptions.icon + '"' : '') + '\n ' + (buttonOptions.modifier ? 'modifier="' + buttonOptions.modifier + '"' : '') + '\n >\n ' + buttonOptions.label + '\n </ons-action-sheet-button>\n '); button.onclick = function (event) { return actionSheet.hide().then(function () { return finish(event, index); }); }; buttons.appendChild(button); }); // Finish component and attach util$1.findChild(actionSheet, '.action-sheet').appendChild(buttons); document.body.appendChild(actionSheet); options.compile && options.compile(el.dialog); // Show setImmediate(function () { return actionSheet.show({ animation: options.animation, animationOptions: options.animationOptions }); }); }); }); /** * MicroEvent - to make any js object an event emitter (server or browser) * * - pure javascript - server compatible, browser compatible * - dont rely on the browser doms * - super simple - you get it immediately, no mystery, no magic involved * * - create a MicroEventDebug with goodies to debug * - make it safer to use */ /** NOTE: This library is customized for Onsen UI. */ var MicroEvent = function MicroEvent() {}; MicroEvent.prototype = { on: function on(event, fct) { this._events = this._events || {}; this._events[event] = this._events[event] || []; this._events[event].push(fct); }, once: function once(event, fct) { var self = this; var wrapper = function wrapper() { self.off(event, wrapper); return fct.apply(null, arguments); }; this.on(event, wrapper); }, off: function off(event, fct) { this._events = this._events || {}; if (event in this._events === false) { return; } this._events[event] = this._events[event].filter(function (_fct) { if (fct) { return fct !== _fct; } else { return false; } }); }, emit: function emit(event /* , args... */) { this._events = this._events || {}; if (event in this._events === false) { return; } for (var i = 0; i < this._events[event].length; i++) { this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1)); } } }; /** * mixin will delegate all MicroEvent.js function in the destination object * * - require('MicroEvent').mixin(Foobar) will make Foobar able to use MicroEvent * * @param {Object} the object which will support MicroEvent */ MicroEvent.mixin = function (destObject) { var props = ['on', 'once', 'off', 'emit']; for (var i = 0; i < props.length; i++) { if (typeof destObject === 'function') { destObject.prototype[props[i]] = MicroEvent.prototype[props[i]]; } else { destObject[props[i]] = MicroEvent.prototype[props[i]]; } } }; window.MicroEvent = MicroEvent; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var create = function create() { /** * @object ons.orientation * @category util * @description * [en]Utility methods for orientation detection.[/en] * [ja]画面のオリエンテーション検知のためのユーティリティメソッドを収めているオブジェクトです。[/ja] */ var obj = { /** * @event change * @description * [en]Fired when the device orientation changes.[/en] * [ja]デバイスのオリエンテーションが変化した際に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクトです。[/ja] * @param {Boolean} event.isPortrait * [en]Will be true if the current orientation is portrait mode.[/en] * [ja]現在のオリエンテーションがportraitの場合にtrueを返します。[/ja] */ /** * @method on * @signature on(eventName, listener) * @description * [en]Add an event listener.[/en] * [ja]イベントリスナーを追加します。[/ja] * @param {String} eventName * [en]Name of the event.[/en] * [ja]イベント名を指定します。[/ja] * @param {Function} listener * [en]Function to execute when the event is triggered.[/en] * [ja]このイベントが発火された際に呼び出される関数オブジェクトを指定します。[/ja] */ /** * @method once * @signature once(eventName, listener) * @description * [en]Add an event listener that's only triggered once.[/en] * [ja]一度だけ呼び出されるイベントリスナーを追加します。[/ja] * @param {String} eventName * [en]Name of the event.[/en] * [ja]イベント名を指定します。[/ja] * @param {Function} listener * [en]Function to execute when the event is triggered.[/en] * [ja]イベントが発火した際に呼び出される関数オブジェクトを指定します。[/ja] */ /** * @method off * @signature off(eventName, [listener]) * @description * [en]Remove an event listener. If the listener is not specified all listeners for the event type will be removed.[/en] * [ja]イベントリスナーを削除します。もしイベントリスナーを指定しなかった場合には、そのイベントに紐づく全てのイベントリスナーが削除されます。[/ja] * @param {String} eventName * [en]Name of the event.[/en] * [ja]イベント名を指定します。[/ja] * @param {Function} listener * [en]Function to execute when the event is triggered.[/en] * [ja]削除するイベントリスナーを指定します。[/ja] */ // actual implementation to detect if whether current screen is portrait or not _isPortrait: false, /** * @method isPortrait * @signature isPortrait() * @return {Boolean} * [en]Will be true if the current orientation is portrait mode.[/en] * [ja]オリエンテーションがportraitモードの場合にtrueになります。[/ja] * @description * [en]Returns whether the current screen orientation is portrait or not.[/en] * [ja]オリエンテーションがportraitモードかどうかを返します。[/ja] */ isPortrait: function isPortrait() { return this._isPortrait(); }, /** * @method isLandscape * @signature isLandscape() * @return {Boolean} * [en]Will be true if the current orientation is landscape mode.[/en] * [ja]オリエンテーションがlandscapeモードの場合にtrueになります。[/ja] * @description * [en]Returns whether the current screen orientation is landscape or not.[/en] * [ja]オリエンテーションがlandscapeモードかどうかを返します。[/ja] */ isLandscape: function isLandscape() { return !this.isPortrait(); }, _init: function _init() { document.addEventListener('DOMContentLoaded', this._onDOMContentLoaded.bind(this), false); if ('orientation' in window) { window.addEventListener('orientationchange', this._onOrientationChange.bind(this), false); } else { window.addEventListener('resize', this._onResize.bind(this), false); } this._isPortrait = function () { return window.innerHeight > window.innerWidth; }; return this; }, _onDOMContentLoaded: function _onDOMContentLoaded() { this._installIsPortraitImplementation(); this.emit('change', { isPortrait: this.isPortrait() }); }, _installIsPortraitImplementation: function _installIsPortraitImplementation() { var isPortrait = window.innerWidth < window.innerHeight; if (!('orientation' in window)) { this._isPortrait = function () { return window.innerHeight > window.innerWidth; }; } else if (window.orientation % 180 === 0) { this._isPortrait = function () { return Math.abs(window.orientation % 180) === 0 ? isPortrait : !isPortrait; }; } else { this._isPortrait = function () { return Math.abs(window.orientation % 180) === 90 ? isPortrait : !isPortrait; }; } }, _onOrientationChange: function _onOrientationChange() { var _this = this; var isPortrait = this._isPortrait(); // Wait for the dimensions to change because // of Android inconsistency. var nIter = 0; var interval = setInterval(function () { nIter++; var w = window.innerWidth; var h = window.innerHeight; if (isPortrait && w <= h || !isPortrait && w >= h) { _this.emit('change', { isPortrait: isPortrait }); clearInterval(interval); } else if (nIter === 50) { _this.emit('change', { isPortrait: isPortrait }); clearInterval(interval); } }, 20); }, // Run on not mobile browser. _onResize: function _onResize() { this.emit('change', { isPortrait: this.isPortrait() }); } }; MicroEvent.mixin(obj); return obj; }; var orientation = create()._init(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @object ons.modifier * @category visual * @description * [en] * Utility methods to change modifier attributes of Onsen UI elements.. * [/en] * [ja][/ja] * @example * ons.modifier.add(myOnsInputElement, 'underbar'); * ons.modifier.toggle(myOnsToastElement, 'custom-modifier'); * */ var modifier = { /** * @method add * @signature add(element, modifier [, modifier]) * @description * [en]Add the specified modifiers to the element if they are not already included.[/en] * [ja][/ja] * @param {HTMLElement} element * [en]Target element.[/en] * [ja][/ja] * @param {String} modifier * [en]Name of the modifier.[/en] * [ja][/ja] */ add: function add(element) { for (var _len = arguments.length, modifiers = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { modifiers[_key - 1] = arguments[_key]; } return modifiers.forEach(function (modifier) { return util$1.addModifier(element, modifier); }); }, /** * @method remove * @signature remove(element, modifier [, modifier]) * @description * [en]Remove the specified modifiers from the element if they are included.[/en] * [ja][/ja] * @param {HTMLElement} element * [en]Target element.[/en] * [ja][/ja] * @param {String} modifier * [en]Name of the modifier.[/en] * [ja][/ja] */ remove: function remove(element) { for (var _len2 = arguments.length, modifiers = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { modifiers[_key2 - 1] = arguments[_key2]; } return modifiers.forEach(function (modifier) { return util$1.removeModifier(element, modifier); }); }, /** * @method contains * @signature contains(element, modifier) * @description * [en]Check whether the specified modifier is included in the element.[/en] * [ja][/ja] * @param {HTMLElement} element * [en]Target element.[/en] * [ja][/ja] * @param {String} modifier * [en]Name of the modifier.[/en] * [ja][/ja] * @return {Boolean} * [en]`true` when the specified modifier is found in the element's `modifier` attribute. `false` otherwise.[/en] * [ja][/ja] */ contains: util$1.hasModifier, /** * @method toggle * @signature toggle(element, modifier [, force]) * @description * [en]Toggle the specified modifier.[/en] * [ja][/ja] * @param {HTMLElement} element * [en]Target element.[/en] * [ja][/ja] * @param {String} modifier * [en]Name of the modifier.[/en] * [ja][/ja] * @param {String} force * [en]If it evaluates to true, add specified modifier value, and if it evaluates to false, remove it.[/en] * [ja][/ja] */ toggle: util$1.toggleModifier }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var softwareKeyboard = new MicroEvent(); softwareKeyboard._visible = false; var onShow = function onShow() { softwareKeyboard._visible = true; softwareKeyboard.emit('show'); }; var onHide = function onHide() { softwareKeyboard._visible = false; softwareKeyboard.emit('hide'); }; var bindEvents = function bindEvents() { if (typeof Keyboard !== 'undefined') { // https://github.com/martinmose/cordova-keyboard/blob/95f3da3a38d8f8e1fa41fbf40145352c13535a00/README.md Keyboard.onshow = onShow; Keyboard.onhide = onHide; softwareKeyboard.emit('init', { visible: Keyboard.isVisible }); return true; } else if (typeof cordova.plugins !== 'undefined' && typeof cordova.plugins.Keyboard !== 'undefined') { // https://github.com/driftyco/ionic-plugins-keyboard/blob/ca27ecf/README.md window.addEventListener('native.keyboardshow', onShow); window.addEventListener('native.keyboardhide', onHide); softwareKeyboard.emit('init', { visible: cordova.plugins.Keyboard.isVisible }); return true; } return false; }; var noPluginError = function noPluginError() { util$1.warn('ons-keyboard: Cordova Keyboard plugin is not present.'); }; document.addEventListener('deviceready', function () { if (!bindEvents()) { if (document.querySelector('[ons-keyboard-active]') || document.querySelector('[ons-keyboard-inactive]')) { noPluginError(); } softwareKeyboard.on = noPluginError; } }); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var generateId = function () { var i = 0; return function () { return i++; }; }(); /** * Door locking system. * * @param {Object} [options] * @param {Function} [options.log] */ var DoorLock = function () { function DoorLock() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; classCallCheck(this, DoorLock); this._lockList = []; this._waitList = []; this._log = options.log || function () {}; } /** * Register a lock. * * @return {Function} Callback for unlocking. */ createClass(DoorLock, [{ key: 'lock', value: function lock() { var _this = this; var unlock = function unlock() { _this._unlock(unlock); }; unlock.id = generateId(); this._lockList.push(unlock); this._log('lock: ' + unlock.id); return unlock; } }, { key: '_unlock', value: function _unlock(fn) { var index = this._lockList.indexOf(fn); if (index === -1) { throw new Error('This function is not registered in the lock list.'); } this._lockList.splice(index, 1); this._log('unlock: ' + fn.id); this._tryToFreeWaitList(); } }, { key: '_tryToFreeWaitList', value: function _tryToFreeWaitList() { while (!this.isLocked() && this._waitList.length > 0) { this._waitList.shift()(); } } /** * Register a callback for waiting unlocked door. * * @params {Function} callback Callback on unlocking the door completely. */ }, { key: 'waitUnlock', value: function waitUnlock(callback) { if (!(callback instanceof Function)) { throw new Error('The callback param must be a function.'); } if (this.isLocked()) { this._waitList.push(callback); } else { callback(); } } /** * @return {Boolean} */ }, { key: 'isLocked', value: function isLocked() { return this._lockList.length > 0; } }]); return DoorLock; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Default implementation for global PageLoader. function loadPage(_ref, done) { var page = _ref.page, parent = _ref.parent, _ref$params = _ref.params; internal$1.getPageHTMLAsync(page).then(function (html) { var pageElement = util$1.createElement(html); parent.appendChild(pageElement); done(pageElement); }); } function unloadPage(element) { if (element._destroy instanceof Function) { element._destroy(); } else { element.remove(); } } var PageLoader = function () { /** * @param {Function} [fn] Returns an object that has "element" property and "unload" function. */ function PageLoader(loader, unloader) { classCallCheck(this, PageLoader); this._loader = loader instanceof Function ? loader : loadPage; this._unloader = unloader instanceof Function ? unloader : unloadPage; } /** * Set internal loader implementation. */ createClass(PageLoader, [{ key: 'load', /** * @param {any} options.page * @param {Element} options.parent A location to load page. * @param {Object} [options.params] Extra parameters for ons-page. * @param {Function} done Take an object that has "element" property and "unload" function. */ value: function load(_ref2, done) { var page = _ref2.page, parent = _ref2.parent, _ref2$params = _ref2.params, params = _ref2$params === undefined ? {} : _ref2$params; this._loader({ page: page, parent: parent, params: params }, function (pageElement) { if (!(pageElement instanceof Element)) { throw Error('pageElement must be an instance of Element.'); } done(pageElement); }); } }, { key: 'unload', value: function unload(pageElement) { if (!(pageElement instanceof Element)) { throw Error('pageElement must be an instance of Element.'); } this._unloader(pageElement); } }, { key: 'internalLoader', set: function set$$1(fn) { if (!(fn instanceof Function)) { throw Error('First parameter must be an instance of Function'); } this._loader = fn; }, get: function get$$1() { return this._loader; } }]); return PageLoader; }(); var defaultPageLoader = new PageLoader(); var instantPageLoader = new PageLoader(function (_ref3, done) { var page = _ref3.page, parent = _ref3.parent, _ref3$params = _ref3.params; var element = util$1.createElement(page.trim()); parent.appendChild(element); done(element); }, unloadPage); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @object ons * @category util * @description * [ja]Onsen UIで利用できるグローバルなオブジェクトです。[/ja] * [en]A global object that's used in Onsen UI. [/en] */ var ons$1 = { animit: Animit, defaultPageLoader: defaultPageLoader, elements: onsElements, GestureDetector: GestureDetector, modifier: modifier, notification: notification, orientation: orientation, pageAttributeExpression: pageAttributeExpression, PageLoader: PageLoader, platform: platform, softwareKeyboard: softwareKeyboard, _autoStyle: autoStyle, _internal: internal$1, _readyLock: new DoorLock(), _util: util$1 }; ons$1.platform.select((window.location.search.match(/platform=([\w-]+)/) || [])[1]); waitDeviceReady(); var readyError = function readyError(after) { return util$1.throw('This method must be called ' + (after ? 'after' : 'before') + ' ons.isReady() is true'); }; /** * @method isReady * @signature isReady() * @return {Boolean} * [en]Will be true if Onsen UI is initialized.[/en] * [ja]初期化されているかどうかを返します。[/ja] * @description * [en]Returns true if Onsen UI is initialized.[/en] * [ja]Onsen UIがすでに初期化されているかどうかを返すメソッドです。[/ja] */ ons$1.isReady = function () { return !ons$1._readyLock.isLocked(); }; /** * @method isWebView * @signature isWebView() * @return {Boolean} * [en]Will be true if the app is running in Cordova.[/en] * [ja]Cordovaで実行されている場合にtrueになります。[/ja] * @description * [en]Returns true if running inside Cordova.[/en] * [ja]Cordovaで実行されているかどうかを返すメソッドです。[/ja] */ ons$1.isWebView = ons$1.platform.isWebView; /** * @method ready * @signature ready(callback) * @description * [ja]アプリの初期化に利用するメソッドです。渡された関数は、Onsen UIの初期化が終了している時点で必ず呼ばれます。[/ja] * [en]Method used to wait for app initialization. Waits for `DOMContentLoaded` and `deviceready`, when necessary, before executing the callback.[/en] * @param {Function} callback * [en]Function that executes after Onsen UI has been initialized.[/en] * [ja]Onsen UIが初期化が完了した後に呼び出される関数オブジェクトを指定します。[/ja] */ ons$1.ready = function (callback) { if (ons$1.isReady()) { callback(); } else { ons$1._readyLock.waitUnlock(callback); } }; /** * @method setDefaultDeviceBackButtonListener * @signature setDefaultDeviceBackButtonListener(listener) * @param {Function} listener * [en]Function that executes when device back button is pressed. Must be called on `ons.ready`.[/en] * [ja]デバイスのバックボタンが押された時に実行される関数オブジェクトを指定します。[/ja] * @description * [en]Set default handler for device back button.[/en] * [ja]デバイスのバックボタンのためのデフォルトのハンドラを設定します。[/ja] */ ons$1.setDefaultDeviceBackButtonListener = function (listener) { if (!ons$1.isReady()) { readyError(true); } ons$1._defaultDeviceBackButtonHandler.setListener(listener); }; /** * @method disableDeviceBackButtonHandler * @signature disableDeviceBackButtonHandler() * @description * [en]Disable device back button event handler. Must be called on `ons.ready`.[/en] * [ja]デバイスのバックボタンのイベントを受け付けないようにします。[/ja] */ ons$1.disableDeviceBackButtonHandler = function () { if (!ons$1.isReady()) { readyError(true); } internal$1.dbbDispatcher.disable(); }; /** * @method enableDeviceBackButtonHandler * @signature enableDeviceBackButtonHandler() * @description * [en]Enable device back button event handler. Must be called on `ons.ready`.[/en] * [ja]デバイスのバックボタンのイベントを受け付けるようにします。[/ja] */ ons$1.enableDeviceBackButtonHandler = function () { if (!ons$1.isReady()) { readyError(true); } internal$1.dbbDispatcher.enable(); }; ons$1.fireDeviceBackButtonEvent = function () { internal$1.dbbDispatcher.fireDeviceBackButtonEvent(); }; /** * @method enableAutoStatusBarFill * @signature enableAutoStatusBarFill() * @description * [en]Enable status bar fill feature on iOS7 and above (except for iPhone X). Must be called before `ons.ready`.[/en] * [ja]iOS7以上(iPhone Xは除く)で、ステータスバー部分の高さを自動的に埋める処理を有効にします。[/ja] */ ons$1.enableAutoStatusBarFill = function () { if (ons$1.isReady()) { readyError(false); } internal$1.config.autoStatusBarFill = true; }; /** * @method disableAutoStatusBarFill * @signature disableAutoStatusBarFill() * @description * [en]Disable status bar fill feature on iOS7 and above (except for iPhone X). Must be called before `ons.ready`.[/en] * [ja]iOS7以上(iPhone Xは除く)で、ステータスバー部分の高さを自動的に埋める処理を無効にします。[/ja] */ ons$1.disableAutoStatusBarFill = function () { if (ons$1.isReady()) { readyError(false); } internal$1.config.autoStatusBarFill = false; }; /** * @method mockStatusBar * @signature mockStatusBar() * @description * [en]Creates a static element similar to iOS status bar. Only useful for browser testing. Must be called before `ons.ready`.[/en] * [ja][/ja] */ ons$1.mockStatusBar = function () { if (ons$1.isReady()) { readyError(false); } var mock = function mock() { if (!document.body.children[0] || !document.body.children[0].classList.contains('ons-status-bar-mock')) { var android = platform.isAndroid(), i = function i(_i) { return '<i class="' + _i.split('-')[0] + ' ' + _i + '"></i>'; }; var left = android ? i('zmdi-twitter') + ' ' + i('zmdi-google-play') : 'No SIM ' + i('fa-wifi'), center = android ? '' : '12:28 PM', right = android ? i('zmdi-network') + ' ' + i('zmdi-wifi') + ' ' + i('zmdi-battery') + ' 12:28 PM' : '80% ' + i('fa-battery-three-quarters'); document.body.insertBefore(util$1.createElement('<div class="ons-status-bar-mock ' + (android ? 'android' : 'ios') + '">' + ('<div>' + left + '</div><div>' + center + '</div><div>' + right + '</div>') + '</div>'), document.body.firstChild); } }; document.body ? mock() : internal$1.waitDOMContentLoaded(mock); }; /** * @method disableAnimations * @signature disableAnimations() * @description * [en]Disable all animations. Could be handy for testing and older devices.[/en] * [ja]アニメーションを全て無効にします。テストの際に便利です。[/ja] */ ons$1.disableAnimations = function () { internal$1.config.animationsDisabled = true; }; /** * @method enableAnimations * @signature enableAnimations() * @description * [en]Enable animations (default).[/en] * [ja]アニメーションを有効にします。[/ja] */ ons$1.enableAnimations = function () { internal$1.config.animationsDisabled = false; }; ons$1._disableWarnings = function () { internal$1.config.warningsDisabled = true; }; ons$1._enableWarnings = function () { internal$1.config.warningsDisabled = false; }; /** * @method disableAutoStyling * @signature disableAutoStyling() * @description * [en]Disable automatic styling.[/en] * [ja][/ja] */ ons$1.disableAutoStyling = autoStyle.disable; /** * @method enableAutoStyling * @signature enableAutoStyling() * @description * [en]Enable automatic styling based on OS (default).[/en] * [ja][/ja] */ ons$1.enableAutoStyling = autoStyle.enable; /** * @method disableIconAutoPrefix * @signature disableIconAutoPrefix() * @description * [en]Disable adding `fa-` prefix automatically to `ons-icon` classes. Useful when including custom icon packs.[/en] * [ja][/ja] */ ons$1.disableIconAutoPrefix = function () { util$1.checkMissingImport('Icon'); onsElements.Icon.setAutoPrefix(false); }; /** * @method forceUIWebViewScrollFix * @signature forceUIWebViewScrollFix() * @param {Boolean} force Enable or disable the fix. * @description * [en]Applies a fix for iOS UIWebView which prevents scroll events jumping to pages under the top layer. This may visually affect normal scrolling of UIWebView if you open a dialog/menu before the scroll momentum finished. Disabled by default.[/en] * [ja][/ja] */ ons$1.forceUIWebViewScrollFix = function () { var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; internal$1.config.forceUIWebViewScrollFix = force; }; /** * @method forcePlatformStyling * @signature forcePlatformStyling(platform) * @description * [en]Refresh styling for the given platform. Only useful for demos. Use `ons.platform.select(...)` instead for development and production.[/en] * [ja][/ja] * @param {string} platform New platform to style the elements. */ ons$1.forcePlatformStyling = function (newPlatform) { ons$1.enableAutoStyling(); ons$1.platform.select(newPlatform || 'ios'); ons$1._util.arrayFrom(document.querySelectorAll('*')).forEach(function (element) { if (element.tagName.toLowerCase() === 'ons-if') { element._platformUpdate(); } else if (element.tagName.match(/^ons-/i)) { autoStyle.prepare(element, true); if (element.tagName.toLowerCase() === 'ons-tabbar') { element._updatePosition(); } } }); }; /** * @method preload * @signature preload(templatePaths) * @param {String|Array} templatePaths * [en]Set of HTML file paths containing 'ons-page' elements.[/en] * [ja][/ja] * @return {Promise} * [en]Promise that resolves when all the templates are cached.[/en] * [ja][/ja] * @description * [en]Separated files need to be requested on demand and this can slightly delay pushing new pages. This method requests and caches templates for later use.[/en] * [ja][/ja] */ ons$1.preload = function () { var templates = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; return Promise.all((templates instanceof Array ? templates : [templates]).map(function (template) { if (typeof template !== 'string') { util$1.throw('Expected string arguments but got ' + (typeof template === 'undefined' ? 'undefined' : _typeof(template))); } return internal$1.getTemplateHTMLAsync(template); })); }; /** * @method createElement * @signature createElement(template, options) * @param {String} template * [en]Either an HTML file path, a `<template>` id or an HTML string such as `'<div id="foo">hoge</div>'`.[/en] * [ja][/ja] * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {Boolean|HTMLElement} [options.append] * [en]Whether or not the element should be automatically appended to the DOM. Defaults to `false`. If `true` value is given, `document.body` will be used as the target.[/en] * [ja][/ja] * @param {HTMLElement} [options.insertBefore] * [en]Reference node that becomes the next sibling of the new node (`options.append` element).[/en] * [ja][/ja] * @return {HTMLElement|Promise} * [en]If the provided template was an inline HTML string, it returns the new element. Otherwise, it returns a promise that resolves to the new element.[/en] * [ja][/ja] * @description * [en]Create a new element from a template. Both inline HTML and external files are supported although the return value differs.[/en] * [ja][/ja] */ ons$1.createElement = function (template) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; template = template.trim(); var create = function create(html) { var element = ons$1._util.createElement(html); element.remove(); if (options.append) { var target = options.append instanceof HTMLElement ? options.append : document.body; target.insertBefore(element, options.insertBefore || null); options.link instanceof Function && options.link(element); } return element; }; return template.charAt(0) === '<' ? create(template) : internal$1.getPageHTMLAsync(template).then(create); }; /** * @method createPopover * @signature createPopover(page, [options]) * @param {String} page * [en]Page name. Can be either an HTML file or a <template> containing a <ons-dialog> component.[/en] * [ja]pageのURLか、もしくは`<template>`で宣言したテンプレートのid属性の値を指定できます。[/ja] * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {Object} [options.parentScope] * [en]Parent scope of the dialog. Used to bind models and access scope methods from the dialog.[/en] * [ja]ダイアログ内で利用する親スコープを指定します。ダイアログからモデルやスコープのメソッドにアクセスするのに使います。このパラメータはAngularJSバインディングでのみ利用できます。[/ja] * @return {Promise} * [en]Promise object that resolves to the popover component object.[/en] * [ja]ポップオーバーのコンポーネントオブジェクトを解決するPromiseオブジェクトを返します。[/ja] * @description * [en]Create a popover instance from a template.[/en] * [ja]テンプレートからポップオーバーのインスタンスを生成します。[/ja] */ /** * @method createDialog * @signature createDialog(page, [options]) * @param {String} page * [en]Page name. Can be either an HTML file or an `<template>` containing a <ons-dialog> component.[/en] * [ja]pageのURLか、もしくは`<template>`で宣言したテンプレートのid属性の値を指定できます。[/ja] * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @return {Promise} * [en]Promise object that resolves to the dialog component object.[/en] * [ja]ダイアログのコンポーネントオブジェクトを解決するPromiseオブジェクトを返します。[/ja] * @description * [en]Create a dialog instance from a template.[/en] * [ja]テンプレートからダイアログのインスタンスを生成します。[/ja] */ /** * @method createAlertDialog * @signature createAlertDialog(page, [options]) * @param {String} page * [en]Page name. Can be either an HTML file or an `<template>` containing a <ons-alert-dialog> component.[/en] * [ja]pageのURLか、もしくは`<template>`で宣言したテンプレートのid属性の値を指定できます。[/ja] * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @return {Promise} * [en]Promise object that resolves to the alert dialog component object.[/en] * [ja]ダイアログのコンポーネントオブジェクトを解決するPromiseオブジェクトを返します。[/ja] * @description * [en]Create a alert dialog instance from a template.[/en] * [ja]テンプレートからアラートダイアログのインスタンスを生成します。[/ja] */ ons$1.createPopover = ons$1.createDialog = ons$1.createAlertDialog = function (template) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return ons$1.createElement(template, _extends({ append: true }, options)); }; /** * @method openActionSheet * @signature openActionSheet(options) * @description * [en]Shows an instant Action Sheet and lets the user choose an action.[/en] * [ja][/ja] * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {Array} [options.buttons] * [en]Represent each button of the action sheet following the specified order. Every item can be either a string label or an object containing `label`, `icon` and `modifier` properties.[/en] * [ja][/ja] * @param {String} [options.title] * [en]Optional title for the action sheet.[/en] * [ja][/ja] * @param {Number} [options.destructive] * [en]Optional index of the "destructive" button (only for iOS). It can be specified in the button array as well.[/en] * [ja][/ja] * @param {Boolean} [options.cancelable] * [en]Whether the action sheet can be canceled by tapping on the background mask or not.[/en] * [ja][/ja] * @param {String} [options.modifier] * [en]Modifier attribute of the action sheet. E.g. `'destructive'`.[/en] * [ja][/ja] * @param {String} [options.maskColor] * [en]Optionally change the background mask color.[/en] * [ja][/ja] * @param {String} [options.id] * [en]The element's id attribute.[/en] * [ja][/ja] * @param {String} [options.class] * [en]The element's class attribute.[/en] * [ja][/ja] * @return {Promise} * [en]Will resolve when the action sheet is closed. The resolve value is either the index of the tapped button or -1 when canceled.[/en] * [ja][/ja] */ ons$1.openActionSheet = actionSheet; /** * @method resolveLoadingPlaceholder * @signature resolveLoadingPlaceholder(page) * @param {String} page * [en]Page name. Can be either an HTML file or a `<template>` id.[/en] * [ja]pageのURLか、もしくは`<template>`で宣言したテンプレートのid属性の値を指定できます。[/ja] * @description * [en]If no page is defined for the `ons-loading-placeholder` attribute it will wait for this method being called before loading the page.[/en] * [ja]ons-loading-placeholderの属性値としてページが指定されていない場合は、ページロード前に呼ばれるons.resolveLoadingPlaceholder処理が行われるまで表示されません。[/ja] */ ons$1.resolveLoadingPlaceholder = function (page, link) { var elements = ons$1._util.arrayFrom(window.document.querySelectorAll('[ons-loading-placeholder]')); if (elements.length === 0) { util$1.throw('No ons-loading-placeholder exists'); } elements.filter(function (element) { return !element.getAttribute('page'); }).forEach(function (element) { element.setAttribute('ons-loading-placeholder', page); ons$1._resolveLoadingPlaceholder(element, page, link); }); }; ons$1._setupLoadingPlaceHolders = function () { ons$1.ready(function () { var elements = ons$1._util.arrayFrom(window.document.querySelectorAll('[ons-loading-placeholder]')); elements.forEach(function (element) { var page = element.getAttribute('ons-loading-placeholder'); if (typeof page === 'string') { ons$1._resolveLoadingPlaceholder(element, page); } }); }); }; ons$1._resolveLoadingPlaceholder = function (parent, page) { var link = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function (el, done) { return done(); }; page && ons$1.createElement(page).then(function (element) { element.style.display = 'none'; parent.appendChild(element); link(element, function () { while (parent.firstChild && parent.firstChild !== element) { parent.removeChild(parent.firstChild); } element.style.display = ''; }); }).catch(function (error) { return Promise.reject('Unabled to resolve placeholder: ' + error); }); }; function waitDeviceReady() { var unlockDeviceReady = ons$1._readyLock.lock(); window.addEventListener('DOMContentLoaded', function () { if (ons$1.isWebView()) { window.document.addEventListener('deviceready', unlockDeviceReady, false); } else { unlockDeviceReady(); } }, false); } /** * @method getScriptPage * @signature getScriptPage() * @description * [en]Access the last created page from the current `script` scope. Only works inside `<script></script>` tags that are direct children of `ons-page` element. Use this to add lifecycle hooks to a page.[/en] * [ja][/ja] * @return {HTMLElement} * [en]Returns the corresponding page element.[/en] * [ja][/ja] */ var getCS = 'currentScript' in document ? function () { return document.currentScript; } : function () { return document.scripts[document.scripts.length - 1]; }; ons$1.getScriptPage = function () { return getCS() && /ons-page/i.test(getCS().parentElement.tagName) && getCS().parentElement || null; }; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var fastclick = createCommonjsModule(function (module) { (function () { function FastClick(layer, options) { var oldOnClick; options = options || {}; /** * Whether a click is currently being tracked. * * @type boolean */ this.trackingClick = false; /** * Timestamp for when click tracking started. * * @type number */ this.trackingClickStart = 0; /** * The element being tracked for a click. * * @type EventTarget */ this.targetElement = null; /** * X-coordinate of touch start event. * * @type number */ this.touchStartX = 0; /** * Y-coordinate of touch start event. * * @type number */ this.touchStartY = 0; /** * ID of the last touch, retrieved from Touch.identifier. * * @type number */ this.lastTouchIdentifier = 0; /** * Touchmove boundary, beyond which a click will be cancelled. * * @type number */ this.touchBoundary = options.touchBoundary || 10; /** * The FastClick layer. * * @type Element */ this.layer = layer; /** * The minimum time between tap(touchstart and touchend) events * * @type number */ this.tapDelay = options.tapDelay || 200; /** * The maximum time for a tap * * @type number */ this.tapTimeout = options.tapTimeout || 700; if (FastClick.notNeeded(layer)) { return; } // Some old versions of Android don't have Function.prototype.bind function bind(method, context) { return function () { return method.apply(context, arguments); }; } var methods = ['onMouse', 'onClick', 'onTouchStart', 'onTouchMove', 'onTouchEnd', 'onTouchCancel']; var context = this; for (var i = 0, l = methods.length; i < l; i++) { context[methods[i]] = bind(context[methods[i]], context); } // Set up event handlers as required if (deviceIsAndroid) { layer.addEventListener('mouseover', this.onMouse, true); layer.addEventListener('mousedown', this.onMouse, true); layer.addEventListener('mouseup', this.onMouse, true); } layer.addEventListener('click', this.onClick, true); layer.addEventListener('touchstart', this.onTouchStart, false); layer.addEventListener('touchmove', this.onTouchMove, false); layer.addEventListener('touchend', this.onTouchEnd, false); layer.addEventListener('touchcancel', this.onTouchCancel, false); // Hack is required for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2) // which is how FastClick normally stops click events bubbling to callbacks registered on the FastClick // layer when they are cancelled. if (!Event.prototype.stopImmediatePropagation) { layer.removeEventListener = function (type, callback, capture) { var rmv = Node.prototype.removeEventListener; if (type === 'click') { rmv.call(layer, type, callback.hijacked || callback, capture); } else { rmv.call(layer, type, callback, capture); } }; layer.addEventListener = function (type, callback, capture) { var adv = Node.prototype.addEventListener; if (type === 'click') { adv.call(layer, type, callback.hijacked || (callback.hijacked = function (event) { if (!event.propagationStopped) { callback(event); } }), capture); } else { adv.call(layer, type, callback, capture); } }; } // If a handler is already declared in the element's onclick attribute, it will be fired before // FastClick's onClick handler. Fix this by pulling out the user-defined handler function and // adding it as listener. if (typeof layer.onclick === 'function') { // Android browser on at least 3.2 requires a new reference to the function in layer.onclick // - the old one won't work if passed to addEventListener directly. oldOnClick = layer.onclick; layer.addEventListener('click', function (event) { oldOnClick(event); }, false); layer.onclick = null; } } /** * Windows Phone 8.1 fakes user agent string to look like Android and iPhone. * * @type boolean */ var deviceIsWindowsPhone = navigator.userAgent.indexOf("Windows Phone") >= 0; /** * Android requires exceptions. * * @type boolean */ var deviceIsAndroid = navigator.userAgent.indexOf('Android') > 0 && !deviceIsWindowsPhone; /** * iOS requires exceptions. * * @type boolean */ var deviceIsIOS = /iP(ad|hone|od)/.test(navigator.userAgent) && !deviceIsWindowsPhone; /** * iOS 4 requires an exception for select elements. * * @type boolean */ var deviceIsIOS4 = deviceIsIOS && /OS 4_\d(_\d)?/.test(navigator.userAgent); /** * iOS 6.0-7.* requires the target element to be manually derived * * @type boolean */ var deviceIsIOSWithBadTarget = deviceIsIOS && /OS [6-7]_\d/.test(navigator.userAgent); /** * BlackBerry requires exceptions. * * @type boolean */ var deviceIsBlackBerry10 = navigator.userAgent.indexOf('BB10') > 0; /** * Valid types for text inputs * * @type array */ var textFields = ['email', 'number', 'password', 'search', 'tel', 'text', 'url']; /** * Determine whether a given element requires a native click. * * @param {EventTarget|Element} target Target DOM element * @returns {boolean} Returns true if the element needs a native click */ FastClick.prototype.needsClick = function (target) { switch (target.nodeName.toLowerCase()) { // Don't send a synthetic click to disabled inputs (issue #62) case 'button': case 'select': case 'textarea': if (target.disabled) { return true; } break; case 'input': // File inputs need real clicks on iOS 6 due to a browser bug (issue #68) if (deviceIsIOS && target.type === 'file' || target.disabled) { return true; } break; case 'label': case 'iframe': // iOS8 homescreen apps can prevent events bubbling into frames case 'video': return true; } return (/\bneedsclick\b/.test(target.className) ); }; /** * Determine whether a given element requires a call to focus to simulate click into element. * * @param {EventTarget|Element} target Target DOM element * @returns {boolean} Returns true if the element requires a call to focus to simulate native click. */ FastClick.prototype.needsFocus = function (target) { switch (target.nodeName.toLowerCase()) { case 'textarea': return true; case 'select': return !deviceIsAndroid; case 'input': switch (target.type) { case 'button': case 'checkbox': case 'file': case 'image': case 'radio': case 'submit': return false; } // No point in attempting to focus disabled inputs return !target.disabled && !target.readOnly; default: return (/\bneedsfocus\b/.test(target.className) ); } }; /** * Send a click event to the specified element. * * @param {EventTarget|Element} targetElement * @param {Event} event */ FastClick.prototype.sendClick = function (targetElement, event) { var clickEvent, touch; // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24) if (document.activeElement && document.activeElement !== targetElement) { document.activeElement.blur(); } touch = event.changedTouches[0]; // Synthesise a click event, with an extra attribute so it can be tracked clickEvent = document.createEvent('MouseEvents'); clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); clickEvent.forwardedTouchEvent = true; targetElement.dispatchEvent(clickEvent); }; FastClick.prototype.determineEventType = function (targetElement) { //Issue #159: Android Chrome Select Box does not open with a synthetic click event if (deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select') { return 'mousedown'; } return 'click'; }; /** * @param {EventTarget|Element} targetElement */ FastClick.prototype.focus = function (targetElement) { var length; // Issue #160: on iOS 7, some input elements (e.g. date datetime month) throw a vague TypeError on setSelectionRange. These elements don't have an integer value for the selectionStart and selectionEnd properties, but unfortunately that can't be used for detection because accessing the properties also throws a TypeError. Just check the type instead. Filed as Apple bug #15122724. if (deviceIsIOS && targetElement.setSelectionRange && targetElement.type.indexOf('date') !== 0 && targetElement.type !== 'time' && targetElement.type !== 'month' && targetElement.type !== 'email' && targetElement.type !== 'number') { length = targetElement.value.length; targetElement.setSelectionRange(length, length); } else { targetElement.focus(); } }; /** * Check whether the given target element is a child of a scrollable layer and if so, set a flag on it. * * @param {EventTarget|Element} targetElement */ FastClick.prototype.updateScrollParent = function (targetElement) { var scrollParent, parentElement; scrollParent = targetElement.fastClickScrollParent; // Attempt to discover whether the target element is contained within a scrollable layer. Re-check if the // target element was moved to another parent. if (!scrollParent || !scrollParent.contains(targetElement)) { parentElement = targetElement; do { if (parentElement.scrollHeight > parentElement.offsetHeight) { scrollParent = parentElement; targetElement.fastClickScrollParent = parentElement; break; } parentElement = parentElement.parentElement; } while (parentElement); } // Always update the scroll top tracker if possible. if (scrollParent) { scrollParent.fastClickLastScrollTop = scrollParent.scrollTop; } }; /** * @param {EventTarget} targetElement * @returns {Element|EventTarget} */ FastClick.prototype.getTargetElementFromEventTarget = function (eventTarget) { // On some older browsers (notably Safari on iOS 4.1 - see issue #56) the event target may be a text node. if (eventTarget.nodeType === Node.TEXT_NODE) { return eventTarget.parentNode; } return eventTarget; }; /** * @param {EventTarget} targetElement * @returns {boolean} */ FastClick.prototype.isTextField = function (targetElement) { return targetElement.tagName.toLowerCase() === 'textarea' || textFields.indexOf(targetElement.type) !== -1; }; /** * On touch start, record the position and scroll offset. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.onTouchStart = function (event) { var targetElement, touch; // Ignore multiple touches, otherwise pinch-to-zoom is prevented if both fingers are on the FastClick element (issue #111). if (event.targetTouches.length > 1) { return true; } targetElement = this.getTargetElementFromEventTarget(event.target); touch = event.targetTouches[0]; // Ignore touches on contenteditable elements to prevent conflict with text selection. // (For details: https://github.com/ftlabs/fastclick/pull/211 ) if (targetElement.isContentEditable) { return true; } if (deviceIsIOS) { // Ignore touchstart in focused text field // Allows normal text selection and commands (select/paste/cut) when a field has focus, while still allowing fast tap-to-focus. // Without this fix, user needs to tap-and-hold a text field for context menu, and double-tap to select text doesn't work at all. if (targetElement === document.activeElement && this.isTextField(targetElement)) { return true; } if (!deviceIsIOS4) { // Weird things happen on iOS when an alert or confirm dialog is opened from a click event callback (issue #23): // when the user next taps anywhere else on the page, new touchstart and touchend events are dispatched // with the same identifier as the touch event that previously triggered the click that triggered the alert. // Sadly, there is an issue on iOS 4 that causes some normal touch events to have the same identifier as an // immediately preceeding touch event (issue #52), so this fix is unavailable on that platform. // Issue 120: touch.identifier is 0 when Chrome dev tools 'Emulate touch events' is set with an iOS device UA string, // which causes all touch events to be ignored. As this block only applies to iOS, and iOS identifiers are always long, // random integers, it's safe to to continue if the identifier is 0 here. if (touch.identifier && touch.identifier === this.lastTouchIdentifier) { event.preventDefault(); return false; } this.lastTouchIdentifier = touch.identifier; // If the target element is a child of a scrollable layer (using -webkit-overflow-scrolling: touch) and: // 1) the user does a fling scroll on the scrollable layer // 2) the user stops the fling scroll with another tap // then the event.target of the last 'touchend' event will be the element that was under the user's finger // when the fling scroll was started, causing FastClick to send a click event to that layer - unless a check // is made to ensure that a parent layer was not scrolled before sending a synthetic click (issue #42). this.updateScrollParent(targetElement); } } this.trackingClick = true; this.trackingClickStart = event.timeStamp; this.targetElement = targetElement; this.touchStartX = touch.pageX; this.touchStartY = touch.pageY; // Prevent phantom clicks on fast double-tap (issue #36) if (event.timeStamp - this.lastClickTime < this.tapDelay && event.timeStamp - this.lastClickTime > -1) { event.preventDefault(); } return true; }; /** * Based on a touchmove event object, check whether the touch has moved past a boundary since it started. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.touchHasMoved = function (event) { var touch = event.changedTouches[0], boundary = this.touchBoundary; if (Math.abs(touch.pageX - this.touchStartX) > boundary || Math.abs(touch.pageY - this.touchStartY) > boundary) { return true; } return false; }; /** * Update the last position. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.onTouchMove = function (event) { if (!this.trackingClick) { return true; } // If the touch has moved, cancel the click tracking if (this.targetElement !== this.getTargetElementFromEventTarget(event.target) || this.touchHasMoved(event)) { this.trackingClick = false; this.targetElement = null; } return true; }; /** * Attempt to find the labelled control for the given label element. * * @param {EventTarget|HTMLLabelElement} labelElement * @returns {Element|null} */ FastClick.prototype.findControl = function (labelElement) { // Fast path for newer browsers supporting the HTML5 control attribute if (labelElement.control !== undefined) { return labelElement.control; } // All browsers under test that support touch events also support the HTML5 htmlFor attribute if (labelElement.htmlFor) { return document.getElementById(labelElement.htmlFor); } // If no for attribute exists, attempt to retrieve the first labellable descendant element // the list of which is defined here: http://www.w3.org/TR/html5/forms.html#category-label return labelElement.querySelector('button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea'); }; /** * On touch end, determine whether to send a click event at once. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.onTouchEnd = function (event) { var forElement, trackingClickStart, targetTagName, scrollParent, touch, targetElement = this.targetElement; if (!this.trackingClick) { return true; } // Prevent phantom clicks on fast double-tap (issue #36) if (event.timeStamp - this.lastClickTime < this.tapDelay && event.timeStamp - this.lastClickTime > -1) { this.cancelNextClick = true; return true; } if (event.timeStamp - this.trackingClickStart > this.tapTimeout) { return true; } // Reset to prevent wrong click cancel on input (issue #156). this.cancelNextClick = false; this.lastClickTime = event.timeStamp; trackingClickStart = this.trackingClickStart; this.trackingClick = false; this.trackingClickStart = 0; // On some iOS devices, the targetElement supplied with the event is invalid if the layer // is performing a transition or scroll, and has to be re-detected manually. Note that // for this to function correctly, it must be called *after* the event target is checked! // See issue #57; also filed as rdar://13048589 . if (deviceIsIOSWithBadTarget) { touch = event.changedTouches[0]; // In certain cases arguments of elementFromPoint can be negative, so prevent setting targetElement to null targetElement = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset) || targetElement; targetElement.fastClickScrollParent = this.targetElement.fastClickScrollParent; } targetTagName = targetElement.tagName.toLowerCase(); if (targetTagName === 'label') { forElement = this.findControl(targetElement); if (forElement) { this.focus(targetElement); if (deviceIsAndroid) { return false; } targetElement = forElement; } } else if (this.needsFocus(targetElement)) { // Case 1: If the touch started a while ago (best guess is 100ms based on tests for issue #36) then focus will be triggered anyway. Return early and unset the target element reference so that the subsequent click will be allowed through. // Case 2: Without this exception for input elements tapped when the document is contained in an iframe, then any inputted text won't be visible even though the value attribute is updated as the user types (issue #37). if (event.timeStamp - trackingClickStart > 100 || deviceIsIOS && window.top !== window && targetTagName === 'input') { this.targetElement = null; return false; } this.focus(targetElement); this.sendClick(targetElement, event); // Select elements need the event to go through on iOS 4, otherwise the selector menu won't open. // Also this breaks opening selects when VoiceOver is active on iOS6, iOS7 (and possibly others) if (!deviceIsIOS4 || targetTagName !== 'select') { this.targetElement = null; event.preventDefault(); } return false; } if (deviceIsIOS && !deviceIsIOS4) { // Don't send a synthetic click event if the target element is contained within a parent layer that was scrolled // and this tap is being used to stop the scrolling (usually initiated by a fling - issue #42). scrollParent = targetElement.fastClickScrollParent; if (scrollParent && scrollParent.fastClickLastScrollTop !== scrollParent.scrollTop) { return true; } } // Prevent the actual click from going though - unless the target node is marked as requiring // real clicks or if it is in the whitelist in which case only non-programmatic clicks are permitted. if (!this.needsClick(targetElement)) { event.preventDefault(); this.sendClick(targetElement, event); } return false; }; /** * On touch cancel, stop tracking the click. * * @returns {void} */ FastClick.prototype.onTouchCancel = function () { this.trackingClick = false; this.targetElement = null; }; /** * Determine mouse events which should be permitted. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.onMouse = function (event) { // If a target element was never set (because a touch event was never fired) allow the event if (!this.targetElement) { return true; } if (event.forwardedTouchEvent) { return true; } // Programmatically generated events targeting a specific element should be permitted if (!event.cancelable) { return true; } // Derive and check the target element to see whether the mouse event needs to be permitted; // unless explicitly enabled, prevent non-touch click events from triggering actions, // to prevent ghost/doubleclicks. if (!this.needsClick(this.targetElement) || this.cancelNextClick) { // Prevent any user-added listeners declared on FastClick element from being fired. if (event.stopImmediatePropagation) { event.stopImmediatePropagation(); } else { // Part of the hack for browsers that don't support Event#stopImmediatePropagation (e.g. Android 2) event.propagationStopped = true; } // Cancel the event event.stopPropagation(); event.preventDefault(); return false; } // If the mouse event is permitted, return true for the action to go through. return true; }; /** * On actual clicks, determine whether this is a touch-generated click, a click action occurring * naturally after a delay after a touch (which needs to be cancelled to avoid duplication), or * an actual click which should be permitted. * * @param {Event} event * @returns {boolean} */ FastClick.prototype.onClick = function (event) { var permitted; // It's possible for another FastClick-like library delivered with third-party code to fire a click event before FastClick does (issue #44). In that case, set the click-tracking flag back to false and return early. This will cause onTouchEnd to return early. if (this.trackingClick) { this.targetElement = null; this.trackingClick = false; return true; } // Very odd behaviour on iOS (issue #18): if a submit element is present inside a form and the user hits enter in the iOS simulator or clicks the Go button on the pop-up OS keyboard the a kind of 'fake' click event will be triggered with the submit-type input element as the target. if (event.target.type === 'submit' && event.detail === 0) { return true; } permitted = this.onMouse(event); // Only unset targetElement if the click is not permitted. This will ensure that the check for !targetElement in onMouse fails and the browser's click doesn't go through. if (!permitted) { this.targetElement = null; } // If clicks are permitted, return true for the action to go through. return permitted; }; /** * Remove all FastClick's event listeners. * * @returns {void} */ FastClick.prototype.destroy = function () { var layer = this.layer; if (deviceIsAndroid) { layer.removeEventListener('mouseover', this.onMouse, true); layer.removeEventListener('mousedown', this.onMouse, true); layer.removeEventListener('mouseup', this.onMouse, true); } layer.removeEventListener('click', this.onClick, true); layer.removeEventListener('touchstart', this.onTouchStart, false); layer.removeEventListener('touchmove', this.onTouchMove, false); layer.removeEventListener('touchend', this.onTouchEnd, false); layer.removeEventListener('touchcancel', this.onTouchCancel, false); }; /** * Check whether FastClick is needed. * * @param {Element} layer The layer to listen on */ FastClick.notNeeded = function (layer) { var metaViewport; var chromeVersion; var blackberryVersion; var firefoxVersion; // Devices that don't support touch don't need FastClick if (typeof window.ontouchstart === 'undefined') { return true; } // Chrome version - zero for other browsers chromeVersion = +(/Chrome\/([0-9]+)/.exec(navigator.userAgent) || [, 0])[1]; if (chromeVersion) { if (deviceIsAndroid) { metaViewport = document.querySelector('meta[name=viewport]'); if (metaViewport) { // Chrome on Android with user-scalable="no" doesn't need FastClick (issue #89) if (metaViewport.content.indexOf('user-scalable=no') !== -1) { return true; } // Chrome 32 and above with width=device-width or less don't need FastClick if (chromeVersion > 31 && document.documentElement.scrollWidth <= window.outerWidth) { return true; } } // Chrome desktop doesn't need FastClick (issue #15) } else { return true; } } if (deviceIsBlackBerry10) { blackberryVersion = navigator.userAgent.match(/Version\/([0-9]*)\.([0-9]*)/); // BlackBerry 10.3+ does not require Fastclick library. // https://github.com/ftlabs/fastclick/issues/251 if (blackberryVersion[1] >= 10 && blackberryVersion[2] >= 3) { metaViewport = document.querySelector('meta[name=viewport]'); if (metaViewport) { // user-scalable=no eliminates click delay. if (metaViewport.content.indexOf('user-scalable=no') !== -1) { return true; } // width=device-width (or less than device-width) eliminates click delay. if (document.documentElement.scrollWidth <= window.outerWidth) { return true; } } } } // IE10 with -ms-touch-action: none or manipulation, which disables double-tap-to-zoom (issue #97) if (layer.style.msTouchAction === 'none' || layer.style.touchAction === 'manipulation') { return true; } // Firefox version - zero for other browsers firefoxVersion = +(/Firefox\/([0-9]+)/.exec(navigator.userAgent) || [, 0])[1]; if (firefoxVersion >= 27) { // Firefox 27+ does not have tap delay if the content is not zoomable - https://bugzilla.mozilla.org/show_bug.cgi?id=922896 metaViewport = document.querySelector('meta[name=viewport]'); if (metaViewport && (metaViewport.content.indexOf('user-scalable=no') !== -1 || document.documentElement.scrollWidth <= window.outerWidth)) { return true; } } // IE11: prefixed -ms-touch-action is no longer supported and it's recomended to use non-prefixed version // http://msdn.microsoft.com/en-us/library/windows/apps/Hh767313.aspx if (layer.style.touchAction === 'none' || layer.style.touchAction === 'manipulation') { return true; } return false; }; /** * Factory method for creating a FastClick object * * @param {Element} layer The layer to listen on * @param {Object} [options={}] The options to override the defaults */ FastClick.attach = function (layer, options) { return new FastClick(layer, options); }; if (typeof undefined === 'function' && _typeof(undefined.amd) === 'object' && undefined.amd) { // AMD. Register as an anonymous module. undefined(function () { return FastClick; }); } else if ('object' !== 'undefined' && module.exports) { module.exports = FastClick.attach; module.exports.FastClick = FastClick; } else { window.FastClick = FastClick; } })(); }); var fastclick_1 = fastclick.FastClick; // For @onsenui/custom-elements if (window.customElements) { // even if native CE1 impl exists, use polyfill window.customElements.forcePolyfill = true; } var _global = createCommonjsModule(function (module) { // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self // eslint-disable-next-line no-new-func : Function('return this')(); if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef }); var _core = createCommonjsModule(function (module) { var core = module.exports = { version: '2.5.1' }; if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef }); var _core_1 = _core.version; var _isObject = function _isObject(it) { return (typeof it === 'undefined' ? 'undefined' : _typeof(it)) === 'object' ? it !== null : typeof it === 'function'; }; var _anObject = function _anObject(it) { if (!_isObject(it)) throw TypeError(it + ' is not an object!'); return it; }; var _fails = function _fails(exec) { try { return !!exec(); } catch (e) { return true; } }; // Thank's IE8 for his funny defineProperty var _descriptors = !_fails(function () { return Object.defineProperty({}, 'a', { get: function get() { return 7; } }).a != 7; }); var document$1 = _global.document; // typeof document.createElement is 'object' in old IE var is = _isObject(document$1) && _isObject(document$1.createElement); var _domCreate = function _domCreate(it) { return is ? document$1.createElement(it) : {}; }; var _ie8DomDefine = !_descriptors && !_fails(function () { return Object.defineProperty(_domCreate('div'), 'a', { get: function get() { return 7; } }).a != 7; }); // 7.1.1 ToPrimitive(input [, PreferredType]) // instead of the ES6 spec version, we didn't implement @@toPrimitive case // and the second argument - flag - preferred type is a string var _toPrimitive = function _toPrimitive(it, S) { if (!_isObject(it)) return it; var fn, val; if (S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val; if (typeof (fn = it.valueOf) == 'function' && !_isObject(val = fn.call(it))) return val; if (!S && typeof (fn = it.toString) == 'function' && !_isObject(val = fn.call(it))) return val; throw TypeError("Can't convert object to primitive value"); }; var dP = Object.defineProperty; var f = _descriptors ? Object.defineProperty : function defineProperty(O, P, Attributes) { _anObject(O); P = _toPrimitive(P, true); _anObject(Attributes); if (_ie8DomDefine) try { return dP(O, P, Attributes); } catch (e) {/* empty */} if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); if ('value' in Attributes) O[P] = Attributes.value; return O; }; var _objectDp = { f: f }; var _propertyDesc = function _propertyDesc(bitmap, value) { return { enumerable: !(bitmap & 1), configurable: !(bitmap & 2), writable: !(bitmap & 4), value: value }; }; var _hide = _descriptors ? function (object, key, value) { return _objectDp.f(object, key, _propertyDesc(1, value)); } : function (object, key, value) { object[key] = value; return object; }; var hasOwnProperty = {}.hasOwnProperty; var _has = function _has(it, key) { return hasOwnProperty.call(it, key); }; var id = 0; var px = Math.random(); var _uid = function _uid(key) { return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); }; var _redefine = createCommonjsModule(function (module) { var SRC = _uid('src'); var TO_STRING = 'toString'; var $toString = Function[TO_STRING]; var TPL = ('' + $toString).split(TO_STRING); _core.inspectSource = function (it) { return $toString.call(it); }; (module.exports = function (O, key, val, safe) { var isFunction = typeof val == 'function'; if (isFunction) _has(val, 'name') || _hide(val, 'name', key); if (O[key] === val) return; if (isFunction) _has(val, SRC) || _hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key))); if (O === _global) { O[key] = val; } else if (!safe) { delete O[key]; _hide(O, key, val); } else if (O[key]) { O[key] = val; } else { _hide(O, key, val); } // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative })(Function.prototype, TO_STRING, function toString() { return typeof this == 'function' && this[SRC] || $toString.call(this); }); }); var _aFunction = function _aFunction(it) { if (typeof it != 'function') throw TypeError(it + ' is not a function!'); return it; }; // optional / simple context binding var _ctx = function _ctx(fn, that, length) { _aFunction(fn); if (that === undefined) return fn; switch (length) { case 1: return function (a) { return fn.call(that, a); }; case 2: return function (a, b) { return fn.call(that, a, b); }; case 3: return function (a, b, c) { return fn.call(that, a, b, c); }; } return function () /* ...args */{ return fn.apply(that, arguments); }; }; var PROTOTYPE = 'prototype'; var $export = function $export(type, name, source) { var IS_FORCED = type & $export.F; var IS_GLOBAL = type & $export.G; var IS_STATIC = type & $export.S; var IS_PROTO = type & $export.P; var IS_BIND = type & $export.B; var target = IS_GLOBAL ? _global : IS_STATIC ? _global[name] || (_global[name] = {}) : (_global[name] || {})[PROTOTYPE]; var exports = IS_GLOBAL ? _core : _core[name] || (_core[name] = {}); var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {}); var key, own, out, exp; if (IS_GLOBAL) source = name; for (key in source) { // contains in native own = !IS_FORCED && target && target[key] !== undefined; // export native or passed out = (own ? target : source)[key]; // bind timers to global for call from export context exp = IS_BIND && own ? _ctx(out, _global) : IS_PROTO && typeof out == 'function' ? _ctx(Function.call, out) : out; // extend global if (target) _redefine(target, key, out, type & $export.U); // export if (exports[key] != out) _hide(exports, key, exp); if (IS_PROTO && expProto[key] != out) expProto[key] = out; } }; _global.core = _core; // type bitmap $export.F = 1; // forced $export.G = 2; // global $export.S = 4; // static $export.P = 8; // proto $export.B = 16; // bind $export.W = 32; // wrap $export.U = 64; // safe $export.R = 128; // real proto method for `library` var _export = $export; var f$2 = {}.propertyIsEnumerable; var _objectPie = { f: f$2 }; var toString = {}.toString; var _cof = function _cof(it) { return toString.call(it).slice(8, -1); }; // fallback for non-array-like ES3 and non-enumerable old V8 strings // eslint-disable-next-line no-prototype-builtins var _iobject = Object('z').propertyIsEnumerable(0) ? Object : function (it) { return _cof(it) == 'String' ? it.split('') : Object(it); }; // 7.2.1 RequireObjectCoercible(argument) var _defined = function _defined(it) { if (it == undefined) throw TypeError("Can't call method on " + it); return it; }; // to indexed object, toObject with fallback for non-array-like ES3 strings var _toIobject = function _toIobject(it) { return _iobject(_defined(it)); }; var gOPD = Object.getOwnPropertyDescriptor; var f$1 = _descriptors ? gOPD : function getOwnPropertyDescriptor(O, P) { O = _toIobject(O); P = _toPrimitive(P, true); if (_ie8DomDefine) try { return gOPD(O, P); } catch (e) {/* empty */} if (_has(O, P)) return _propertyDesc(!_objectPie.f.call(O, P), O[P]); }; var _objectGopd = { f: f$1 }; // Works with __proto__ only. Old v8 can't work with null proto objects. /* eslint-disable no-proto */ var check = function check(O, proto) { _anObject(O); if (!_isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!"); }; var _setProto = { set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line function (test, buggy, set) { try { set = _ctx(Function.call, _objectGopd.f(Object.prototype, '__proto__').set, 2); set(test, []); buggy = !(test instanceof Array); } catch (e) { buggy = true; } return function setPrototypeOf(O, proto) { check(O, proto); if (buggy) O.__proto__ = proto;else set(O, proto); return O; }; }({}, false) : undefined), check: check }; // 19.1.3.19 Object.setPrototypeOf(O, proto) _export(_export.S, 'Object', { setPrototypeOf: _setProto.set }); var setPrototypeOf = _core.Object.setPrototypeOf; var SHARED = '__core-js_shared__'; var store = _global[SHARED] || (_global[SHARED] = {}); var _shared = function _shared(key) { return store[key] || (store[key] = {}); }; var _wks = createCommonjsModule(function (module) { var store = _shared('wks'); var _Symbol = _global.Symbol; var USE_SYMBOL = typeof _Symbol == 'function'; var $exports = module.exports = function (name) { return store[name] || (store[name] = USE_SYMBOL && _Symbol[name] || (USE_SYMBOL ? _Symbol : _uid)('Symbol.' + name)); }; $exports.store = store; }); // getting tag from 19.1.3.6 Object.prototype.toString() var TAG = _wks('toStringTag'); // ES3 wrong here var ARG = _cof(function () { return arguments; }()) == 'Arguments'; // fallback for IE11 Script Access Denied error var tryGet = function tryGet(it, key) { try { return it[key]; } catch (e) {/* empty */} }; var _classof = function _classof(it) { var O, T, B; return it === undefined ? 'Undefined' : it === null ? 'Null' // @@toStringTag case : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T // builtinTag case : ARG ? _cof(O) // ES3 arguments fallback : (B = _cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; }; // 19.1.3.6 Object.prototype.toString() var test = {}; test[_wks('toStringTag')] = 'z'; if (test + '' != '[object z]') { _redefine(Object.prototype, 'toString', function toString() { return '[object ' + _classof(this) + ']'; }, true); } // 7.1.4 ToInteger var ceil = Math.ceil; var floor = Math.floor; var _toInteger = function _toInteger(it) { return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); }; // true -> String#at // false -> String#codePointAt var _stringAt = function _stringAt(TO_STRING) { return function (that, pos) { var s = String(_defined(that)); var i = _toInteger(pos); var l = s.length; var a, b; if (i < 0 || i >= l) return TO_STRING ? '' : undefined; a = s.charCodeAt(i); return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff ? TO_STRING ? s.charAt(i) : a : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; }; }; var _library = false; var _iterators = {}; // 7.1.15 ToLength var min = Math.min; var _toLength = function _toLength(it) { return it > 0 ? min(_toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 }; var max = Math.max; var min$1 = Math.min; var _toAbsoluteIndex = function _toAbsoluteIndex(index, length) { index = _toInteger(index); return index < 0 ? max(index + length, 0) : min$1(index, length); }; // false -> Array#indexOf // true -> Array#includes var _arrayIncludes = function _arrayIncludes(IS_INCLUDES) { return function ($this, el, fromIndex) { var O = _toIobject($this); var length = _toLength(O.length); var index = _toAbsoluteIndex(fromIndex, length); var value; // Array#includes uses SameValueZero equality algorithm // eslint-disable-next-line no-self-compare if (IS_INCLUDES && el != el) while (length > index) { value = O[index++]; // eslint-disable-next-line no-self-compare if (value != value) return true; // Array#indexOf ignores holes, Array#includes - not } else for (; length > index; index++) { if (IS_INCLUDES || index in O) { if (O[index] === el) return IS_INCLUDES || index || 0; } }return !IS_INCLUDES && -1; }; }; var shared = _shared('keys'); var _sharedKey = function _sharedKey(key) { return shared[key] || (shared[key] = _uid(key)); }; var arrayIndexOf = _arrayIncludes(false); var IE_PROTO$1 = _sharedKey('IE_PROTO'); var _objectKeysInternal = function _objectKeysInternal(object, names) { var O = _toIobject(object); var i = 0; var result = []; var key; for (key in O) { if (key != IE_PROTO$1) _has(O, key) && result.push(key); } // Don't enum bug & hidden keys while (names.length > i) { if (_has(O, key = names[i++])) { ~arrayIndexOf(result, key) || result.push(key); } }return result; }; // IE 8- don't enum bug keys var _enumBugKeys = 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'.split(','); // 19.1.2.14 / 15.2.3.14 Object.keys(O) var _objectKeys = Object.keys || function keys(O) { return _objectKeysInternal(O, _enumBugKeys); }; var _objectDps = _descriptors ? Object.defineProperties : function defineProperties(O, Properties) { _anObject(O); var keys = _objectKeys(Properties); var length = keys.length; var i = 0; var P; while (length > i) { _objectDp.f(O, P = keys[i++], Properties[P]); }return O; }; var document$2 = _global.document; var _html = document$2 && document$2.documentElement; // 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) var IE_PROTO = _sharedKey('IE_PROTO'); var Empty = function Empty() {/* empty */}; var PROTOTYPE$1 = 'prototype'; // Create object with fake `null` prototype: use iframe Object with cleared prototype var _createDict = function createDict() { // Thrash, waste and sodomy: IE GC bug var iframe = _domCreate('iframe'); var i = _enumBugKeys.length; var lt = '<'; var gt = '>'; var iframeDocument; iframe.style.display = 'none'; _html.appendChild(iframe); iframe.src = 'javascript:'; // eslint-disable-line no-script-url // createDict = iframe.contentWindow.Object; // html.removeChild(iframe); iframeDocument = iframe.contentWindow.document; iframeDocument.open(); iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); iframeDocument.close(); _createDict = iframeDocument.F; while (i--) { delete _createDict[PROTOTYPE$1][_enumBugKeys[i]]; }return _createDict(); }; var _objectCreate = Object.create || function create(O, Properties) { var result; if (O !== null) { Empty[PROTOTYPE$1] = _anObject(O); result = new Empty(); Empty[PROTOTYPE$1] = null; // add "__proto__" for Object.getPrototypeOf polyfill result[IE_PROTO] = O; } else result = _createDict(); return Properties === undefined ? result : _objectDps(result, Properties); }; var def = _objectDp.f; var TAG$1 = _wks('toStringTag'); var _setToStringTag = function _setToStringTag(it, tag, stat) { if (it && !_has(it = stat ? it : it.prototype, TAG$1)) def(it, TAG$1, { configurable: true, value: tag }); }; var IteratorPrototype = {}; // 25.1.2.1.1 %IteratorPrototype%[@@iterator]() _hide(IteratorPrototype, _wks('iterator'), function () { return this; }); var _iterCreate = function _iterCreate(Constructor, NAME, next) { Constructor.prototype = _objectCreate(IteratorPrototype, { next: _propertyDesc(1, next) }); _setToStringTag(Constructor, NAME + ' Iterator'); }; // 7.1.13 ToObject(argument) var _toObject = function _toObject(it) { return Object(_defined(it)); }; // 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) var IE_PROTO$2 = _sharedKey('IE_PROTO'); var ObjectProto = Object.prototype; var _objectGpo = Object.getPrototypeOf || function (O) { O = _toObject(O); if (_has(O, IE_PROTO$2)) return O[IE_PROTO$2]; if (typeof O.constructor == 'function' && O instanceof O.constructor) { return O.constructor.prototype; }return O instanceof Object ? ObjectProto : null; }; var ITERATOR = _wks('iterator'); var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` var FF_ITERATOR = '@@iterator'; var KEYS = 'keys'; var VALUES = 'values'; var returnThis = function returnThis() { return this; }; var _iterDefine = function _iterDefine(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) { _iterCreate(Constructor, NAME, next); var getMethod = function getMethod(kind) { if (!BUGGY && kind in proto) return proto[kind]; switch (kind) { case KEYS: return function keys() { return new Constructor(this, kind); }; case VALUES: return function values() { return new Constructor(this, kind); }; }return function entries() { return new Constructor(this, kind); }; }; var TAG = NAME + ' Iterator'; var DEF_VALUES = DEFAULT == VALUES; var VALUES_BUG = false; var proto = Base.prototype; var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; var $default = $native || getMethod(DEFAULT); var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; var methods, key, IteratorPrototype; // Fix native if ($anyNative) { IteratorPrototype = _objectGpo($anyNative.call(new Base())); if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) { // Set @@toStringTag to native iterators _setToStringTag(IteratorPrototype, TAG, true); // fix for some old engines if (!_library && !_has(IteratorPrototype, ITERATOR)) _hide(IteratorPrototype, ITERATOR, returnThis); } } // fix Array#{values, @@iterator}.name in V8 / FF if (DEF_VALUES && $native && $native.name !== VALUES) { VALUES_BUG = true; $default = function values() { return $native.call(this); }; } // Define iterator if ((!_library || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) { _hide(proto, ITERATOR, $default); } // Plug for library _iterators[NAME] = $default; _iterators[TAG] = returnThis; if (DEFAULT) { methods = { values: DEF_VALUES ? $default : getMethod(VALUES), keys: IS_SET ? $default : getMethod(KEYS), entries: $entries }; if (FORCED) for (key in methods) { if (!(key in proto)) _redefine(proto, key, methods[key]); } else _export(_export.P + _export.F * (BUGGY || VALUES_BUG), NAME, methods); } return methods; }; var $at = _stringAt(true); // 21.1.3.27 String.prototype[@@iterator]() _iterDefine(String, 'String', function (iterated) { this._t = String(iterated); // target this._i = 0; // next index // 21.1.5.2.1 %StringIteratorPrototype%.next() }, function () { var O = this._t; var index = this._i; var point; if (index >= O.length) return { value: undefined, done: true }; point = $at(O, index); this._i += point.length; return { value: point, done: false }; }); // 22.1.3.31 Array.prototype[@@unscopables] var UNSCOPABLES = _wks('unscopables'); var ArrayProto = Array.prototype; if (ArrayProto[UNSCOPABLES] == undefined) _hide(ArrayProto, UNSCOPABLES, {}); var _addToUnscopables = function _addToUnscopables(key) { ArrayProto[UNSCOPABLES][key] = true; }; var _iterStep = function _iterStep(done, value) { return { value: value, done: !!done }; }; // 22.1.3.4 Array.prototype.entries() // 22.1.3.13 Array.prototype.keys() // 22.1.3.29 Array.prototype.values() // 22.1.3.30 Array.prototype[@@iterator]() var es6_array_iterator = _iterDefine(Array, 'Array', function (iterated, kind) { this._t = _toIobject(iterated); // target this._i = 0; // next index this._k = kind; // kind // 22.1.5.2.1 %ArrayIteratorPrototype%.next() }, function () { var O = this._t; var kind = this._k; var index = this._i++; if (!O || index >= O.length) { this._t = undefined; return _iterStep(1); } if (kind == 'keys') return _iterStep(0, index); if (kind == 'values') return _iterStep(0, O[index]); return _iterStep(0, [index, O[index]]); }, 'values'); // argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) _iterators.Arguments = _iterators.Array; _addToUnscopables('keys'); _addToUnscopables('values'); _addToUnscopables('entries'); var ITERATOR$1 = _wks('iterator'); var TO_STRING_TAG = _wks('toStringTag'); var ArrayValues = _iterators.Array; var DOMIterables = { CSSRuleList: true, // TODO: Not spec compliant, should be false. CSSStyleDeclaration: false, CSSValueList: false, ClientRectList: false, DOMRectList: false, DOMStringList: false, DOMTokenList: true, DataTransferItemList: false, FileList: false, HTMLAllCollection: false, HTMLCollection: false, HTMLFormElement: false, HTMLSelectElement: false, MediaList: true, // TODO: Not spec compliant, should be false. MimeTypeArray: false, NamedNodeMap: false, NodeList: true, PaintRequestList: false, Plugin: false, PluginArray: false, SVGLengthList: false, SVGNumberList: false, SVGPathSegList: false, SVGPointList: false, SVGStringList: false, SVGTransformList: false, SourceBufferList: false, StyleSheetList: true, // TODO: Not spec compliant, should be false. TextTrackCueList: false, TextTrackList: false, TouchList: false }; for (var collections = _objectKeys(DOMIterables), i = 0; i < collections.length; i++) { var NAME = collections[i]; var explicit = DOMIterables[NAME]; var Collection = _global[NAME]; var proto = Collection && Collection.prototype; var key; if (proto) { if (!proto[ITERATOR$1]) _hide(proto, ITERATOR$1, ArrayValues); if (!proto[TO_STRING_TAG]) _hide(proto, TO_STRING_TAG, NAME); _iterators[NAME] = ArrayValues; if (explicit) for (key in es6_array_iterator) { if (!proto[key]) _redefine(proto, key, es6_array_iterator[key], true); } } } var _redefineAll = function _redefineAll(target, src, safe) { for (var key in src) { _redefine(target, key, src[key], safe); }return target; }; var _anInstance = function _anInstance(it, Constructor, name, forbiddenField) { if (!(it instanceof Constructor) || forbiddenField !== undefined && forbiddenField in it) { throw TypeError(name + ': incorrect invocation!'); }return it; }; // call something on iterator step with safe closing on error var _iterCall = function _iterCall(iterator, fn, value, entries) { try { return entries ? fn(_anObject(value)[0], value[1]) : fn(value); // 7.4.6 IteratorClose(iterator, completion) } catch (e) { var ret = iterator['return']; if (ret !== undefined) _anObject(ret.call(iterator)); throw e; } }; // check on default Array iterator var ITERATOR$2 = _wks('iterator'); var ArrayProto$1 = Array.prototype; var _isArrayIter = function _isArrayIter(it) { return it !== undefined && (_iterators.Array === it || ArrayProto$1[ITERATOR$2] === it); }; var ITERATOR$3 = _wks('iterator'); var core_getIteratorMethod = _core.getIteratorMethod = function (it) { if (it != undefined) return it[ITERATOR$3] || it['@@iterator'] || _iterators[_classof(it)]; }; var _forOf = createCommonjsModule(function (module) { var BREAK = {}; var RETURN = {}; var exports = module.exports = function (iterable, entries, fn, that, ITERATOR) { var iterFn = ITERATOR ? function () { return iterable; } : core_getIteratorMethod(iterable); var f = _ctx(fn, that, entries ? 2 : 1); var index = 0; var length, step, iterator, result; if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!'); // fast case for arrays with default iterator if (_isArrayIter(iterFn)) for (length = _toLength(iterable.length); length > index; index++) { result = entries ? f(_anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); if (result === BREAK || result === RETURN) return result; } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) { result = _iterCall(iterator, f, step.value, entries); if (result === BREAK || result === RETURN) return result; } }; exports.BREAK = BREAK; exports.RETURN = RETURN; }); var SPECIES = _wks('species'); var _setSpecies = function _setSpecies(KEY) { var C = _global[KEY]; if (_descriptors && C && !C[SPECIES]) _objectDp.f(C, SPECIES, { configurable: true, get: function get() { return this; } }); }; var _meta = createCommonjsModule(function (module) { var META = _uid('meta'); var setDesc = _objectDp.f; var id = 0; var isExtensible = Object.isExtensible || function () { return true; }; var FREEZE = !_fails(function () { return isExtensible(Object.preventExtensions({})); }); var setMeta = function setMeta(it) { setDesc(it, META, { value: { i: 'O' + ++id, // object ID w: {} // weak collections IDs } }); }; var fastKey = function fastKey(it, create) { // return primitive with prefix if (!_isObject(it)) return (typeof it === 'undefined' ? 'undefined' : _typeof(it)) == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; if (!_has(it, META)) { // can't set metadata to uncaught frozen object if (!isExtensible(it)) return 'F'; // not necessary to add metadata if (!create) return 'E'; // add missing metadata setMeta(it); // return object ID }return it[META].i; }; var getWeak = function getWeak(it, create) { if (!_has(it, META)) { // can't set metadata to uncaught frozen object if (!isExtensible(it)) return true; // not necessary to add metadata if (!create) return false; // add missing metadata setMeta(it); // return hash weak collections IDs }return it[META].w; }; // add metadata on freeze-family methods calling var onFreeze = function onFreeze(it) { if (FREEZE && meta.NEED && isExtensible(it) && !_has(it, META)) setMeta(it); return it; }; var meta = module.exports = { KEY: META, NEED: false, fastKey: fastKey, getWeak: getWeak, onFreeze: onFreeze }; }); var _meta_1 = _meta.KEY; var _meta_2 = _meta.NEED; var _meta_3 = _meta.fastKey; var _meta_4 = _meta.getWeak; var _meta_5 = _meta.onFreeze; var _validateCollection = function _validateCollection(it, TYPE) { if (!_isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!'); return it; }; var dP$1 = _objectDp.f; var fastKey = _meta.fastKey; var SIZE = _descriptors ? '_s' : 'size'; var getEntry = function getEntry(that, key) { // fast case var index = fastKey(key); var entry; if (index !== 'F') return that._i[index]; // frozen object case for (entry = that._f; entry; entry = entry.n) { if (entry.k == key) return entry; } }; var _collectionStrong = { getConstructor: function getConstructor(wrapper, NAME, IS_MAP, ADDER) { var C = wrapper(function (that, iterable) { _anInstance(that, C, NAME, '_i'); that._t = NAME; // collection type that._i = _objectCreate(null); // index that._f = undefined; // first entry that._l = undefined; // last entry that[SIZE] = 0; // size if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that); }); _redefineAll(C.prototype, { // 23.1.3.1 Map.prototype.clear() // 23.2.3.2 Set.prototype.clear() clear: function clear() { for (var that = _validateCollection(this, NAME), data = that._i, entry = that._f; entry; entry = entry.n) { entry.r = true; if (entry.p) entry.p = entry.p.n = undefined; delete data[entry.i]; } that._f = that._l = undefined; that[SIZE] = 0; }, // 23.1.3.3 Map.prototype.delete(key) // 23.2.3.4 Set.prototype.delete(value) 'delete': function _delete(key) { var that = _validateCollection(this, NAME); var entry = getEntry(that, key); if (entry) { var next = entry.n; var prev = entry.p; delete that._i[entry.i]; entry.r = true; if (prev) prev.n = next; if (next) next.p = prev; if (that._f == entry) that._f = next; if (that._l == entry) that._l = prev; that[SIZE]--; }return !!entry; }, // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined) // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined) forEach: function forEach(callbackfn /* , that = undefined */) { _validateCollection(this, NAME); var f = _ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3); var entry; while (entry = entry ? entry.n : this._f) { f(entry.v, entry.k, this); // revert to the last existing entry while (entry && entry.r) { entry = entry.p; } } }, // 23.1.3.7 Map.prototype.has(key) // 23.2.3.7 Set.prototype.has(value) has: function has(key) { return !!getEntry(_validateCollection(this, NAME), key); } }); if (_descriptors) dP$1(C.prototype, 'size', { get: function get() { return _validateCollection(this, NAME)[SIZE]; } }); return C; }, def: function def(that, key, value) { var entry = getEntry(that, key); var prev, index; // change existing entry if (entry) { entry.v = value; // create new entry } else { that._l = entry = { i: index = fastKey(key, true), // <- index k: key, // <- key v: value, // <- value p: prev = that._l, // <- previous entry n: undefined, // <- next entry r: false // <- removed }; if (!that._f) that._f = entry; if (prev) prev.n = entry; that[SIZE]++; // add to index if (index !== 'F') that._i[index] = entry; }return that; }, getEntry: getEntry, setStrong: function setStrong(C, NAME, IS_MAP) { // add .keys, .values, .entries, [@@iterator] // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11 _iterDefine(C, NAME, function (iterated, kind) { this._t = _validateCollection(iterated, NAME); // target this._k = kind; // kind this._l = undefined; // previous }, function () { var that = this; var kind = that._k; var entry = that._l; // revert to the last existing entry while (entry && entry.r) { entry = entry.p; } // get next entry if (!that._t || !(that._l = entry = entry ? entry.n : that._t._f)) { // or finish the iteration that._t = undefined; return _iterStep(1); } // return step by kind if (kind == 'keys') return _iterStep(0, entry.k); if (kind == 'values') return _iterStep(0, entry.v); return _iterStep(0, [entry.k, entry.v]); }, IS_MAP ? 'entries' : 'values', !IS_MAP, true); // add [@@species], 23.1.2.2, 23.2.2.2 _setSpecies(NAME); } }; var ITERATOR$4 = _wks('iterator'); var SAFE_CLOSING = false; try { var riter = [7][ITERATOR$4](); riter['return'] = function () { SAFE_CLOSING = true; }; // eslint-disable-next-line no-throw-literal } catch (e) {/* empty */} var _iterDetect = function _iterDetect(exec, skipClosing) { if (!skipClosing && !SAFE_CLOSING) return false; var safe = false; try { var arr = [7]; var iter = arr[ITERATOR$4](); iter.next = function () { return { done: safe = true }; }; arr[ITERATOR$4] = function () { return iter; }; exec(arr); } catch (e) {/* empty */} return safe; }; var setPrototypeOf$2 = _setProto.set; var _inheritIfRequired = function _inheritIfRequired(that, target, C) { var S = target.constructor; var P; if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && _isObject(P) && setPrototypeOf$2) { setPrototypeOf$2(that, P); }return that; }; var _collection = function _collection(NAME, wrapper, methods, common, IS_MAP, IS_WEAK) { var Base = _global[NAME]; var C = Base; var ADDER = IS_MAP ? 'set' : 'add'; var proto = C && C.prototype; var O = {}; var fixMethod = function fixMethod(KEY) { var fn = proto[KEY]; _redefine(proto, KEY, KEY == 'delete' ? function (a) { return IS_WEAK && !_isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); } : KEY == 'has' ? function has(a) { return IS_WEAK && !_isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); } : KEY == 'get' ? function get(a) { return IS_WEAK && !_isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a); } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a);return this; } : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b);return this; }); }; if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !_fails(function () { new C().entries().next(); }))) { // create collection constructor C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER); _redefineAll(C.prototype, methods); _meta.NEED = true; } else { var instance = new C(); // early implementations not supports chaining var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance; // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false var THROWS_ON_PRIMITIVES = _fails(function () { instance.has(1); }); // most early implementations doesn't supports iterables, most modern - not close it correctly var ACCEPT_ITERABLES = _iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new // for early implementations -0 and +0 not the same var BUGGY_ZERO = !IS_WEAK && _fails(function () { // V8 ~ Chromium 42- fails only with 5+ elements var $instance = new C(); var index = 5; while (index--) { $instance[ADDER](index, index); }return !$instance.has(-0); }); if (!ACCEPT_ITERABLES) { C = wrapper(function (target, iterable) { _anInstance(target, C, NAME); var that = _inheritIfRequired(new Base(), target, C); if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that); return that; }); C.prototype = proto; proto.constructor = C; } if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) { fixMethod('delete'); fixMethod('has'); IS_MAP && fixMethod('get'); } if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER); // weak collections should not contains .clear method if (IS_WEAK && proto.clear) delete proto.clear; } _setToStringTag(C, NAME); O[NAME] = C; _export(_export.G + _export.W + _export.F * (C != Base), O); if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP); return C; }; var SET = 'Set'; // 23.2 Set Objects var es6_set = _collection(SET, function (get) { return function Set() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; }, { // 23.2.3.1 Set.prototype.add(value) add: function add(value) { return _collectionStrong.def(_validateCollection(this, SET), value = value === 0 ? 0 : value, value); } }, _collectionStrong); var _arrayFromIterable = function _arrayFromIterable(iter, ITERATOR) { var result = []; _forOf(iter, false, result.push, result, ITERATOR); return result; }; // https://github.com/DavidBruant/Map-Set.prototype.toJSON var _collectionToJson = function _collectionToJson(NAME) { return function toJSON() { if (_classof(this) != NAME) throw TypeError(NAME + "#toJSON isn't generic"); return _arrayFromIterable(this); }; }; // https://github.com/DavidBruant/Map-Set.prototype.toJSON _export(_export.P + _export.R, 'Set', { toJSON: _collectionToJson('Set') }); // https://tc39.github.io/proposal-setmap-offrom/ var _setCollectionOf = function _setCollectionOf(COLLECTION) { _export(_export.S, COLLECTION, { of: function of() { var length = arguments.length; var A = Array(length); while (length--) { A[length] = arguments[length]; }return new this(A); } }); }; // https://tc39.github.io/proposal-setmap-offrom/#sec-set.of _setCollectionOf('Set'); // https://tc39.github.io/proposal-setmap-offrom/ var _setCollectionFrom = function _setCollectionFrom(COLLECTION) { _export(_export.S, COLLECTION, { from: function from(source /* , mapFn, thisArg */) { var mapFn = arguments[1]; var mapping, A, n, cb; _aFunction(this); mapping = mapFn !== undefined; if (mapping) _aFunction(mapFn); if (source == undefined) return new this(); A = []; if (mapping) { n = 0; cb = _ctx(mapFn, arguments[2], 2); _forOf(source, false, function (nextItem) { A.push(cb(nextItem, n++)); }); } else { _forOf(source, false, A.push, A); } return new this(A); } }); }; // https://tc39.github.io/proposal-setmap-offrom/#sec-set.from _setCollectionFrom('Set'); var set$1 = _core.Set; var MAP = 'Map'; // 23.1 Map Objects var es6_map = _collection(MAP, function (get) { return function Map() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; }, { // 23.1.3.6 Map.prototype.get(key) get: function get(key) { var entry = _collectionStrong.getEntry(_validateCollection(this, MAP), key); return entry && entry.v; }, // 23.1.3.9 Map.prototype.set(key, value) set: function set(key, value) { return _collectionStrong.def(_validateCollection(this, MAP), key === 0 ? 0 : key, value); } }, _collectionStrong, true); // https://github.com/DavidBruant/Map-Set.prototype.toJSON _export(_export.P + _export.R, 'Map', { toJSON: _collectionToJson('Map') }); // https://tc39.github.io/proposal-setmap-offrom/#sec-map.of _setCollectionOf('Map'); // https://tc39.github.io/proposal-setmap-offrom/#sec-map.from _setCollectionFrom('Map'); var map = _core.Map; // 7.2.2 IsArray(argument) var _isArray = Array.isArray || function isArray(arg) { return _cof(arg) == 'Array'; }; var SPECIES$1 = _wks('species'); var _arraySpeciesConstructor = function _arraySpeciesConstructor(original) { var C; if (_isArray(original)) { C = original.constructor; // cross-realm fallback if (typeof C == 'function' && (C === Array || _isArray(C.prototype))) C = undefined; if (_isObject(C)) { C = C[SPECIES$1]; if (C === null) C = undefined; } }return C === undefined ? Array : C; }; // 9.4.2.3 ArraySpeciesCreate(originalArray, length) var _arraySpeciesCreate = function _arraySpeciesCreate(original, length) { return new (_arraySpeciesConstructor(original))(length); }; // 0 -> Array#forEach // 1 -> Array#map // 2 -> Array#filter // 3 -> Array#some // 4 -> Array#every // 5 -> Array#find // 6 -> Array#findIndex var _arrayMethods = function _arrayMethods(TYPE, $create) { var IS_MAP = TYPE == 1; var IS_FILTER = TYPE == 2; var IS_SOME = TYPE == 3; var IS_EVERY = TYPE == 4; var IS_FIND_INDEX = TYPE == 6; var NO_HOLES = TYPE == 5 || IS_FIND_INDEX; var create = $create || _arraySpeciesCreate; return function ($this, callbackfn, that) { var O = _toObject($this); var self = _iobject(O); var f = _ctx(callbackfn, that, 3); var length = _toLength(self.length); var index = 0; var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined; var val, res; for (; length > index; index++) { if (NO_HOLES || index in self) { val = self[index]; res = f(val, index, O); if (TYPE) { if (IS_MAP) result[index] = res; // map else if (res) switch (TYPE) { case 3: return true; // some case 5: return val; // find case 6: return index; // findIndex case 2: result.push(val); // filter } else if (IS_EVERY) return false; // every } } }return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result; }; }; var f$3 = Object.getOwnPropertySymbols; var _objectGops = { f: f$3 }; // 19.1.2.1 Object.assign(target, source, ...) var $assign = Object.assign; // should work with symbols and should have deterministic property order (V8 bug) var _objectAssign = !$assign || _fails(function () { var A = {}; var B = {}; // eslint-disable-next-line no-undef var S = Symbol(); var K = 'abcdefghijklmnopqrst'; A[S] = 7; K.split('').forEach(function (k) { B[k] = k; }); return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; }) ? function assign(target, source) { // eslint-disable-line no-unused-vars var T = _toObject(target); var aLen = arguments.length; var index = 1; var getSymbols = _objectGops.f; var isEnum = _objectPie.f; while (aLen > index) { var S = _iobject(arguments[index++]); var keys = getSymbols ? _objectKeys(S).concat(getSymbols(S)) : _objectKeys(S); var length = keys.length; var j = 0; var key; while (length > j) { if (isEnum.call(S, key = keys[j++])) T[key] = S[key]; } }return T; } : $assign; var getWeak = _meta.getWeak; var arrayFind = _arrayMethods(5); var arrayFindIndex = _arrayMethods(6); var id$1 = 0; // fallback for uncaught frozen keys var uncaughtFrozenStore = function uncaughtFrozenStore(that) { return that._l || (that._l = new UncaughtFrozenStore()); }; var UncaughtFrozenStore = function UncaughtFrozenStore() { this.a = []; }; var findUncaughtFrozen = function findUncaughtFrozen(store, key) { return arrayFind(store.a, function (it) { return it[0] === key; }); }; UncaughtFrozenStore.prototype = { get: function get(key) { var entry = findUncaughtFrozen(this, key); if (entry) return entry[1]; }, has: function has(key) { return !!findUncaughtFrozen(this, key); }, set: function set(key, value) { var entry = findUncaughtFrozen(this, key); if (entry) entry[1] = value;else this.a.push([key, value]); }, 'delete': function _delete(key) { var index = arrayFindIndex(this.a, function (it) { return it[0] === key; }); if (~index) this.a.splice(index, 1); return !!~index; } }; var _collectionWeak = { getConstructor: function getConstructor(wrapper, NAME, IS_MAP, ADDER) { var C = wrapper(function (that, iterable) { _anInstance(that, C, NAME, '_i'); that._t = NAME; // collection type that._i = id$1++; // collection id that._l = undefined; // leak store for uncaught frozen objects if (iterable != undefined) _forOf(iterable, IS_MAP, that[ADDER], that); }); _redefineAll(C.prototype, { // 23.3.3.2 WeakMap.prototype.delete(key) // 23.4.3.3 WeakSet.prototype.delete(value) 'delete': function _delete(key) { if (!_isObject(key)) return false; var data = getWeak(key); if (data === true) return uncaughtFrozenStore(_validateCollection(this, NAME))['delete'](key); return data && _has(data, this._i) && delete data[this._i]; }, // 23.3.3.4 WeakMap.prototype.has(key) // 23.4.3.4 WeakSet.prototype.has(value) has: function has(key) { if (!_isObject(key)) return false; var data = getWeak(key); if (data === true) return uncaughtFrozenStore(_validateCollection(this, NAME)).has(key); return data && _has(data, this._i); } }); return C; }, def: function def(that, key, value) { var data = getWeak(_anObject(key), true); if (data === true) uncaughtFrozenStore(that).set(key, value);else data[that._i] = value; return that; }, ufstore: uncaughtFrozenStore }; var es6_weakMap = createCommonjsModule(function (module) { var each = _arrayMethods(0); var WEAK_MAP = 'WeakMap'; var getWeak = _meta.getWeak; var isExtensible = Object.isExtensible; var uncaughtFrozenStore = _collectionWeak.ufstore; var tmp = {}; var InternalMap; var wrapper = function wrapper(get) { return function WeakMap() { return get(this, arguments.length > 0 ? arguments[0] : undefined); }; }; var methods = { // 23.3.3.3 WeakMap.prototype.get(key) get: function get(key) { if (_isObject(key)) { var data = getWeak(key); if (data === true) return uncaughtFrozenStore(_validateCollection(this, WEAK_MAP)).get(key); return data ? data[this._i] : undefined; } }, // 23.3.3.5 WeakMap.prototype.set(key, value) set: function set(key, value) { return _collectionWeak.def(_validateCollection(this, WEAK_MAP), key, value); } }; // 23.3 WeakMap Objects var $WeakMap = module.exports = _collection(WEAK_MAP, wrapper, methods, _collectionWeak, true, true); // IE11 WeakMap frozen keys fix if (_fails(function () { return new $WeakMap().set((Object.freeze || Object)(tmp), 7).get(tmp) != 7; })) { InternalMap = _collectionWeak.getConstructor(wrapper, WEAK_MAP); _objectAssign(InternalMap.prototype, methods); _meta.NEED = true; each(['delete', 'has', 'get', 'set'], function (key) { var proto = $WeakMap.prototype; var method = proto[key]; _redefine(proto, key, function (a, b) { // store frozen objects on internal weakmap shim if (_isObject(a) && !isExtensible(a)) { if (!this._f) this._f = new InternalMap(); var result = this._f[key](a, b); return key == 'set' ? this : result; // store all the rest on native weakmap }return method.call(this, a, b); }); }); } }); // https://tc39.github.io/proposal-setmap-offrom/#sec-weakmap.of _setCollectionOf('WeakMap'); // https://tc39.github.io/proposal-setmap-offrom/#sec-weakmap.from _setCollectionFrom('WeakMap'); var weakMap = _core.WeakMap; var _createProperty = function _createProperty(object, index, value) { if (index in object) _objectDp.f(object, index, _propertyDesc(0, value));else object[index] = value; }; _export(_export.S + _export.F * !_iterDetect(function (iter) { }), 'Array', { // 22.1.2.1 Array.from(arrayLike, mapfn = undefined, thisArg = undefined) from: function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) { var O = _toObject(arrayLike); var C = typeof this == 'function' ? this : Array; var aLen = arguments.length; var mapfn = aLen > 1 ? arguments[1] : undefined; var mapping = mapfn !== undefined; var index = 0; var iterFn = core_getIteratorMethod(O); var length, result, step, iterator; if (mapping) mapfn = _ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2); // if object isn't iterable or it's array with default iterator - use simple case if (iterFn != undefined && !(C == Array && _isArrayIter(iterFn))) { for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) { _createProperty(result, index, mapping ? _iterCall(iterator, mapfn, [step.value, index], true) : step.value); } } else { length = _toLength(O.length); for (result = new C(length); length > index; index++) { _createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]); } } result.length = index; return result; } }); var from$1 = _core.Array.from; var reservedTagList = new Set(['annotation-xml', 'color-profile', 'font-face', 'font-face-src', 'font-face-uri', 'font-face-format', 'font-face-name', 'missing-glyph']); /** * @param {string} localName * @returns {boolean} */ function isValidCustomElementName(localName) { var reserved = reservedTagList.has(localName); var validForm = /^[a-z][.0-9_a-z]*-[\-.0-9_a-z]*$/.test(localName); return !reserved && validForm; } /** * @private * @param {!Node} node * @return {boolean} */ function isConnected(node) { // Use `Node#isConnected`, if defined. var nativeValue = node.isConnected; if (nativeValue !== undefined) { return nativeValue; } /** @type {?Node|undefined} */ var current = node; while (current && !(current.__CE_isImportDocument || current instanceof Document)) { current = current.parentNode || (window.ShadowRoot && current instanceof ShadowRoot ? current.host : undefined); } return !!(current && (current.__CE_isImportDocument || current instanceof Document)); } /** * @param {!Node} root * @param {!Node} start * @return {?Node} */ function nextSiblingOrAncestorSibling(root, start) { var node = start; while (node && node !== root && !node.nextSibling) { node = node.parentNode; } return !node || node === root ? null : node.nextSibling; } /** * @param {!Node} root * @param {!Node} start * @return {?Node} */ function nextNode(root, start) { return start.firstChild ? start.firstChild : nextSiblingOrAncestorSibling(root, start); } /** * @param {!Node} root * @param {!function(!Element)} callback * @param {!Set<Node>=} visitedImports */ function walkDeepDescendantElements(root, callback) { var visitedImports = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new Set(); var node = root; while (node) { if (node.nodeType === Node.ELEMENT_NODE) { var element = /** @type {!Element} */node; callback(element); var localName = element.localName; if (localName === 'link' && element.getAttribute('rel') === 'import') { // If this import (polyfilled or not) has it's root node available, // walk it. var importNode = /** @type {!Node} */element.import; if (importNode instanceof Node && !visitedImports.has(importNode)) { // Prevent multiple walks of the same import root. visitedImports.add(importNode); for (var child = importNode.firstChild; child; child = child.nextSibling) { walkDeepDescendantElements(child, callback, visitedImports); } } // Ignore descendants of import links to prevent attempting to walk the // elements created by the HTML Imports polyfill that we just walked // above. node = nextSiblingOrAncestorSibling(root, element); continue; } else if (localName === 'template') { // Ignore descendants of templates. There shouldn't be any descendants // because they will be moved into `.content` during construction in // browsers that support template but, in case they exist and are still // waiting to be moved by a polyfill, they will be ignored. node = nextSiblingOrAncestorSibling(root, element); continue; } // Walk shadow roots. var shadowRoot = element.__CE_shadowRoot; if (shadowRoot) { for (var _child = shadowRoot.firstChild; _child; _child = _child.nextSibling) { walkDeepDescendantElements(_child, callback, visitedImports); } } } node = nextNode(root, node); } } /** * Used to suppress Closure's "Modifying the prototype is only allowed if the * constructor is in the same scope" warning without using * `@suppress {newCheckTypes, duplicate}` because `newCheckTypes` is too broad. * * @param {!Object} destination * @param {string} name * @param {*} value */ function setPropertyUnchecked(destination, name, value) { destination[name] = value; } /** * @enum {number} */ var CustomElementState = { custom: 1, failed: 2 }; var CustomElementInternals = function () { function CustomElementInternals() { classCallCheck(this, CustomElementInternals); /** @type {!Map<string, !CustomElementDefinition>} */ this._localNameToDefinition = new Map(); /** @type {!Map<!Function, !CustomElementDefinition>} */ this._constructorToDefinition = new Map(); /** @type {!Array<!function(!Node)>} */ this._patches = []; /** @type {boolean} */ this._hasPatches = false; } /** * @param {string} localName * @param {!CustomElementDefinition} definition */ createClass(CustomElementInternals, [{ key: 'setDefinition', value: function setDefinition(localName, definition) { this._localNameToDefinition.set(localName, definition); this._constructorToDefinition.set(definition.constructor, definition); } /** * @param {string} localName * @return {!CustomElementDefinition|undefined} */ }, { key: 'localNameToDefinition', value: function localNameToDefinition(localName) { return this._localNameToDefinition.get(localName); } /** * @param {!Function} constructor * @return {!CustomElementDefinition|undefined} */ }, { key: 'constructorToDefinition', value: function constructorToDefinition(constructor) { return this._constructorToDefinition.get(constructor); } /** * @param {!function(!Node)} listener */ }, { key: 'addPatch', value: function addPatch(listener) { this._hasPatches = true; this._patches.push(listener); } /** * @param {!Node} node */ }, { key: 'patchTree', value: function patchTree(node) { var _this = this; if (!this._hasPatches) return; walkDeepDescendantElements(node, function (element) { return _this.patch(element); }); } /** * @param {!Node} node */ }, { key: 'patch', value: function patch(node) { if (!this._hasPatches) return; if (node.__CE_patched) return; node.__CE_patched = true; for (var i = 0; i < this._patches.length; i++) { this._patches[i](node); } } /** * @param {!Node} root */ }, { key: 'connectTree', value: function connectTree(root) { var elements = []; walkDeepDescendantElements(root, function (element) { return elements.push(element); }); for (var i = 0; i < elements.length; i++) { var element = elements[i]; if (element.__CE_state === CustomElementState.custom) { if (isConnected(element)) { this.connectedCallback(element); } } else { this.upgradeElement(element); } } } /** * @param {!Node} root */ }, { key: 'disconnectTree', value: function disconnectTree(root) { var elements = []; walkDeepDescendantElements(root, function (element) { return elements.push(element); }); for (var i = 0; i < elements.length; i++) { var element = elements[i]; if (element.__CE_state === CustomElementState.custom) { this.disconnectedCallback(element); } } } /** * Upgrades all uncustomized custom elements at and below a root node for * which there is a definition. When custom element reaction callbacks are * assumed to be called synchronously (which, by the current DOM / HTML spec * definitions, they are *not*), callbacks for both elements customized * synchronously by the parser and elements being upgraded occur in the same * relative order. * * NOTE: This function, when used to simulate the construction of a tree that * is already created but not customized (i.e. by the parser), does *not* * prevent the element from reading the 'final' (true) state of the tree. For * example, the element, during truly synchronous parsing / construction would * see that it contains no children as they have not yet been inserted. * However, this function does not modify the tree, the element will * (incorrectly) have children. Additionally, self-modification restrictions * for custom element constructors imposed by the DOM spec are *not* enforced. * * * The following nested list shows the steps extending down from the HTML * spec's parsing section that cause elements to be synchronously created and * upgraded: * * The "in body" insertion mode: * https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inbody * - Switch on token: * .. other cases .. * -> Any other start tag * - [Insert an HTML element](below) for the token. * * Insert an HTML element: * https://html.spec.whatwg.org/multipage/syntax.html#insert-an-html-element * - Insert a foreign element for the token in the HTML namespace: * https://html.spec.whatwg.org/multipage/syntax.html#insert-a-foreign-element * - Create an element for a token: * https://html.spec.whatwg.org/multipage/syntax.html#create-an-element-for-the-token * - Will execute script flag is true? * - (Element queue pushed to the custom element reactions stack.) * - Create an element: * https://dom.spec.whatwg.org/#concept-create-element * - Sync CE flag is true? * - Constructor called. * - Self-modification restrictions enforced. * - Sync CE flag is false? * - (Upgrade reaction enqueued.) * - Attributes appended to element. * (`attributeChangedCallback` reactions enqueued.) * - Will execute script flag is true? * - (Element queue popped from the custom element reactions stack. * Reactions in the popped stack are invoked.) * - (Element queue pushed to the custom element reactions stack.) * - Insert the element: * https://dom.spec.whatwg.org/#concept-node-insert * - Shadow-including descendants are connected. During parsing * construction, there are no shadow-*excluding* descendants. * However, the constructor may have validly attached a shadow * tree to itself and added descendants to that shadow tree. * (`connectedCallback` reactions enqueued.) * - (Element queue popped from the custom element reactions stack. * Reactions in the popped stack are invoked.) * * @param {!Node} root * @param {!Set<Node>=} visitedImports */ }, { key: 'patchAndUpgradeTree', value: function patchAndUpgradeTree(root) { var _this2 = this; var visitedImports = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Set(); var elements = []; var gatherElements = function gatherElements(element) { if (element.localName === 'link' && element.getAttribute('rel') === 'import') { // The HTML Imports polyfill sets a descendant element of the link to // the `import` property, specifically this is *not* a Document. var importNode = /** @type {?Node} */element.import; if (importNode instanceof Node && importNode.readyState === 'complete') { importNode.__CE_isImportDocument = true; // Connected links are associated with the registry. importNode.__CE_hasRegistry = true; } else { // If this link's import root is not available, its contents can't be // walked. Wait for 'load' and walk it when it's ready. element.addEventListener('load', function () { var importNode = /** @type {!Node} */element.import; if (importNode.__CE_documentLoadHandled) return; importNode.__CE_documentLoadHandled = true; importNode.__CE_isImportDocument = true; // Connected links are associated with the registry. importNode.__CE_hasRegistry = true; // Clone the `visitedImports` set that was populated sync during // the `patchAndUpgradeTree` call that caused this 'load' handler to // be added. Then, remove *this* link's import node so that we can // walk that import again, even if it was partially walked later // during the same `patchAndUpgradeTree` call. visitedImports.delete(importNode); _this2.patchAndUpgradeTree(importNode, visitedImports); }); } } else { elements.push(element); } }; // `walkDeepDescendantElements` populates (and internally checks against) // `visitedImports` when traversing a loaded import. walkDeepDescendantElements(root, gatherElements, visitedImports); if (this._hasPatches) { for (var i = 0; i < elements.length; i++) { this.patch(elements[i]); } } for (var _i = 0; _i < elements.length; _i++) { this.upgradeElement(elements[_i]); } } /** * @param {!Element} element */ }, { key: 'upgradeElement', value: function upgradeElement(element) { var currentState = element.__CE_state; if (currentState !== undefined) return; var definition = this.localNameToDefinition(element.localName); if (!definition) return; definition.constructionStack.push(element); var constructor = definition.constructor; try { try { var result = new constructor(); if (result !== element) { throw new Error('The custom element constructor did not produce the element being upgraded.'); } } finally { definition.constructionStack.pop(); } } catch (e) { element.__CE_state = CustomElementState.failed; throw e; } element.__CE_state = CustomElementState.custom; element.__CE_definition = definition; if (definition.attributeChangedCallback) { var observedAttributes = definition.observedAttributes; for (var i = 0; i < observedAttributes.length; i++) { var name = observedAttributes[i]; var value = element.getAttribute(name); if (value !== null) { this.attributeChangedCallback(element, name, null, value, null); } } } if (isConnected(element)) { this.connectedCallback(element); } } /** * @param {!Element} element */ }, { key: 'connectedCallback', value: function connectedCallback(element) { var definition = element.__CE_definition; if (definition.connectedCallback) { definition.connectedCallback.call(element); } element.__CE_isConnectedCallbackCalled = true; } /** * @param {!Element} element */ }, { key: 'disconnectedCallback', value: function disconnectedCallback(element) { if (!element.__CE_isConnectedCallbackCalled) { this.connectedCallback(element); } var definition = element.__CE_definition; if (definition.disconnectedCallback) { definition.disconnectedCallback.call(element); } element.__CE_isConnectedCallbackCalled = undefined; } /** * @param {!Element} element * @param {string} name * @param {?string} oldValue * @param {?string} newValue * @param {?string} namespace */ }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(element, name, oldValue, newValue, namespace) { var definition = element.__CE_definition; if (definition.attributeChangedCallback && definition.observedAttributes.indexOf(name) > -1) { definition.attributeChangedCallback.call(element, name, oldValue, newValue, namespace); } } }]); return CustomElementInternals; }(); var DocumentConstructionObserver = function () { function DocumentConstructionObserver(internals, doc) { classCallCheck(this, DocumentConstructionObserver); /** * @type {!CustomElementInternals} */ this._internals = internals; /** * @type {!Document} */ this._document = doc; /** * @type {MutationObserver|undefined} */ this._observer = undefined; // Simulate tree construction for all currently accessible nodes in the // document. this._internals.patchAndUpgradeTree(this._document); if (this._document.readyState === 'loading') { this._observer = new MutationObserver(this._handleMutations.bind(this)); // Nodes created by the parser are given to the observer *before* the next // task runs. Inline scripts are run in a new task. This means that the // observer will be able to handle the newly parsed nodes before the inline // script is run. this._observer.observe(this._document, { childList: true, subtree: true }); } } createClass(DocumentConstructionObserver, [{ key: 'disconnect', value: function disconnect() { if (this._observer) { this._observer.disconnect(); } } /** * @param {!Array<!MutationRecord>} mutations */ }, { key: '_handleMutations', value: function _handleMutations(mutations) { // Once the document's `readyState` is 'interactive' or 'complete', all new // nodes created within that document will be the result of script and // should be handled by patching. var readyState = this._document.readyState; if (readyState === 'interactive' || readyState === 'complete') { this.disconnect(); } for (var i = 0; i < mutations.length; i++) { var addedNodes = mutations[i].addedNodes; for (var j = 0; j < addedNodes.length; j++) { var node = addedNodes[j]; this._internals.patchAndUpgradeTree(node); } } } }]); return DocumentConstructionObserver; }(); /** * @template T */ var Deferred = function () { function Deferred() { var _this = this; classCallCheck(this, Deferred); /** * @private * @type {T|undefined} */ this._value = undefined; /** * @private * @type {Function|undefined} */ this._resolve = undefined; /** * @private * @type {!Promise<T>} */ this._promise = new Promise(function (resolve) { _this._resolve = resolve; if (_this._value) { resolve(_this._value); } }); } /** * @param {T} value */ createClass(Deferred, [{ key: 'resolve', value: function resolve(value) { if (this._value) { throw new Error('Already resolved.'); } this._value = value; if (this._resolve) { this._resolve(value); } } /** * @return {!Promise<T>} */ }, { key: 'toPromise', value: function toPromise() { return this._promise; } }]); return Deferred; }(); /** * @unrestricted */ var CustomElementRegistry = function () { /** * @param {!CustomElementInternals} internals */ function CustomElementRegistry(internals) { classCallCheck(this, CustomElementRegistry); /** * @private * @type {boolean} */ this._elementDefinitionIsRunning = false; /** * @private * @type {!CustomElementInternals} */ this._internals = internals; /** * @private * @type {!Map<string, !Deferred<undefined>>} */ this._whenDefinedDeferred = new Map(); /** * The default flush callback triggers the document walk synchronously. * @private * @type {!Function} */ this._flushCallback = function (fn) { return fn(); }; /** * @private * @type {boolean} */ this._flushPending = false; /** * @private * @type {!Array<string>} */ this._unflushedLocalNames = []; /** * @private * @type {!DocumentConstructionObserver} */ this._documentConstructionObserver = new DocumentConstructionObserver(internals, document); } /** * @param {string} localName * @param {!Function} constructor */ createClass(CustomElementRegistry, [{ key: 'define', value: function define(localName, constructor) { var _this = this; if (!(constructor instanceof Function)) { throw new TypeError('Custom element constructors must be functions.'); } if (!isValidCustomElementName(localName)) { throw new SyntaxError('The element name \'' + localName + '\' is not valid.'); } if (this._internals.localNameToDefinition(localName)) { throw new Error('A custom element with name \'' + localName + '\' has already been defined.'); } if (this._elementDefinitionIsRunning) { throw new Error('A custom element is already being defined.'); } this._elementDefinitionIsRunning = true; var connectedCallback = void 0; var disconnectedCallback = void 0; var adoptedCallback = void 0; var attributeChangedCallback = void 0; var observedAttributes = void 0; try { var getCallback = function getCallback(name) { var callbackValue = prototype[name]; if (callbackValue !== undefined && !(callbackValue instanceof Function)) { throw new Error('The \'' + name + '\' callback must be a function.'); } return callbackValue; }; /** @type {!Object} */ var prototype = constructor.prototype; if (!(prototype instanceof Object)) { throw new TypeError('The custom element constructor\'s prototype is not an object.'); } connectedCallback = getCallback('connectedCallback'); disconnectedCallback = getCallback('disconnectedCallback'); adoptedCallback = getCallback('adoptedCallback'); attributeChangedCallback = getCallback('attributeChangedCallback'); observedAttributes = constructor['observedAttributes'] || []; } catch (e) { return; } finally { this._elementDefinitionIsRunning = false; } var definition = { localName: localName, constructor: constructor, connectedCallback: connectedCallback, disconnectedCallback: disconnectedCallback, adoptedCallback: adoptedCallback, attributeChangedCallback: attributeChangedCallback, observedAttributes: observedAttributes, constructionStack: [] }; this._internals.setDefinition(localName, definition); this._unflushedLocalNames.push(localName); // If we've already called the flush callback and it hasn't called back yet, // don't call it again. if (!this._flushPending) { this._flushPending = true; this._flushCallback(function () { return _this._flush(); }); } } }, { key: '_flush', value: function _flush() { // If no new definitions were defined, don't attempt to flush. This could // happen if a flush callback keeps the function it is given and calls it // multiple times. if (this._flushPending === false) return; this._flushPending = false; this._internals.patchAndUpgradeTree(document); while (this._unflushedLocalNames.length > 0) { var localName = this._unflushedLocalNames.shift(); var deferred = this._whenDefinedDeferred.get(localName); if (deferred) { deferred.resolve(undefined); } } } /** * @param {string} localName * @return {Function|undefined} */ }, { key: 'get', value: function get$$1(localName) { var definition = this._internals.localNameToDefinition(localName); if (definition) { return definition.constructor; } return undefined; } /** * @param {string} localName * @return {!Promise<undefined>} */ }, { key: 'whenDefined', value: function whenDefined(localName) { if (!isValidCustomElementName(localName)) { return Promise.reject(new SyntaxError('\'' + localName + '\' is not a valid custom element name.')); } var prior = this._whenDefinedDeferred.get(localName); if (prior) { return prior.toPromise(); } var deferred = new Deferred(); this._whenDefinedDeferred.set(localName, deferred); var definition = this._internals.localNameToDefinition(localName); // Resolve immediately only if the given local name has a definition *and* // the full document walk to upgrade elements with that local name has // already happened. if (definition && this._unflushedLocalNames.indexOf(localName) === -1) { deferred.resolve(undefined); } return deferred.toPromise(); } }, { key: 'polyfillWrapFlushCallback', value: function polyfillWrapFlushCallback(outer) { this._documentConstructionObserver.disconnect(); var inner = this._flushCallback; this._flushCallback = function (flush) { return outer(function () { return inner(flush); }); }; } }]); return CustomElementRegistry; }(); window['CustomElementRegistry'] = CustomElementRegistry; CustomElementRegistry.prototype['define'] = CustomElementRegistry.prototype.define; CustomElementRegistry.prototype['get'] = CustomElementRegistry.prototype.get; CustomElementRegistry.prototype['whenDefined'] = CustomElementRegistry.prototype.whenDefined; CustomElementRegistry.prototype['polyfillWrapFlushCallback'] = CustomElementRegistry.prototype.polyfillWrapFlushCallback; var Native = { Document_createElement: window.Document.prototype.createElement, Document_createElementNS: window.Document.prototype.createElementNS, Document_importNode: window.Document.prototype.importNode, Document_prepend: window.Document.prototype['prepend'], Document_append: window.Document.prototype['append'], Node_cloneNode: window.Node.prototype.cloneNode, Node_appendChild: window.Node.prototype.appendChild, Node_insertBefore: window.Node.prototype.insertBefore, Node_removeChild: window.Node.prototype.removeChild, Node_replaceChild: window.Node.prototype.replaceChild, Node_textContent: Object.getOwnPropertyDescriptor(window.Node.prototype, 'textContent'), Element_attachShadow: window.Element.prototype['attachShadow'], Element_innerHTML: Object.getOwnPropertyDescriptor(window.Element.prototype, 'innerHTML'), Element_getAttribute: window.Element.prototype.getAttribute, Element_setAttribute: window.Element.prototype.setAttribute, Element_removeAttribute: window.Element.prototype.removeAttribute, Element_getAttributeNS: window.Element.prototype.getAttributeNS, Element_setAttributeNS: window.Element.prototype.setAttributeNS, Element_removeAttributeNS: window.Element.prototype.removeAttributeNS, Element_insertAdjacentElement: window.Element.prototype['insertAdjacentElement'], Element_prepend: window.Element.prototype['prepend'], Element_append: window.Element.prototype['append'], Element_before: window.Element.prototype['before'], Element_after: window.Element.prototype['after'], Element_replaceWith: window.Element.prototype['replaceWith'], Element_remove: window.Element.prototype['remove'], HTMLElement: window.HTMLElement, HTMLElement_innerHTML: Object.getOwnPropertyDescriptor(window.HTMLElement.prototype, 'innerHTML'), HTMLElement_insertAdjacentElement: window.HTMLElement.prototype['insertAdjacentElement'] }; /** * This class exists only to work around Closure's lack of a way to describe * singletons. It represents the 'already constructed marker' used in custom * element construction stacks. * * https://html.spec.whatwg.org/#concept-already-constructed-marker */ var AlreadyConstructedMarker = function AlreadyConstructedMarker() { classCallCheck(this, AlreadyConstructedMarker); }; var AlreadyConstructedMarker$1 = new AlreadyConstructedMarker(); /** * @param {!CustomElementInternals} internals */ var PatchHTMLElement = function (internals) { window['HTMLElement'] = function () { /** * @type {function(new: HTMLElement): !HTMLElement} */ function HTMLElement() { // This should really be `new.target` but `new.target` can't be emulated // in ES5. Assuming the user keeps the default value of the constructor's // prototype's `constructor` property, this is equivalent. /** @type {!Function} */ var constructor = this.constructor; var definition = internals.constructorToDefinition(constructor); if (!definition) { throw new Error('The custom element being constructed was not registered with `customElements`.'); } var constructionStack = definition.constructionStack; if (constructionStack.length === 0) { var _element = Native.Document_createElement.call(document, definition.localName); Object.setPrototypeOf(_element, constructor.prototype); _element.__CE_state = CustomElementState.custom; _element.__CE_definition = definition; internals.patch(_element); return _element; } var lastIndex = constructionStack.length - 1; var element = constructionStack[lastIndex]; if (element === AlreadyConstructedMarker$1) { throw new Error('The HTMLElement constructor was either called reentrantly for this constructor or called multiple times.'); } constructionStack[lastIndex] = AlreadyConstructedMarker$1; Object.setPrototypeOf(element, constructor.prototype); internals.patch( /** @type {!HTMLElement} */element); return element; } HTMLElement.prototype = Native.HTMLElement.prototype; return HTMLElement; }(); }; /** * @param {!CustomElementInternals} internals * @param {!Object} destination * @param {!ParentNodeNativeMethods} builtIn */ var PatchParentNode = function (internals, destination, builtIn) { /** * @param {...(!Node|string)} nodes */ destination['prepend'] = function () { for (var _len = arguments.length, nodes = Array(_len), _key = 0; _key < _len; _key++) { nodes[_key] = arguments[_key]; } // TODO: Fix this for when one of `nodes` is a DocumentFragment! var connectedBefore = /** @type {!Array<!Node>} */nodes.filter(function (node) { // DocumentFragments are not connected and will not be added to the list. return node instanceof Node && isConnected(node); }); builtIn.prepend.apply(this, nodes); for (var i = 0; i < connectedBefore.length; i++) { internals.disconnectTree(connectedBefore[i]); } if (isConnected(this)) { for (var _i = 0; _i < nodes.length; _i++) { var node = nodes[_i]; if (node instanceof Element) { internals.connectTree(node); } } } }; /** * @param {...(!Node|string)} nodes */ destination['append'] = function () { for (var _len2 = arguments.length, nodes = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { nodes[_key2] = arguments[_key2]; } // TODO: Fix this for when one of `nodes` is a DocumentFragment! var connectedBefore = /** @type {!Array<!Node>} */nodes.filter(function (node) { // DocumentFragments are not connected and will not be added to the list. return node instanceof Node && isConnected(node); }); builtIn.append.apply(this, nodes); for (var i = 0; i < connectedBefore.length; i++) { internals.disconnectTree(connectedBefore[i]); } if (isConnected(this)) { for (var _i2 = 0; _i2 < nodes.length; _i2++) { var node = nodes[_i2]; if (node instanceof Element) { internals.connectTree(node); } } } }; }; /** * @param {!CustomElementInternals} internals */ var PatchDocument = function (internals) { setPropertyUnchecked(Document.prototype, 'createElement', /** * @this {Document} * @param {string} localName * @return {!Element} */ function (localName) { // Only create custom elements if this document is associated with the registry. if (this.__CE_hasRegistry) { var definition = internals.localNameToDefinition(localName); if (definition) { return new definition.constructor(); } } var result = /** @type {!Element} */ Native.Document_createElement.call(this, localName); internals.patch(result); return result; }); setPropertyUnchecked(Document.prototype, 'importNode', /** * @this {Document} * @param {!Node} node * @param {boolean=} deep * @return {!Node} */ function (node, deep) { var clone = Native.Document_importNode.call(this, node, deep); // Only create custom elements if this document is associated with the registry. if (!this.__CE_hasRegistry) { internals.patchTree(clone); } else { internals.patchAndUpgradeTree(clone); } return clone; }); var NS_HTML = "http://www.w3.org/1999/xhtml"; setPropertyUnchecked(Document.prototype, 'createElementNS', /** * @this {Document} * @param {?string} namespace * @param {string} localName * @return {!Element} */ function (namespace, localName) { // Only create custom elements if this document is associated with the registry. if (this.__CE_hasRegistry && (namespace === null || namespace === NS_HTML)) { var definition = internals.localNameToDefinition(localName); if (definition) { return new definition.constructor(); } } var result = /** @type {!Element} */ Native.Document_createElementNS.call(this, namespace, localName); internals.patch(result); return result; }); PatchParentNode(internals, Document.prototype, { prepend: Native.Document_prepend, append: Native.Document_append }); }; /** * @param {!CustomElementInternals} internals */ var PatchNode = function (internals) { // `Node#nodeValue` is implemented on `Attr`. // `Node#textContent` is implemented on `Attr`, `Element`. setPropertyUnchecked(Node.prototype, 'insertBefore', /** * @this {Node} * @param {!Node} node * @param {?Node} refNode * @return {!Node} */ function (node, refNode) { if (node instanceof DocumentFragment) { var insertedNodes = Array.prototype.slice.apply(node.childNodes); var _nativeResult = Native.Node_insertBefore.call(this, node, refNode); // DocumentFragments can't be connected, so `disconnectTree` will never // need to be called on a DocumentFragment's children after inserting it. if (isConnected(this)) { for (var i = 0; i < insertedNodes.length; i++) { internals.connectTree(insertedNodes[i]); } } return _nativeResult; } var nodeWasConnected = isConnected(node); var nativeResult = Native.Node_insertBefore.call(this, node, refNode); if (nodeWasConnected) { internals.disconnectTree(node); } if (isConnected(this)) { internals.connectTree(node); } return nativeResult; }); setPropertyUnchecked(Node.prototype, 'appendChild', /** * @this {Node} * @param {!Node} node * @return {!Node} */ function (node) { if (node instanceof DocumentFragment) { var insertedNodes = Array.prototype.slice.apply(node.childNodes); var _nativeResult2 = Native.Node_appendChild.call(this, node); // DocumentFragments can't be connected, so `disconnectTree` will never // need to be called on a DocumentFragment's children after inserting it. if (isConnected(this)) { for (var i = 0; i < insertedNodes.length; i++) { internals.connectTree(insertedNodes[i]); } } return _nativeResult2; } var nodeWasConnected = isConnected(node); var nativeResult = Native.Node_appendChild.call(this, node); if (nodeWasConnected) { internals.disconnectTree(node); } if (isConnected(this)) { internals.connectTree(node); } return nativeResult; }); setPropertyUnchecked(Node.prototype, 'cloneNode', /** * @this {Node} * @param {boolean=} deep * @return {!Node} */ function (deep) { var clone = Native.Node_cloneNode.call(this, deep); // Only create custom elements if this element's owner document is // associated with the registry. if (!this.ownerDocument.__CE_hasRegistry) { internals.patchTree(clone); } else { internals.patchAndUpgradeTree(clone); } return clone; }); setPropertyUnchecked(Node.prototype, 'removeChild', /** * @this {Node} * @param {!Node} node * @return {!Node} */ function (node) { var nodeWasConnected = isConnected(node); var nativeResult = Native.Node_removeChild.call(this, node); if (nodeWasConnected) { internals.disconnectTree(node); } return nativeResult; }); setPropertyUnchecked(Node.prototype, 'replaceChild', /** * @this {Node} * @param {!Node} nodeToInsert * @param {!Node} nodeToRemove * @return {!Node} */ function (nodeToInsert, nodeToRemove) { if (nodeToInsert instanceof DocumentFragment) { var insertedNodes = Array.prototype.slice.apply(nodeToInsert.childNodes); var _nativeResult3 = Native.Node_replaceChild.call(this, nodeToInsert, nodeToRemove); // DocumentFragments can't be connected, so `disconnectTree` will never // need to be called on a DocumentFragment's children after inserting it. if (isConnected(this)) { internals.disconnectTree(nodeToRemove); for (var i = 0; i < insertedNodes.length; i++) { internals.connectTree(insertedNodes[i]); } } return _nativeResult3; } var nodeToInsertWasConnected = isConnected(nodeToInsert); var nativeResult = Native.Node_replaceChild.call(this, nodeToInsert, nodeToRemove); var thisIsConnected = isConnected(this); if (thisIsConnected) { internals.disconnectTree(nodeToRemove); } if (nodeToInsertWasConnected) { internals.disconnectTree(nodeToInsert); } if (thisIsConnected) { internals.connectTree(nodeToInsert); } return nativeResult; }); function patch_textContent(destination, baseDescriptor) { Object.defineProperty(destination, 'textContent', { enumerable: baseDescriptor.enumerable, configurable: true, get: baseDescriptor.get, set: /** @this {Node} */function set(assignedValue) { // If this is a text node then there are no nodes to disconnect. if (this.nodeType === Node.TEXT_NODE) { baseDescriptor.set.call(this, assignedValue); return; } var removedNodes = undefined; // Checking for `firstChild` is faster than reading `childNodes.length` // to compare with 0. if (this.firstChild) { // Using `childNodes` is faster than `children`, even though we only // care about elements. var childNodes = this.childNodes; var childNodesLength = childNodes.length; if (childNodesLength > 0 && isConnected(this)) { // Copying an array by iterating is faster than using slice. removedNodes = new Array(childNodesLength); for (var i = 0; i < childNodesLength; i++) { removedNodes[i] = childNodes[i]; } } } baseDescriptor.set.call(this, assignedValue); if (removedNodes) { for (var _i = 0; _i < removedNodes.length; _i++) { internals.disconnectTree(removedNodes[_i]); } } } }); } if (Native.Node_textContent && Native.Node_textContent.get) { patch_textContent(Node.prototype, Native.Node_textContent); } else { internals.addPatch(function (element) { patch_textContent(element, { enumerable: true, configurable: true, // NOTE: This implementation of the `textContent` getter assumes that // text nodes' `textContent` getter will not be patched. get: /** @this {Node} */function get() { /** @type {!Array<string>} */ var parts = []; for (var i = 0; i < this.childNodes.length; i++) { parts.push(this.childNodes[i].textContent); } return parts.join(''); }, set: /** @this {Node} */function set(assignedValue) { while (this.firstChild) { Native.Node_removeChild.call(this, this.firstChild); } Native.Node_appendChild.call(this, document.createTextNode(assignedValue)); } }); }); } }; /** * @param {!CustomElementInternals} internals * @param {!Object} destination * @param {!ChildNodeNativeMethods} builtIn */ var PatchChildNode = function (internals, destination, builtIn) { /** * @param {...(!Node|string)} nodes */ destination['before'] = function () { for (var _len = arguments.length, nodes = Array(_len), _key = 0; _key < _len; _key++) { nodes[_key] = arguments[_key]; } // TODO: Fix this for when one of `nodes` is a DocumentFragment! var connectedBefore = /** @type {!Array<!Node>} */nodes.filter(function (node) { // DocumentFragments are not connected and will not be added to the list. return node instanceof Node && isConnected(node); }); builtIn.before.apply(this, nodes); for (var i = 0; i < connectedBefore.length; i++) { internals.disconnectTree(connectedBefore[i]); } if (isConnected(this)) { for (var _i = 0; _i < nodes.length; _i++) { var node = nodes[_i]; if (node instanceof Element) { internals.connectTree(node); } } } }; /** * @param {...(!Node|string)} nodes */ destination['after'] = function () { for (var _len2 = arguments.length, nodes = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { nodes[_key2] = arguments[_key2]; } // TODO: Fix this for when one of `nodes` is a DocumentFragment! var connectedBefore = /** @type {!Array<!Node>} */nodes.filter(function (node) { // DocumentFragments are not connected and will not be added to the list. return node instanceof Node && isConnected(node); }); builtIn.after.apply(this, nodes); for (var i = 0; i < connectedBefore.length; i++) { internals.disconnectTree(connectedBefore[i]); } if (isConnected(this)) { for (var _i2 = 0; _i2 < nodes.length; _i2++) { var node = nodes[_i2]; if (node instanceof Element) { internals.connectTree(node); } } } }; /** * @param {...(!Node|string)} nodes */ destination['replaceWith'] = function () { for (var _len3 = arguments.length, nodes = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { nodes[_key3] = arguments[_key3]; } // TODO: Fix this for when one of `nodes` is a DocumentFragment! var connectedBefore = /** @type {!Array<!Node>} */nodes.filter(function (node) { // DocumentFragments are not connected and will not be added to the list. return node instanceof Node && isConnected(node); }); var wasConnected = isConnected(this); builtIn.replaceWith.apply(this, nodes); for (var i = 0; i < connectedBefore.length; i++) { internals.disconnectTree(connectedBefore[i]); } if (wasConnected) { internals.disconnectTree(this); for (var _i3 = 0; _i3 < nodes.length; _i3++) { var node = nodes[_i3]; if (node instanceof Element) { internals.connectTree(node); } } } }; destination['remove'] = function () { var wasConnected = isConnected(this); builtIn.remove.call(this); if (wasConnected) { internals.disconnectTree(this); } }; }; /** * @param {!CustomElementInternals} internals */ var PatchElement = function (internals) { if (Native.Element_attachShadow) { setPropertyUnchecked(Element.prototype, 'attachShadow', /** * @this {Element} * @param {!{mode: string}} init * @return {ShadowRoot} */ function (init) { var shadowRoot = Native.Element_attachShadow.call(this, init); this.__CE_shadowRoot = shadowRoot; return shadowRoot; }); } else { console.warn('Custom Elements: `Element#attachShadow` was not patched.'); } function patch_innerHTML(destination, baseDescriptor) { Object.defineProperty(destination, 'innerHTML', { enumerable: baseDescriptor.enumerable, configurable: true, get: baseDescriptor.get, set: /** @this {Element} */function set(htmlString) { var _this = this; var isConnected$$1 = isConnected(this); // NOTE: In IE11, when using the native `innerHTML` setter, all nodes // that were previously descendants of the context element have all of // their children removed as part of the set - the entire subtree is // 'disassembled'. This work around walks the subtree *before* using the // native setter. /** @type {!Array<!Element>|undefined} */ var removedElements = undefined; if (isConnected$$1) { removedElements = []; walkDeepDescendantElements(this, function (element) { if (element !== _this) { removedElements.push(element); } }); } baseDescriptor.set.call(this, htmlString); if (removedElements) { for (var i = 0; i < removedElements.length; i++) { var element = removedElements[i]; if (element.__CE_state === CustomElementState.custom) { internals.disconnectedCallback(element); } } } // Only create custom elements if this element's owner document is // associated with the registry. if (!this.ownerDocument.__CE_hasRegistry) { internals.patchTree(this); } else { internals.patchAndUpgradeTree(this); } return htmlString; } }); } if (Native.Element_innerHTML && Native.Element_innerHTML.get) { patch_innerHTML(Element.prototype, Native.Element_innerHTML); } else if (Native.HTMLElement_innerHTML && Native.HTMLElement_innerHTML.get) { patch_innerHTML(HTMLElement.prototype, Native.HTMLElement_innerHTML); } else { /** @type {HTMLDivElement} */ var rawDiv = Native.Document_createElement.call(document, 'div'); internals.addPatch(function (element) { patch_innerHTML(element, { enumerable: true, configurable: true, // Implements getting `innerHTML` by performing an unpatched `cloneNode` // of the element and returning the resulting element's `innerHTML`. // TODO: Is this too expensive? get: /** @this {Element} */function get() { return Native.Node_cloneNode.call(this, true).innerHTML; }, // Implements setting `innerHTML` by creating an unpatched element, // setting `innerHTML` of that element and replacing the target // element's children with those of the unpatched element. set: /** @this {Element} */function set(assignedValue) { // NOTE: re-route to `content` for `template` elements. // We need to do this because `template.appendChild` does not // route into `template.content`. /** @type {!Node} */ var content = this.localName === 'template' ? /** @type {!HTMLTemplateElement} */this.content : this; rawDiv.innerHTML = assignedValue; while (content.childNodes.length > 0) { Native.Node_removeChild.call(content, content.childNodes[0]); } while (rawDiv.childNodes.length > 0) { Native.Node_appendChild.call(content, rawDiv.childNodes[0]); } } }); }); } setPropertyUnchecked(Element.prototype, 'setAttribute', /** * @this {Element} * @param {string} name * @param {string} newValue */ function (name, newValue) { // Fast path for non-custom elements. if (this.__CE_state !== CustomElementState.custom) { return Native.Element_setAttribute.call(this, name, newValue); } var oldValue = Native.Element_getAttribute.call(this, name); Native.Element_setAttribute.call(this, name, newValue); newValue = Native.Element_getAttribute.call(this, name); internals.attributeChangedCallback(this, name, oldValue, newValue, null); }); setPropertyUnchecked(Element.prototype, 'setAttributeNS', /** * @this {Element} * @param {?string} namespace * @param {string} name * @param {string} newValue */ function (namespace, name, newValue) { // Fast path for non-custom elements. if (this.__CE_state !== CustomElementState.custom) { return Native.Element_setAttributeNS.call(this, namespace, name, newValue); } var oldValue = Native.Element_getAttributeNS.call(this, namespace, name); Native.Element_setAttributeNS.call(this, namespace, name, newValue); newValue = Native.Element_getAttributeNS.call(this, namespace, name); internals.attributeChangedCallback(this, name, oldValue, newValue, namespace); }); setPropertyUnchecked(Element.prototype, 'removeAttribute', /** * @this {Element} * @param {string} name */ function (name) { // Fast path for non-custom elements. if (this.__CE_state !== CustomElementState.custom) { return Native.Element_removeAttribute.call(this, name); } var oldValue = Native.Element_getAttribute.call(this, name); Native.Element_removeAttribute.call(this, name); if (oldValue !== null) { internals.attributeChangedCallback(this, name, oldValue, null, null); } }); setPropertyUnchecked(Element.prototype, 'removeAttributeNS', /** * @this {Element} * @param {?string} namespace * @param {string} name */ function (namespace, name) { // Fast path for non-custom elements. if (this.__CE_state !== CustomElementState.custom) { return Native.Element_removeAttributeNS.call(this, namespace, name); } var oldValue = Native.Element_getAttributeNS.call(this, namespace, name); Native.Element_removeAttributeNS.call(this, namespace, name); // In older browsers, `Element#getAttributeNS` may return the empty string // instead of null if the attribute does not exist. For details, see; // https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttributeNS#Notes var newValue = Native.Element_getAttributeNS.call(this, namespace, name); if (oldValue !== newValue) { internals.attributeChangedCallback(this, name, oldValue, newValue, namespace); } }); function patch_insertAdjacentElement(destination, baseMethod) { setPropertyUnchecked(destination, 'insertAdjacentElement', /** * @this {Element} * @param {string} where * @param {!Element} element * @return {?Element} */ function (where, element) { var wasConnected = isConnected(element); var insertedElement = /** @type {!Element} */ baseMethod.call(this, where, element); if (wasConnected) { internals.disconnectTree(element); } if (isConnected(insertedElement)) { internals.connectTree(element); } return insertedElement; }); } if (Native.HTMLElement_insertAdjacentElement) { patch_insertAdjacentElement(HTMLElement.prototype, Native.HTMLElement_insertAdjacentElement); } else if (Native.Element_insertAdjacentElement) { patch_insertAdjacentElement(Element.prototype, Native.Element_insertAdjacentElement); } else { console.warn('Custom Elements: `Element#insertAdjacentElement` was not patched.'); } PatchParentNode(internals, Element.prototype, { prepend: Native.Element_prepend, append: Native.Element_append }); PatchChildNode(internals, Element.prototype, { before: Native.Element_before, after: Native.Element_after, replaceWith: Native.Element_replaceWith, remove: Native.Element_remove }); }; /** * @license * Copyright (c) 2016 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ var priorCustomElements = window['customElements']; if (!priorCustomElements || priorCustomElements['forcePolyfill'] || typeof priorCustomElements['define'] != 'function' || typeof priorCustomElements['get'] != 'function') { /** @type {!CustomElementInternals} */ var internals = new CustomElementInternals(); PatchHTMLElement(internals); PatchDocument(internals); PatchNode(internals); PatchElement(internals); // The main document is always associated with the registry. document.__CE_hasRegistry = true; /** @type {!CustomElementRegistry} */ var customElements$1 = new CustomElementRegistry(internals); Object.defineProperty(window, 'customElements', { configurable: true, enumerable: true, value: customElements$1 }); } /** * @license * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ // @version 0.7.22 (function (global) { if (global.JsMutationObserver) { return; } var registrationsTable = new WeakMap(); var setImmediate; if (/Trident|Edge/.test(navigator.userAgent)) { setImmediate = setTimeout; } else if (window.setImmediate) { setImmediate = window.setImmediate; } else { var setImmediateQueue = []; var sentinel = String(Math.random()); window.addEventListener("message", function (e) { if (e.data === sentinel) { var queue = setImmediateQueue; setImmediateQueue = []; queue.forEach(function (func) { func(); }); } }); setImmediate = function setImmediate(func) { setImmediateQueue.push(func); window.postMessage(sentinel, "*"); }; } var isScheduled = false; var scheduledObservers = []; function scheduleCallback(observer) { scheduledObservers.push(observer); if (!isScheduled) { isScheduled = true; setImmediate(dispatchCallbacks); } } function wrapIfNeeded(node) { return window.ShadowDOMPolyfill && window.ShadowDOMPolyfill.wrapIfNeeded(node) || node; } function dispatchCallbacks() { isScheduled = false; var observers = scheduledObservers; scheduledObservers = []; observers.sort(function (o1, o2) { return o1.uid_ - o2.uid_; }); var anyNonEmpty = false; observers.forEach(function (observer) { var queue = observer.takeRecords(); removeTransientObserversFor(observer); if (queue.length) { observer.callback_(queue, observer); anyNonEmpty = true; } }); if (anyNonEmpty) dispatchCallbacks(); } function removeTransientObserversFor(observer) { observer.nodes_.forEach(function (node) { var registrations = registrationsTable.get(node); if (!registrations) return; registrations.forEach(function (registration) { if (registration.observer === observer) registration.removeTransientObservers(); }); }); } function forEachAncestorAndObserverEnqueueRecord(target, callback) { for (var node = target; node; node = node.parentNode) { var registrations = registrationsTable.get(node); if (registrations) { for (var j = 0; j < registrations.length; j++) { var registration = registrations[j]; var options = registration.options; if (node !== target && !options.subtree) continue; var record = callback(options); if (record) registration.enqueue(record); } } } } var uidCounter = 0; function JsMutationObserver(callback) { this.callback_ = callback; this.nodes_ = []; this.records_ = []; this.uid_ = ++uidCounter; } JsMutationObserver.prototype = { observe: function observe(target, options) { target = wrapIfNeeded(target); if (!options.childList && !options.attributes && !options.characterData || options.attributeOldValue && !options.attributes || options.attributeFilter && options.attributeFilter.length && !options.attributes || options.characterDataOldValue && !options.characterData) { throw new SyntaxError(); } var registrations = registrationsTable.get(target); if (!registrations) registrationsTable.set(target, registrations = []); var registration; for (var i = 0; i < registrations.length; i++) { if (registrations[i].observer === this) { registration = registrations[i]; registration.removeListeners(); registration.options = options; break; } } if (!registration) { registration = new Registration(this, target, options); registrations.push(registration); this.nodes_.push(target); } registration.addListeners(); }, disconnect: function disconnect() { this.nodes_.forEach(function (node) { var registrations = registrationsTable.get(node); for (var i = 0; i < registrations.length; i++) { var registration = registrations[i]; if (registration.observer === this) { registration.removeListeners(); registrations.splice(i, 1); break; } } }, this); this.records_ = []; }, takeRecords: function takeRecords() { var copyOfRecords = this.records_; this.records_ = []; return copyOfRecords; } }; function MutationRecord(type, target) { this.type = type; this.target = target; this.addedNodes = []; this.removedNodes = []; this.previousSibling = null; this.nextSibling = null; this.attributeName = null; this.attributeNamespace = null; this.oldValue = null; } function copyMutationRecord(original) { var record = new MutationRecord(original.type, original.target); record.addedNodes = original.addedNodes.slice(); record.removedNodes = original.removedNodes.slice(); record.previousSibling = original.previousSibling; record.nextSibling = original.nextSibling; record.attributeName = original.attributeName; record.attributeNamespace = original.attributeNamespace; record.oldValue = original.oldValue; return record; } var currentRecord, recordWithOldValue; function getRecord(type, target) { return currentRecord = new MutationRecord(type, target); } function getRecordWithOldValue(oldValue) { if (recordWithOldValue) return recordWithOldValue; recordWithOldValue = copyMutationRecord(currentRecord); recordWithOldValue.oldValue = oldValue; return recordWithOldValue; } function clearRecords() { currentRecord = recordWithOldValue = undefined; } function recordRepresentsCurrentMutation(record) { return record === recordWithOldValue || record === currentRecord; } function selectRecord(lastRecord, newRecord) { if (lastRecord === newRecord) return lastRecord; if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord)) return recordWithOldValue; return null; } function Registration(observer, target, options) { this.observer = observer; this.target = target; this.options = options; this.transientObservedNodes = []; } Registration.prototype = { enqueue: function enqueue(record) { var records = this.observer.records_; var length = records.length; if (records.length > 0) { var lastRecord = records[length - 1]; var recordToReplaceLast = selectRecord(lastRecord, record); if (recordToReplaceLast) { records[length - 1] = recordToReplaceLast; return; } } else { scheduleCallback(this.observer); } records[length] = record; }, addListeners: function addListeners() { this.addListeners_(this.target); }, addListeners_: function addListeners_(node) { var options = this.options; if (options.attributes) node.addEventListener("DOMAttrModified", this, true); if (options.characterData) node.addEventListener("DOMCharacterDataModified", this, true); if (options.childList) node.addEventListener("DOMNodeInserted", this, true); if (options.childList || options.subtree) node.addEventListener("DOMNodeRemoved", this, true); }, removeListeners: function removeListeners() { this.removeListeners_(this.target); }, removeListeners_: function removeListeners_(node) { var options = this.options; if (options.attributes) node.removeEventListener("DOMAttrModified", this, true); if (options.characterData) node.removeEventListener("DOMCharacterDataModified", this, true); if (options.childList) node.removeEventListener("DOMNodeInserted", this, true); if (options.childList || options.subtree) node.removeEventListener("DOMNodeRemoved", this, true); }, addTransientObserver: function addTransientObserver(node) { if (node === this.target) return; this.addListeners_(node); this.transientObservedNodes.push(node); var registrations = registrationsTable.get(node); if (!registrations) registrationsTable.set(node, registrations = []); registrations.push(this); }, removeTransientObservers: function removeTransientObservers() { var transientObservedNodes = this.transientObservedNodes; this.transientObservedNodes = []; transientObservedNodes.forEach(function (node) { this.removeListeners_(node); var registrations = registrationsTable.get(node); for (var i = 0; i < registrations.length; i++) { if (registrations[i] === this) { registrations.splice(i, 1); break; } } }, this); }, handleEvent: function handleEvent(e) { e.stopImmediatePropagation(); switch (e.type) { case "DOMAttrModified": var name = e.attrName; var namespace = e.relatedNode.namespaceURI; var target = e.target; var record = new getRecord("attributes", target); record.attributeName = name; record.attributeNamespace = namespace; var oldValue = e.attrChange === MutationEvent.ADDITION ? null : e.prevValue; forEachAncestorAndObserverEnqueueRecord(target, function (options) { if (!options.attributes) return; if (options.attributeFilter && options.attributeFilter.length && options.attributeFilter.indexOf(name) === -1 && options.attributeFilter.indexOf(namespace) === -1) { return; } if (options.attributeOldValue) return getRecordWithOldValue(oldValue); return record; }); break; case "DOMCharacterDataModified": var target = e.target; var record = getRecord("characterData", target); var oldValue = e.prevValue; forEachAncestorAndObserverEnqueueRecord(target, function (options) { if (!options.characterData) return; if (options.characterDataOldValue) return getRecordWithOldValue(oldValue); return record; }); break; case "DOMNodeRemoved": this.addTransientObserver(e.target); case "DOMNodeInserted": var changedNode = e.target; var addedNodes, removedNodes; if (e.type === "DOMNodeInserted") { addedNodes = [changedNode]; removedNodes = []; } else { addedNodes = []; removedNodes = [changedNode]; } var previousSibling = changedNode.previousSibling; var nextSibling = changedNode.nextSibling; var record = getRecord("childList", e.target.parentNode); record.addedNodes = addedNodes; record.removedNodes = removedNodes; record.previousSibling = previousSibling; record.nextSibling = nextSibling; forEachAncestorAndObserverEnqueueRecord(e.relatedNode, function (options) { if (!options.childList) return; return record; }); } clearRecords(); } }; global.JsMutationObserver = JsMutationObserver; if (!global.MutationObserver) { global.MutationObserver = JsMutationObserver; JsMutationObserver._isPolyfilled = true; } })(self); /* Copyright (c) 2012 Barnesandnoble.com, llc, Donavon West, and Domenic Denicola Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ (function (global, undefined) { if (global.setImmediate) { return; } var nextHandle = 1; // Spec says greater than zero var tasksByHandle = {}; var currentlyRunningATask = false; var doc = global.document; var setImmediate; function addFromSetImmediateArguments(args) { tasksByHandle[nextHandle] = partiallyApplied.apply(undefined, args); return nextHandle++; } // This function accepts the same arguments as setImmediate, but // returns a function that requires no arguments. function partiallyApplied(handler) { var args = [].slice.call(arguments, 1); return function () { if (typeof handler === "function") { handler.apply(undefined, args); } else { new Function("" + handler)(); } }; } function runIfPresent(handle) { // From the spec: "Wait until any invocations of this algorithm started before this one have completed." // So if we're currently running a task, we'll need to delay this invocation. if (currentlyRunningATask) { // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a // "too much recursion" error. setTimeout(partiallyApplied(runIfPresent, handle), 0); } else { var task = tasksByHandle[handle]; if (task) { currentlyRunningATask = true; try { task(); } finally { clearImmediate(handle); currentlyRunningATask = false; } } } } function clearImmediate(handle) { delete tasksByHandle[handle]; } function installNextTickImplementation() { setImmediate = function setImmediate() { var handle = addFromSetImmediateArguments(arguments); process.nextTick(partiallyApplied(runIfPresent, handle)); return handle; }; } function canUsePostMessage() { // The test against `importScripts` prevents this implementation from being installed inside a web worker, // where `global.postMessage` means something completely different and can't be used for this purpose. if (global.postMessage && !global.importScripts) { var postMessageIsAsynchronous = true; var oldOnMessage = global.onmessage; global.onmessage = function () { postMessageIsAsynchronous = false; }; global.postMessage("", "*"); global.onmessage = oldOnMessage; return postMessageIsAsynchronous; } } function installPostMessageImplementation() { // Installs an event handler on `global` for the `message` event: see // * https://developer.mozilla.org/en/DOM/window.postMessage // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages var messagePrefix = "setImmediate$" + Math.random() + "$"; var onGlobalMessage = function onGlobalMessage(event) { if (event.source === global && typeof event.data === "string" && event.data.indexOf(messagePrefix) === 0) { runIfPresent(+event.data.slice(messagePrefix.length)); } }; if (global.addEventListener) { global.addEventListener("message", onGlobalMessage, false); } else { global.attachEvent("onmessage", onGlobalMessage); } setImmediate = function setImmediate() { var handle = addFromSetImmediateArguments(arguments); global.postMessage(messagePrefix + handle, "*"); return handle; }; } function installMessageChannelImplementation() { var channel = new MessageChannel(); channel.port1.onmessage = function (event) { var handle = event.data; runIfPresent(handle); }; setImmediate = function setImmediate() { var handle = addFromSetImmediateArguments(arguments); channel.port2.postMessage(handle); return handle; }; } function installReadyStateChangeImplementation() { var html = doc.documentElement; setImmediate = function setImmediate() { var handle = addFromSetImmediateArguments(arguments); // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called. var script = doc.createElement("script"); script.onreadystatechange = function () { runIfPresent(handle); script.onreadystatechange = null; html.removeChild(script); script = null; }; html.appendChild(script); return handle; }; } function installSetTimeoutImplementation() { setImmediate = function setImmediate() { var handle = addFromSetImmediateArguments(arguments); setTimeout(partiallyApplied(runIfPresent, handle), 0); return handle; }; } // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live. var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global); attachTo = attachTo && attachTo.setTimeout ? attachTo : global; // Don't get fooled by e.g. browserify environments. if ({}.toString.call(global.process) === "[object process]") { // For Node.js before 0.9 installNextTickImplementation(); } else if (canUsePostMessage()) { // For non-IE10 modern browsers installPostMessageImplementation(); } else if (global.MessageChannel) { // For web workers, where supported installMessageChannelImplementation(); } else if (doc && "onreadystatechange" in doc.createElement("script")) { // For IE 6–8 installReadyStateChangeImplementation(); } else { // For older browsers installSetTimeoutImplementation(); } attachTo.setImmediate = setImmediate; attachTo.clearImmediate = clearImmediate; })(self); // Caution: // Do not replace this import statement with codes. // // If you replace this import statement with codes, // the codes will be executed after the following polyfills are imported // because import statements are hoisted during compilation. // Polyfill ECMAScript standard features with global namespace pollution // Polyfill Custom Elements v1 with global namespace pollution // Polyfill MutationObserver with global namespace pollution // Polyfill setImmediate with global namespace pollution (function () { var DEFAULT_VIEWPORT = 'width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no'; var Viewport = { ensureViewportElement: function ensureViewportElement() { var viewportElement = document.querySelector('meta[name=viewport]'); if (!viewportElement) { viewportElement = document.createElement('meta'); viewportElement.name = 'viewport'; document.head.appendChild(viewportElement); } return viewportElement; }, setup: function setup() { var viewportElement = Viewport.ensureViewportElement(); if (!viewportElement) { return; } if (!viewportElement.hasAttribute('content')) { viewportElement.setAttribute('content', DEFAULT_VIEWPORT); } } }; window.Viewport = Viewport; })(); function setup$1(ons) { if (window._onsLoaded) { ons._util.warn('Onsen UI is loaded more than once.'); } window._onsLoaded = true; // fastclick window.addEventListener('load', function () { ons.fastClick = fastclick_1.attach(document.body); var supportTouchAction = 'touch-action' in document.body.style; ons.platform._runOnActualPlatform(function () { if (ons.platform.isAndroid()) { // In Android4.4+, correct viewport settings can remove click delay. // So disable FastClick on Android. ons.fastClick.destroy(); } else if (ons.platform.isIOS()) { if (supportTouchAction && (ons.platform.isIOSSafari() || ons.platform.isWKWebView())) { // If 'touch-action' supported in iOS Safari or WKWebView, disable FastClick. ons.fastClick.destroy(); } else { // Do nothing. 'touch-action: manipulation' has no effect on UIWebView. } } }); }, false); ons.ready(function () { ons.enableDeviceBackButtonHandler(); ons._defaultDeviceBackButtonHandler = ons._internal.dbbDispatcher.createHandler(window.document.body, function () { if (Object.hasOwnProperty.call(navigator, 'app')) { navigator.app.exitApp(); } else { console.warn('Could not close the app. Is \'cordova.js\' included?\nError: \'window.navigator.app\' is undefined.'); } }); document.body._gestureDetector = new ons.GestureDetector(document.body, { passive: true }); // Simulate Device Back Button on ESC press if (!ons.platform.isWebView()) { document.body.addEventListener('keydown', function (event) { if (event.keyCode === 27) { ons.fireDeviceBackButtonEvent(); } }); } // setup loading placeholder ons._setupLoadingPlaceHolders(); }); // viewport.js Viewport.setup(); } /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ function getElementClass() { if (typeof HTMLElement !== 'function') { // case of Safari var _BaseElement = function _BaseElement() {}; _BaseElement.prototype = document.createElement('div'); return _BaseElement; } else { return HTMLElement; } } var BaseElement = function (_getElementClass) { inherits(BaseElement, _getElementClass); function BaseElement() { classCallCheck(this, BaseElement); return possibleConstructorReturn(this, (BaseElement.__proto__ || Object.getPrototypeOf(BaseElement)).call(this)); } return BaseElement; }(getElementClass()); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-template * @category util * @description * [en] * Define a separate HTML fragment and use as a template. These templates can be loaded as pages in `<ons-navigator>`, `<ons-tabbar>` and `<ons-splitter>`. They can also be used to generate dialogs. Since Onsen UI 2.4.0, the native `<template>` element can be used instead of `<ons-template>` for better performance and features. `<ons-template>` is still supported for backward compatibility. * [/en] * [ja]テンプレートとして使用するためのHTMLフラグメントを定義します。この要素でHTMLを宣言すると、id属性に指定した名前をpageのURLとしてons-navigatorなどのコンポーネントから参照できます。[/ja] * @seealso ons-navigator * [en]The `<ons-navigator>` component enables stack based navigation.[/en] * [ja][/ja] * @seealso ons-tabbar * [en]The `<ons-tabbar>` component is used to add tab navigation.[/en] * [ja][/ja] * @seealso ons-splitter * [en]The `<ons-splitter>` component can be used to create a draggable menu or column based layout.[/en] * [ja][/ja] * @example * <ons-template id="foobar.html"> * <ons-page> * Page content * </ons-page> * </ons-template> * * <ons-navigator page="foobar.html"></ons-navigator> */ var TemplateElement = function (_BaseElement) { inherits(TemplateElement, _BaseElement); /** * @property template * @type {String} * @description * [en]Template content. This property can not be used with AngularJS bindings.[/en] * [ja][/ja] */ function TemplateElement() { classCallCheck(this, TemplateElement); var _this = possibleConstructorReturn(this, (TemplateElement.__proto__ || Object.getPrototypeOf(TemplateElement)).call(this)); _this.template = _this.innerHTML; while (_this.firstChild) { _this.removeChild(_this.firstChild); } return _this; } createClass(TemplateElement, [{ key: 'connectedCallback', value: function connectedCallback() { if (this.parentNode) { // Note: this.parentNode is not set in some CE0/CE1 polyfills. // Show warning when the ons-template is not located just under document.body if (this.parentNode !== document.body) { // if the parent is not document.body util$1.warn('ons-template (id = ' + this.getAttribute('id') + ') must be located just under document.body' + (this.parentNode.outerHTML ? ':\n\n' + this.parentNode.outerHTML : '.')); } } var event = new CustomEvent('_templateloaded', { bubbles: true, cancelable: true }); event.template = this.template; event.templateId = this.getAttribute('id'); this.dispatchEvent(event); } }]); return TemplateElement; }(BaseElement); onsElements.Template = TemplateElement; customElements.define('ons-template', TemplateElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-if * @category conditional * @tutorial vanilla/Reference/if * @description * [en] * Conditionally display content depending on the platform, device orientation or both. * * Sometimes it is useful to conditionally hide or show certain components based on platform. When running on iOS the `<ons-if>` element can be used to hide the `<ons-fab>` element. * [/en] * [ja][/ja] * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja] * @example * <ons-page> * <ons-if orientation="landscape"> * Landscape view! * </ons-if> * <ons-if platform="android"> * This is Android. * </ons-if> * <ons-if platform="ios other"> * This is not Android. * </ons-if> * </ons-page> */ var IfElement = function (_BaseElement) { inherits(IfElement, _BaseElement); /** * @attribute platform * @initonly * @type {string} * @description * [en]Space-separated platform names. Possible values are `"ios"`, `"android"`, `"windows"` and `"other"`.[/en] * [ja][/ja] */ /** * @attribute orientation * @type {string} * @description * [en]Either `"portrait"` or `"landscape"`.[/en] * [ja]portraitもしくはlandscapeを指定します[/ja] */ function IfElement() { classCallCheck(this, IfElement); var _this = possibleConstructorReturn(this, (IfElement.__proto__ || Object.getPrototypeOf(IfElement)).call(this)); contentReady(_this, function () { if (platform._getSelectedPlatform() !== null) { _this._platformUpdate(); } else if (!_this._isAllowedPlatform()) { while (_this.childNodes[0]) { _this.childNodes[0].remove(); } _this._platformUpdate(); } }); _this._onOrientationChange(); return _this; } createClass(IfElement, [{ key: 'connectedCallback', value: function connectedCallback() { orientation.on('change', this._onOrientationChange.bind(this)); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name) { if (name === 'orientation') { this._onOrientationChange(); } } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { orientation.off('change', this._onOrientationChange); } }, { key: '_platformUpdate', value: function _platformUpdate() { this.style.display = this._isAllowedPlatform() ? '' : 'none'; } }, { key: '_isAllowedPlatform', value: function _isAllowedPlatform() { return !this.getAttribute('platform') || this.getAttribute('platform').split(/\s+/).indexOf(platform.getMobileOS()) >= 0; } }, { key: '_onOrientationChange', value: function _onOrientationChange() { if (this.hasAttribute('orientation') && this._isAllowedPlatform()) { var conditionalOrientation = this.getAttribute('orientation').toLowerCase(); var currentOrientation = orientation.isPortrait() ? 'portrait' : 'landscape'; this.style.display = conditionalOrientation === currentOrientation ? '' : 'none'; } } }], [{ key: 'observedAttributes', get: function get$$1() { return ['orientation']; } }]); return IfElement; }(BaseElement); onsElements.If = IfElement; customElements.define('ons-if', IfElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var BaseAnimator = function () { /** * @param {Object} options * @param {String} options.timing * @param {Number} options.duration * @param {Number} options.delay */ function BaseAnimator() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; classCallCheck(this, BaseAnimator); this.timing = options.timing || 'linear'; this.duration = options.duration || 0; this.delay = options.delay || 0; this.def = { timing: this.timing, duration: this.duration, delay: this.delay }; } createClass(BaseAnimator, null, [{ key: 'extend', value: function extend() { var properties = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var extendedAnimator = this; var newAnimator = function newAnimator() { extendedAnimator.apply(this, arguments); util$1.extend(this, properties); }; newAnimator.prototype = this.prototype; return newAnimator; } }]); return BaseAnimator; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // This object should not be exposed to users. Please keep this private. var iPhoneXPatch = {}; iPhoneXPatch.isIPhoneXPortraitPatchActive = function () { return document.documentElement.getAttribute('onsflag-iphonex-portrait') != null && window.innerWidth < window.innerHeight; }; iPhoneXPatch.isIPhoneXLandscapePatchActive = function () { // If width === height, treat it as landscape return document.documentElement.getAttribute('onsflag-iphonex-landscape') != null && window.innerWidth >= window.innerHeight; }; /** * Returns the safe area lengths based on the current state of the safe areas. */ iPhoneXPatch.getSafeAreaLengths = function () { var safeAreaLengths = void 0; if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) { safeAreaLengths = { top: 44, right: 0, bottom: 34, left: 0 }; } else if (iPhoneXPatch.isIPhoneXLandscapePatchActive()) { safeAreaLengths = { top: 0, right: 44, bottom: 21, left: 44 }; } else { safeAreaLengths = { top: 0, right: 0, bottom: 0, left: 0 }; } return safeAreaLengths; }; /** * Returns the safe area rect based on the current state of the safe areas. */ iPhoneXPatch.getSafeAreaDOMRect = function () { var safeAreaRect = void 0; if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) { safeAreaRect = { x: 0, y: 44, /* 0 + 44 (top safe area) */ width: window.innerWidth, height: window.innerHeight - 78 /* height - 44 (top safe area) - 34 (bottom safe area) */ }; } else if (iPhoneXPatch.isIPhoneXLandscapePatchActive()) { safeAreaRect = { x: 44, /* 0 + 44 (left safe area) */ y: 0, width: window.innerWidth - 88, /* width - 44 (left safe area) - 34 (right safe area) */ height: window.innerHeight - 21 /* height - 21 (bottom safe area) */ }; } else { safeAreaRect = { x: 0, y: 0, width: window.innerWidth, height: window.innerHeight }; } return _extends({}, safeAreaRect, { left: safeAreaRect.x, top: safeAreaRect.y, right: safeAreaRect.x + safeAreaRect.width, bottom: safeAreaRect.y + safeAreaRect.height }); }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var ActionSheetAnimator = function (_BaseAnimator) { inherits(ActionSheetAnimator, _BaseAnimator); function ActionSheetAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'linear' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.2 : _ref$duration; classCallCheck(this, ActionSheetAnimator); return possibleConstructorReturn(this, (ActionSheetAnimator.__proto__ || Object.getPrototypeOf(ActionSheetAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } /** * @param {HTMLElement} dialog * @param {Function} done */ createClass(ActionSheetAnimator, [{ key: 'show', value: function show(dialog, done) { done(); } /** * @param {HTMLElement} dialog * @param {Function} done */ }, { key: 'hide', value: function hide(dialog, done) { done(); } }]); return ActionSheetAnimator; }(BaseAnimator); /** * Android style animator for Action Sheet. */ var MDActionSheetAnimator = function (_ActionSheetAnimator) { inherits(MDActionSheetAnimator, _ActionSheetAnimator); function MDActionSheetAnimator() { var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref2$timing = _ref2.timing, timing = _ref2$timing === undefined ? 'ease' : _ref2$timing, _ref2$delay = _ref2.delay, delay = _ref2$delay === undefined ? 0 : _ref2$delay, _ref2$duration = _ref2.duration, duration = _ref2$duration === undefined ? 0.4 : _ref2$duration; classCallCheck(this, MDActionSheetAnimator); var _this2 = possibleConstructorReturn(this, (MDActionSheetAnimator.__proto__ || Object.getPrototypeOf(MDActionSheetAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); _this2.maskTiming = 'linear'; _this2.maskDuration = 0.2; return _this2; } /** * @param {Object} dialog * @param {Function} callback */ createClass(MDActionSheetAnimator, [{ key: 'show', value: function show(dialog, callback) { Animit.runAll(Animit(dialog._mask).queue({ opacity: 0 }).wait(this.delay).queue({ opacity: 1.0 }, { duration: this.maskDuration, timing: this.maskTiming }), Animit(dialog._sheet, this.def).default({ transform: 'translate3d(0, 80%, 0)', opacity: 0 }, { transform: 'translate3d(0, 0, 0)', opacity: 1 }).queue(function (done) { callback && callback(); done(); })); } /** * @param {Object} dialog * @param {Function} callback */ }, { key: 'hide', value: function hide(dialog, callback) { Animit.runAll(Animit(dialog._mask).queue({ opacity: 1 }).wait(this.delay).queue({ opacity: 0 }, { duration: this.maskDuration, timing: this.maskTiming }), Animit(dialog._sheet, this.def).default({ transform: 'translate3d(0, 0, 0)', opacity: 1 }, { transform: 'translate3d(0, 80%, 0)', opacity: 0 }).queue(function (done) { callback && callback(); done(); })); } }]); return MDActionSheetAnimator; }(ActionSheetAnimator); /** * iOS style animator for dialog. */ var IOSActionSheetAnimator = function (_ActionSheetAnimator2) { inherits(IOSActionSheetAnimator, _ActionSheetAnimator2); function IOSActionSheetAnimator() { var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref3$timing = _ref3.timing, timing = _ref3$timing === undefined ? 'ease' : _ref3$timing, _ref3$delay = _ref3.delay, delay = _ref3$delay === undefined ? 0 : _ref3$delay, _ref3$duration = _ref3.duration, duration = _ref3$duration === undefined ? 0.3 : _ref3$duration; classCallCheck(this, IOSActionSheetAnimator); var _this3 = possibleConstructorReturn(this, (IOSActionSheetAnimator.__proto__ || Object.getPrototypeOf(IOSActionSheetAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); _this3.maskTiming = 'linear'; _this3.maskDuration = 0.2; if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) { _this3.liftAmount = 'calc(100% + 48px)'; } else if (iPhoneXPatch.isIPhoneXLandscapePatchActive()) { _this3.liftAmount = 'calc(100% + 33px)'; } else { _this3.liftAmount = document.body.clientHeight / 2.0 - 1 + 'px'; // avoid Forced Synchronous Layout } return _this3; } /** * @param {Object} dialog * @param {Function} callback */ createClass(IOSActionSheetAnimator, [{ key: 'show', value: function show(dialog, callback) { Animit.runAll(Animit(dialog._mask).queue({ opacity: 0 }).wait(this.delay).queue({ opacity: 1 }, { duration: this.maskDuration, timing: this.maskTiming }), Animit(dialog._sheet, this.def).default({ transform: 'translate3d(0, ' + this.liftAmount + ', 0)' }, { transform: 'translate3d(0, 0, 0)' }).queue(function (done) { callback && callback(); done(); })); } /** * @param {Object} dialog * @param {Function} callback */ }, { key: 'hide', value: function hide(dialog, callback) { Animit.runAll(Animit(dialog._mask).queue({ opacity: 1 }).wait(this.delay).queue({ opacity: 0 }, { duration: this.maskDuration, timing: this.maskTiming }), Animit(dialog._sheet, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(0, ' + this.liftAmount + ', 0)' }).queue(function (done) { callback && callback(); done(); })); } }]); return IOSActionSheetAnimator; }(ActionSheetAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var BaseDialogElement = function (_BaseElement) { inherits(BaseDialogElement, _BaseElement); createClass(BaseDialogElement, [{ key: '_updateAnimatorFactory', value: function _updateAnimatorFactory() { util$1.throwMember(); } }, { key: '_toggleStyle', value: function _toggleStyle(shouldShow) { this.style.display = shouldShow ? 'block' : 'none'; } }, { key: '_scheme', get: function get$$1() { util$1.throwMember(); } }]); function BaseDialogElement() { classCallCheck(this, BaseDialogElement); var _this = possibleConstructorReturn(this, (BaseDialogElement.__proto__ || Object.getPrototypeOf(BaseDialogElement)).call(this)); if (_this.constructor === BaseDialogElement) { util$1.throwAbstract(); } _this._visible = false; _this._doorLock = new DoorLock(); _this._cancel = _this._cancel.bind(_this); _this._selfCamelName = util$1.camelize(_this.tagName.slice(4)); _this._defaultDBB = function (e) { return _this.cancelable ? _this._cancel() : e.callParentHandler(); }; _this._animatorFactory = _this._updateAnimatorFactory(); return _this; } createClass(BaseDialogElement, [{ key: '_cancel', value: function _cancel() { var _this2 = this; if (this.cancelable && !this._running) { this._running = true; this.hide().then(function () { _this2._running = false; util$1.triggerElementEvent(_this2, 'dialog-cancel'); }, function () { return _this2._running = false; }); } } }, { key: 'show', value: function show() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return this._setVisible.apply(this, [true].concat(args)); } }, { key: 'hide', value: function hide() { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return this._setVisible.apply(this, [false].concat(args)); } }, { key: 'toggle', value: function toggle() { for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } return this._setVisible.apply(this, [!this.visible].concat(args)); } }, { key: '_setVisible', value: function _setVisible(shouldShow) { var _util$triggerElementE, _this3 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var action = shouldShow ? 'show' : 'hide'; options = _extends({}, options); options.animationOptions = util$1.extend(options.animationOptions || {}, AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options'))); var canceled = false; util$1.triggerElementEvent(this, 'pre' + action, (_util$triggerElementE = {}, defineProperty(_util$triggerElementE, this._selfCamelName, this), defineProperty(_util$triggerElementE, 'cancel', function cancel() { return canceled = true; }), _util$triggerElementE)); if (canceled) { return Promise.reject('Canceled in pre' + action + ' event.'); } return new Promise(function (resolve) { _this3._doorLock.waitUnlock(function () { var unlock = _this3._doorLock.lock(); var animator = _this3._animatorFactory.newAnimator(options); shouldShow && _this3._toggleStyle(true, options); _this3._visible = shouldShow; util$1.iosPageScrollFix(shouldShow); contentReady(_this3, function () { animator[action](_this3, function () { !shouldShow && _this3._toggleStyle(false, options); unlock(); util$1.propagateAction(_this3, '_' + action); util$1.triggerElementEvent(_this3, 'post' + action, defineProperty({}, _this3._selfCamelName, _this3)); // postshow posthide if (options.callback instanceof Function) { options.callback(_this3); } resolve(_this3); }); }); }); }); } }, { key: '_updateMask', value: function _updateMask() { var _this4 = this; contentReady(this, function () { if (_this4._mask && _this4.getAttribute('mask-color')) { _this4._mask.style.backgroundColor = _this4.getAttribute('mask-color'); } }); } }, { key: 'connectedCallback', value: function connectedCallback() { var _this5 = this; if (typeof this._defaultDBB === 'function') { this.onDeviceBackButton = this._defaultDBB.bind(this); } contentReady(this, function () { if (_this5._mask) { _this5._mask.addEventListener('click', _this5._cancel, false); util$1.iosMaskScrollFix(_this5._mask, true); } }); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { if (this._backButtonHandler) { this._backButtonHandler.destroy(); this._backButtonHandler = null; } if (this._mask) { this._mask.removeEventListener('click', this._cancel, false); util$1.iosMaskScrollFix(this._mask, false); } } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'modifier': ModifierUtil.onModifierChanged(last, current, this, this._scheme); break; case 'animation': this._animatorFactory = this._updateAnimatorFactory(); break; case 'mask-color': this._updateMask(); break; } } }, { key: 'onDeviceBackButton', get: function get$$1() { return this._backButtonHandler; }, set: function set$$1(callback) { if (this._backButtonHandler) { this._backButtonHandler.destroy(); } this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback); } }, { key: 'visible', get: function get$$1() { return this._visible; } }, { key: 'disabled', set: function set$$1(value) { return util$1.toggleAttribute(this, 'disabled', value); }, get: function get$$1() { return this.hasAttribute('disabled'); } }, { key: 'cancelable', set: function set$$1(value) { return util$1.toggleAttribute(this, 'cancelable', value); }, get: function get$$1() { return this.hasAttribute('cancelable'); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'animation', 'mask-color']; } }, { key: 'events', get: function get$$1() { return ['preshow', 'postshow', 'prehide', 'posthide', 'dialog-cancel']; } }]); return BaseDialogElement; }(BaseElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme = { '.action-sheet': 'action-sheet--*', '.action-sheet-mask': 'action-sheet-mask--*', '.action-sheet-title': 'action-sheet-title--*' }; var _animatorDict = { 'default': function _default() { return platform.isAndroid() ? MDActionSheetAnimator : IOSActionSheetAnimator; }, 'none': ActionSheetAnimator }; /** * @element ons-action-sheet * @category dialog * @description * [en] * Action/bottom sheet that is displayed on top of current screen. * * This element can either be attached directly to the `<body>` or dynamically created from a template using the `ons.createElement(template, { append: true })` utility function and the `<template>` tag. * * The action sheet is useful for displaying a list of options and asking the user to make a decision. A `ons-action-sheet-button` is provided for this purpose, although it can contain any type of content. * * It will automatically be displayed as Material Design (bottom sheet) when running on an Android device. * [/en] * [ja] * アクションシート、もしくはボトムシートを現在のスクリーン上に表示します。 * * この要素は、`<body>`要素に直接アタッチされるか、もしくは`ons.createElement(template, { append: true })`と`<template>`タグを使ってテンプレートから動的に生成されます。 * * アクションシートは、選択肢のリストを表示してユーザーに尋ねるのに便利です。`ons-action-sheet-button`は、この要素の中に置くために提供されていますが、それ以外にも他のどのような要素を含むことができます。 * * Androidデバイスで実行されるときには、自動的にマテリアルデザイン(ボトムシート)として表示されます。 * [/ja] * @modifier material * [en]Display a Material Design bottom sheet.[/en] * [ja]マテリアルデザインのボトムシートを表示します。[/ja] * @tutorial vanilla/reference/action-sheet * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @seealso ons-popover * [en]`<ons-popover>` component[/en] * [ja]ons-popoverコンポーネント[/ja] * @seealso ons-modal * [en]`<ons-modal>` component[/en] * [ja]ons-modalコンポーネント[/ja] * @example * <ons-action-sheet id="sheet"> * <ons-action-sheet-button>Label</ons-action-sheet-button> * <ons-action-sheet-button>Label</ons-action-sheet-button> * </ons-action-sheet> * * <script> * document.getElementById('sheet').show(); * </script> */ var ActionSheetElement = function (_BaseDialogElement) { inherits(ActionSheetElement, _BaseDialogElement); /** * @event preshow * @description * [en]Fired just before the action sheet is displayed.[/en] * [ja]ダイアログが表示される直前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.actionSheet * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Execute this function to stop the action sheet from being shown.[/en] * [ja]この関数を実行すると、ダイアログの表示がキャンセルされます。[/ja] */ /** * @event postshow * @description * [en]Fired just after the action sheet is displayed.[/en] * [ja]ダイアログが表示された直後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.actionSheet * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @event prehide * @description * [en]Fired just before the action sheet is hidden.[/en] * [ja]ダイアログが隠れる直前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.actionSheet * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Execute this function to stop the action sheet from being hidden.[/en] * [ja]この関数を実行すると、ダイアログの非表示がキャンセルされます。[/ja] */ /** * @event posthide * @description * [en]Fired just after the action sheet is hidden.[/en] * [ja]ダイアログが隠れた後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.actionSheet * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @attribute title * @type {String} * @description * [en]Optional title of the action sheet. A new element will be created containing this string.[/en] * [ja]アクションシートのタイトルを指定します。ここで指定した文字列を含む新しい要素が作成されます。[/ja] */ /** * @attribute modifier * @type {String} * @description * [en]The appearance of the action sheet.[/en] * [ja]ダイアログの表現を指定します。[/ja] */ /** * @attribute cancelable * @description * [en]If this attribute is set the action sheet can be closed by tapping the background or by pressing the back button on Android devices.[/en] * [ja]この属性が設定されると、アクションシートの背景やAndroidデバイスのバックボタンを推すことでアクションシートが閉じるようになります。[/ja] */ /** * @attribute disabled * @description * [en]If this attribute is set the action sheet is disabled.[/en] * [ja]この属性がある時、ダイアログはdisabled状態になります。[/ja] */ /** * @attribute animation * @type {String} * @default default * @description * [en]The animation used when showing and hiding the action sheet. Can be either `"none"` or `"default"`.[/en] * [ja]ダイアログを表示する際のアニメーション名を指定します。"none"もしくは"default"を指定できます。[/ja] */ /** * @attribute animation-options * @type {Expression} * @description * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/ja] */ /** * @attribute mask-color * @type {String} * @default rgba(0, 0, 0, 0.2) * @description * [en]Color of the background mask. Default is `"rgba(0, 0, 0, 0.2)"`.[/en] * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja] */ function ActionSheetElement() { classCallCheck(this, ActionSheetElement); var _this = possibleConstructorReturn(this, (ActionSheetElement.__proto__ || Object.getPrototypeOf(ActionSheetElement)).call(this)); contentReady(_this, function () { return _this._compile(); }); return _this; } createClass(ActionSheetElement, [{ key: '_updateAnimatorFactory', value: function _updateAnimatorFactory() { return new AnimatorFactory({ animators: _animatorDict, baseClass: ActionSheetAnimator, baseClassName: 'ActionSheetAnimator', defaultAnimation: this.getAttribute('animation') }); } }, { key: '_compile', value: function _compile() { autoStyle.prepare(this); this.style.display = 'none'; this.style.zIndex = 10001; /* Expected result: * <ons-action-sheet> * <div class="action-sheet-mask"></div> * <div class="action-sheet"> * <div class="action-sheet-title></div> * ... * </div> * </ons-action-sheet> */ if (!this._sheet) { var sheet = document.createElement('div'); sheet.classList.add('action-sheet'); while (this.firstChild) { sheet.appendChild(this.firstChild); } this.appendChild(sheet); } if (!this._title && this.hasAttribute('title')) { var title = document.createElement('div'); title.innerHTML = this.getAttribute('title'); title.classList.add('action-sheet-title'); this._sheet.insertBefore(title, this._sheet.firstChild); } if (!this._mask) { var mask = document.createElement('div'); mask.classList.add('action-sheet-mask'); this.insertBefore(mask, this.firstChild); } this._sheet.style.zIndex = 20001; this._mask.style.zIndex = 20000; ModifierUtil.initModifier(this, this._scheme); } }, { key: '_updateTitle', value: function _updateTitle() { if (this._title) { this._title.innerHTML = this.getAttribute('title'); } } /** * @property onDeviceBackButton * @type {Object} * @description * [en]Back-button handler.[/en] * [ja]バックボタンハンドラ。[/ja] */ /** * @method show * @signature show([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"none"` and `"slide"`.[/en] * [ja]アニメーション名を指定します。"none", "slide"のいずれかを指定します。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja] * @param {Function} [options.callback] * [en]This function is called after the action sheet has been revealed.[/en] * [ja]ダイアログが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Show the action sheet.[/en] * [ja]ダイアログを開きます。[/ja] * @return {Promise} Resolves to the displayed element. */ /** * @method hide * @signature hide([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"none"` and `"slide"`.[/en] * [ja]アニメーション名を指定します。"none", "slide"のいずれかを指定できます。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/ja] * @param {Function} [options.callback] * [en]This functions is called after the action sheet has been hidden.[/en] * [ja]ダイアログが隠れた後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Hide the action sheet.[/en] * [ja]ダイアログを閉じます。[/ja] * @return {Promise} * [en]Resolves to the hidden element[/en] * [ja]隠れた要素を解決します。[/ja] */ /** * @property visible * @readonly * @type {Boolean} * @description * [en]Whether the action sheet is visible or not.[/en] * [ja]要素が見える場合に`true`。[/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the action sheet is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ /** * @property cancelable * @type {Boolean} * @description * [en]Whether the action sheet is cancelable or not. A cancelable action sheet can be closed by tapping the background or by pressing the back button on Android devices.[/en] * [ja]アクションシートがキャンセル可能かどうかを設定します。キャンセル可能なアクションシートは、背景をタップしたりAndroidデバイスのバックボタンを推すことで閉じるようになります。[/ja] */ }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'title') { this._updateTitle(); } else { get(ActionSheetElement.prototype.__proto__ || Object.getPrototypeOf(ActionSheetElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current); } } /** * @param {String} name * @param {ActionSheetAnimator} Animator */ }, { key: '_scheme', get: function get$$1() { return scheme; } }, { key: '_mask', get: function get$$1() { return util$1.findChild(this, '.action-sheet-mask'); } }, { key: '_sheet', get: function get$$1() { return util$1.findChild(this, '.action-sheet'); } }, { key: '_title', get: function get$$1() { return this.querySelector('.action-sheet-title'); } }], [{ key: 'registerAnimator', value: function registerAnimator(name, Animator) { if (!(Animator.prototype instanceof ActionSheetAnimator)) { util$1.throwAnimator('ActionSheet'); } _animatorDict[name] = Animator; } }, { key: 'observedAttributes', get: function get$$1() { return [].concat(toConsumableArray(get(ActionSheetElement.__proto__ || Object.getPrototypeOf(ActionSheetElement), 'observedAttributes', this)), ['title']); } }, { key: 'animators', get: function get$$1() { return _animatorDict; } }, { key: 'ActionSheetAnimator', get: function get$$1() { return ActionSheetAnimator; } }]); return ActionSheetElement; }(BaseDialogElement); onsElements.ActionSheet = ActionSheetElement; customElements.define('ons-action-sheet', ActionSheetElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var BaseButtonElement = function (_BaseElement) { inherits(BaseButtonElement, _BaseElement); createClass(BaseButtonElement, [{ key: '_scheme', get: function get$$1() { util$1.throwMember(); } }, { key: '_defaultClassName', get: function get$$1() { util$1.throwMember(); } }, { key: '_rippleOpt', get: function get$$1() { return [this]; } }]); function BaseButtonElement() { classCallCheck(this, BaseButtonElement); var _this = possibleConstructorReturn(this, (BaseButtonElement.__proto__ || Object.getPrototypeOf(BaseButtonElement)).call(this)); if (_this.constructor === BaseButtonElement) { util$1.throwAbstract(); } contentReady(_this, function () { return _this._compile(); }); return _this; } createClass(BaseButtonElement, [{ key: '_compile', value: function _compile() { autoStyle.prepare(this); this.classList.add(this._defaultClassName); if (!this._icon && this.hasAttribute('icon')) { util$1.checkMissingImport('Icon'); var icon = util$1.createElement('<ons-icon icon="' + this.getAttribute('icon') + '"></ons-icon>'); icon.classList.add(this._defaultClassName.replace('button', 'icon')); this.insertBefore(icon, this.firstChild); } this._updateRipple(); ModifierUtil.initModifier(this, this._scheme); } }, { key: '_updateIcon', value: function _updateIcon() { if (this._icon) { this._icon.setAttribute('icon', this.getAttribute('icon')); } } }, { key: '_updateRipple', value: function _updateRipple() { this._rippleOpt && util$1.updateRipple.apply(util$1, toConsumableArray(this._rippleOpt)); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, this._defaultClassName, this._scheme); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, this._scheme); break; case 'icon': this._updateIcon(); break; case 'ripple': this.classList.contains(this._defaultClassName) && this._updateRipple(); break; } } }, { key: 'disabled', set: function set$$1(value) { return util$1.toggleAttribute(this, 'disabled', value); }, get: function get$$1() { return this.hasAttribute('disabled'); } }, { key: '_icon', get: function get$$1() { return util$1.findChild(this, 'ons-icon'); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'class', 'icon', 'ripple']; } }]); return BaseButtonElement; }(BaseElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-action-sheet-button * @category dialog * @modifier destructive * [en]Shows a "destructive" button (only for iOS).[/en] * [ja]"destructive"なボタンを表示します(iOSでのみ有効)。[/ja] * @description * [en]Component that represent each button of the action sheet.[/en] * [ja]アクションシートに表示される各ボタンを表現するコンポーネントです。[/ja] * @seealso ons-action-sheet * [en]The `<ons-action-sheet>` component[/en] * [ja]ons-action-sheetコンポーネント[/ja] * @seealso ons-list-item * [en]The `<ons-list-item>` component[/en] * [ja]ons-list-itemコンポーネント[/ja] * @seealso ons-icon * [en]The `<ons-icon>` component[/en] * [ja]ons-iconコンポーネント[/ja] * @tutorial vanilla/Reference/action-sheet * @guide appsize.html#removing-icon-packs [en]Removing icon packs.[/en][ja][/ja] * @guide faq.html#how-can-i-use-custom-icon-packs [en]Adding custom icon packs.[/en][ja][/ja] * @modifier material * [en]Display a Material Design action sheet button.[/en] * [ja]マテリアルデザインのアクションシート用のボタンを表示します。[/ja] * @example * <ons-action-sheet id="sheet"> * <ons-action-sheet-button>Label</ons-action-sheet-button> * <ons-action-sheet-button>Label</ons-action-sheet-button> * </ons-action-sheet> * * <script> * document.getElementById('sheet').show(); * </script> */ var ActionSheetButtonElement = function (_BaseButtonElement) { inherits(ActionSheetButtonElement, _BaseButtonElement); function ActionSheetButtonElement() { classCallCheck(this, ActionSheetButtonElement); return possibleConstructorReturn(this, (ActionSheetButtonElement.__proto__ || Object.getPrototypeOf(ActionSheetButtonElement)).apply(this, arguments)); } createClass(ActionSheetButtonElement, [{ key: '_scheme', /** * @attribute icon * @type {String} * @description * [en]Creates an `ons-icon` component with this string. Only visible on Android. Check [See also](#seealso) section for more information.[/en] * [ja]`ons-icon`コンポーネントを悪性します。Androidでのみ表示されます。[/ja] */ /** * @attribute modifier * @type {String} * @description * [en]The appearance of the action sheet button.[/en] * [ja]アクションシートボタンの見た目を設定します。[/ja] */ get: function get$$1() { return { '': 'action-sheet-button--*', '.action-sheet-icon': 'action-sheet-icon--*' }; } }, { key: '_defaultClassName', get: function get$$1() { return 'action-sheet-button'; } }, { key: '_rippleOpt', get: function get$$1() { return undefined; } }]); return ActionSheetButtonElement; }(BaseButtonElement); onsElements.ActionSheetButton = ActionSheetButtonElement; customElements.define('ons-action-sheet-button', ActionSheetButtonElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var AlertDialogAnimator = function (_BaseAnimator) { inherits(AlertDialogAnimator, _BaseAnimator); function AlertDialogAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'linear' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.2 : _ref$duration; classCallCheck(this, AlertDialogAnimator); return possibleConstructorReturn(this, (AlertDialogAnimator.__proto__ || Object.getPrototypeOf(AlertDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } /** * @param {HTMLElement} dialog * @param {Function} done */ createClass(AlertDialogAnimator, [{ key: 'show', value: function show(dialog, done) { done(); } /** * @param {HTMLElement} dialog * @param {Function} done */ }, { key: 'hide', value: function hide(dialog, done) { done(); } }]); return AlertDialogAnimator; }(BaseAnimator); /** * Android style animator for alert dialog. */ var AndroidAlertDialogAnimator = function (_AlertDialogAnimator) { inherits(AndroidAlertDialogAnimator, _AlertDialogAnimator); function AndroidAlertDialogAnimator() { var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref2$timing = _ref2.timing, timing = _ref2$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref2$timing, _ref2$duration = _ref2.duration, duration = _ref2$duration === undefined ? 0.2 : _ref2$duration, _ref2$delay = _ref2.delay, delay = _ref2$delay === undefined ? 0 : _ref2$delay; classCallCheck(this, AndroidAlertDialogAnimator); return possibleConstructorReturn(this, (AndroidAlertDialogAnimator.__proto__ || Object.getPrototypeOf(AndroidAlertDialogAnimator)).call(this, { duration: duration, timing: timing, delay: delay })); } /** * @param {Object} dialog * @param {Function} callback */ createClass(AndroidAlertDialogAnimator, [{ key: 'show', value: function show(dialog, callback) { callback = callback ? callback : function () {}; Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 0 }, { opacity: 1 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0) scale3d(.9, .9, 1)', opacity: 0 }, { transform: 'translate3d(-50%, -50%, 0) scale3d(1, 1, 1)', opacity: 1 }).queue(function (done) { callback(); done(); })); } /** * @param {Object} dialog * @param {Function} callback */ }, { key: 'hide', value: function hide(dialog, callback) { callback = callback ? callback : function () {}; Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0) scale3d(1, 1, 1)', opacity: 1 }, { transform: 'translate3d(-50%, -50%, 0) scale3d(.9, .9, 1)', opacity: 0 }).queue(function (done) { callback(); done(); })); } }]); return AndroidAlertDialogAnimator; }(AlertDialogAnimator); /** * iOS style animator for alert dialog. */ var IOSAlertDialogAnimator = function (_AlertDialogAnimator2) { inherits(IOSAlertDialogAnimator, _AlertDialogAnimator2); function IOSAlertDialogAnimator() { var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref3$timing = _ref3.timing, timing = _ref3$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref3$timing, _ref3$duration = _ref3.duration, duration = _ref3$duration === undefined ? 0.2 : _ref3$duration, _ref3$delay = _ref3.delay, delay = _ref3$delay === undefined ? 0 : _ref3$delay; classCallCheck(this, IOSAlertDialogAnimator); return possibleConstructorReturn(this, (IOSAlertDialogAnimator.__proto__ || Object.getPrototypeOf(IOSAlertDialogAnimator)).call(this, { duration: duration, timing: timing, delay: delay })); } /* * @param {Object} dialog * @param {Function} callback */ createClass(IOSAlertDialogAnimator, [{ key: 'show', value: function show(dialog, callback) { callback = callback ? callback : function () {}; Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 0 }, { opacity: 1 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0) scale3d(1.3, 1.3, 1)', opacity: 0 }, { transform: 'translate3d(-50%, -50%, 0) scale3d(1, 1, 1)', opacity: 1 }).queue(function (done) { callback(); done(); })); } /** * @param {Object} dialog * @param {Function} callback */ }, { key: 'hide', value: function hide(dialog, callback) { callback = callback ? callback : function () {}; Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(dialog._dialog, this.def).default({ opacity: 1 }, { opacity: 0 }).queue(function (done) { callback(); done(); })); } }]); return IOSAlertDialogAnimator; }(AlertDialogAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$1 = { '.alert-dialog': 'alert-dialog--*', '.alert-dialog-container': 'alert-dialog-container--*', '.alert-dialog-title': 'alert-dialog-title--*', '.alert-dialog-content': 'alert-dialog-content--*', '.alert-dialog-footer': 'alert-dialog-footer--*', '.alert-dialog-footer--rowfooter': 'alert-dialog-footer--rowfooter--*', '.alert-dialog-button--rowfooter': 'alert-dialog-button--rowfooter--*', '.alert-dialog-button--primal': 'alert-dialog-button--primal--*', '.alert-dialog-button': 'alert-dialog-button--*', 'ons-alert-dialog-button': 'alert-dialog-button--*', '.alert-dialog-mask': 'alert-dialog-mask--*', '.text-input': 'text-input--*' }; var _animatorDict$1 = { 'none': AlertDialogAnimator, 'default': function _default() { return platform.isAndroid() ? AndroidAlertDialogAnimator : IOSAlertDialogAnimator; }, 'fade': function fade() { return platform.isAndroid() ? AndroidAlertDialogAnimator : IOSAlertDialogAnimator; } }; /** * @element ons-alert-dialog * @category dialog * @description * [en] * Alert dialog that is displayed on top of the current screen. Useful for displaying questions, warnings or error messages to the user. The title, content and buttons can be easily customized and it will automatically switch style based on the platform. * * To use the element it can either be attached directly to the `<body>` element or dynamically created from a template using the `ons.createAlertDialog(template)` utility function and the `<template>` tag. * [/en] * [ja] * 現在のスクリーンの上に表示するアラートダイアログです。ユーザに対する問いかけ、警告、エラーメッセージを表示するのに利用できます。タイトルやコンテンツやボタンは簡単にカスタマイズでき、実行しているプラットフォームに併せてスタイルが自動的に切り替わります。 * [/ja] * @codepen Qwwxyp * @tutorial vanilla/Reference/alert-dialog * @modifier material * [en]Material Design style[/en] * [ja]マテリアルデザインのスタイル[/ja] * @modifier rowfooter * [en]Horizontally aligns the footer buttons.[/en] * [ja]フッターの複数のボタンを水平に配置[/ja] * @seealso ons-dialog * [en]ons-dialog component[/en] * [ja]ons-dialogコンポーネント[/ja] * @seealso ons-popover * [en]ons-popover component[/en] * [ja]ons-dialogコンポーネント[/ja] * @seealso ons.notification * [en]Using ons.notification utility functions.[/en] * [ja]アラートダイアログを表示するには、ons.notificationオブジェクトのメソッドを使うこともできます。[/ja] * @example * <ons-alert-dialog id="alert-dialog"> * <div class="alert-dialog-title">Warning!</div> * <div class="alert-dialog-content"> * An error has occurred! * </div> * <div class="alert-dialog-footer"> * <button id="alert-dialog-button" class="alert-dialog-button">OK</button> * </div> * </ons-alert-dialog> * <script> * document.getElementById('alert-dialog').show(); * </script> */ var AlertDialogElement = function (_BaseDialogElement) { inherits(AlertDialogElement, _BaseDialogElement); /** * @event preshow * @description * [en]Fired just before the alert dialog is displayed.[/en] * [ja]アラートダイアログが表示される直前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.alertDialog * [en]Alert dialog object.[/en] * [ja]アラートダイアログのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Execute to stop the dialog from showing.[/en] * [ja]この関数を実行すると、アラートダイアログの表示を止めます。[/ja] */ /** * @event postshow * @description * [en]Fired just after the alert dialog is displayed.[/en] * [ja]アラートダイアログが表示された直後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.alertDialog * [en]Alert dialog object.[/en] * [ja]アラートダイアログのオブジェクト。[/ja] */ /** * @event prehide * @description * [en]Fired just before the alert dialog is hidden.[/en] * [ja]アラートダイアログが隠れる直前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.alertDialog * [en]Alert dialog object.[/en] * [ja]アラートダイアログのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Execute to stop the dialog from hiding.[/en] * [ja]この関数を実行すると、アラートダイアログが閉じようとするのを止めます。[/ja] */ /** * @event posthide * @description * [en]Fired just after the alert dialog is hidden.[/en] * [ja]アラートダイアログが隠れた後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.alertDialog * [en]Alert dialog object.[/en] * [ja]アラートダイアログのオブジェクト。[/ja] */ /** * @attribute modifier * @type {String} * @description * [en]The appearance of the dialog.[/en] * [ja]ダイアログの見た目を指定します。[/ja] */ /** * @attribute cancelable * @description * [en]If this attribute is set the dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en] * [ja]この属性を設定すると、ダイアログの背景をタップしたりAndroidデバイスのバックボタンを押すとダイアログが閉じるようになります。[/ja] */ /** * @attribute disabled * @description * [en]If this attribute is set the dialog is disabled.[/en] * [ja]この属性がある時、アラートダイアログはdisabled状態になります。[/ja] */ /** * @attribute animation * @type {String} * @default default * @description * [en]The animation used when showing and hiding the dialog. Can be either `"none"` or `"default"`.[/en] * [ja]ダイアログを表示する際のアニメーション名を指定します。デフォルトでは"none"か"default"が指定できます。[/ja] */ /** * @attribute animation-options * @type {Expression} * @description * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。例:{duration: 0.2, delay: 1, timing: 'ease-in'}[/ja] */ /** * @attribute mask-color * @type {String} * @default rgba(0, 0, 0, 0.2) * @description * [en]Color of the background mask. Default is "rgba(0, 0, 0, 0.2)".[/en] * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja] */ function AlertDialogElement() { classCallCheck(this, AlertDialogElement); var _this = possibleConstructorReturn(this, (AlertDialogElement.__proto__ || Object.getPrototypeOf(AlertDialogElement)).call(this)); contentReady(_this, function () { return _this._compile(); }); return _this; } createClass(AlertDialogElement, [{ key: '_updateAnimatorFactory', value: function _updateAnimatorFactory() { return new AnimatorFactory({ animators: _animatorDict$1, baseClass: AlertDialogAnimator, baseClassName: 'AlertDialogAnimator', defaultAnimation: this.getAttribute('animation') }); } }, { key: '_compile', value: function _compile() { autoStyle.prepare(this); this.style.display = 'none'; this.style.zIndex = 10001; /** * Expected result after compile: * * <ons-alert-dialog style="none"> * <div class="alert-dialog-mask"></div> * <div class="alert-dialog"> * <div class="alert-dialog-container">...</div> * </div> * </ons-alert-dialog> */ var content = document.createDocumentFragment(); if (!this._mask && !this._dialog) { while (this.firstChild) { content.appendChild(this.firstChild); } } if (!this._mask) { var mask = document.createElement('div'); mask.classList.add('alert-dialog-mask'); this.insertBefore(mask, this.children[0]); } if (!this._dialog) { var dialog = document.createElement('div'); dialog.classList.add('alert-dialog'); this.insertBefore(dialog, null); } if (!util$1.findChild(this._dialog, '.alert-dialog-container')) { var container = document.createElement('div'); container.classList.add('alert-dialog-container'); this._dialog.appendChild(container); } this._dialog.children[0].appendChild(content); this._dialog.style.zIndex = 20001; this._mask.style.zIndex = 20000; ModifierUtil.initModifier(this, this._scheme); } /** * @property disabled * @type {Boolean} * @description * [en]Whether the element is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ /** * @property cancelable * @type {Boolean} * @description * [en]Whether the dialog is cancelable or not. A cancelable dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en] * [ja]そのダイアログがキャンセル可能かどうかを表します。キャンセル可能なダイアログは、背景をタップするかAndroidデバイスのバックボタンを押すことで閉じることが出来るようになります。[/ja] */ /** * @method show * @signature show([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクトです。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"fade"` and `"none"`.[/en] * [ja]アニメーション名を指定します。指定できるのは、"fade", "none"のいずれかです。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. <code>{duration: 0.2, delay: 0.4, timing: 'ease-in'}</code> [/ja] * @param {Function} [options.callback] * [en]Function to execute after the dialog has been revealed.[/en] * [ja]ダイアログが表示され終わった時に呼び出されるコールバックを指定します。[/ja] * @description * [en]Show the alert dialog.[/en] * [ja]ダイアログを表示します。[/ja] * @return {Promise} * [en]A `Promise` object that resolves to the displayed element.[/en] * [ja]表示される要素を解決する`Promise`オブジェクトを返します。[/ja] */ /** * @method hide * @signature hide([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"fade"` and `"none"`.[/en] * [ja]アニメーション名を指定します。"fade", "none"のいずれかを指定します。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. <code>{duration: 0.2, delay: 0.4, timing: 'ease-in'}</code>[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. <code>{duration: 0.2, delay: 0.4, timing: 'ease-in'}</code> [/ja] * @param {Function} [options.callback] * [en]Function to execute after the dialog has been hidden.[/en] * [ja]このダイアログが閉じた時に呼び出されるコールバックを指定します。[/ja] * @description * [en]Hide the alert dialog.[/en] * [ja]ダイアログを閉じます。[/ja] * @return {Promise} * [en]Resolves to the hidden element[/en] * [ja]隠れた要素を解決する`Promise`オブジェクトを返します。[/ja] */ /** * @property visible * @readonly * @type {Boolean} * @description * [en]Whether the dialog is visible or not.[/en] * [ja]要素が見える場合に`true`。[/ja] */ /** * @property onDeviceBackButton * @type {Object} * @description * [en]Back-button handler.[/en] * [ja]バックボタンハンドラ。[/ja] */ /** * @param {String} name * @param {DialogAnimator} Animator */ }, { key: '_scheme', get: function get$$1() { return scheme$1; } /** * @return {Element} */ }, { key: '_mask', get: function get$$1() { return util$1.findChild(this, '.alert-dialog-mask'); } /** * @return {Element} */ }, { key: '_dialog', get: function get$$1() { return util$1.findChild(this, '.alert-dialog'); } /** * @return {Element} */ }, { key: '_titleElement', get: function get$$1() { return util$1.findChild(this._dialog.children[0], '.alert-dialog-title'); } /** * @return {Element} */ }, { key: '_contentElement', get: function get$$1() { return util$1.findChild(this._dialog.children[0], '.alert-dialog-content'); } }], [{ key: 'registerAnimator', value: function registerAnimator(name, Animator) { if (!(Animator.prototype instanceof AlertDialogAnimator)) { util$1.throwAnimator('AlertDialog'); } _animatorDict$1[name] = Animator; } }, { key: 'animators', get: function get$$1() { return _animatorDict$1; } }, { key: 'AlertDialogAnimator', get: function get$$1() { return AlertDialogAnimator; } }]); return AlertDialogElement; }(BaseDialogElement); onsElements.AlertDialog = AlertDialogElement; customElements.define('ons-alert-dialog', AlertDialogElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-alert-dialog-button * @modifier material * [en]Material Design alert-dialog button.[/en] * [ja]マテリアルデザインのボタンを表示します。[/ja] * @description * [en][/en] * [ja][/ja] * @seealso ons-alert-dialog * [en]The `<ons-alert-dialog>` component displays a alert dialog.[/en] * [ja]ons-alert-dialogコンポーネント[/ja] * @example * <ons-alert-dialog> * <div class="alert-dialog-title">Warning!</div> * <div class="alert-dialog-content"> * An error has occurred! * </div> * <div class="alert-dialog-footer"> * <alert-dialog-button onclick="app.close()">Cancel</alert-dialog-button> * <alert-dialog-button class="alert-dialog-button" onclick="app.close()">OK</alert-dialog-button> * </div> * </ons-alert-dialog> */ var AlertDialogButtonElement = function (_BaseButtonElement) { inherits(AlertDialogButtonElement, _BaseButtonElement); function AlertDialogButtonElement() { classCallCheck(this, AlertDialogButtonElement); return possibleConstructorReturn(this, (AlertDialogButtonElement.__proto__ || Object.getPrototypeOf(AlertDialogButtonElement)).apply(this, arguments)); } createClass(AlertDialogButtonElement, [{ key: '_scheme', /** * @attribute modifier * @type {String} * @description * [en]The appearance of the button.[/en] * [ja]ボタンの表現を指定します。[/ja] */ /** * @attribute disabled * @description * [en]Specify if button should be disabled.[/en] * [ja]ボタンを無効化する場合は指定してください。[/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the element is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ get: function get$$1() { return { '': 'alert-dialog-button--*' }; } }, { key: '_defaultClassName', get: function get$$1() { return 'alert-dialog-button'; } }, { key: '_rippleOpt', get: function get$$1() { return [this, undefined, { 'modifier': 'light-gray' }]; } }]); return AlertDialogButtonElement; }(BaseButtonElement); onsElements.AlertDialogButton = AlertDialogButtonElement; customElements.define('ons-alert-dialog-button', AlertDialogButtonElement); var iosBackButtonIcon = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg width=\"13px\" height=\"21px\" viewBox=\"0 0 13 21\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <title>ios-back-button-icon</title>\n <desc>Created with Sketch.</desc>\n <defs></defs>\n <g id=\"toolbar-back-button\" stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n <g id=\"ios\" transform=\"translate(-34.000000, -30.000000)\">\n <polygon id=\"ios-back-button-icon\" points=\"34 40.5 44.5 30 46.5 32 38 40.5 46.5 49 44.5 51\"></polygon>\n </g>\n </g>\n</svg>\n"; var mdBackButtonIcon = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg width=\"16px\" height=\"16px\" viewBox=\"0 0 16 16\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <title>md-back-button-icon</title>\n <desc>Created with Sketch.</desc>\n <defs></defs>\n <g id=\"toolbar-back-button\" stroke=\"none\" stroke-width=\"1\" fill-rule=\"evenodd\">\n <g id=\"android\" transform=\"translate(-32.000000, -32.000000)\" fill-rule=\"nonzero\">\n <polygon id=\"md-back-button-icon\" points=\"48 39 35.83 39 41.42 33.41 40 32 32 40 40 48 41.41 46.59 35.83 41 48 41\"></polygon>\n </g>\n </g>\n</svg>\n"; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName = 'back-button'; var scheme$2 = { '': 'back-button--*', '.back-button__icon': 'back-button--*__icon', '.back-button__label': 'back-button--*__label' }; /** * @element ons-back-button * @category navigation * @description * [en] * Back button component for `<ons-toolbar>`. Put it in the left part of the `<ons-toolbar>`. * * It will find the parent `<ons-navigator>` element and pop a page when clicked. This behavior can be overriden by specifying the `onClick` property. * [/en] * [ja][/ja] * @codepen aHmGL * @tutorial vanilla/Reference/back-button * @modifier material * [en]Material Design style[/en] * [ja][/ja] * @seealso ons-toolbar * [en]ons-toolbar component[/en] * [ja]ons-toolbarコンポーネント[/ja] * @seealso ons-navigator * [en]ons-navigator component[/en] * [ja]ons-navigatorコンポーネント[/ja] * @example * <ons-toolbar> * <div class="left"> * <ons-back-button>Back</ons-back-button> * </div> * <div class="center"> * Title * <div> * </ons-toolbar> */ var BackButtonElement = function (_BaseElement) { inherits(BackButtonElement, _BaseElement); /** * @attribute modifier * @type {String} * @description * [en]The appearance of the back button.[/en] * [ja]バックボタンの見た目を指定します。[/ja] */ function BackButtonElement() { classCallCheck(this, BackButtonElement); var _this = possibleConstructorReturn(this, (BackButtonElement.__proto__ || Object.getPrototypeOf(BackButtonElement)).call(this)); contentReady(_this, function () { _this._compile(); }); _this._options = {}; _this._boundOnClick = _this._onClick.bind(_this); return _this; } createClass(BackButtonElement, [{ key: '_updateIcon', value: function _updateIcon() { var icon = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : util$1.findChild(this, '.back-button__icon'); icon.innerHTML = autoStyle.getPlatform(this) === 'android' || util$1.hasModifier(this, 'material') ? mdBackButtonIcon : iosBackButtonIcon; } }, { key: '_compile', value: function _compile() { autoStyle.prepare(this); this.classList.add(defaultClassName); if (!util$1.findChild(this, '.back-button__label')) { var label = util$1.create('span.back-button__label'); while (this.childNodes[0]) { label.appendChild(this.childNodes[0]); } this.appendChild(label); } if (!util$1.findChild(this, '.back-button__icon')) { var icon = util$1.create('span.back-button__icon'); this._updateIcon(icon); this.insertBefore(icon, this.children[0]); } util$1.updateRipple(this, undefined, { center: '', 'size': 'contain', 'background': 'transparent' }); ModifierUtil.initModifier(this, scheme$2); } /** * @property options * @type {Object} * @description * [en]Options object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] */ /** * @property options.animation * @type {String} * @description * [en]Animation name. Available animations are "slide", "lift", "fade" and "none". * These are platform based animations. For fixed animations, add "-ios" or "-md" * suffix to the animation name. E.g. "lift-ios", "lift-md". Defaults values are "slide-ios" and "fade-md". * [/en] * [ja][/ja] */ /** * @property options.animationOptions * @type {String} * @description * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja] */ /** * @property options.callback * @type {String} * @description * [en]Function that is called when the transition has ended.[/en] * [ja]このメソッドによる画面遷移が終了した際に呼び出される関数オブジェクトを指定します。[/ja] */ }, { key: '_onClick', /** * @property onClick * @type {Function} * @description * [en]Used to override the default back button behavior.[/en] * [ja][/ja] */ value: function _onClick() { if (this.onClick) { this.onClick.apply(this); } else { var navigator = util$1.findParent(this, 'ons-navigator'); if (navigator) { navigator.popPage(this.options); } } } }, { key: 'connectedCallback', value: function connectedCallback() { this.addEventListener('click', this._boundOnClick, false); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName, scheme$2); break; case 'modifier': { ModifierUtil.onModifierChanged(last, current, this, scheme$2) && this._updateIcon(); break; } } } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this.removeEventListener('click', this._boundOnClick, false); } }, { key: 'show', value: function show() { this.style.display = 'inline-block'; } }, { key: 'hide', value: function hide() { this.style.display = 'none'; } }, { key: 'options', get: function get$$1() { return this._options; }, set: function set$$1(object) { this._options = object; } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'class']; } }]); return BackButtonElement; }(BaseElement); onsElements.BackButton = BackButtonElement; customElements.define('ons-back-button', BackButtonElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$1 = 'bottom-bar'; var scheme$3 = { '': 'bottom-bar--*' }; /** * @element ons-bottom-toolbar * @category page * @description * [en]Toolbar component that is positioned at the bottom of the page. Since bottom toolbars are very versatile elements, `ons-bottom-toolbar` does not provide any specific layout syntax for its children. Modifiers or custom CSS must be used.[/en] * [ja]ページ下部に配置されるツールバー用コンポーネントです。[/ja] * @modifier transparent * [en]Make the toolbar transparent.[/en] * [ja]ツールバーの背景を透明にして表示します。[/ja] * @modifier aligned * [en]Vertically aligns its children and applies flexbox for block elements. `justify-content` CSS rule can be used to change horizontal align.[/en] * [ja]ツールバーの背景を透明にして表示します。[/ja] * @seealso ons-toolbar [en]ons-toolbar component[/en][ja]ons-toolbarコンポーネント[/ja] * @example * <ons-bottom-toolbar> * Content * </ons-bottom-toolbar> */ var BottomToolbarElement = function (_BaseElement) { inherits(BottomToolbarElement, _BaseElement); /** * @attribute modifier * @type {String} * @description * [en]The appearance of the toolbar.[/en] * [ja]ツールバーの見た目の表現を指定します。[/ja] */ function BottomToolbarElement() { classCallCheck(this, BottomToolbarElement); var _this = possibleConstructorReturn(this, (BottomToolbarElement.__proto__ || Object.getPrototypeOf(BottomToolbarElement)).call(this)); _this.classList.add(defaultClassName$1); ModifierUtil.initModifier(_this, scheme$3); return _this; } createClass(BottomToolbarElement, [{ key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$1, scheme$3); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$3); break; } } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'class']; } }]); return BottomToolbarElement; }(BaseElement); onsElements.BottomToolbar = BottomToolbarElement; customElements.define('ons-bottom-toolbar', BottomToolbarElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-button * @category form * @modifier outline * [en]Button with outline and transparent background[/en] * [ja]アウトラインを持ったボタンを表示します。[/ja] * @modifier light * [en]Button that doesn't stand out.[/en] * [ja]目立たないボタンを表示します。[/ja] * @modifier quiet * [en]Button with no outline and or background..[/en] * [ja]枠線や背景が無い文字だけのボタンを表示します。[/ja] * @modifier cta * [en]Button that really stands out.[/en] * [ja]目立つボタンを表示します。[/ja] * @modifier large * [en]Large button that covers the width of the screen.[/en] * [ja]横いっぱいに広がる大きなボタンを表示します。[/ja] * @modifier large--quiet * [en]Large quiet button.[/en] * [ja]横いっぱいに広がるquietボタンを表示します。[/ja] * @modifier large--cta * [en]Large call to action button.[/en] * [ja]横いっぱいに広がるctaボタンを表示します。[/ja] * @modifier material * [en]Material Design button[/en] * [ja]マテリアルデザインのボタン[/ja] * @modifier material--flat * [en]Material Design flat button[/en] * [ja]マテリアルデザインのフラットボタン[/ja] * @description * [en] * Button component. If you want to place a button in a toolbar, use `<ons-toolbar-button>` or `<ons-back-button>` instead. * * Will automatically display as a Material Design button with a ripple effect on Android. * [/en] * [ja]ボタン用コンポーネント。ツールバーにボタンを設置する場合は、ons-toolbar-buttonもしくはons-back-buttonコンポーネントを使用します。[/ja] * @codepen hLayx * @tutorial vanilla/Reference/button * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja] * @example * <ons-button modifier="large--cta"> * Tap Me * </ons-button> */ var ButtonElement = function (_BaseButtonElement) { inherits(ButtonElement, _BaseButtonElement); function ButtonElement() { classCallCheck(this, ButtonElement); return possibleConstructorReturn(this, (ButtonElement.__proto__ || Object.getPrototypeOf(ButtonElement)).apply(this, arguments)); } createClass(ButtonElement, [{ key: '_scheme', /** * @attribute modifier * @type {String} * @description * [en]The appearance of the button.[/en] * [ja]ボタンの表現を指定します。[/ja] */ /** * @attribute ripple * @description * [en]If this attribute is defined, the button will have a ripple effect.[/en] * [ja][/ja] */ /** * @attribute disabled * @description * [en]Specify if button should be disabled.[/en] * [ja]ボタンを無効化する場合は指定します。[/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the button is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ get: function get$$1() { return { '': 'button--*' }; } }, { key: '_defaultClassName', get: function get$$1() { return 'button'; } }]); return ButtonElement; }(BaseButtonElement); onsElements.Button = ButtonElement; customElements.define('ons-button', ButtonElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$2 = 'card'; var scheme$4 = { '': 'card--*', '.card__title': 'card--*__title', '.card__content': 'card--*__content' }; /** * @element ons-card * @category visual * @modifier material * [en]A card with material design.[/en] * [ja]リストの上下のボーダーが無いリストを表示します。[/ja] * @description * [en] * Component to create a card that displays some information. * * The card may be composed by divs with specially prepared classes `title` and/or `content`. You can also add your own content as you please.[/en] * [ja][/ja] * @tutorial vanilla/Reference/card * @example * <ons-card> * <p>Some content</p> * </ons-card> */ var CardElement = function (_BaseElement) { inherits(CardElement, _BaseElement); /** * @attribute modifier * @type {String} * @description * [en]The appearance of the card.[/en] * [ja]リストの表現を指定します。[/ja] */ function CardElement() { classCallCheck(this, CardElement); var _this = possibleConstructorReturn(this, (CardElement.__proto__ || Object.getPrototypeOf(CardElement)).call(this)); contentReady(_this, function () { _this._compile(); }); return _this; } createClass(CardElement, [{ key: '_compile', value: function _compile() { for (var i = 0; i < this.children.length; i++) { var el = this.children[i]; if (el.classList.contains('title')) { el.classList.add('card__title'); } else if (el.classList.contains('content')) { el.classList.add('card__content'); } } autoStyle.prepare(this); this.classList.add(defaultClassName$2); ModifierUtil.initModifier(this, scheme$4); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$2, scheme$4); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$4); break; } } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'class']; } }]); return CardElement; }(BaseElement); onsElements.Card = CardElement; customElements.define('ons-card', CardElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$5 = { '': 'carousel-item--*' }; /** * @element ons-carousel-item * @category carousel * @description * [en] * Carousel item component. Used as a child of the `<ons-carousel>` element. * [/en] * [ja][/ja] * @codepen xbbzOQ * @tutorial vanilla/Reference/carousel * @seealso ons-carousel * [en]`<ons-carousel>` components[/en] * [ja]<ons-carousel>コンポーネント[/ja] * @example * <ons-carousel style="width: 100%; height: 200px"> * <ons-carousel-item> * ... * </ons-carousel-item> * <ons-carousel-item> * ... * </ons-carousel-item> * </ons-carousel> */ var CarouselItemElement = function (_BaseElement) { inherits(CarouselItemElement, _BaseElement); function CarouselItemElement() { classCallCheck(this, CarouselItemElement); var _this = possibleConstructorReturn(this, (CarouselItemElement.__proto__ || Object.getPrototypeOf(CarouselItemElement)).call(this)); _this.style.width = '100%'; ModifierUtil.initModifier(_this, scheme$5); return _this; } createClass(CarouselItemElement, [{ key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'modifier') { return ModifierUtil.onModifierChanged(last, current, this, scheme$5); } } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier']; } }]); return CarouselItemElement; }(BaseElement); onsElements.CarouselItem = CarouselItemElement; customElements.define('ons-carousel-item', CarouselItemElement); var directionMap = { vertical: { axis: 'Y', size: 'Height', dir: ['up', 'down'], t3d: ['0px, ', 'px, 0px'] }, horizontal: { axis: 'X', size: 'Width', dir: ['left', 'right'], t3d: ['', 'px, 0px, 0px'] } }; var Swiper = function () { function Swiper(params) { var _this = this; classCallCheck(this, Swiper); // Parameters var FALSE = function FALSE() { return false; }; 'getInitialIndex getBubbleWidth isVertical isOverScrollable isCentered\n isAutoScrollable refreshHook preChangeHook postChangeHook overScrollHook'.split(/\s+/).forEach(function (key) { return _this[key] = params[key] || FALSE; }); this.getElement = params.getElement; // Required this.scrollHook = params.scrollHook; // Optional this.itemSize = params.itemSize || '100%'; this.getAutoScrollRatio = function () { var ratio = params.getAutoScrollRatio && params.getAutoScrollRatio.apply(params, arguments); ratio = typeof ratio === 'number' && ratio === ratio ? ratio : .5; if (ratio < 0.0 || ratio > 1.0) { util$1.throw('Invalid auto-scroll-ratio ' + ratio + '. Must be between 0 and 1'); } return ratio; }; // Prevent clicks only on desktop this.shouldBlock = util$1.globals.actualMobileOS === 'other'; // Bind handlers this.onDragStart = this.onDragStart.bind(this); this.onDrag = this.onDrag.bind(this); this.onDragEnd = this.onDragEnd.bind(this); this.onResize = this.onResize.bind(this); this._shouldFixScroll = util$1.globals.actualMobileOS === 'ios'; } createClass(Swiper, [{ key: 'init', value: function init() { var _this2 = this; var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, swipeable = _ref.swipeable, autoRefresh = _ref.autoRefresh; this.initialized = true; this.target = this.getElement().children[0]; this.blocker = this.getElement().children[1]; if (!this.target || !this.blocker) { util$1.throw('Expected "target" and "blocker" elements to exist before initializing Swiper'); } if (!this.shouldBlock) { this.blocker.style.display = 'none'; } // Add classes this.getElement().classList.add('ons-swiper'); this.target.classList.add('ons-swiper-target'); this.blocker.classList.add('ons-swiper-blocker'); // Setup listeners this._gestureDetector = new GestureDetector(this.getElement(), { dragMinDistance: 1, dragLockToAxis: true, passive: !this._shouldFixScroll }); this._mutationObserver = new MutationObserver(function () { return _this2.refresh(); }); this.updateSwipeable(swipeable); this.updateAutoRefresh(autoRefresh); // Setup initial layout this._scroll = this._offset = this._lastActiveIndex = 0; this._updateLayout(); this._setupInitialIndex(); setImmediate(function () { return _this2.initialized && _this2._setupInitialIndex(); }); // Fix rendering glitch on Android 4.1 // Fix for iframes where the width is inconsistent at the beginning if (window !== window.parent || this.offsetHeight === 0) { window.requestAnimationFrame(function () { return _this2.initialized && _this2.onResize(); }); } } }, { key: 'dispose', value: function dispose() { this.initialized = false; this.updateSwipeable(false); this.updateAutoRefresh(false); this._gestureDetector && this._gestureDetector.dispose(); this.target = this.blocker = this._gestureDetector = this._mutationObserver = null; this.setupResize(false); } }, { key: 'onResize', value: function onResize() { var i = this._scroll / this.targetSize; this._reset(); this.setActiveIndex(i); this.refresh(); } }, { key: '_calculateItemSize', value: function _calculateItemSize() { var matches = this.itemSize.match(/^(\d+)(px|%)/); if (!matches) { util$1.throw('Invalid state: swiper\'s size unit must be \'%\' or \'px\''); } var value = parseInt(matches[1], 10); return matches[2] === '%' ? Math.round(value / 100 * this.targetSize) : value; } }, { key: '_setupInitialIndex', value: function _setupInitialIndex() { this._reset(); this._lastActiveIndex = Math.max(Math.min(Number(this.getInitialIndex()), this.itemCount), 0); this._scroll = this._offset + this.itemNumSize * this._lastActiveIndex; this._scrollTo(this._scroll); } }, { key: '_setSwiping', value: function _setSwiping(toggle) { this.target.classList.toggle('swiping', toggle); // Hides everything except shown pages } }, { key: 'setActiveIndex', value: function setActiveIndex(index) { var _this3 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; this._setSwiping(true); index = Math.max(0, Math.min(index, this.itemCount - 1)); var scroll = Math.max(0, Math.min(this.maxScroll, this._offset + this.itemNumSize * index)); if (platform.isUIWebView()) { /* Dirty fix for #2231(https://github.com/OnsenUI/OnsenUI/issues/2231). begin */ var concat = function concat(arrayOfArray) { return Array.prototype.concat.apply([], arrayOfArray); }; var contents = concat(util$1.arrayFrom(this.target.children).map(function (page) { return util$1.arrayFrom(page.children).filter(function (child) { return child.classList.contains('page__content'); }); })); var map = new Map(); return new Promise(function (resolve) { contents.forEach(function (content) { map.set(content, content.getAttribute('class')); content.classList.add('page__content--suppress-layer-creation'); }); requestAnimationFrame(resolve); }).then(function () { return _this3._changeTo(scroll, options); }).then(function () { return new Promise(function (resolve) { contents.forEach(function (content) { content.setAttribute('class', map.get(content)); }); requestAnimationFrame(resolve); }); }); /* end */ } else { return this._changeTo(scroll, options); } } }, { key: 'getActiveIndex', value: function getActiveIndex() { var scroll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this._scroll; scroll -= this._offset; var count = this.itemCount, size = this.itemNumSize; if (this.itemNumSize === 0 || !util$1.isInteger(scroll)) { return this._lastActiveIndex; } if (scroll <= 0) { return 0; } for (var i = 0; i < count; i++) { if (size * i <= scroll && size * (i + 1) > scroll) { return i; } } return count - 1; } }, { key: 'setupResize', value: function setupResize(add) { window[(add ? 'add' : 'remove') + 'EventListener']('resize', this.onResize, true); } }, { key: 'show', value: function show() { var _this4 = this; this.setupResize(true); this.onResize(); setTimeout(function () { return _this4.target && _this4.target.classList.add('active'); }, 1000 / 60); // Hide elements after animations } }, { key: 'hide', value: function hide() { this.setupResize(false); this.target.classList.remove('active'); // Show elements before animations } }, { key: 'updateSwipeable', value: function updateSwipeable(shouldUpdate) { if (this._gestureDetector) { var action = shouldUpdate ? 'on' : 'off'; this._gestureDetector[action]('drag', this.onDrag); this._gestureDetector[action]('dragstart', this.onDragStart); this._gestureDetector[action]('dragend', this.onDragEnd); } } }, { key: 'updateAutoRefresh', value: function updateAutoRefresh(shouldWatch) { if (this._mutationObserver) { shouldWatch ? this._mutationObserver.observe(this.target, { childList: true }) : this._mutationObserver.disconnect(); } } }, { key: 'updateItemSize', value: function updateItemSize(newSize) { this.itemSize = newSize || '100%'; this.refresh(); } }, { key: 'toggleBlocker', value: function toggleBlocker(block) { this.blocker.style.pointerEvents = block ? 'auto' : 'none'; } }, { key: '_canConsumeGesture', value: function _canConsumeGesture(gesture) { var d = gesture.direction; var isFirst = this._scroll === 0 && !this.isOverScrollable(); var isLast = this._scroll === this.maxScroll && !this.isOverScrollable(); return this.isVertical() ? d === 'down' && !isFirst || d === 'up' && !isLast : d === 'right' && !isFirst || d === 'left' && !isLast; } }, { key: 'onDragStart', value: function onDragStart(event) { var _this5 = this; this._ignoreDrag = event.consumed || !util$1.isValidGesture(event); if (!this._ignoreDrag) { var consume = event.consume; event.consume = function () { consume && consume();_this5._ignoreDrag = true; }; if (this._canConsumeGesture(event.gesture)) { var startX = event.gesture.center && event.gesture.center.clientX || 0, distFromEdge = this.getBubbleWidth() || 0, start = function start() { consume && consume(); event.consumed = true; _this5._started = true; // Avoid starting drag from outside _this5.shouldBlock && _this5.toggleBlocker(true); _this5._setSwiping(true); util$1.iosPreventScroll(_this5._gestureDetector); }; // Let parent elements consume the gesture or consume it right away startX < distFromEdge || startX > this.targetSize - distFromEdge ? setImmediate(function () { return !_this5._ignoreDrag && start(); }) : start(); } } } }, { key: 'onDrag', value: function onDrag(event) { if (!event.gesture || this._ignoreDrag || !this._started) { return; } this._continued = true; // Fix for random 'dragend' without 'drag' event.stopPropagation(); this._scrollTo(this._scroll - this._getDelta(event), { throttle: true }); } }, { key: 'onDragEnd', value: function onDragEnd(event) { this._started = false; if (!event.gesture || this._ignoreDrag || !this._continued) { this._ignoreDrag = true; // onDragEnd might fire before onDragStart's setImmediate return; } this._continued = false; event.stopPropagation(); var scroll = this._scroll - this._getDelta(event); var normalizedScroll = this._normalizeScroll(scroll); scroll === normalizedScroll ? this._startMomentumScroll(scroll, event) : this._killOverScroll(normalizedScroll); this.shouldBlock && this.toggleBlocker(false); } }, { key: '_startMomentumScroll', value: function _startMomentumScroll(scroll, event) { var velocity = this._getVelocity(event), matchesDirection = event.gesture.interimDirection === this.dM.dir[this._getDelta(event) < 0 ? 0 : 1]; var nextScroll = this._getAutoScroll(scroll, velocity, matchesDirection); var duration = Math.abs(nextScroll - scroll) / (velocity + 0.01) / 1000; duration = Math.min(.25, Math.max(.1, duration)); this._changeTo(nextScroll, { swipe: true, animationOptions: { duration: duration, timing: 'cubic-bezier(.4, .7, .5, 1)' } }); } }, { key: '_killOverScroll', value: function _killOverScroll(scroll) { var _this6 = this; this._scroll = scroll; var direction = this.dM.dir[Number(scroll > 0)]; var killOverScroll = function killOverScroll() { return _this6._changeTo(scroll, { animationOptions: { duration: .4, timing: 'cubic-bezier(.1, .4, .1, 1)' } }); }; this.overScrollHook({ direction: direction, killOverScroll: killOverScroll }) || killOverScroll(); } }, { key: '_changeTo', value: function _changeTo(scroll) { var _this7 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var e = { activeIndex: this.getActiveIndex(scroll), lastActiveIndex: this._lastActiveIndex, swipe: options.swipe || false }; var change = e.activeIndex !== e.lastActiveIndex; var canceled = change ? this.preChangeHook(e) : false; this._scroll = canceled ? this._offset + e.lastActiveIndex * this.itemNumSize : scroll; this._lastActiveIndex = canceled ? e.lastActiveIndex : e.activeIndex; return this._scrollTo(this._scroll, options).then(function () { if (scroll === _this7._scroll && !canceled) { _this7._setSwiping(false); change && _this7.postChangeHook(e); } else if (options.reject) { _this7._setSwiping(false); return Promise.reject('Canceled'); } }); } }, { key: '_scrollTo', value: function _scrollTo(scroll) { var _this8 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (options.throttle) { var ratio = 0.35; if (scroll < 0) { scroll = this.isOverScrollable() ? Math.round(scroll * ratio) : 0; } else { var maxScroll = this.maxScroll; if (maxScroll < scroll) { scroll = this.isOverScrollable() ? maxScroll + Math.round((scroll - maxScroll) * ratio) : maxScroll; } } } var opt = options.animation === 'none' ? {} : options.animationOptions; this.scrollHook && this.itemNumSize > 0 && this.scrollHook((scroll / this.itemNumSize).toFixed(2), options.animationOptions || {}); return new Promise(function (resolve) { return Animit(_this8.target).queue({ transform: _this8._getTransform(scroll) }, opt).play(resolve); }); } }, { key: '_getAutoScroll', value: function _getAutoScroll(scroll, velocity, matchesDirection) { var max = this.maxScroll, offset = this._offset, size = this.itemNumSize; if (!this.isAutoScrollable()) { return Math.max(0, Math.min(max, scroll)); } var arr = []; for (var s = offset; s < max; s += size) { arr.push(s); } arr.push(max); arr = arr.sort(function (left, right) { return Math.abs(left - scroll) - Math.abs(right - scroll); }).filter(function (item, pos) { return !pos || item !== arr[pos - 1]; }); var result = arr[0]; var lastScroll = this._lastActiveIndex * size + offset; var scrollRatio = Math.abs(scroll - lastScroll) / size; if (scrollRatio <= this.getAutoScrollRatio(matchesDirection, velocity, size)) { result = lastScroll; } else { if (scrollRatio < 1.0 && arr[0] === lastScroll && arr.length > 1) { result = arr[1]; } } return Math.max(0, Math.min(max, result)); } }, { key: '_reset', value: function _reset() { this._targetSize = this._itemNumSize = undefined; } }, { key: '_normalizeScroll', value: function _normalizeScroll(scroll) { return Math.max(Math.min(scroll, this.maxScroll), 0); } }, { key: 'refresh', value: function refresh() { this._reset(); this._updateLayout(); if (util$1.isInteger(this._scroll)) { var scroll = this._normalizeScroll(this._scroll); scroll !== this._scroll ? this._killOverScroll(scroll) : this._changeTo(scroll); } else { this._setupInitialIndex(); } this.refreshHook(); } }, { key: '_getDelta', value: function _getDelta(event) { return event.gesture['delta' + this.dM.axis]; } }, { key: '_getVelocity', value: function _getVelocity(event) { return event.gesture['velocity' + this.dM.axis]; } }, { key: '_getTransform', value: function _getTransform(scroll) { return 'translate3d(' + this.dM.t3d[0] + -scroll + this.dM.t3d[1] + ')'; } }, { key: '_updateLayout', value: function _updateLayout() { this.dM = directionMap[this.isVertical() ? 'vertical' : 'horizontal']; this.target.classList.toggle('ons-swiper-target--vertical', this.isVertical()); for (var c = this.target.children[0]; c; c = c.nextElementSibling) { c.style[this.dM.size.toLowerCase()] = this.itemSize; } if (this.isCentered()) { this._offset = (this.targetSize - this.itemNumSize) / -2 || 0; } } }, { key: 'itemCount', get: function get$$1() { return this.target.children.length; } }, { key: 'itemNumSize', get: function get$$1() { if (typeof this._itemNumSize !== 'number' || this._itemNumSize !== this._itemNumSize) { this._itemNumSize = this._calculateItemSize(); } return this._itemNumSize; } }, { key: 'maxScroll', get: function get$$1() { var max = this.itemCount * this.itemNumSize - this.targetSize; return Math.ceil(max < 0 ? 0 : max); // Need to return an integer value. } }, { key: 'targetSize', get: function get$$1() { if (!this._targetSize) { this._targetSize = this.target['offset' + this.dM.size]; } return this._targetSize; } }]); return Swiper; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-carousel * @category carousel * @description * [en] * Carousel component. A carousel can be used to display several items in the same space. * * The component supports displaying content both horizontally and vertically. The user can scroll through the items by dragging and it can also be controller programmatically. * [/en] * [ja][/ja] * @codepen xbbzOQ * @tutorial vanilla/Reference/carousel * @seealso ons-carousel-item * [en]`<ons-carousel-item>` component[/en] * [ja]ons-carousel-itemコンポーネント[/ja] * @example * <ons-carousel style="width: 100%; height: 200px"> * <ons-carousel-item> * ... * </ons-carousel-item> * <ons-carousel-item> * ... * </ons-carousel-item> * </ons-carousel> */ var CarouselElement = function (_BaseElement) { inherits(CarouselElement, _BaseElement); /** * @event postchange * @description * [en]Fired just after the current carousel item has changed.[/en] * [ja]現在表示しているカルーセルの要素が変わった時に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクトです。[/ja] * @param {Object} event.carousel * [en]Carousel object.[/en] * [ja]イベントが発火したCarouselオブジェクトです。[/ja] * @param {Number} event.activeIndex * [en]Current active index.[/en] * [ja]現在アクティブになっている要素のインデックス。[/ja] * @param {Number} event.lastActiveIndex * [en]Previous active index.[/en] * [ja]以前アクティブだった要素のインデックス。[/ja] */ /** * @event refresh * @description * [en]Fired when the carousel has been refreshed.[/en] * [ja]カルーセルが更新された時に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクトです。[/ja] * @param {Object} event.carousel * [en]Carousel object.[/en] * [ja]イベントが発火したCarouselオブジェクトです。[/ja] */ /** * @event overscroll * @description * [en]Fired when the carousel has been overscrolled.[/en] * [ja]カルーセルがオーバースクロールした時に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクトです。[/ja] * @param {Object} event.carousel * [en]Fired when the carousel has been refreshed.[/en] * [ja]カルーセルが更新された時に発火します。[/ja] * @param {Number} event.activeIndex * [en]Current active index.[/en] * [ja]現在アクティブになっている要素のインデックス。[/ja] * @param {String} event.direction * [en]Can be one of either "up", "down", "left" or "right".[/en] * [ja]オーバースクロールされた方向が得られます。"up", "down", "left", "right"のいずれかの方向が渡されます。[/ja] * @param {Function} event.waitToReturn * [en]Takes a <code>Promise</code> object as an argument. The carousel will not scroll back until the promise has been resolved or rejected.[/en] * [ja]この関数はPromiseオブジェクトを引数として受け取ります。渡したPromiseオブジェクトがresolveされるかrejectされるまで、カルーセルはスクロールバックしません。[/ja] */ /** * @attribute direction * @type {String} * @description * [en]The direction of the carousel. Can be either "horizontal" or "vertical". Default is "horizontal".[/en] * [ja]カルーセルの方向を指定します。"horizontal"か"vertical"を指定できます。"horizontal"がデフォルト値です。[/ja] */ /** * @attribute fullscreen * @description * [en]If this attribute is set the carousel will cover the whole screen.[/en] * [ja]この属性があると、absoluteポジションを使ってカルーセルが自動的に画面いっぱいに広がります。[/ja] */ /** * @attribute overscrollable * @description * [en]If this attribute is set the carousel will be scrollable over the edge. It will bounce back when released.[/en] * [ja]この属性がある時、タッチやドラッグで端までスクロールした時に、バウンドするような効果が当たります。[/ja] */ /** * @attribute centered * @description * [en]If this attribute is set the carousel then the selected item will be in the center of the carousel instead of the beginning. Useful only when the items are smaller than the carousel. [/en] * [ja]この属性がある時、選んでいるons-carousel-itemはカルーセルの真ん中へ行きます。項目がカルーセルよりも小さい場合にのみ、これは便利です。[/ja] */ /** * @attribute item-width * @type {String} * @description * [en]ons-carousel-item's width. Only works when the direction is set to "horizontal".[/en] * [ja]ons-carousel-itemの幅を指定します。この属性は、direction属性に"horizontal"を指定した時のみ有効になります。[/ja] */ /** * @attribute item-height * @type {String} * @description * [en]ons-carousel-item's height. Only works when the direction is set to "vertical".[/en] * [ja]ons-carousel-itemの高さを指定します。この属性は、direction属性に"vertical"を指定した時のみ有効になります。[/ja] */ /** * @attribute auto-scroll * @description * [en]If this attribute is set the carousel will be automatically scrolled to the closest item border when released.[/en] * [ja]この属性がある時、一番近いcarousel-itemの境界まで自動的にスクロールするようになります。[/ja] */ /** * @attribute auto-scroll-ratio * @type {Number} * @description * [en]A number between 0.0 and 1.0 that specifies how much the user must drag the carousel in order for it to auto scroll to the next item.[/en] * [ja]0.0から1.0までの値を指定します。カルーセルの要素をどれぐらいの割合までドラッグすると次の要素に自動的にスクロールするかを指定します。[/ja] */ /** * @attribute swipeable * @description * [en]If this attribute is set the carousel can be scrolled by drag or swipe.[/en] * [ja]この属性がある時、カルーセルをスワイプやドラッグで移動できるようになります。[/ja] */ /** * @attribute disabled * @description * [en]If this attribute is set the carousel is disabled.[/en] * [ja]この属性がある時、dragやtouchやswipeを受け付けなくなります。[/ja] */ /** * @attribute initial-index * @initonly * @default 0 * @type {Number} * @description * [en]Specify the index of the ons-carousel-item to show initially. Default is 0.[/en] * [ja]最初に表示するons-carousel-itemを0始まりのインデックスで指定します。デフォルト値は 0 です。[/ja] */ /** * @attribute auto-refresh * @description * [en]When this attribute is set the carousel will automatically refresh when the number of child nodes change.[/en] * [ja]この属性がある時、子要素の数が変わるとカルーセルは自動的に更新されるようになります。[/ja] */ /** * @attribute animation * @type {String} * @description * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en] * [ja][/ja] */ /** * @attribute animation-options * @type {Expression} * @description * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。例:{duration: 0.2, delay: 1, timing: 'ease-in'}[/ja] */ function CarouselElement() { classCallCheck(this, CarouselElement); var _this = possibleConstructorReturn(this, (CarouselElement.__proto__ || Object.getPrototypeOf(CarouselElement)).call(this)); contentReady(_this, function () { return _this._compile(); }); return _this; } createClass(CarouselElement, [{ key: '_compile', value: function _compile() { var target = this.children[0] && this.children[0].tagName !== 'ONS-CAROUSEL-ITEM' && this.children[0] || document.createElement('div'); if (!target.parentNode) { while (this.firstChild) { target.appendChild(this.firstChild); } this.appendChild(target); } !this.children[1] && this.appendChild(document.createElement('div')); this.appendChild = this.appendChild.bind(target); this.insertBefore = this.insertBefore.bind(target); } }, { key: 'connectedCallback', value: function connectedCallback() { var _this2 = this; if (!this._swiper) { this._swiper = new Swiper({ getElement: function getElement() { return _this2; }, getInitialIndex: function getInitialIndex() { return _this2.getAttribute('initial-index'); }, getAutoScrollRatio: function getAutoScrollRatio() { return _this2.autoScrollRatio; }, isVertical: function isVertical() { return _this2.vertical; }, isOverScrollable: function isOverScrollable() { return _this2.overscrollable; }, isCentered: function isCentered() { return _this2.centered; }, isAutoScrollable: function isAutoScrollable() { return _this2.autoScroll; }, itemSize: this.itemSize, overScrollHook: this._onOverScroll.bind(this), preChangeHook: this._onChange.bind(this, 'prechange'), postChangeHook: this._onChange.bind(this, 'postchange'), refreshHook: this._onRefresh.bind(this), scrollHook: function scrollHook() { return _this2._onSwipe && _this2._onSwipe.apply(_this2, arguments); } }); contentReady(this, function () { return _this2._swiper.init({ swipeable: _this2.hasAttribute('swipeable'), autoRefresh: _this2.hasAttribute('auto-refresh') }); }); } } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { if (this._swiper && this._swiper.initialized) { this._swiper.dispose(); this._swiper = null; } } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (!this._swiper) { return; } switch (name) { case 'swipeable': this._swiper.updateSwipeable(this.hasAttribute('swipeable')); break; case 'auto-refresh': this._swiper.updateAutoRefresh(this.hasAttribute('auto-refresh')); break; case 'item-height': this.vertical && this._swiper.updateItemSize(this.itemSize); break; case 'item-width': this.vertical || this._swiper.updateItemSize(this.itemSize); break; case 'direction': this._swiper.refresh(); } } }, { key: '_show', value: function _show() { this._swiper.show(); } }, { key: '_hide', value: function _hide() { this._swiper.hide(); } }, { key: '_onOverScroll', value: function _onOverScroll(_ref) { var direction = _ref.direction, killOverScroll = _ref.killOverScroll; var waitForAction = false; util$1.triggerElementEvent(this, 'overscroll', { carousel: this, activeIndex: this.getActiveIndex(), direction: direction, waitToReturn: function waitToReturn(promise) { waitForAction = true; promise.then(killOverScroll); } }); return waitForAction; } }, { key: '_onChange', value: function _onChange(eventName, _ref2) { var activeIndex = _ref2.activeIndex, lastActiveIndex = _ref2.lastActiveIndex; util$1.triggerElementEvent(this, eventName, { carousel: this, activeIndex: activeIndex, lastActiveIndex: lastActiveIndex }); } }, { key: '_onRefresh', value: function _onRefresh() { util$1.triggerElementEvent(this, 'refresh', { carousel: this }); } /** * @method setActiveIndex * @signature setActiveIndex(index, [options]) * @param {Number} index * [en]The index that the carousel should be set to.[/en] * [ja]carousel要素のインデックスを指定します。[/ja] * @param {Object} [options] * [en]Parameter object.[/en] * [ja][/ja] * @param {Function} [options.callback] * [en]A function that will be called after the animation is finished.[/en] * [ja][/ja] * @param {String} [options.animation] * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en] * [ja][/ja] * @param {Object} [options.animationOptions] * [en]An object that can be used to specify duration, delay and timing function of the animation.[/en] * [ja][/ja] * @description * [en]Specify the index of the `<ons-carousel-item>` to show.[/en] * [ja]表示するons-carousel-itemをindexで指定します。[/ja] * @return {Promise} * [en]Resolves to the carousel element.[/en] * [ja][/ja] */ }, { key: 'setActiveIndex', value: function setActiveIndex(index) { var _this3 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; options = _extends({ animation: this.getAttribute('animation'), animationOptions: this.hasAttribute('animation-options') ? util$1.animationOptionsParse(this.getAttribute('animation-options')) : { duration: .3, timing: 'cubic-bezier(.4, .7, .5, 1)' } }, options); return this._swiper.setActiveIndex(index, options).then(function () { options.callback instanceof Function && options.callback(_this3); return Promise.resolve(_this3); }); } /** * @method getActiveIndex * @signature getActiveIndex() * @return {Number} * [en]The current carousel item index.[/en] * [ja]現在表示しているカルーセル要素のインデックスが返されます。[/ja] * @description * [en]Returns the index of the currently visible `<ons-carousel-item>`.[/en] * [ja]現在表示されているons-carousel-item要素のインデックスを返します。[/ja] */ }, { key: 'getActiveIndex', value: function getActiveIndex() { return this._swiper.getActiveIndex(); } /** * @method next * @signature next([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja][/ja] * @param {Function} [options.callback] * [en]A function that will be executed after the animation has finished.[/en] * [ja][/ja] * @param {String} [options.animation] * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en] * [ja][/ja] * @param {Object} [options.animationOptions] * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en] * [ja][/ja] * @return {Promise} * [en]Resolves to the carousel element[/en] * [ja][/ja] * @description * [en]Show next `<ons-carousel-item>`.[/en] * [ja]次のons-carousel-itemを表示します。[/ja] */ }, { key: 'next', value: function next(options) { return this.setActiveIndex(this.getActiveIndex() + 1, options); } /** * @method prev * @signature prev([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja][/ja] * @param {Function} [options.callback] * [en]A function that will be executed after the animation has finished.[/en] * [ja][/ja] * @param {String} [options.animation] * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en] * [ja][/ja] * @param {Object} [options.animationOptions] * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en] * [ja][/ja] * @return {Promise} * [en]Resolves to the carousel element[/en] * [ja][/ja] * @description * [en]Show previous `<ons-carousel-item>`.[/en] * [ja]前のons-carousel-itemを表示します。[/ja] */ }, { key: 'prev', value: function prev(options) { return this.setActiveIndex(this.getActiveIndex() - 1, options); } /** * @method first * @signature first() * @param {Object} [options] * [en]Parameter object.[/en] * [ja][/ja] * @param {Function} [options.callback] * [en]A function that will be executed after the animation has finished.[/en] * [ja][/ja] * @param {String} [options.animation] * [en]If this is set to `"none"`, the transitions will not be animated.[/en] * [ja][/ja] * @param {Object} [options.animationOptions] * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en] * [ja][/ja] * @return {Promise} * [en]Resolves to the carousel element[/en] * [ja][/ja] * @description * [en]Show first `<ons-carousel-item>`.[/en] * [ja]最初のons-carousel-itemを表示します。[/ja] */ }, { key: 'first', value: function first(options) { return this.setActiveIndex(0, options); } /** * @method last * @signature last() * @param {Object} [options] * [en]Parameter object.[/en] * [ja][/ja] * @param {Function} [options.callback] * [en]A function that will be executed after the animation has finished.[/en] * [ja][/ja] * @param {String} [options.animation] * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en] * [ja][/ja] * @param {Object} [options.animationOptions] * [en]An object that can be used to specify the duration, delay and timing function of the animation.[/en] * [ja][/ja] * @return {Promise} * [en]Resolves to the carousel element[/en] * [ja]Resolves to the carousel element[/ja] * @description * [en]Show last ons-carousel item.[/en] * [ja]最後のons-carousel-itemを表示します。[/ja] */ }, { key: 'last', value: function last(options) { this.setActiveIndex(Math.max(this.itemCount - 1, 0), options); } /** * @method refresh * @signature refresh() * @description * [en]Update the layout of the carousel. Used when adding `<ons-carousel-items>` dynamically or to automatically adjust the size.[/en] * [ja]レイアウトや内部の状態を最新のものに更新します。ons-carousel-itemを動的に増やしたり、ons-carouselの大きさを動的に変える際に利用します。[/ja] */ }, { key: 'refresh', value: function refresh() { this._swiper.refresh(); } /** * @property itemCount * @readonly * @type {Number} * @description * [en]The number of carousel items.[/en] * [ja]カルーセル要素の数です。[/ja] */ }, { key: 'itemCount', get: function get$$1() { return this._swiper.itemCount; } /** * @property swipeable * @type {Boolean} * @description * [en]true if the carousel is swipeable.[/en] * [ja]swipeableであればtrueを返します。[/ja] */ }, { key: 'swipeable', get: function get$$1() { return this.hasAttribute('swipeable'); }, set: function set$$1(value) { return util$1.toggleAttribute(this, 'swipeable', value); } /** * @property onSwipe * @type {Function} * @description * [en]Hook called whenever the user slides the carousel. It gets a decimal index and an animationOptions object as arguments.[/en] * [ja][/ja] */ }, { key: 'onSwipe', get: function get$$1() { return this._onSwipe; }, set: function set$$1(value) { if (value && !(value instanceof Function)) { util$1.throw('"onSwipe" must be a function'); } this._onSwipe = value; } /** * @property autoScroll * @type {Boolean} * @description * [en]true if auto scroll is enabled.[/en] * [ja]オートスクロールが有効であればtrueを返します。[/ja] */ }, { key: 'autoScroll', get: function get$$1() { return this.hasAttribute('auto-scroll'); }, set: function set$$1(value) { return util$1.toggleAttribute(this, 'auto-scroll', value); } }, { key: 'vertical', get: function get$$1() { return this.getAttribute('direction') === 'vertical'; } }, { key: 'itemSize', get: function get$$1() { var itemSizeAttr = (this.getAttribute('item-' + (this.vertical ? 'height' : 'width')) || '').trim(); return itemSizeAttr.match(/^\d+(px|%)$/) ? itemSizeAttr : '100%'; } /** * @property autoScrollRatio * @type {Number} * @description * [en]The current auto scroll ratio. [/en] * [ja]現在のオートスクロールのratio値。[/ja] */ }, { key: 'autoScrollRatio', get: function get$$1() { return parseFloat(this.getAttribute('auto-scroll-ratio')); }, set: function set$$1(ratio) { this.setAttribute('auto-scroll-ratio', ratio); } /** * @property disabled * @type {Boolean} * @description * [en]Whether the carousel is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ }, { key: 'disabled', get: function get$$1() { return this.hasAttribute('disabled'); }, set: function set$$1(value) { return util$1.toggleAttribute(this, 'disabled', value); } /** * @property overscrollable * @type {Boolean} * @description * [en]Whether the carousel is overscrollable or not.[/en] * [ja]overscrollできればtrueを返します。[/ja] */ }, { key: 'overscrollable', get: function get$$1() { return this.hasAttribute('overscrollable'); }, set: function set$$1(value) { return util$1.toggleAttribute(this, 'overscrollable', value); } /** * @property centered * @type {Boolean} * @description * [en]Whether the carousel is centered or not.[/en] * [ja]centered状態になっていればtrueを返します。[/ja] */ }, { key: 'centered', get: function get$$1() { return this.hasAttribute('centered'); }, set: function set$$1(value) { return util$1.toggleAttribute(this, 'centered', value); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['swipeable', 'auto-refresh', 'direction', 'item-height', 'item-width']; } }, { key: 'events', get: function get$$1() { return ['postchange', 'refresh', 'overscroll']; } }]); return CarouselElement; }(BaseElement); onsElements.Carousel = CarouselElement; customElements.define('ons-carousel', CarouselElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-col * @category grid * @description * [en]Represents a column in the grid system. Use with `<ons-row>` to layout components.[/en] * [ja]グリッドシステムにて列を定義します。ons-rowとともに使用し、コンポーネントのレイアウトに利用します。[/ja] * @note * [en]For Android 4.3 and earlier, and iOS6 and earlier, when using mixed alignment with ons-row and ons-column, they may not be displayed correctly. You can use only one alignment.[/en] * [ja]Android 4.3以前、もしくはiOS 6以前のOSの場合、ons-rowとons-columnを組み合わせた場合に描画が崩れる場合があります。[/ja] * @codepen GgujC {wide} * @guide theming.html [en]Layouting guide[/en][ja]レイアウト機能[/ja] * @seealso ons-row * [en]The `<ons-row>` component is the parent of `<ons-col>`.[/en] * [ja]ons-rowコンポーネント[/ja] * @example * <ons-row> * <ons-col width="50px"><ons-icon icon="fa-twitter"></ons-icon></ons-col> * <ons-col>Text</ons-col> * </ons-row> */ /** * @attribute vertical-align * @type {String} * @description * [en]Vertical alignment of the column. Valid values are "top", "center", and "bottom".[/en] * [ja]縦の配置を指定する。"top", "center", "bottom"のいずれかを指定します。[/ja] */ /** * @attribute width * @type {String} * @description * [en]The width of the column. Valid values are css width values ("10%", "50px").[/en] * [ja]カラムの横幅を指定する。パーセントもしくはピクセルで指定します(10%や50px)。[/ja] */ var ColElement = function (_BaseElement) { inherits(ColElement, _BaseElement); function ColElement() { classCallCheck(this, ColElement); var _this = possibleConstructorReturn(this, (ColElement.__proto__ || Object.getPrototypeOf(ColElement)).call(this)); if (_this.getAttribute('width')) { _this._updateWidth(); } return _this; } createClass(ColElement, [{ key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'width') { this._updateWidth(); } } }, { key: '_updateWidth', value: function _updateWidth() { var width = this.getAttribute('width'); if (!width) { styler.clear(this, 'flex maxWidth'); } else { width = width.trim().match(/^\d+$/) ? width + '%' : width; styler(this, { flex: '0 0 ' + width, maxWidth: width }); } } }], [{ key: 'observedAttributes', get: function get$$1() { return ['width']; } }]); return ColElement; }(BaseElement); onsElements.Col = ColElement; customElements.define('ons-col', ColElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var DialogAnimator = function (_BaseAnimator) { inherits(DialogAnimator, _BaseAnimator); function DialogAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'linear' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.2 : _ref$duration; classCallCheck(this, DialogAnimator); return possibleConstructorReturn(this, (DialogAnimator.__proto__ || Object.getPrototypeOf(DialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } /** * @param {HTMLElement} dialog * @param {Function} done */ createClass(DialogAnimator, [{ key: 'show', value: function show(dialog, done) { done(); } /** * @param {HTMLElement} dialog * @param {Function} done */ }, { key: 'hide', value: function hide(dialog, done) { done(); } }]); return DialogAnimator; }(BaseAnimator); /** * Android style animator for dialog. */ var AndroidDialogAnimator = function (_DialogAnimator) { inherits(AndroidDialogAnimator, _DialogAnimator); function AndroidDialogAnimator() { var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref2$timing = _ref2.timing, timing = _ref2$timing === undefined ? 'ease-in-out' : _ref2$timing, _ref2$delay = _ref2.delay, delay = _ref2$delay === undefined ? 0 : _ref2$delay, _ref2$duration = _ref2.duration, duration = _ref2$duration === undefined ? 0.3 : _ref2$duration; classCallCheck(this, AndroidDialogAnimator); return possibleConstructorReturn(this, (AndroidDialogAnimator.__proto__ || Object.getPrototypeOf(AndroidDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } /** * @param {Object} dialog * @param {Function} callback */ createClass(AndroidDialogAnimator, [{ key: 'show', value: function show(dialog, callback) { callback = callback ? callback : function () {}; Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 0 }, { opacity: 1 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -60%, 0)', opacity: 0 }, { transform: 'translate3d(-50%, -50%, 0)', opacity: 1 }).queue(function (done) { callback(); done(); })); } /** * @param {Object} dialog * @param {Function} callback */ }, { key: 'hide', value: function hide(dialog, callback) { callback = callback ? callback : function () {}; Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0)', opacity: 1 }, { transform: 'translate3d(-50%, -60%, 0)', opacity: 0 }).queue(function (done) { callback(); done(); })); } }]); return AndroidDialogAnimator; }(DialogAnimator); /** * iOS style animator for dialog. */ var IOSDialogAnimator = function (_DialogAnimator2) { inherits(IOSDialogAnimator, _DialogAnimator2); function IOSDialogAnimator() { var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref3$timing = _ref3.timing, timing = _ref3$timing === undefined ? 'ease-in-out' : _ref3$timing, _ref3$delay = _ref3.delay, delay = _ref3$delay === undefined ? 0 : _ref3$delay, _ref3$duration = _ref3.duration, duration = _ref3$duration === undefined ? 0.2 : _ref3$duration; classCallCheck(this, IOSDialogAnimator); var _this3 = possibleConstructorReturn(this, (IOSDialogAnimator.__proto__ || Object.getPrototypeOf(IOSDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); _this3.bodyHeight = document.body.clientHeight; // avoid Forced Synchronous Layout return _this3; } /** * @param {Object} dialog * @param {Function} callback */ createClass(IOSDialogAnimator, [{ key: 'show', value: function show(dialog, callback) { callback = callback ? callback : function () {}; Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 0 }, { opacity: 1 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, ' + (this.bodyHeight / 2.0 - 1) + 'px, 0)' }, { transform: 'translate3d(-50%, -50%, 0)' }).queue(function (done) { callback(); done(); })); } /** * @param {Object} dialog * @param {Function} callback */ }, { key: 'hide', value: function hide(dialog, callback) { callback = callback ? callback : function () {}; Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0)' }, { transform: 'translate3d(-50%, ' + (this.bodyHeight / 2.0 - 1) + 'px, 0)' }).queue(function (done) { callback(); done(); })); } }]); return IOSDialogAnimator; }(DialogAnimator); /** * Slide animator for dialog. */ var SlideDialogAnimator = function (_DialogAnimator3) { inherits(SlideDialogAnimator, _DialogAnimator3); function SlideDialogAnimator() { var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref4$timing = _ref4.timing, timing = _ref4$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref4$timing, _ref4$delay = _ref4.delay, delay = _ref4$delay === undefined ? 0 : _ref4$delay, _ref4$duration = _ref4.duration, duration = _ref4$duration === undefined ? 0.2 : _ref4$duration; classCallCheck(this, SlideDialogAnimator); var _this4 = possibleConstructorReturn(this, (SlideDialogAnimator.__proto__ || Object.getPrototypeOf(SlideDialogAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); _this4.bodyHeight = document.body.clientHeight; // avoid Forced Synchronous Layout return _this4; } /** * @param {Object} dialog * @param {Function} callback */ createClass(SlideDialogAnimator, [{ key: 'show', value: function show(dialog, callback) { callback = callback ? callback : function () {}; Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 0 }, { opacity: 1 }), Animit(dialog._dialog, this.def).default( // FIXME: This should avoid Forced Synchronous Layout. Otherwise, fade animation of mask will be broken. { transform: 'translate3d(-50%, ' + (-(this.bodyHeight / 2.0) + 1 - dialog._dialog.clientHeight) + 'px, 0)' }, { transform: 'translate3d(-50%, -50%, 0)' }).queue(function (done) { callback(); done(); })); } /** * @param {Object} dialog * @param {Function} callback */ }, { key: 'hide', value: function hide(dialog, callback) { callback = callback ? callback : function () {}; Animit.runAll(Animit(dialog._mask, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(dialog._dialog, this.def).default({ transform: 'translate3d(-50%, -50%, 0)' }, // FIXME: This should avoid Forced Synchronous Layout. Otherwise, fade animation of mask will be broken. { transform: 'translate3d(-50%, ' + (-(this.bodyHeight / 2.0) + 1 - dialog._dialog.clientHeight) + 'px, 0)' }).queue(function (done) { callback(); done(); })); } }]); return SlideDialogAnimator; }(DialogAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$6 = { '.dialog': 'dialog--*', '.dialog-container': 'dialog-container--*', '.dialog-mask': 'dialog-mask--*' }; var _animatorDict$2 = { 'default': function _default() { return platform.isAndroid() ? AndroidDialogAnimator : IOSDialogAnimator; }, 'slide': SlideDialogAnimator, 'none': DialogAnimator }; /** * @element ons-dialog * @category dialog * @description * [en] * Dialog that is displayed on top of current screen. As opposed to the `<ons-alert-dialog>` element, this component can contain any kind of content. * * To use the element it can either be attached directly to the `<body>` element or dynamically created from a template using the `ons.createDialog(template)` utility function and the `<template>` tag. * * The dialog is useful for displaying menus, additional information or to ask the user to make a decision. * * It will automatically be displayed as Material Design when running on an Android device. * [/en] * [ja][/ja] * @modifier material * [en]Display a Material Design dialog.[/en] * [ja]マテリアルデザインのダイアログを表示します。[/ja] * @codepen zxxaGa * @tutorial vanilla/Reference/dialog * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @seealso ons-alert-dialog * [en]`<ons-alert-dialog>` component[/en] * [ja]ons-alert-dialogコンポーネント[/ja] * @seealso ons-popover * [en]`<ons-popover>` component[/en] * [ja]ons-popoverコンポーネント[/ja] * @seealso ons-modal * [en]`<ons-modal>` component[/en] * [ja]ons-modalコンポーネント[/ja] * @example * <ons-dialog id="dialog"> * <p>This is a dialog!</p> * </ons-dialog> * * <script> * document.getElementById('dialog').show(); * </script> */ var DialogElement = function (_BaseDialogElement) { inherits(DialogElement, _BaseDialogElement); /** * @event preshow * @description * [en]Fired just before the dialog is displayed.[/en] * [ja]ダイアログが表示される直前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.dialog * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Execute this function to stop the dialog from being shown.[/en] * [ja]この関数を実行すると、ダイアログの表示がキャンセルされます。[/ja] */ /** * @event postshow * @description * [en]Fired just after the dialog is displayed.[/en] * [ja]ダイアログが表示された直後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.dialog * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @event prehide * @description * [en]Fired just before the dialog is hidden.[/en] * [ja]ダイアログが隠れる直前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.dialog * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Execute this function to stop the dialog from being hidden.[/en] * [ja]この関数を実行すると、ダイアログの非表示がキャンセルされます。[/ja] */ /** * @event posthide * @description * [en]Fired just after the dialog is hidden.[/en] * [ja]ダイアログが隠れた後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.dialog * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @attribute modifier * @type {String} * @description * [en]The appearance of the dialog.[/en] * [ja]ダイアログの表現を指定します。[/ja] */ /** * @attribute cancelable * @description * [en]If this attribute is set the dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en] * [ja][/ja] */ /** * @attribute disabled * @description * [en]If this attribute is set the dialog is disabled.[/en] * [ja]この属性がある時、ダイアログはdisabled状態になります。[/ja] */ /** * @attribute animation * @type {String} * @default default * @description * [en]The animation used when showing and hiding the dialog. Can be either `"none"` or `"default"`.[/en] * [ja]ダイアログを表示する際のアニメーション名を指定します。"none"もしくは"default"を指定できます。[/ja] */ /** * @attribute animation-options * @type {Expression} * @description * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/ja] */ /** * @attribute mask-color * @type {String} * @default rgba(0, 0, 0, 0.2) * @description * [en]Color of the background mask. Default is `"rgba(0, 0, 0, 0.2)"`.[/en] * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja] */ function DialogElement() { classCallCheck(this, DialogElement); var _this = possibleConstructorReturn(this, (DialogElement.__proto__ || Object.getPrototypeOf(DialogElement)).call(this)); contentReady(_this, function () { return _this._compile(); }); return _this; } createClass(DialogElement, [{ key: '_updateAnimatorFactory', value: function _updateAnimatorFactory() { return new AnimatorFactory({ animators: _animatorDict$2, baseClass: DialogAnimator, baseClassName: 'DialogAnimator', defaultAnimation: this.getAttribute('animation') }); } }, { key: '_compile', value: function _compile() { autoStyle.prepare(this); this.style.display = 'none'; this.style.zIndex = 10001; /* Expected result: * <ons-dialog> * <div class="dialog-mask"></div> * <div class="dialog"> * <div class="dialog-container">...</div> * </div> * </ons-dialog> */ if (!this._dialog) { var dialog = document.createElement('div'); dialog.classList.add('dialog'); var container = document.createElement('div'); container.classList.add('dialog-container'); while (this.firstChild) { container.appendChild(this.firstChild); } dialog.appendChild(container); this.appendChild(dialog); } if (!this._mask) { var mask = document.createElement('div'); mask.classList.add('dialog-mask'); this.insertBefore(mask, this.firstChild); } this._dialog.style.zIndex = 20001; this._mask.style.zIndex = 20000; this.setAttribute('status-bar-fill', ''); ModifierUtil.initModifier(this, this._scheme); } /** * @property onDeviceBackButton * @type {Object} * @description * [en]Back-button handler.[/en] * [ja]バックボタンハンドラ。[/ja] */ /** * @method show * @signature show([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"none"` and `"slide"`.[/en] * [ja]アニメーション名を指定します。"none", "slide"のいずれかを指定します。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja] * @param {Function} [options.callback] * [en]This function is called after the dialog has been revealed.[/en] * [ja]ダイアログが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Show the dialog.[/en] * [ja]ダイアログを開きます。[/ja] * @return {Promise} Resolves to the displayed element. */ /** * @method hide * @signature hide([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"none"` and `"slide"`.[/en] * [ja]アニメーション名を指定します。"none", "slide"のいずれかを指定できます。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/ja] * @param {Function} [options.callback] * [en]This functions is called after the dialog has been hidden.[/en] * [ja]ダイアログが隠れた後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Hide the dialog.[/en] * [ja]ダイアログを閉じます。[/ja] * @return {Promise} * [en]Resolves to the hidden element[/en] * [ja][/ja] */ /** * @property visible * @readonly * @type {Boolean} * @description * [en]Whether the dialog is visible or not.[/en] * [ja]要素が見える場合に`true`。[/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the dialog is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ /** * @property cancelable * @type {Boolean} * @description * [en]Whether the dialog is cancelable or not. A cancelable dialog can be closed by tapping the background or by pressing the back button on Android devices.[/en] * [ja][/ja] */ /** * @param {String} name * @param {DialogAnimator} Animator */ }, { key: '_scheme', get: function get$$1() { return scheme$6; } }, { key: '_mask', get: function get$$1() { return util$1.findChild(this, '.dialog-mask'); } }, { key: '_dialog', get: function get$$1() { return util$1.findChild(this, '.dialog'); } }], [{ key: 'registerAnimator', value: function registerAnimator(name, Animator) { if (!(Animator.prototype instanceof DialogAnimator)) { util$1.throwAnimator('Dialog'); } _animatorDict$2[name] = Animator; } }, { key: 'animators', get: function get$$1() { return _animatorDict$2; } }, { key: 'DialogAnimator', get: function get$$1() { return DialogAnimator; } }]); return DialogElement; }(BaseDialogElement); onsElements.Dialog = DialogElement; customElements.define('ons-dialog', DialogElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$3 = 'fab'; var scheme$7 = { '': 'fab--*', '.fab__icon': 'fab--*__icon' }; /** * @element ons-fab * @category form * @description * [en] * The Floating action button is a circular button defined in the [Material Design specification](https://www.google.com/design/spec/components/buttons-floating-action-button.html). They are often used to promote the primary action of the app. * * It can be displayed either as an inline element or in one of the corners. Normally it will be positioned in the lower right corner of the screen. * [/en] * [ja][/ja] * @tutorial vanilla/Reference/fab * @modifier mini * [en]Makes the `ons-fab` smaller.[/en] * [ja][/ja] * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja] * @seealso ons-speed-dial * [en]The `<ons-speed-dial>` component is a Floating action button that displays a menu when tapped.[/en] * [ja][/ja] */ var FabElement = function (_BaseElement) { inherits(FabElement, _BaseElement); /** * @attribute modifier * @type {String} * @description * [en]The appearance of the button.[/en] * [ja]ボタンの表現を指定します。[/ja] */ /** * @attribute ripple * @description * [en]If this attribute is defined, the button will have a ripple effect when tapped.[/en] * [ja][/ja] */ /** * @attribute position * @type {String} * @description * [en]The position of the button. Should be a string like `"bottom right"` or `"top left"`. If this attribute is not defined it will be displayed as an inline element.[/en] * [ja][/ja] */ /** * @attribute disabled * @description * [en]Specify if button should be disabled.[/en] * [ja]ボタンを無効化する場合は指定します。[/ja] */ function FabElement() { classCallCheck(this, FabElement); // The following statements can be executed before contentReady // since these do not access the children var _this = possibleConstructorReturn(this, (FabElement.__proto__ || Object.getPrototypeOf(FabElement)).call(this)); _this._hide(); _this.classList.add(defaultClassName$3); contentReady(_this, function () { _this._compile(); }); return _this; } createClass(FabElement, [{ key: '_compile', value: function _compile() { autoStyle.prepare(this); if (!util$1.findChild(this, '.fab__icon')) { var content = document.createElement('span'); content.classList.add('fab__icon'); util$1.arrayFrom(this.childNodes).forEach(function (element) { if (!element.tagName || element.tagName.toLowerCase() !== 'ons-ripple') { content.appendChild(element); } }); this.appendChild(content); } this._updateRipple(); ModifierUtil.initModifier(this, scheme$7); this._updatePosition(); } }, { key: 'connectedCallback', value: function connectedCallback() { var _this2 = this; setImmediate(function () { return _this2._show(); }); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$3, scheme$7); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$7); break; case 'ripple': this._updateRipple(); break; case 'position': this._updatePosition(); break; } } }, { key: '_show', value: function _show() { if (!this._manuallyHidden) { // if user has not called ons-fab.hide() this._toggle(true); } } }, { key: '_hide', value: function _hide() { var _this3 = this; setImmediate(function () { return _this3._toggle(false); }); } }, { key: '_updateRipple', value: function _updateRipple() { util$1.updateRipple(this); } }, { key: '_updatePosition', value: function _updatePosition() { var position = this.getAttribute('position'); this.classList.remove('fab--top__left', 'fab--bottom__right', 'fab--bottom__left', 'fab--top__right', 'fab--top__center', 'fab--bottom__center'); switch (position) { case 'top right': case 'right top': this.classList.add('fab--top__right'); break; case 'top left': case 'left top': this.classList.add('fab--top__left'); break; case 'bottom right': case 'right bottom': this.classList.add('fab--bottom__right'); break; case 'bottom left': case 'left bottom': this.classList.add('fab--bottom__left'); break; case 'center top': case 'top center': this.classList.add('fab--top__center'); break; case 'center bottom': case 'bottom center': this.classList.add('fab--bottom__center'); break; default: break; } } /** * @method show * @signature show() * @description * [en]Show the floating action button.[/en] * [ja][/ja] */ }, { key: 'show', value: function show() { this.toggle(true); } /** * @method hide * @signature hide() * @description * [en]Hide the floating action button.[/en] * [ja][/ja] */ }, { key: 'hide', value: function hide() { this.toggle(false); } /** * @method toggle * @signature toggle() * @description * [en]Toggle the visibility of the button.[/en] * [ja][/ja] */ }, { key: 'toggle', value: function toggle() { var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : !this.visible; this._manuallyHidden = !action; this._toggle(action); } }, { key: '_toggle', value: function _toggle() { var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : !this.visible; var isBottom = (this.getAttribute('position') || '').indexOf('bottom') >= 0; var translate = isBottom ? 'translate3d(0px, -' + (util$1.globals.fabOffset || 0) + 'px, 0px)' : ''; styler(this, { transform: translate + ' scale(' + Number(action) + ')' }); } /** * @property disabled * @type {Boolean} * @description * [en]Whether the element is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ }, { key: 'disabled', set: function set$$1(value) { return util$1.toggleAttribute(this, 'disabled', value); }, get: function get$$1() { return this.hasAttribute('disabled'); } /** * @property visible * @readonly * @type {Boolean} * @description * [en]Whether the element is visible or not.[/en] * [ja]要素が見える場合に`true`。[/ja] */ }, { key: 'visible', get: function get$$1() { return this.style.transform.indexOf('scale(0)') === -1 && this.style.display !== 'none'; } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'ripple', 'position', 'class']; } }]); return FabElement; }(BaseElement); onsElements.Fab = FabElement; customElements.define('ons-fab', FabElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-gesture-detector * @category gesture * @description * [en] * Component to detect finger gestures within the wrapped element. Following gestures are supported: * - Drag gestures: `drag`, `dragleft`, `dragright`, `dragup`, `dragdown` * - Hold gestures: `hold`, `release` * - Swipe gestures: `swipe`, `swipeleft`, `swiperight`, `swipeup`, `swipedown` * - Tap gestures: `tap`, `doubletap` * - Pinch gestures: `pinch`, `pinchin`, `pinchout` * - Other gestures: `touch`, `transform`, `rotate` * [/en] * [ja]要素内のジェスチャー操作を検知します。詳しくはガイドを参照してください。[/ja] * @guide features.html#gesture-detection * [en]Detecting finger gestures[/en] * [ja]ジェスチャー操作の検知[/ja] * @example * <ons-gesture-detector> * <div id="detect-area" style="width: 100px; height: 100px;"> * Swipe Here * </div> * </ons-gesture-detector> * * <script> * document.addEventListener('swipeleft', function(event) { * if (event.target.matches('#detect-area')) { * console.log('Swipe left is detected.'); * } * }); * </script> */ var GestureDetectorElement = function (_BaseElement) { inherits(GestureDetectorElement, _BaseElement); function GestureDetectorElement() { classCallCheck(this, GestureDetectorElement); var _this = possibleConstructorReturn(this, (GestureDetectorElement.__proto__ || Object.getPrototypeOf(GestureDetectorElement)).call(this)); _this._gestureDetector = new GestureDetector(_this, { passive: true }); return _this; } return GestureDetectorElement; }(BaseElement); onsElements.GestureDetector = GestureDetectorElement; customElements.define('ons-gesture-detector', GestureDetectorElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var autoPrefix = 'fa'; // FIXME: To be removed in v3 /** * @element ons-icon * @category visual * @description * [en] * Displays an icon. The following icon suites are available: * * * [Font Awesome](https://fortawesome.github.io/Font-Awesome/) * * [Ionicons](http://ionicons.com/) * * [Material Design Iconic Font](http://zavoloklom.github.io/material-design-iconic-font/) * [/en] * [ja][/ja] * @codepen xAhvg * @tutorial vanilla/Reference/icon * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja][/ja] * @guide appsize.html#removing-icon-packs [en]Removing icon packs.[/en][ja][/ja] * @guide faq.html#how-can-i-use-custom-icon-packs [en]Adding custom icon packs.[/en][ja][/ja] * @example * <ons-icon * icon="md-car" * size="20px" * style="color: red"> * </ons-icon> * * <ons-button> * <ons-icon icon="md-car"></ons-icon> * Car * </ons-button> */ var IconElement = function (_BaseElement) { inherits(IconElement, _BaseElement); /** * @attribute icon * @type {String} * @description * [en] * The icon name. `"md-"` prefix for Material Icons, `"fa-"` for Font Awesome and `"ion-"` prefix for Ionicons. * * See all available icons on the element description (at the top). * * Icons can also be styled based on modifier presence. Add comma-separated icons with `"modifierName:"` prefix. * * The code `<ons-icon icon="ion-edit, material:md-edit"></ons-icon>` will display `"md-edit"` for Material Design and `"ion-edit"` as the default icon. * * `fa-` prefix is added automatically if none is provided. Check [See also](#seealso) section for more information. * [/en] * [ja][/ja] */ /** * @attribute size * @type {String} * @description * [en] * The sizes of the icon. Valid values are lg, 2x, 3x, 4x, 5x, or in the size in pixels. * Icons can also be styled based on modifier presence. Add comma-separated icons with `"modifierName:"` prefix. * * The code: * * ``` * <ons-icon * icon="ion-edit" * size="32px, material:24px"> * </ons-icon> * ``` * * will render as a `24px` icon if the `"material"` modifier is present and `32px` otherwise. * [/en] * [ja][/ja] */ /** * @attribute rotate * @type {Number} * @description * [en]Number of degrees to rotate the icon. Valid values are 90, 180 and 270.[/en] * [ja]アイコンを回転して表示します。90, 180, 270から指定できます。[/ja] */ /** * @attribute fixed-width * @type {Boolean} * @default false * @description * [en]When used in a list, you want the icons to have the same width so that they align vertically by defining this attribute.[/en] * [ja][/ja] */ /** * @attribute spin * @description * [en]Specify whether the icon should be spinning.[/en] * [ja]アイコンを回転するかどうかを指定します。[/ja] */ function IconElement() { classCallCheck(this, IconElement); var _this = possibleConstructorReturn(this, (IconElement.__proto__ || Object.getPrototypeOf(IconElement)).call(this)); contentReady(_this, function () { _this._compile(); }); return _this; } createClass(IconElement, [{ key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { this._cleanClassAttribute(name === 'icon' ? last : this.getAttribute('icon'), name === 'modifier' ? last : undefined); this._update(); } }, { key: '_compile', value: function _compile() { autoStyle.prepare(this); this._update(); } }, { key: '_update', value: function _update() { var _this2 = this; var _buildClassAndStyle2 = this._buildClassAndStyle(this._parseAttr('icon'), this._parseAttr('size')), classList = _buildClassAndStyle2.classList, style = _buildClassAndStyle2.style; util$1.extend(this.style, style); classList.forEach(function (className) { return _this2.classList.add(className); }); } }, { key: '_parseAttr', value: function _parseAttr(attrName) { var modifier = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.getAttribute('modifier') || ''; var attr = this.getAttribute(attrName) || attrName || ''; var parts = attr.split(/\s*,\s*/); var def = parts[0]; var md = parts[1]; md = (md || '').split(/\s*:\s*/); return (modifier && RegExp('(^|\\s+)' + md[0] + '($|\\s+)', 'i').test(modifier) ? md[1] : def) || ''; } /** * Remove unneeded class value. */ }, { key: '_cleanClassAttribute', value: function _cleanClassAttribute(lastIcon, lastModifier) { var _this3 = this; var _prefixIcon2 = this._prefixIcon(this._parseAttr(lastIcon, lastModifier)), className = _prefixIcon2.className, prefix = _prefixIcon2.prefix; var customPrefixRE = className !== prefix ? '|' + prefix + '$|' + prefix + '-' : '|' + className + '$' || ''; var re = new RegExp('^(fa$|fa-|ion-|zmdi$|zmdi-|ons-icon--' + customPrefixRE + ')'); util$1.arrayFrom(this.classList).filter(function (className) { return re.test(className); }).forEach(function (className) { return _this3.classList.remove(className); }); } }, { key: '_prefixIcon', value: function _prefixIcon(iconName) { var className = autoPrefix + (autoPrefix ? '-' : '') + iconName; return { className: className, prefix: className.split('-')[0] }; } }, { key: '_buildClassAndStyle', value: function _buildClassAndStyle(iconName, size) { var classList = ['ons-icon']; var style = {}; // Icon if (iconName.indexOf('ion-') === 0) { classList.push(iconName); classList.push('ons-icon--ion'); } else if (iconName.indexOf('fa-') === 0) { classList.push(iconName); // default icon style to Font Awesome Solid if icon style is not specified already if (!(this.classList.contains('far') || this.classList.contains('fab') || this.classList.contains('fal'))) { classList.push('fa'); } } else if (iconName.indexOf('md-') === 0) { classList.push('zmdi'); classList.push('zmdi-' + iconName.split(/-(.+)?/)[1]); } else { var _prefixIcon3 = this._prefixIcon(iconName), className = _prefixIcon3.className, prefix = _prefixIcon3.prefix; prefix && classList.push(prefix); className && classList.push(className); } // Size if (size.match(/^[1-5]x|lg$/)) { classList.push('ons-icon--' + size); this.style.removeProperty('font-size'); } else { style.fontSize = size; } return { classList: classList, style: style }; } }], [{ key: 'setAutoPrefix', value: function setAutoPrefix(prefix) { autoPrefix = prefix ? typeof prefix === 'string' && prefix || 'fa' : ''; } }, { key: 'observedAttributes', get: function get$$1() { return ['icon', 'size', 'modifier', 'class']; } }]); return IconElement; }(BaseElement); onsElements.Icon = IconElement; customElements.define('ons-icon', IconElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var LazyRepeatDelegate = function () { function LazyRepeatDelegate(userDelegate) { var templateElement = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; classCallCheck(this, LazyRepeatDelegate); if ((typeof userDelegate === 'undefined' ? 'undefined' : _typeof(userDelegate)) !== 'object' || userDelegate === null) { util$1.throw('"delegate" parameter must be an object'); } this._userDelegate = userDelegate; if (!(templateElement instanceof Element) && templateElement !== null) { util$1.throw('"templateElement" parameter must be an instance of Element or null'); } this._templateElement = templateElement; } createClass(LazyRepeatDelegate, [{ key: 'hasRenderFunction', /** * @return {Boolean} */ value: function hasRenderFunction() { return this._userDelegate._render instanceof Function; } /** * @return {void} */ }, { key: '_render', value: function _render() { this._userDelegate._render.apply(this._userDelegate, arguments); } /** * @param {Number} index * @param {Function} done A function that take item object as parameter. */ }, { key: 'loadItemElement', value: function loadItemElement(index, done) { if (this._userDelegate.loadItemElement instanceof Function) { this._userDelegate.loadItemElement(index, done); } else { var element = this._userDelegate.createItemContent(index, this._templateElement); if (!(element instanceof Element)) { util$1.throw('"createItemContent" must return an instance of Element'); } done({ element: element }); } } /** * @return {Number} */ }, { key: 'countItems', value: function countItems() { var count = this._userDelegate.countItems(); if (typeof count !== 'number') { util$1.throw('"countItems" must return a number'); } return count; } /** * @param {Number} index * @param {Object} item * @param {Element} item.element */ }, { key: 'updateItem', value: function updateItem(index, item) { if (this._userDelegate.updateItemContent instanceof Function) { this._userDelegate.updateItemContent(index, item); } } /** * @return {Number} */ }, { key: 'calculateItemHeight', value: function calculateItemHeight(index) { if (this._userDelegate.calculateItemHeight instanceof Function) { var height = this._userDelegate.calculateItemHeight(index); if (typeof height !== 'number') { util$1.throw('"calculateItemHeight" must return a number'); } return height; } return 0; } /** * @param {Number} index * @param {Object} item */ }, { key: 'destroyItem', value: function destroyItem(index, item) { if (this._userDelegate.destroyItem instanceof Function) { this._userDelegate.destroyItem(index, item); } } /** * @return {void} */ }, { key: 'destroy', value: function destroy() { if (this._userDelegate.destroy instanceof Function) { this._userDelegate.destroy(); } this._userDelegate = this._templateElement = null; } }, { key: 'itemHeight', get: function get$$1() { return this._userDelegate.itemHeight; } }]); return LazyRepeatDelegate; }(); /** * This class provide core functions for ons-lazy-repeat. */ var LazyRepeatProvider = function () { /** * @param {Element} wrapperElement * @param {LazyRepeatDelegate} delegate */ function LazyRepeatProvider(wrapperElement, delegate) { classCallCheck(this, LazyRepeatProvider); if (!(delegate instanceof LazyRepeatDelegate)) { util$1.throw('"delegate" parameter must be an instance of LazyRepeatDelegate'); } this._wrapperElement = wrapperElement; this._delegate = delegate; this._insertIndex = this._wrapperElement.children[0] && this._wrapperElement.children[0].tagName === 'ONS-LAZY-REPEAT' ? 1 : 0; if (wrapperElement.tagName.toLowerCase() === 'ons-list') { wrapperElement.classList.add('lazy-list'); } this._pageContent = this._findPageContentElement(wrapperElement); if (!this._pageContent) { util$1.throw('LazyRepeat must be descendant of a Page element'); } this.lastScrollTop = this._pageContent.scrollTop; this.padding = 0; this._topPositions = [0]; this._renderedItems = {}; if (!this._delegate.itemHeight && !this._delegate.calculateItemHeight(0)) { this._unknownItemHeight = true; } this._addEventListeners(); this._onChange(); } createClass(LazyRepeatProvider, [{ key: '_findPageContentElement', value: function _findPageContentElement(wrapperElement) { var pageContent = util$1.findParent(wrapperElement, '.page__content'); if (pageContent) { return pageContent; } var page = util$1.findParent(wrapperElement, 'ons-page'); if (page) { var content = util$1.findChild(page, '.content'); if (content) { return content; } } return null; } }, { key: '_checkItemHeight', value: function _checkItemHeight(callback) { var _this = this; this._delegate.loadItemElement(0, function (item) { if (!_this._unknownItemHeight) { util$1.throw('Invalid state'); } _this._wrapperElement.appendChild(item.element); var done = function done() { _this._delegate.destroyItem(0, item); item.element && item.element.remove(); delete _this._unknownItemHeight; callback(); }; _this._itemHeight = item.element.offsetHeight; if (_this._itemHeight > 0) { done(); return; } // retry to measure offset height // dirty fix for angular2 directive _this._wrapperElement.style.visibility = 'hidden'; item.element.style.visibility = 'hidden'; setImmediate(function () { _this._itemHeight = item.element.offsetHeight; if (_this._itemHeight == 0) { util$1.throw('Invalid state: "itemHeight" must be greater than zero'); } _this._wrapperElement.style.visibility = ''; done(); }); }); } }, { key: '_countItems', value: function _countItems() { return this._delegate.countItems(); } }, { key: '_getItemHeight', value: function _getItemHeight(i) { // Item is rendered if (this._renderedItems.hasOwnProperty(i)) { if (!this._renderedItems[i].hasOwnProperty('height')) { this._renderedItems[i].height = this._renderedItems[i].element.offsetHeight; } return this._renderedItems[i].height; } // Item is not rendered, scroll up if (this._topPositions[i + 1] && this._topPositions[i]) { return this._topPositions[i + 1] - this._topPositions[i]; } // Item is not rendered, scroll down return this.staticItemHeight || this._delegate.calculateItemHeight(i); } }, { key: '_calculateRenderedHeight', value: function _calculateRenderedHeight() { var _this2 = this; return Object.keys(this._renderedItems).reduce(function (a, b) { return a + _this2._getItemHeight(+b); }, 0); } }, { key: '_onChange', value: function _onChange() { this._render(); } }, { key: '_lastItemRendered', value: function _lastItemRendered() { return Math.max.apply(Math, toConsumableArray(Object.keys(this._renderedItems))); } }, { key: '_firstItemRendered', value: function _firstItemRendered() { return Math.min.apply(Math, toConsumableArray(Object.keys(this._renderedItems))); } }, { key: 'refresh', value: function refresh() { var forceRender = { forceScrollDown: true }; var firstItemIndex = this._firstItemRendered(); if (util$1.isInteger(firstItemIndex)) { this._wrapperElement.style.height = this._topPositions[firstItemIndex] + this._calculateRenderedHeight() + 'px'; this.padding = this._topPositions[firstItemIndex]; forceRender.forceFirstIndex = firstItemIndex; } this._removeAllElements(); this._render(forceRender); this._wrapperElement.style.height = 'inherit'; } }, { key: '_render', value: function _render() { var _this3 = this; var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$forceScrollDown = _ref.forceScrollDown, forceScrollDown = _ref$forceScrollDown === undefined ? false : _ref$forceScrollDown, forceFirstIndex = _ref.forceFirstIndex, forceLastIndex = _ref.forceLastIndex; if (this._unknownItemHeight) { return this._checkItemHeight(this._render.bind(this, arguments[0])); } var isScrollUp = !forceScrollDown && this.lastScrollTop > this._pageContent.scrollTop; this.lastScrollTop = this._pageContent.scrollTop; var keep = {}; var offset = this._wrapperElement.getBoundingClientRect().top; var limit = 4 * window.innerHeight - offset; var count = this._countItems(); var start = forceFirstIndex || Math.max(0, this._calculateStartIndex(offset) - 30); // Recalculate for 0 or undefined var i = start; for (var top = this._topPositions[i]; i < count && top < limit; i++) { if (i >= this._topPositions.length) { // perf optimization this._topPositions.length += 100; } this._topPositions[i] = top; top += this._getItemHeight(i); } if (this._delegate.hasRenderFunction && this._delegate.hasRenderFunction()) { return this._delegate._render(start, i, function () { _this3.padding = _this3._topPositions[start]; }); } if (isScrollUp) { for (var j = i - 1; j >= start; j--) { keep[j] = true; this._renderElement(j, isScrollUp); } } else { var lastIndex = forceLastIndex || Math.max.apply(Math, [i - 1].concat(toConsumableArray(Object.keys(this._renderedItems)))); // Recalculate for 0 or undefined for (var _j = start; _j <= lastIndex; _j++) { keep[_j] = true; this._renderElement(_j, isScrollUp); } } Object.keys(this._renderedItems).forEach(function (key) { return keep[key] || _this3._removeElement(key, isScrollUp); }); } /** * @param {Number} index * @param {Boolean} isScrollUp */ }, { key: '_renderElement', value: function _renderElement(index, isScrollUp) { var _this4 = this; var item = this._renderedItems[index]; if (item) { this._delegate.updateItem(index, item); // update if it exists return; } this._delegate.loadItemElement(index, function (item) { if (isScrollUp) { _this4._wrapperElement.insertBefore(item.element, _this4._wrapperElement.children[_this4._insertIndex]); _this4.padding = _this4._topPositions[index]; item.height = _this4._topPositions[index + 1] - _this4._topPositions[index]; } else { _this4._wrapperElement.appendChild(item.element); } _this4._renderedItems[index] = item; }); } /** * @param {Number} index * @param {Boolean} isScrollUp */ }, { key: '_removeElement', value: function _removeElement(index) { var isScrollUp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; index = +index; var item = this._renderedItems[index]; this._delegate.destroyItem(index, item); if (isScrollUp) { this._topPositions[index + 1] = undefined; } else { this.padding = this.padding + this._getItemHeight(index); } if (item.element.parentElement) { item.element.parentElement.removeChild(item.element); } delete this._renderedItems[index]; } }, { key: '_removeAllElements', value: function _removeAllElements() { var _this5 = this; Object.keys(this._renderedItems).forEach(function (key) { return _this5._removeElement(key); }); } }, { key: '_recalculateTopPositions', value: function _recalculateTopPositions(start, end) { for (var i = start; i <= end; i++) { this._topPositions[i + 1] = this._topPositions[i] + this._getItemHeight(i); } } }, { key: '_calculateStartIndex', value: function _calculateStartIndex(current) { var firstItemIndex = this._firstItemRendered(); var lastItemIndex = this._lastItemRendered(); // Fix for Safari scroll and Angular 2 this._recalculateTopPositions(firstItemIndex, lastItemIndex); var start = 0; var end = this._countItems() - 1; // Binary search for index at top of screen so we can speed up rendering. for (;;) { var middle = Math.floor((start + end) / 2); var value = current + this._topPositions[middle]; if (end < start) { return 0; } else if (value <= 0 && value + this._getItemHeight(middle) > 0) { return middle; } else if (isNaN(value) || value >= 0) { end = middle - 1; } else { start = middle + 1; } } } }, { key: '_debounce', value: function _debounce(func, wait, immediate) { var timeout = void 0; return function () { var _this6 = this, _arguments = arguments; var callNow = immediate && !timeout; clearTimeout(timeout); if (callNow) { func.apply(this, arguments); } else { timeout = setTimeout(function () { timeout = null; func.apply(_this6, _arguments); }, wait); } }; } }, { key: '_doubleFireOnTouchend', value: function _doubleFireOnTouchend() { this._render(); this._debounce(this._render.bind(this), 100); } }, { key: '_addEventListeners', value: function _addEventListeners() { util$1.bindListeners(this, ['_onChange', '_doubleFireOnTouchend']); if (platform.isIOS()) { this._boundOnChange = this._debounce(this._boundOnChange, 30); } this._pageContent.addEventListener('scroll', this._boundOnChange, true); if (platform.isIOS()) { util$1.addEventListener(this._pageContent, 'touchmove', this._boundOnChange, { capture: true, passive: true }); this._pageContent.addEventListener('touchend', this._boundDoubleFireOnTouchend, true); } window.document.addEventListener('resize', this._boundOnChange, true); } }, { key: '_removeEventListeners', value: function _removeEventListeners() { this._pageContent.removeEventListener('scroll', this._boundOnChange, true); if (platform.isIOS()) { util$1.removeEventListener(this._pageContent, 'touchmove', this._boundOnChange, { capture: true, passive: true }); this._pageContent.removeEventListener('touchend', this._boundDoubleFireOnTouchend, true); } window.document.removeEventListener('resize', this._boundOnChange, true); } }, { key: 'destroy', value: function destroy() { this._removeAllElements(); this._delegate.destroy(); this._parentElement = this._delegate = this._renderedItems = null; this._removeEventListeners(); } }, { key: 'padding', get: function get$$1() { return parseInt(this._wrapperElement.style.paddingTop, 10); }, set: function set$$1(newValue) { this._wrapperElement.style.paddingTop = newValue + 'px'; } }, { key: 'staticItemHeight', get: function get$$1() { return this._delegate.itemHeight || this._itemHeight; } }]); return LazyRepeatProvider; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-lazy-repeat * @category list * @description * [en] * Using this component a list with millions of items can be rendered without a drop in performance. * It does that by "lazily" loading elements into the DOM when they come into view and * removing items from the DOM when they are not visible. * [/en] * [ja] * このコンポーネント内で描画されるアイテムのDOM要素の読み込みは、画面に見えそうになった時まで自動的に遅延され、 * 画面から見えなくなった場合にはその要素は動的にアンロードされます。 * このコンポーネントを使うことで、パフォーマンスを劣化させること無しに巨大な数の要素を描画できます。 * [/ja] * @codepen QwrGBm * @tutorial vanilla/Reference/lazy-repeat * @seealso ons-list * [en]The `<ons-list>` element is used to render a list.[/en] * [ja]`<ons-list>`要素はリストを描画するのに使われます。[/ja] * @example * <script> * window.addEventListener('load', function() { * var lazyRepeat = document.querySelector('#list'); * lazyRepeat.delegate = { * createItemContent: function(i, template) { * var dom = template.cloneNode(true); * dom.innerText = i; * * return dom; * }, * countItems: function() { * return 10000000; * }, * destroyItem: function(index, item) { * console.log('Destroyed item with index: ' + index); * } * }; * }); * </script> * * <ons-list id="list"> * <ons-lazy-repeat> * <ons-list-item></ons-list-item> * </ons-lazy-repeat> * </ons-list> */ var LazyRepeatElement = function (_BaseElement) { inherits(LazyRepeatElement, _BaseElement); function LazyRepeatElement() { classCallCheck(this, LazyRepeatElement); return possibleConstructorReturn(this, (LazyRepeatElement.__proto__ || Object.getPrototypeOf(LazyRepeatElement)).apply(this, arguments)); } createClass(LazyRepeatElement, [{ key: 'connectedCallback', value: function connectedCallback() { // not very good idea and also not documented if (this.hasAttribute('delegate')) { this.delegate = window[this.getAttribute('delegate')]; } } /** * @property delegate * @type {Object} * @description * [en]Specify a delegate object to load and unload item elements.[/en] * [ja]要素のロード、アンロードなどの処理を委譲するオブジェクトを指定します。[/ja] */ /** * @property delegate.createItemContent * @type {Function} * @description * [en] * This function should return a `HTMLElement`. * * To help rendering the element, the current index and a template is supplied as arguments. The template is the initial content of the `<ons-lazy-repeat>` element. * [/en] * [ja] * この関数は`HTMLElement`を返してください。 * 要素を生成しやすくするために、現在のアイテムのインデックスとテンプレートが引数に渡されます。 * このテンプレートは、`<ons-lazy-repeat>`要素のコンテンツが渡されます。 * [/ja] */ /** * @property delegate.countItems * @type {Function} * @description * [en]Should return the number of items in the list.[/en] * [ja]リスト内のアイテム数を返してください。[/ja] */ /** * @property delegate.calculateItemHeight * @type {Function} * @description * [en] * Should return the height of an item. The index is provided as an argument. * * This is important when rendering lists where the items have different height. * * The function is optional and if it isn't present the height of the first item will be automatically calculated and used for all other items. * [/en] * [ja] * アイテムの高さ(ピクセル)を返してください。アイテムのインデックス値は引数で渡されます。 * この関数は、それぞれのアイムが違った高さを持つリストをレンダリングする際に重要です。 * この関数はオプショナルです。もしこの関数が無い場合には、 * 最初のアイテムの高さが他のすべてのアイテムの高さとして利用されます。 * [/ja] */ /** * @property delegate.destroyItem * @type {Function} * @description * [en] * This function is used called when an item is removed from the DOM. The index and DOM element is provided as arguments. * * The function is optional but may be important in order to avoid memory leaks. * [/en] * [ja] * この関数は、あるアイテムがDOMツリーから除かれた時に呼び出されます。 * アイテムのインデックス値とDOM要素が引数として渡されます。 * この関数はオプショナルですが、各アイテムの後処理が必要な場合にはメモリーリークを避けるために重要です。 * [/ja] */ }, { key: 'refresh', /** * @method refresh * @signature refresh() * @description * [en]Refresh the list. Use this method when the data has changed.[/en] * [ja]リストを更新します。もしデータが変わった場合にはこのメソッドを使ってください。[/ja] */ value: function refresh() { this._lazyRepeatProvider && this._lazyRepeatProvider.refresh(); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) {} }, { key: 'disconnectedCallback', value: function disconnectedCallback() { if (this._lazyRepeatProvider) { this._lazyRepeatProvider.destroy(); this._lazyRepeatProvider = null; } } }, { key: 'delegate', set: function set$$1(userDelegate) { this._lazyRepeatProvider && this._lazyRepeatProvider.destroy(); if (!this._templateElement && this.children[0]) { this._templateElement = this.removeChild(this.children[0]); } var delegate = new LazyRepeatDelegate(userDelegate, this._templateElement || null); this._lazyRepeatProvider = new LazyRepeatProvider(this.parentElement, delegate); }, get: function get$$1() { util$1.throw('No delegate getter'); } }]); return LazyRepeatElement; }(BaseElement); internal$1.LazyRepeatDelegate = LazyRepeatDelegate; internal$1.LazyRepeatProvider = LazyRepeatProvider; onsElements.LazyRepeat = LazyRepeatElement; customElements.define('ons-lazy-repeat', LazyRepeatElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$4 = 'list-header'; var scheme$8 = { '': 'list-header--*' }; /** * @element ons-list-header * @category list * @description * [en]Header element for list items. Must be put inside the `<ons-list>` component.[/en] * [ja]リスト要素に使用するヘッダー用コンポーネント。ons-listと共に使用します。[/ja] * @seealso ons-list * [en]The `<ons-list>` component[/en] * [ja]ons-listコンポーネント[/ja] * @seealso ons-list-item * [en]The `<ons-list-item>` component[/en] * [ja]ons-list-itemコンポーネント[/ja] * @codepen yxcCt * @tutorial vanilla/Reference/list * @modifier material * [en]Display a Material Design list header.[/en] * [ja][/ja] * @example * <ons-list> * <ons-list-header>Header Text</ons-list-header> * <ons-list-item>Item</ons-list-item> * <ons-list-item>Item</ons-list-item> * </ons-list> */ var ListHeaderElement = function (_BaseElement) { inherits(ListHeaderElement, _BaseElement); /** * @attribute modifier * @type {String} * @description * [en]The appearance of the list header.[/en] * [ja]ヘッダーの表現を指定します。[/ja] */ function ListHeaderElement() { classCallCheck(this, ListHeaderElement); var _this = possibleConstructorReturn(this, (ListHeaderElement.__proto__ || Object.getPrototypeOf(ListHeaderElement)).call(this)); _this._compile(); return _this; } createClass(ListHeaderElement, [{ key: '_compile', value: function _compile() { autoStyle.prepare(this); this.classList.add(defaultClassName$4); ModifierUtil.initModifier(this, scheme$8); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$4, scheme$8); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$8); break; } } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'class']; } }]); return ListHeaderElement; }(BaseElement); onsElements.ListHeader = ListHeaderElement; customElements.define('ons-list-header', ListHeaderElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$5 = 'list-title'; var scheme$9 = { '': 'list-title--*' }; /** * @element ons-list-title * @category list * @description * [en]Represents a list title.[/en] * [ja]リストのタイトルを表現します。[/ja] * @example * <ons-list-title>List Title</ons-list-title> * <ons-list> * <ons-list-item>Item</ons-list-item> * </ons-list> * @modifier material * [en]Display a Material Design list title.[/en] * [ja][/ja] */ var ListTitleElement = function (_BaseElement) { inherits(ListTitleElement, _BaseElement); function ListTitleElement() { classCallCheck(this, ListTitleElement); var _this = possibleConstructorReturn(this, (ListTitleElement.__proto__ || Object.getPrototypeOf(ListTitleElement)).call(this)); _this._compile(); return _this; } createClass(ListTitleElement, [{ key: '_compile', value: function _compile() { autoStyle.prepare(this); this.classList.add(defaultClassName$5); ModifierUtil.initModifier(this, scheme$9); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$5, scheme$9); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$9); break; } } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'class']; } }]); return ListTitleElement; }(BaseElement); onsElements.ListTitle = ListTitleElement; customElements.define('ons-list-title', ListTitleElement); /* Copyright 2013-2018 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var ListItemAnimator = function (_BaseAnimator) { inherits(ListItemAnimator, _BaseAnimator); function ListItemAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'linear' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.2 : _ref$duration; classCallCheck(this, ListItemAnimator); return possibleConstructorReturn(this, (ListItemAnimator.__proto__ || Object.getPrototypeOf(ListItemAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } createClass(ListItemAnimator, [{ key: 'showExpansion', value: function showExpansion(listItem, callback) { callback(); } }, { key: 'hideExpansion', value: function hideExpansion(listItem, callback) { callback(); } }]); return ListItemAnimator; }(BaseAnimator); var SlideListItemAnimator = function (_ListItemAnimator) { inherits(SlideListItemAnimator, _ListItemAnimator); function SlideListItemAnimator() { classCallCheck(this, SlideListItemAnimator); return possibleConstructorReturn(this, (SlideListItemAnimator.__proto__ || Object.getPrototypeOf(SlideListItemAnimator)).apply(this, arguments)); } createClass(SlideListItemAnimator, [{ key: 'showExpansion', value: function showExpansion(listItem, callback) { this._animateExpansion(listItem, true, callback); } }, { key: 'hideExpansion', value: function hideExpansion(listItem, callback) { this._animateExpansion(listItem, false, callback); } }, { key: '_animateExpansion', value: function _animateExpansion(listItem, shouldOpen, callback) { var _animit; // To animate the opening of the expansion panel correctly, we need to know its // height. To calculate this, we set its height to auto, and then get the computed // height and padding. Once this is done, we set the height back to its original value. var oldHeight = listItem.expandableContent.style.height; var oldDisplay = listItem.expandableContent.style.display; listItem.expandableContent.style.height = 'auto'; listItem.expandableContent.style.display = 'block'; var computedStyle = window.getComputedStyle(listItem.expandableContent); var expansionOpenTransition = [{ height: 0, paddingTop: 0, paddingBottom: 0 }, { height: computedStyle.height, paddingTop: computedStyle.paddingTop, paddingBottom: computedStyle.paddingBottom }]; var iconOpenTransition = [{ transform: 'rotate(45deg)' }, { transform: 'rotate(225deg)' }]; // Now that we have the values we need, reset the height back to its original state listItem.expandableContent.style.height = oldHeight; (_animit = Animit(listItem.expandableContent, { duration: this.duration, property: 'height padding-top padding-bottom' })).default.apply(_animit, toConsumableArray(shouldOpen ? expansionOpenTransition : expansionOpenTransition.reverse())).play(function () { listItem.expandableContent.style.display = oldDisplay; callback && callback(); }); if (listItem.expandChevron) { var _animit2; (_animit2 = Animit(listItem.expandChevron, { duration: this.duration, property: 'transform' })).default.apply(_animit2, toConsumableArray(shouldOpen ? iconOpenTransition : iconOpenTransition.reverse())).play(); } } }]); return SlideListItemAnimator; }(ListItemAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$6 = 'list-item'; var scheme$10 = { '.list-item': 'list-item--*', '.list-item__left': 'list-item--*__left', '.list-item__center': 'list-item--*__center', '.list-item__right': 'list-item--*__right', '.list-item__label': 'list-item--*__label', '.list-item__title': 'list-item--*__title', '.list-item__subtitle': 'list-item--*__subtitle', '.list-item__thumbnail': 'list-item--*__thumbnail', '.list-item__icon': 'list-item--*__icon' }; var _animatorDict$3 = { 'default': SlideListItemAnimator, 'none': ListItemAnimator }; /** * @element ons-list-item * @category list * @modifier tappable * [en]Make the list item change appearance when it's tapped. On iOS it is better to use the "tappable" and "tap-background-color" attribute for better behavior when scrolling.[/en] * [ja]タップやクリックした時に効果が表示されるようになります。[/ja] * @modifier chevron * [en]Display a chevron at the right end of the list item and make it change appearance when tapped.[/en] * [ja][/ja] * @modifier longdivider * [en]Displays a long horizontal divider between items.[/en] * [ja][/ja] * @modifier nodivider * [en]Removes the divider between list items.[/en] * [ja][/ja] * @modifier material * [en]Display a Material Design list item.[/en] * [ja][/ja] * @description * [en] * Component that represents each item in a list. The list item is composed of four parts that are represented with the `left`, `center`, `right` and `expandable-content` classes. These classes can be used to ensure that the content of the list items is properly aligned. * * ``` * <ons-list-item> * <div class="left">Left</div> * <div class="center">Center</div> * <div class="right">Right</div> * <div class="expandable-content">Expandable content</div> * </ons-list-item> * ``` * * There are also a number of classes (prefixed with `list-item__*`) that help when putting things like icons and thumbnails into the list items. * [/en] * [ja][/ja] * @seealso ons-list * [en]ons-list component[/en] * [ja]ons-listコンポーネント[/ja] * @seealso ons-list-header * [en]ons-list-header component[/en] * [ja]ons-list-headerコンポーネント[/ja] * @codepen yxcCt * @tutorial vanilla/Reference/list * @example * <ons-list-item> * <div class="left"> * <ons-icon icon="md-face" class="list-item__icon"></ons-icon> * </div> * <div class="center"> * <div class="list-item__title">Title</div> * <div class="list-item__subtitle">Subtitle</div> * </div> * <div class="right"> * <ons-switch></ons-switch> * </div> * </ons-list-item> */ var ListItemElement = function (_BaseElement) { inherits(ListItemElement, _BaseElement); /** * @attribute modifier * @type {String} * @description * [en]The appearance of the list item.[/en] * [ja]各要素の表現を指定します。[/ja] */ /** * @attribute lock-on-drag * @type {String} * @description * [en]Prevent vertical scrolling when the user drags horizontally.[/en] * [ja]この属性があると、ユーザーがこの要素を横方向にドラッグしている時に、縦方向のスクロールが起きないようになります。[/ja] */ /** * @attribute tappable * @type {Boolean} * @description * [en]Makes the element react to taps. `prevent-tap` attribute can be added to child elements like buttons or inputs to prevent this effect. `ons-*` elements are ignored by default.[/en] * [ja][/ja] */ /** * @attribute tap-background-color * @type {Color} * @description * [en] Changes the background color when tapped. For this to work, the attribute "tappable" needs to be set. The default color is "#d9d9d9". It will display as a ripple effect on Android.[/en] * [ja][/ja] */ /** * @attribute expandable * @type {Boolean} * @description * [en]Makes the element able to be expanded to reveal extra content. For this to work, the expandable content must be defined in `div.expandable-content`.[/en] * [ja][/ja] */ /** * @attribute animation * @type {String} * @default default * @description * [en]The animation used when showing and hiding the expandable content. Can be either `"default"` or `"none"`.[/en] * [ja][/ja] */ function ListItemElement() { classCallCheck(this, ListItemElement); var _this = possibleConstructorReturn(this, (ListItemElement.__proto__ || Object.getPrototypeOf(ListItemElement)).call(this)); _this._animatorFactory = _this._updateAnimatorFactory(); _this.toggleExpansion = _this.toggleExpansion.bind(_this); // Elements ignored when tapping var re = /^ons-(?!col$|row$|if$)/i; _this._shouldIgnoreTap = function (e) { return e.hasAttribute('prevent-tap') || re.test(e.tagName); }; // show and hide functions for Vue hidable mixin _this.show = _this.showExpansion; _this.hide = _this.hideExpansion; contentReady(_this, function () { _this._compile(); }); return _this; } /** * Compiles the list item. * * Various elements are allowed in the body of a list item: * * - div.left, div.right, and div.center are allowed as direct children * - if div.center is not defined, anything that isn't div.left, div.right or div.expandable-content will be put in a div.center * - if div.center is defined, anything that isn't div.left, div.right or div.expandable-content will be ignored * - if list item has expandable attribute: * - div.expandable-content is allowed as a direct child * - div.top is allowed as direct child * - if div.top is defined, anything that isn't div.expandable-content should be inside div.top - anything else will be ignored * - if div.right is not defined, a div.right will be created with a drop-down chevron * * See the tests for examples. */ createClass(ListItemElement, [{ key: '_compile', value: function _compile() { autoStyle.prepare(this); this.classList.add(defaultClassName$6); var top = void 0, expandableContent = void 0; var topContent = []; Array.from(this.childNodes).forEach(function (node) { if (node.nodeType !== Node.ELEMENT_NODE) { topContent.push(node); } else if (node.classList.contains('top')) { top = node; } else if (node.classList.contains('expandable-content')) { expandableContent = node; } else { topContent.push(node); } if (node.nodeName !== 'ONS-RIPPLE') { node.remove(); } }); topContent = top ? Array.from(top.childNodes) : topContent; var left = void 0, right = void 0, center = void 0; var centerContent = []; topContent.forEach(function (node) { if (node.nodeType !== Node.ELEMENT_NODE) { centerContent.push(node); } else if (node.classList.contains('left')) { left = node; } else if (node.classList.contains('right')) { right = node; } else if (node.classList.contains('center')) { center = node; } else { centerContent.push(node); } }); if (this.hasAttribute('expandable')) { this.classList.add('list-item--expandable'); if (!top) { top = document.createElement('div'); top.classList.add('top'); } top.classList.add('list-item__top'); this.appendChild(top); this._top = top; if (expandableContent) { expandableContent.classList.add('list-item__expandable-content'); this.appendChild(expandableContent); } if (!right) { right = document.createElement('div'); right.classList.add('list-item__right', 'right'); // We cannot use a pseudo-element for this chevron, as we cannot animate it using // JS. So, we make a chevron span instead. var chevron = document.createElement('span'); chevron.classList.add('list-item__expand-chevron'); right.appendChild(chevron); } } else { top = this; } if (!center) { center = document.createElement('div'); center.classList.add('center'); centerContent.forEach(function (node) { return center.appendChild(node); }); } center.classList.add('list-item__center'); top.appendChild(center); if (left) { left.classList.add('list-item__left'); top.appendChild(left); } if (right) { right.classList.add('list-item__right'); top.appendChild(right); } util$1.updateRipple(this); ModifierUtil.initModifier(this, scheme$10); } /** * @method showExpansion * @signature showExpansion() * @description * [en]Show the expandable content if the element is expandable.[/en] * [ja][/ja] */ }, { key: 'showExpansion', value: function showExpansion() { var _this2 = this; if (this.hasAttribute('expandable') && !this._expanding) { this.expanded = true; this._expanding = true; var animator = this._animatorFactory.newAnimator(); animator.showExpansion(this, function () { _this2.classList.add('expanded'); _this2._expanding = false; }); } } /** * @method hideExpansion * @signature hideExpansion() * @description * [en]Hide the expandable content if the element expandable.[/en] * [ja][/ja] */ }, { key: 'hideExpansion', value: function hideExpansion() { var _this3 = this; if (this.hasAttribute('expandable') && !this._expanding) { this.expanded = false; this._expanding = true; var animator = this._animatorFactory.newAnimator(); animator.hideExpansion(this, function () { _this3.classList.remove('expanded'); _this3._expanding = false; }); } } }, { key: 'toggleExpansion', value: function toggleExpansion() { this.classList.contains('expanded') ? this.hideExpansion() : this.showExpansion(); this.dispatchEvent(new Event('expansion')); } }, { key: '_updateAnimatorFactory', value: function _updateAnimatorFactory() { return new AnimatorFactory({ animators: _animatorDict$3, baseClass: ListItemAnimator, baseClassName: 'ListItemAnimator', defaultAnimation: this.getAttribute('animation') || 'default' }); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$6, scheme$10); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$10); break; case 'ripple': util$1.updateRipple(this); break; case 'animation': this._animatorFactory = this._updateAnimatorFactory(); break; } } }, { key: 'connectedCallback', value: function connectedCallback() { var _this4 = this; contentReady(this, function () { _this4._setupListeners(true); _this4._originalBackgroundColor = _this4.style.backgroundColor; _this4.tapped = false; }); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this._setupListeners(false); } }, { key: '_setupListeners', value: function _setupListeners(add) { var action = (add ? 'add' : 'remove') + 'EventListener'; util$1[action](this, 'touchstart', this._onTouch, { passive: true }); util$1[action](this, 'touchmove', this._onRelease, { passive: true }); this[action]('touchcancel', this._onRelease); this[action]('touchend', this._onRelease); this[action]('touchleave', this._onRelease); this[action]('drag', this._onDrag); this[action]('mousedown', this._onTouch); this[action]('mouseup', this._onRelease); this[action]('mouseout', this._onRelease); if (this._top) { this._top[action]('click', this.toggleExpansion); } } }, { key: '_onDrag', value: function _onDrag(event) { var gesture = event.gesture; // Prevent vertical scrolling if the users pans left or right. if (this.hasAttribute('lock-on-drag') && ['left', 'right'].indexOf(gesture.direction) > -1) { gesture.preventDefault(); } } }, { key: '_onTouch', value: function _onTouch(e) { var _this5 = this; if (this.tapped || this !== e.target && (this._shouldIgnoreTap(e.target) || util$1.findParent(e.target, this._shouldIgnoreTap, function (p) { return p === _this5; }))) { return; // Ignore tap } this.tapped = true; var touchStyle = { transition: 'background-color 0.0s linear 0.02s, box-shadow 0.0s linear 0.02s' }; if (this.hasAttribute('tappable')) { if (this.style.backgroundColor) { this._originalBackgroundColor = this.style.backgroundColor; } touchStyle.backgroundColor = this.getAttribute('tap-background-color') || '#d9d9d9'; touchStyle.boxShadow = '0px -1px 0px 0px ' + touchStyle.backgroundColor; } styler(this, touchStyle); } }, { key: '_onRelease', value: function _onRelease() { this.tapped = false; this.style.backgroundColor = this._originalBackgroundColor || ''; styler.clear(this, 'transition boxShadow'); } }, { key: 'expandableContent', get: function get$$1() { return this.querySelector('.list-item__expandable-content'); } }, { key: 'expandChevron', get: function get$$1() { return this.querySelector('.list-item__expand-chevron'); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'class', 'ripple', 'animation']; } }]); return ListItemElement; }(BaseElement); onsElements.ListItem = ListItemElement; customElements.define('ons-list-item', ListItemElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$7 = 'list'; var scheme$11 = { '': 'list--*' }; /** * @element ons-list * @category list * @modifier inset * [en]Inset list that doesn't cover the whole width of the parent.[/en] * [ja]親要素の画面いっぱいに広がらないリストを表示します。[/ja] * @modifier noborder * [en]A list with no borders at the top and bottom.[/en] * [ja]リストの上下のボーダーが無いリストを表示します。[/ja] * @description * [en]Component to define a list, and the container for ons-list-item(s).[/en] * [ja]リストを表現するためのコンポーネント。ons-list-itemのコンテナとして使用します。[/ja] * @seealso ons-list-item * [en]ons-list-item component[/en] * [ja]ons-list-itemコンポーネント[/ja] * @seealso ons-list-header * [en]ons-list-header component[/en] * [ja]ons-list-headerコンポーネント[/ja] * @seealso ons-lazy-repeat * [en]ons-lazy-repeat component[/en] * [ja]ons-lazy-repeatコンポーネント[/ja] * @codepen yxcCt * @tutorial vanilla/Reference/list * @example * <ons-list> * <ons-list-header>Header Text</ons-list-header> * <ons-list-item>Item</ons-list-item> * <ons-list-item>Item</ons-list-item> * </ons-list> */ var ListElement = function (_BaseElement) { inherits(ListElement, _BaseElement); /** * @attribute modifier * @type {String} * @description * [en]The appearance of the list.[/en] * [ja]リストの表現を指定します。[/ja] */ function ListElement() { classCallCheck(this, ListElement); var _this = possibleConstructorReturn(this, (ListElement.__proto__ || Object.getPrototypeOf(ListElement)).call(this)); _this._compile(); return _this; } createClass(ListElement, [{ key: '_compile', value: function _compile() { autoStyle.prepare(this); this.classList.add(defaultClassName$7); ModifierUtil.initModifier(this, scheme$11); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$7, scheme$11); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$11); break; } } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'class']; } }]); return ListElement; }(BaseElement); onsElements.List = ListElement; customElements.define('ons-list', ListElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var INPUT_ATTRIBUTES = ['autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'disabled', 'inputmode', 'max', 'maxlength', 'min', 'minlength', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'size', 'step', 'validator', 'value']; var BaseInputElement = function (_BaseElement) { inherits(BaseInputElement, _BaseElement); createClass(BaseInputElement, [{ key: '_update', value: function _update() {} // Optionally implemented }, { key: '_scheme', get: function get$$1() { util$1.throwMember(); } }, { key: '_template', get: function get$$1() { util$1.throwMember(); } }, { key: 'type', get: function get$$1() { util$1.throwMember(); } }]); function BaseInputElement() { classCallCheck(this, BaseInputElement); var _this = possibleConstructorReturn(this, (BaseInputElement.__proto__ || Object.getPrototypeOf(BaseInputElement)).call(this)); if (_this.constructor === BaseInputElement) { util$1.throwAbstract(); } contentReady(_this, function () { return _this._compile(); }); _this._boundDelegateEvent = _this._delegateEvent.bind(_this); return _this; } createClass(BaseInputElement, [{ key: '_compile', value: function _compile() { autoStyle.prepare(this); this._defaultClassName && this.classList.add(this._defaultClassName); if (this.children.length !== 0) { return; } this.appendChild(util$1.createFragment(this._template)); this._setInputId(); this._updateBoundAttributes(); ModifierUtil.initModifier(this, this._scheme); } }, { key: '_updateBoundAttributes', value: function _updateBoundAttributes() { var _this2 = this; INPUT_ATTRIBUTES.forEach(function (attr) { if (_this2.hasAttribute(attr)) { _this2._input.setAttribute(attr, _this2.getAttribute(attr)); } else { _this2._input.removeAttribute(attr); } }); this._update(); } }, { key: '_delegateEvent', value: function _delegateEvent(event) { var e = new CustomEvent(event.type, { bubbles: false, cancelable: true }); return this.dispatchEvent(e); } }, { key: '_setInputId', value: function _setInputId() { if (this.hasAttribute('input-id')) { this._input.id = this.getAttribute('input-id'); } } }, { key: 'connectedCallback', value: function connectedCallback() { var _this3 = this; contentReady(this, function () { _this3._input.addEventListener('focus', _this3._boundDelegateEvent); _this3._input.addEventListener('blur', _this3._boundDelegateEvent); }); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { var _this4 = this; contentReady(this, function () { _this4._input.removeEventListener('focus', _this4._boundDelegateEvent); _this4._input.removeEventListener('blur', _this4._boundDelegateEvent); }); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { var _this5 = this; switch (name) { case 'modifier': contentReady(this, function () { return ModifierUtil.onModifierChanged(last, current, _this5, _this5._scheme); }); break; case 'input-id': contentReady(this, function () { return _this5._setInputId(); }); break; case 'class': util$1.restoreClass(this, this._defaultClassName, this._scheme); break; } if (INPUT_ATTRIBUTES.indexOf(name) >= 0) { contentReady(this, function () { return _this5._updateBoundAttributes(); }); } } }, { key: '_defaultClassName', get: function get$$1() { return ''; } }, { key: '_input', get: function get$$1() { return this.querySelector('input'); } }, { key: 'value', get: function get$$1() { return this._input === null ? this.getAttribute('value') : this._input.value; }, set: function set$$1(val) { var _this6 = this; contentReady(this, function () { if (val instanceof Date) { val = val.toISOString().substring(0, 10); } _this6._input.value = val; _this6._update(); }); } }, { key: 'disabled', set: function set$$1(value) { return util$1.toggleAttribute(this, 'disabled', value); }, get: function get$$1() { return this.hasAttribute('disabled'); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'input-id', 'class'].concat(INPUT_ATTRIBUTES); } }]); return BaseInputElement; }(BaseElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$12 = { '.text-input': 'text-input--*', '.text-input__label': 'text-input--*__label' }; /** * @element ons-input * @category form * @modifier material * [en]Displays a Material Design input.[/en] * [ja][/ja] * @modifier underbar * [en]Displays a horizontal line underneath a text input.[/en] * [ja][/ja] * @modifier transparent * [en]Displays a transparent input. Works for Material Design.[/en] * [ja][/ja] * @description * [en] * An input element. The `type` attribute can be used to change the input type. All text input types are supported. * * The component will automatically render as a Material Design input on Android devices. * * Most attributes that can be used for a normal `<input>` element can also be used on the `<ons-input>` element. * [/en] * [ja][/ja] * @tutorial vanilla/Reference/input * @seealso ons-checkbox * [en]The `<ons-checkbox>` element is used to display a checkbox.[/en] * [ja][/ja] * @seealso ons-radio * [en]The `<ons-radio>` element is used to display a radio button.[/en] * [ja][/ja] * @seealso ons-range * [en]The `<ons-range>` element is used to display a range slider.[/en] * [ja][/ja] * @seealso ons-switch * [en]The `<ons-switch>` element is used to display a draggable toggle switch.[/en] * [ja][/ja] * @seealso ons-select * [en]The `<ons-select>` element is used to display a select box.[/en] * [ja][/ja] * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @example * <ons-input placeholder="Username" float></ons-input> */ var InputElement = function (_BaseInputElement) { inherits(InputElement, _BaseInputElement); function InputElement() { classCallCheck(this, InputElement); var _this = possibleConstructorReturn(this, (InputElement.__proto__ || Object.getPrototypeOf(InputElement)).call(this)); _this._boundOnInput = _this._update.bind(_this); _this._boundOnFocusin = _this._update.bind(_this); return _this; } /* Inherited props */ createClass(InputElement, [{ key: '_update', value: function _update() { this._updateLabel(); this._updateLabelClass(); } }, { key: '_updateLabel', /* Own props */ value: function _updateLabel() { var label = this.getAttribute('placeholder') || ''; if (typeof this._helper.textContent !== 'undefined') { this._helper.textContent = label; } else { this._helper.innerText = label; } } }, { key: '_updateLabelClass', value: function _updateLabelClass() { if (this.value === '') { this._helper.classList.remove('text-input--material__label--active'); } else { this._helper.classList.add('text-input--material__label--active'); } } }, { key: 'connectedCallback', value: function connectedCallback() { var _this2 = this; get(InputElement.prototype.__proto__ || Object.getPrototypeOf(InputElement.prototype), 'connectedCallback', this).call(this); contentReady(this, function () { _this2._input.addEventListener('input', _this2._boundOnInput); _this2._input.addEventListener('focusin', _this2._boundOnFocusin); }); var type = this.getAttribute('type'); if (['checkbox', 'radio'].indexOf(type) >= 0) { util$1.warn('Warn: <ons-input type="' + type + '"> is deprecated since v2.4.0. Use <ons-' + type + '> instead.'); } } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { var _this3 = this; get(InputElement.prototype.__proto__ || Object.getPrototypeOf(InputElement.prototype), 'disconnectedCallback', this).call(this); contentReady(this, function () { _this3._input.removeEventListener('input', _this3._boundOnInput); _this3._input.removeEventListener('focusin', _this3._boundOnFocusin); }); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { var _this4 = this; switch (name) { case 'type': contentReady(this, function () { return _this4._input.setAttribute('type', _this4.type); }); break; default: get(InputElement.prototype.__proto__ || Object.getPrototypeOf(InputElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current); } } /** * @attribute placeholder * @type {String} * @description * [en]Placeholder text. In Material Design, this placeholder will be a floating label.[/en] * [ja][/ja] */ /** * @attribute float * @description * [en]If this attribute is present, the placeholder will be animated in Material Design.[/en] * [ja]この属性が設定された時、ラベルはアニメーションするようになります。[/ja] */ /** * @attribute type * @type {String} * @description * [en] * Specify the input type. This is the same as the "type" attribute for normal inputs. It expects strict text types such as `text`, `password`, etc. For checkbox, radio button, select or range, please have a look at the corresponding elements. * * Please take a look at [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-type) for an exhaustive list of possible values. Depending on the platform and browser version some of these might not work. * [/en] * [ja][/ja] */ /** * @attribute input-id * @type {String} * @description * [en]Specify the "id" attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en] * [ja][/ja] */ /** * @property value * @type {String} * @description * [en]The current value of the input.[/en] * [ja][/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the input is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ }, { key: '_scheme', get: function get$$1() { return scheme$12; } }, { key: '_template', get: function get$$1() { return '\n <input type="' + this.type + '" class="text-input">\n <span class="text-input__label"></span>\n '; } }, { key: 'type', get: function get$$1() { var type = this.getAttribute('type'); return ['checkbox', 'radio'].indexOf(type) < 0 && type || 'text'; } }, { key: '_helper', get: function get$$1() { return this.querySelector('span'); } }], [{ key: 'observedAttributes', get: function get$$1() { return [].concat(toConsumableArray(get(InputElement.__proto__ || Object.getPrototypeOf(InputElement), 'observedAttributes', this)), ['type']); } }]); return InputElement; }(BaseInputElement); onsElements.Input = InputElement; customElements.define('ons-input', InputElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var BaseCheckboxElement = function (_BaseInputElement) { inherits(BaseCheckboxElement, _BaseInputElement); function BaseCheckboxElement() { classCallCheck(this, BaseCheckboxElement); var _this = possibleConstructorReturn(this, (BaseCheckboxElement.__proto__ || Object.getPrototypeOf(BaseCheckboxElement)).call(this)); if (_this.constructor === BaseCheckboxElement) { util.throwAbstract(); } contentReady(_this, function () { _this.attributeChangedCallback('checked', null, _this.getAttribute('checked')); }); return _this; } /* Inherited props */ createClass(BaseCheckboxElement, [{ key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'checked': this.checked = current !== null; break; default: get(BaseCheckboxElement.prototype.__proto__ || Object.getPrototypeOf(BaseCheckboxElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current); } } }, { key: '_template', get: function get$$1() { return '\n <input type="' + this.type + '" class="' + this._defaultClassName + '__input">\n <span class="' + this._defaultClassName + '__checkmark"></span>\n '; } /* Own props */ }, { key: '_helper', get: function get$$1() { return this.querySelector('span'); } }, { key: 'checked', get: function get$$1() { return this._input.checked; }, set: function set$$1(val) { var _this2 = this; contentReady(this, function () { _this2._input.checked = val; }); } }], [{ key: 'observedAttributes', get: function get$$1() { return [].concat(toConsumableArray(get(BaseCheckboxElement.__proto__ || Object.getPrototypeOf(BaseCheckboxElement), 'observedAttributes', this)), ['checked']); } }]); return BaseCheckboxElement; }(BaseInputElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$13 = { '.checkbox': 'checkbox--*', '.checkbox__input': 'checkbox--*__input', '.checkbox__checkmark': 'checkbox--*__checkmark' }; /** * @element ons-checkbox * @category form * @modifier material * [en]Displays a Material Design checkbox.[/en] * [ja][/ja] * @modifier noborder * [en]iOS borderless checkbox.[/en] * [ja][/ja] * @description * [en] * A checkbox element. The component will automatically render as a Material Design checkbox on Android devices. * * Most attributes that can be used for a normal `<input type="checkbox">` element can also be used on the `<ons-checkbox>` element. * [/en] * [ja][/ja] * @tutorial vanilla/Reference/checkbox * @seealso ons-switch * [en]The `<ons-switch>` element is used to display a draggable toggle switch.[/en] * [ja][/ja] * @seealso ons-radio * [en]The `<ons-radio>` element is used to display a radio button.[/en] * [ja][/ja] * @seealso ons-input * [en]The `<ons-input>` element is used to display a text input.[/en] * [ja][/ja] * @seealso ons-search-input * [en]The `<ons-search-input>` element is used to display a search input.[/en] * [ja][/ja] * @seealso ons-range * [en]The `<ons-range>` element is used to display a range slider.[/en] * [ja][/ja] * @seealso ons-select * [en]The `<ons-select>` element is used to display a select box.[/en] * [ja][/ja] * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @example * <ons-checkbox checked></ons-checkbox> */ var CheckboxElement = function (_BaseCheckboxElement) { inherits(CheckboxElement, _BaseCheckboxElement); function CheckboxElement() { classCallCheck(this, CheckboxElement); return possibleConstructorReturn(this, (CheckboxElement.__proto__ || Object.getPrototypeOf(CheckboxElement)).apply(this, arguments)); } createClass(CheckboxElement, [{ key: '_scheme', get: function get$$1() { return scheme$13; } }, { key: '_defaultClassName', get: function get$$1() { return 'checkbox'; } }, { key: 'type', get: function get$$1() { return 'checkbox'; } /** * @attribute input-id * @type {String} * @description * [en]Specify the "id" attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en] * [ja][/ja] */ /** * @property value * @type {String} * @description * [en]The current value of the checkbox.[/en] * [ja][/ja] */ /** * @property checked * @type {Boolean} * @description * [en]Whether the checkbox is checked or not.[/en] * [ja][/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the checkbox is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ }]); return CheckboxElement; }(BaseCheckboxElement); onsElements.Checkbox = CheckboxElement; customElements.define('ons-checkbox', CheckboxElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$14 = { '.radio-button': 'radio-button--*', '.radio-button__input': 'radio-button--*__input', '.radio-button__checkmark': 'radio-button--*__checkmark' }; /** * @element ons-radio * @category form * @modifier material * [en]Displays a Material Design radio button.[/en] * [ja][/ja] * @description * [en] * A radio button element. The component will automatically render as a Material Design radio button on Android devices. * * Most attributes that can be used for a normal `<input type="radio">` element can also be used on the `<ons-radio>` element. * [/en] * [ja][/ja] * @tutorial vanilla/Reference/radio * @seealso ons-select * [en]The `<ons-select>` element is used to display a select box.[/en] * [ja][/ja] * @seealso ons-checkbox * [en]The `<ons-checkbox>` element is used to display a checkbox.[/en] * [ja][/ja] * @seealso ons-switch * [en]The `<ons-switch>` element is used to display a draggable toggle switch.[/en] * [ja][/ja] * @seealso ons-input * [en]The `<ons-input>` element is used to display a text input.[/en] * [ja][/ja] * @seealso ons-search-input * [en]The `<ons-search-input>` element is used to display a search input.[/en] * [ja][/ja] * @seealso ons-range * [en]The `<ons-range>` element is used to display a range slider.[/en] * [ja][/ja] * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @example * <ons-radio checked></ons-radio> */ var RadioElement = function (_BaseCheckboxElement) { inherits(RadioElement, _BaseCheckboxElement); function RadioElement() { classCallCheck(this, RadioElement); return possibleConstructorReturn(this, (RadioElement.__proto__ || Object.getPrototypeOf(RadioElement)).apply(this, arguments)); } createClass(RadioElement, [{ key: '_scheme', get: function get$$1() { return scheme$14; } }, { key: '_defaultClassName', get: function get$$1() { return 'radio-button'; } }, { key: 'type', get: function get$$1() { return 'radio'; } /** * @attribute input-id * @type {String} * @description * [en]Specify the "id" attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en] * [ja][/ja] */ /** * @property value * @type {String} * @description * [en]The current value of the radio button.[/en] * [ja][/ja] */ /** * @property checked * @type {Boolean} * @description * [en]Whether the radio button is checked or not.[/en] * [ja][/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the radio button is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ }]); return RadioElement; }(BaseCheckboxElement); onsElements.Radio = RadioElement; customElements.define('ons-radio', RadioElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$15 = { '.search-input': 'search-input--*' }; /** * @element ons-search-input * @category form * @modifier material * [en]Displays a Material Design search input.[/en] * [ja][/ja] * @description * [en] * A search input element. The component will automatically render as a Material Design search input on Android devices. * * Most attributes that can be used for a normal `<input>` element can also be used on the `<ons-search-input>` element. * [/en] * [ja][/ja] * @tutorial vanilla/Reference/search-input * @seealso ons-input * [en]The `<ons-input>` element is used to display a text input.[/en] * [ja][/ja] * @seealso ons-range * [en]The `<ons-range>` element is used to display a range slider.[/en] * [ja][/ja] * @seealso ons-switch * [en]The `<ons-switch>` element is used to display a draggable toggle switch.[/en] * [ja][/ja] * @seealso ons-select * [en]The `<ons-select>` element is used to display a select box.[/en] * [ja][/ja] * @seealso ons-checkbox * [en]The `<ons-checkbox>` element is used to display a checkbox.[/en] * [ja][/ja] * @seealso ons-radio * [en]The `<ons-radio>` element is used to display a radio button.[/en] * [ja][/ja] * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @example * <ons-search-input placeholder="Search"></ons-search-input> */ var SearchInputElement = function (_BaseInputElement) { inherits(SearchInputElement, _BaseInputElement); function SearchInputElement() { classCallCheck(this, SearchInputElement); return possibleConstructorReturn(this, (SearchInputElement.__proto__ || Object.getPrototypeOf(SearchInputElement)).apply(this, arguments)); } createClass(SearchInputElement, [{ key: '_scheme', get: function get$$1() { return scheme$15; } }, { key: '_template', get: function get$$1() { return '\n <input type="' + this.type + '" class="search-input">\n '; } }, { key: 'type', get: function get$$1() { return 'search'; } /** * @attribute input-id * @type {String} * @description * [en]Specify the "id" attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en] * [ja][/ja] */ /** * @property value * @type {String} * @description * [en]The current value of the input.[/en] * [ja][/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the input is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ }]); return SearchInputElement; }(BaseInputElement); onsElements.SearchInput = SearchInputElement; customElements.define('ons-search-input', SearchInputElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var ModalAnimator = function (_BaseAnimator) { inherits(ModalAnimator, _BaseAnimator); /** * @param {Object} options * @param {String} options.timing * @param {Number} options.duration * @param {Number} options.delay */ function ModalAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'linear' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.2 : _ref$duration; classCallCheck(this, ModalAnimator); return possibleConstructorReturn(this, (ModalAnimator.__proto__ || Object.getPrototypeOf(ModalAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } /** * @param {HTMLElement} modal * @param {Function} callback */ createClass(ModalAnimator, [{ key: 'show', value: function show(modal, callback) { callback(); } /** * @param {HTMLElement} modal * @param {Function} callback */ }, { key: 'hide', value: function hide(modal, callback) { callback(); } }]); return ModalAnimator; }(BaseAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * iOS style animator for dialog. */ var FadeModalAnimator = function (_ModalAnimator) { inherits(FadeModalAnimator, _ModalAnimator); function FadeModalAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'linear' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.3 : _ref$duration; classCallCheck(this, FadeModalAnimator); return possibleConstructorReturn(this, (FadeModalAnimator.__proto__ || Object.getPrototypeOf(FadeModalAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } /** * @param {HTMLElement} modal * @param {Function} callback */ createClass(FadeModalAnimator, [{ key: 'show', value: function show(modal, callback) { callback = callback ? callback : function () {}; Animit(modal, this.def).default({ opacity: 0 }, { opacity: 1 }).queue(function (done) { callback(); done(); }).play(); } /** * @param {HTMLElement} modal * @param {Function} callback */ }, { key: 'hide', value: function hide(modal, callback) { callback = callback ? callback : function () {}; Animit(modal, this.def).default({ opacity: 1 }, { opacity: 0 }).queue(function (done) { callback(); done(); }).play(); } }]); return FadeModalAnimator; }(ModalAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * iOS style animator for modal. */ var LiftModalAnimator = function (_ModalAnimator) { inherits(LiftModalAnimator, _ModalAnimator); function LiftModalAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'cubic-bezier( .1, .7, .1, 1)' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.4 : _ref$duration; classCallCheck(this, LiftModalAnimator); return possibleConstructorReturn(this, (LiftModalAnimator.__proto__ || Object.getPrototypeOf(LiftModalAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } /** * @param {HTMLElement} modal * @param {Function} callback */ createClass(LiftModalAnimator, [{ key: 'show', value: function show(modal, callback) { callback = callback ? callback : function () {}; Animit(modal, this.def).default({ transform: 'translate3d(0, 100%, 0)' }, { transform: 'translate3d(0, 0, 0)' }).queue(function (done) { callback(); done(); }).play(); } /** * @param {HTMLElement} modal * @param {Function} callback */ }, { key: 'hide', value: function hide(modal, callback) { callback = callback ? callback : function () {}; Animit(modal, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(0, 100%, 0)' }).queue(function (done) { callback(); done(); }).play(); } }]); return LiftModalAnimator; }(ModalAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$16 = { '': 'modal--*', 'modal__content': 'modal--*__content' }; var defaultClassName$8 = 'modal'; var _animatorDict$4 = { 'default': ModalAnimator, 'fade': FadeModalAnimator, 'lift': LiftModalAnimator, 'none': ModalAnimator }; /** * @element ons-modal * @category dialog * @description * [en] * Modal component that masks current screen. Underlying components are not subject to any events while the modal component is shown. * * This component can be used to block user input while some operation is running or to show some information to the user. * [/en] * [ja] * 画面全体をマスクするモーダル用コンポーネントです。下側にあるコンポーネントは、 * モーダルが表示されている間はイベント通知が行われません。 * [/ja] * @seealso ons-dialog * [en]The `<ons-dialog>` component can be used to create a modal dialog.[/en] * [ja][/ja] * @codepen devIg * @tutorial vanilla/reference/modal * @example * <ons-modal id="modal"> * Modal content * </ons-modal> * <script> * var modal = document.getElementById('modal'); * modal.show(); * </script> */ var ModalElement = function (_BaseDialogElement) { inherits(ModalElement, _BaseDialogElement); /** * @event preshow * @description * [en]Fired just before the modal is displayed.[/en] * [ja]モーダルが表示される直前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.modal * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Execute this function to stop the modal from being shown.[/en] * [ja]この関数を実行すると、ダイアログの表示がキャンセルされます。[/ja] */ /** * @event postshow * @description * [en]Fired just after the modal is displayed.[/en] * [ja]モーダルが表示された直後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.modal * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @event prehide * @description * [en]Fired just before the modal is hidden.[/en] * [ja]モーダルが隠れる直前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.modal * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Execute this function to stop the modal from being hidden.[/en] * [ja]この関数を実行すると、ダイアログの非表示がキャンセルされます。[/ja] */ /** * @event posthide * @description * [en]Fired just after the modal is hidden.[/en] * [ja]モーダルが隠れた後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.modal * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @attribute animation * @type {String} * @default default * @description * [en]The animation used when showing and hiding the modal. Can be either `"none"`, `"fade"` or `"lift"`.[/en] * [ja]モーダルを表示する際のアニメーション名を指定します。"none"もしくは"fade","lift"を指定できます。[/ja] */ /** * @attribute animation-options * @type {Expression} * @description * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. <code>{duration: 0.2, delay: 1, timing: 'ease-in'}</code>[/ja] */ function ModalElement() { classCallCheck(this, ModalElement); var _this = possibleConstructorReturn(this, (ModalElement.__proto__ || Object.getPrototypeOf(ModalElement)).call(this)); _this._defaultDBB = function () { return undefined; }; contentReady(_this, function () { return _this._compile(); }); return _this; } createClass(ModalElement, [{ key: '_updateAnimatorFactory', value: function _updateAnimatorFactory() { return new AnimatorFactory({ animators: _animatorDict$4, baseClass: ModalAnimator, baseClassName: 'ModalAnimator', defaultAnimation: this.getAttribute('animation') }); } /** * @property onDeviceBackButton * @type {Object} * @description * [en]Back-button handler.[/en] * [ja]バックボタンハンドラ。[/ja] */ }, { key: '_compile', value: function _compile() { this.style.display = 'none'; this.style.zIndex = 10001; this.classList.add(defaultClassName$8); if (!util$1.findChild(this, '.modal__content')) { var content = document.createElement('div'); content.classList.add('modal__content'); while (this.childNodes[0]) { var node = this.childNodes[0]; this.removeChild(node); content.insertBefore(node, null); } this.appendChild(content); } ModifierUtil.initModifier(this, this._scheme); } }, { key: '_toggleStyle', value: function _toggleStyle(shouldShow) { this.style.display = shouldShow ? 'table' : 'none'; } }, { key: 'connectedCallback', value: function connectedCallback() { get(ModalElement.prototype.__proto__ || Object.getPrototypeOf(ModalElement.prototype), 'connectedCallback', this).call(this); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { get(ModalElement.prototype.__proto__ || Object.getPrototypeOf(ModalElement.prototype), 'disconnectedCallback', this).call(this); } /** * @property visible * @readonly * @type {Boolean} * @description * [en]Whether the element is visible or not.[/en] * [ja]要素が見える場合に`true`。[/ja] */ /** * @method show * @signature show([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"none"` and `"fade"`.[/en] * [ja]アニメーション名を指定します。"none", "fade"のいずれかを指定します。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja] * @param {Function} [options.callback] * [en]This function is called after the modal has been revealed.[/en] * [ja]モーダルが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Show modal.[/en] * [ja]モーダルを表示します。[/ja] * @return {Promise} * [en]Resolves to the displayed element[/en] * [ja][/ja] */ /** * @method toggle * @signature toggle([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"none"` and `"fade"`.[/en] * [ja]アニメーション名を指定します。"none", "fade"のいずれかを指定します。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja] * @param {Function} [options.callback] * [en]This function is called after the modal has been revealed.[/en] * [ja]モーダルが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Toggle modal visibility.[/en] * [ja]モーダルの表示を切り替えます。[/ja] */ /** * @method hide * @signature hide([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"none"` and `"fade"`.[/en] * [ja]アニメーション名を指定します。"none", "fade"のいずれかを指定します。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja] * @param {Function} [options.callback] * [en]This function is called after the modal has been revealed.[/en] * [ja]モーダルが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Hide modal.[/en] * [ja]モーダルを非表示にします。[/ja] * @return {Promise} * [en]Resolves to the hidden element[/en] * [ja][/ja] */ }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'class') { util$1.restoreClass(this, defaultClassName$8, scheme$16); } else { get(ModalElement.prototype.__proto__ || Object.getPrototypeOf(ModalElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current); } } /** * @param {String} name * @param {Function} Animator */ }, { key: '_scheme', get: function get$$1() { return scheme$16; } }], [{ key: 'registerAnimator', value: function registerAnimator(name, Animator) { if (!(Animator.prototype instanceof ModalAnimator)) { util$1.throwAnimator('Modal'); } _animatorDict$4[name] = Animator; } }, { key: 'observedAttributes', get: function get$$1() { return [].concat(toConsumableArray(get(ModalElement.__proto__ || Object.getPrototypeOf(ModalElement), 'observedAttributes', this)), ['class']); } }, { key: 'animators', get: function get$$1() { return _animatorDict$4; } }, { key: 'ModalAnimator', get: function get$$1() { return ModalAnimator; } }]); return ModalElement; }(BaseDialogElement); onsElements.Modal = ModalElement; customElements.define('ons-modal', ModalElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var widthToPx = function widthToPx(width) { var _ref = [parseInt(width, 10), /px/.test(width)], value = _ref[0], px = _ref[1]; return px ? value : Math.round(document.body.offsetWidth * value / 100); }; var SwipeReveal = function () { function SwipeReveal(params) { var _this = this; classCallCheck(this, SwipeReveal); 'element ignoreSwipe isInitialState onDragCallback swipeMax swipeMin swipeMid'.split(/\s+/).forEach(function (key) { return _this[key] = params[key]; }); this.elementHandler = params.elementHandler || params.element; this.getThreshold = params.getThreshold || function () { return .5; }; this.getSide = params.getSide || function () { return 'left'; }; this.handleGesture = this.handleGesture.bind(this); this._shouldFixScroll = util$1.globals.actualMobileOS === 'ios'; } createClass(SwipeReveal, [{ key: 'update', value: function update() { var swipeable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.element.hasAttribute('swipeable'); if (!this.gestureDetector) { this.gestureDetector = new GestureDetector(this.elementHandler, { dragMinDistance: 1, passive: !this._shouldFixScroll }); } var action = swipeable ? 'on' : 'off'; this.gestureDetector[action]('drag dragstart dragend', this.handleGesture); } }, { key: 'handleGesture', value: function handleGesture(e) { if (e.gesture) { if (e.type === 'dragstart') { this.onDragStart(e); } else if (!this._ignoreDrag) { e.type === 'dragend' ? this.onDragEnd(e) : this.onDrag(e); } } } }, { key: 'onDragStart', value: function onDragStart(event) { var _this2 = this; var getDistance = function getDistance() { return _this2.getSide() === 'left' ? event.gesture.center.clientX : window.innerWidth - event.gesture.center.clientX; }; this._ignoreDrag = event.consumed || !util$1.isValidGesture(event) || this.ignoreSwipe(event, getDistance()); if (!this._ignoreDrag) { event.consume && event.consume(); event.consumed = true; this._width = widthToPx(this.element.style.width || '100%'); this._startDistance = this._distance = !(this.isInitialState instanceof Function) || this.isInitialState() ? 0 : this._width; util$1.iosPreventScroll(this.gestureDetector); } } }, { key: 'onDrag', value: function onDrag(event) { event.stopPropagation(); var delta = this.getSide() === 'left' ? event.gesture.deltaX : -event.gesture.deltaX; var distance = Math.max(0, Math.min(this._width, this._startDistance + delta)); if (distance !== this._distance) { this._distance = distance; this.swipeMid(this._distance, this._width); } } }, { key: 'onDragEnd', value: function onDragEnd(event) { event.stopPropagation(); var direction = event.gesture.interimDirection; var isSwipeMax = this.getSide() !== direction && this._distance > this._width * this.getThreshold(); isSwipeMax ? this.swipeMax() : this.swipeMin(); } }, { key: 'dispose', value: function dispose() { this.gestureDetector && this.gestureDetector.dispose(); this.gestureDetector = this.element = this.elementHandler = null; } }]); return SwipeReveal; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var NavigatorAnimator = function (_BaseAnimator) { inherits(NavigatorAnimator, _BaseAnimator); /** * @param {Object} options * @param {String} options.timing * @param {Number} options.duration * @param {Number} options.delay */ function NavigatorAnimator(options) { classCallCheck(this, NavigatorAnimator); options = util$1.extend({ timing: 'linear', duration: '0.4', delay: '0' }, options || {}); return possibleConstructorReturn(this, (NavigatorAnimator.__proto__ || Object.getPrototypeOf(NavigatorAnimator)).call(this, options)); } createClass(NavigatorAnimator, [{ key: 'push', value: function push(enterPage, leavePage, callback) { callback(); } }, { key: 'pop', value: function pop(enterPage, leavePage, callback) { callback(); } }, { key: 'block', value: function block(page) { var blocker = util$1.createElement('\n <div style="position: absolute; background-color: transparent; width: 100%; height: 100%; z-index: 100000"></div>\n '); page.parentNode.appendChild(blocker); return function () { return blocker.remove(); }; } }]); return NavigatorAnimator; }(BaseAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Abstract swipe animator for iOS navigator transition. */ var IOSSwipeNavigatorAnimator = function (_NavigatorAnimator) { inherits(IOSSwipeNavigatorAnimator, _NavigatorAnimator); createClass(IOSSwipeNavigatorAnimator, null, [{ key: 'swipeable', get: function get$$1() { return true; } }]); function IOSSwipeNavigatorAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var _ref$durationRestore = _ref.durationRestore, durationRestore = _ref$durationRestore === undefined ? 0.1 : _ref$durationRestore, _ref$durationSwipe = _ref.durationSwipe, durationSwipe = _ref$durationSwipe === undefined ? 0.15 : _ref$durationSwipe, _ref$timingSwipe = _ref.timingSwipe, timingSwipe = _ref$timingSwipe === undefined ? 'linear' : _ref$timingSwipe, rest = objectWithoutProperties(_ref, ['durationRestore', 'durationSwipe', 'timingSwipe']); classCallCheck(this, IOSSwipeNavigatorAnimator); var _this = possibleConstructorReturn(this, (IOSSwipeNavigatorAnimator.__proto__ || Object.getPrototypeOf(IOSSwipeNavigatorAnimator)).call(this, _extends({}, rest))); if (_this.constructor === IOSSwipeNavigatorAnimator) { util$1.throwAbstract(); } _this.durationRestore = durationRestore; _this.durationSwipe = durationSwipe; _this.timingSwipe = timingSwipe; _this.optSwipe = { timing: timingSwipe, duration: durationSwipe }; _this.optRestore = { timing: timingSwipe, duration: durationRestore }; _this.swipeShadow = util$1.createElement('<div style="position: absolute; height: 100%; width: 12px; right: 100%; top: 0; bottom: 0; z-index: -1;' + 'background: linear-gradient(to right, transparent 0, rgba(0,0,0,.04) 40%, rgba(0,0,0,.12) 80%, rgba(0,0,0,.16) 100%);"></div>'); _this.isDragStart = true; return _this; } createClass(IOSSwipeNavigatorAnimator, [{ key: '_decompose', value: function _decompose() { util$1.throwMember(); } }, { key: '_shouldAnimateToolbar', value: function _shouldAnimateToolbar() { util$1.throwMember(); } }, { key: '_calculateDelta', value: function _calculateDelta() { util$1.throwMember(); } }, { key: '_dragStartSetup', value: function _dragStartSetup(enterPage, leavePage) { this.isDragStart = false; // Avoid content clicks this.unblock = get(IOSSwipeNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSSwipeNavigatorAnimator.prototype), 'block', this).call(this, leavePage); // Mask enterPage.parentElement.insertBefore(this.backgroundMask, enterPage); // Decomposition this.target = { enter: util$1.findToolbarPage(enterPage) || enterPage, leave: util$1.findToolbarPage(leavePage) || leavePage }; this.decomp = { enter: this._decompose(this.target.enter), leave: this._decompose(this.target.leave) }; // Animation values this.delta = this._calculateDelta(leavePage, this.decomp.leave); this.shouldAnimateToolbar = this._shouldAnimateToolbar(this.target.enter, this.target.leave); // Shadow && styles if (this.shouldAnimateToolbar) { this.swipeShadow.style.top = this.decomp.leave.toolbar.offsetHeight + 'px'; this.target.leave.appendChild(this.swipeShadow); this._saveStyle(this.target.enter, this.target.leave); } else { leavePage.appendChild(this.swipeShadow); this._saveStyle(enterPage, leavePage); } leavePage.classList.add('overflow-visible'); this.overflowElement = leavePage; this.decomp.leave.content.classList.add('content-swiping'); } }, { key: 'translate', value: function translate(distance, maxWidth, enterPage, leavePage) { this.isSwiping = true; if (enterPage.style.display === 'none') { enterPage.style.display = ''; } if (this.isDragStart) { this.maxWidth = maxWidth; this._dragStartSetup(enterPage, leavePage); } var swipeRatio = (distance - maxWidth) / maxWidth; if (this.shouldAnimateToolbar) { Animit.runAll( /* Enter page */ Animit([this.decomp.enter.content, this.decomp.enter.bottomToolbar, this.decomp.enter.background]).queue({ transform: 'translate3d(' + swipeRatio * 25 + '%, 0, 0)', opacity: 1 + swipeRatio * 10 / 100 // 0.9 -> 1 }), Animit(this.decomp.enter.toolbarCenter).queue({ transform: 'translate3d(' + this.delta.title * swipeRatio + 'px, 0, 0)', opacity: 1 + swipeRatio // 0 -> 1 }), Animit(this.decomp.enter.backButtonLabel).queue({ opacity: 1 + swipeRatio * 10 / 100, // 0.9 -> 1 transform: 'translate3d(' + this.delta.label * swipeRatio + 'px, 0, 0)' }), Animit(this.decomp.enter.other).queue({ opacity: 1 + swipeRatio // 0 -> 1 }), /* Leave page */ Animit([this.decomp.leave.content, this.decomp.leave.bottomToolbar, this.decomp.leave.background, this.swipeShadow]).queue({ transform: 'translate3d(' + distance + 'px, 0, 0)' }), Animit(this.decomp.leave.toolbar).queue({ opacity: -1 * swipeRatio // 1 -> 0 }), Animit(this.decomp.leave.toolbarCenter).queue({ transform: 'translate3d(' + (1 + swipeRatio) * 125 + '%, 0, 0)' }), Animit(this.decomp.leave.backButtonLabel).queue({ opacity: -1 * swipeRatio, // 1 -> 0 transform: 'translate3d(' + this.delta.title * (1 + swipeRatio) + 'px, 0, 0)' }), /* Other */ Animit(this.swipeShadow).queue({ opacity: -1 * swipeRatio // 1 -> 0 })); } else { Animit.runAll(Animit(leavePage).queue({ transform: 'translate3d(' + distance + 'px, 0, 0)' }), Animit(enterPage).queue({ transform: 'translate3d(' + swipeRatio * 25 + '%, 0, 0)', opacity: 1 + swipeRatio * 10 / 100 // 0.9 -> 1 }), Animit(this.swipeShadow).queue({ opacity: -1 * swipeRatio // 1 -> 0 })); } } }, { key: 'restore', value: function restore(enterPage, leavePage, callback) { var _this2 = this; if (this.isDragStart) { return; } if (this.shouldAnimateToolbar) { Animit.runAll( /* Enter page */ Animit([this.decomp.enter.content, this.decomp.enter.bottomToolbar, this.decomp.enter.background]).queue({ transform: 'translate3d(-25%, 0, 0)', opacity: 0.9 }, this.optRestore), Animit(this.decomp.enter.toolbarCenter).queue({ transform: 'translate3d(-' + this.delta.title + 'px, 0, 0)', transition: 'opacity ' + this.durationRestore + 's linear, transform ' + this.durationRestore + 's ' + this.timingSwipe, opacity: 0 }), Animit(this.decomp.enter.backButtonLabel).queue({ transform: 'translate3d(-' + this.delta.label + 'px, 0, 0)' }, this.optRestore), Animit(this.decomp.enter.other).queue({ opacity: 0 }, this.optRestore), /* Leave page */ Animit([this.decomp.leave.content, this.decomp.leave.bottomToolbar, this.decomp.leave.background, this.swipeShadow]).queue({ transform: 'translate3d(0, 0, 0)' }, this.optRestore), Animit(this.decomp.leave.toolbar).queue({ opacity: 1 }, this.optRestore), Animit(this.decomp.leave.toolbarCenter).queue({ transform: 'translate3d(0, 0, 0)' }, this.optRestore), Animit(this.decomp.leave.backButtonLabel).queue({ opacity: 1, transform: 'translate3d(0, 0, 0)', transition: 'opacity ' + this.durationRestore + 's linear, transform ' + this.durationRestore + 's ' + this.timingSwipe }), /* Other */ Animit(this.swipeShadow).queue({ opacity: 0 }, this.optRestore).queue(function (done) { _this2._reset(_this2.target.enter, _this2.target.leave); enterPage.style.display = 'none'; callback && callback(); done(); })); } else { Animit.runAll(Animit(enterPage).queue({ transform: 'translate3D(-25%, 0, 0)', opacity: 0.9 }, this.optRestore), Animit(leavePage).queue({ transform: 'translate3D(0, 0, 0)' }, this.optRestore).queue(function (done) { _this2._reset(enterPage, leavePage); enterPage.style.display = 'none'; callback && callback(); done(); })); } } }, { key: 'popSwipe', value: function popSwipe(enterPage, leavePage, callback) { var _this3 = this; if (this.isDragStart) { return; } if (this.shouldAnimateToolbar) { Animit.runAll( /* Enter page */ Animit([this.decomp.enter.content, this.decomp.enter.bottomToolbar, this.decomp.enter.background]).queue({ transform: 'translate3d(0, 0, 0)', opacity: 1 }, this.optSwipe), Animit(this.decomp.enter.toolbarCenter).queue({ transform: 'translate3d(0, 0, 0)', transition: 'opacity ' + this.durationSwipe + 's linear, transform ' + this.durationSwipe + 's ' + this.timingSwipe, opacity: 1 }), Animit(this.decomp.enter.backButtonLabel).queue({ transform: 'translate3d(0, 0, 0)' }, this.optSwipe), Animit(this.decomp.enter.other).queue({ opacity: 1 }, this.optSwipe), /* Leave page */ Animit([this.decomp.leave.content, this.decomp.leave.bottomToolbar, this.decomp.leave.background]).queue({ transform: 'translate3d(100%, 0, 0)' }, this.optSwipe), Animit(this.decomp.leave.toolbar).queue({ opacity: 0 }, this.optSwipe), Animit(this.decomp.leave.toolbarCenter).queue({ transform: 'translate3d(125%, 0, 0)' }, this.optSwipe), Animit(this.decomp.leave.backButtonLabel).queue({ opacity: 0, transform: 'translate3d(' + this.delta.title + 'px, 0, 0)', transition: 'opacity ' + this.durationSwipe + 's linear, transform ' + this.durationSwipe + 's ' + this.timingSwipe }), /* Other */ Animit(this.swipeShadow).queue({ opacity: 0, transform: 'translate3d(' + this.maxWidth + 'px, 0, 0)' }, this.optSwipe).queue(function (done) { _this3._reset(_this3.target.enter, _this3.target.leave); callback && callback(); done(); })); } else { Animit.runAll(Animit(enterPage).queue({ transform: 'translate3D(0, 0, 0)', opacity: 1.0 }, this.optSwipe), Animit(leavePage).queue({ transform: 'translate3D(100%, 0, 0)' }, this.optSwipe).queue(function (done) { _this3._reset(enterPage, leavePage); callback && callback(); done(); })); } } }, { key: '_saveStyle', value: function _saveStyle() { var _this4 = this; this._savedStyle = new WeakMap(); var save = function save(el) { return _this4._savedStyle.set(el, el.getAttribute('style')); }; for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } args.forEach(save); Object.keys(this.decomp).forEach(function (p) { Object.keys(_this4.decomp[p]).forEach(function (k) { (_this4.decomp[p][k] instanceof Array ? _this4.decomp[p][k] : [_this4.decomp[p][k]]).forEach(save); }); }); } }, { key: '_restoreStyle', value: function _restoreStyle() { var _this5 = this; var restore = function restore(el) { _this5._savedStyle.get(el) === null ? el.removeAttribute('style') : el.setAttribute('style', _this5._savedStyle.get(el)); _this5._savedStyle.delete(el); }; for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } args.forEach(restore); Object.keys(this.decomp).forEach(function (p) { Object.keys(_this5.decomp[p]).forEach(function (k) { (_this5.decomp[p][k] instanceof Array ? _this5.decomp[p][k] : [_this5.decomp[p][k]]).forEach(restore); }); }); } }, { key: '_reset', value: function _reset() { this.isSwiping = false; this._savedStyle && this._restoreStyle.apply(this, arguments); this.unblock && this.unblock(); this.swipeShadow.remove(); this.backgroundMask.remove(); this.overflowElement.classList.remove('overflow-visible'); this.decomp.leave.content.classList.remove('content-swiping'); this.decomp = this.target = this.overflowElement = this._savedStyle = null; this.isDragStart = true; } }]); return IOSSwipeNavigatorAnimator; }(NavigatorAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var translate3d = function translate3d() { var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; return 'translate3d(' + x + ', ' + y + ', ' + z + ')'; }; /** * Slide animator for navigator transition like iOS's screen slide transition. */ var IOSSlideNavigatorAnimator = function (_IOSSwipeNavigatorAni) { inherits(IOSSlideNavigatorAnimator, _IOSSwipeNavigatorAni); function IOSSlideNavigatorAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'cubic-bezier(0.3, .4, 0, .9)' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.4 : _ref$duration, rest = objectWithoutProperties(_ref, ['timing', 'delay', 'duration']); classCallCheck(this, IOSSlideNavigatorAnimator); var _this = possibleConstructorReturn(this, (IOSSlideNavigatorAnimator.__proto__ || Object.getPrototypeOf(IOSSlideNavigatorAnimator)).call(this, _extends({ timing: timing, delay: delay, duration: duration }, rest))); _this.backgroundMask = util$1.createElement('<div style="position: absolute; width: 100%; height: 100%;' + 'background-color: black; z-index: 2"></div>'); return _this; } createClass(IOSSlideNavigatorAnimator, [{ key: '_decompose', value: function _decompose(page) { var toolbar = page._getToolbarElement(); var left = toolbar._getToolbarLeftItemsElement(); var right = toolbar._getToolbarRightItemsElement(); var excludeBackButton = function excludeBackButton(elements) { var result = []; for (var i = 0; i < elements.length; i++) { if (elements[i].nodeName.toLowerCase() !== 'ons-back-button') { result.push(elements[i]); } } return result; }; var other = [].concat(left.children.length === 0 ? left : excludeBackButton(left.children)).concat(right.children.length === 0 ? right : excludeBackButton(right.children)); return { toolbarCenter: toolbar._getToolbarCenterItemsElement(), backButtonIcon: toolbar._getToolbarBackButtonIconElement(), backButtonLabel: toolbar._getToolbarBackButtonLabelElement(), other: other, content: page._getContentElement(), background: page._getBackgroundElement(), toolbar: toolbar, bottomToolbar: page._getBottomToolbarElement() }; } }, { key: '_shouldAnimateToolbar', value: function _shouldAnimateToolbar(enterPage, leavePage) { var toolbars = enterPage._canAnimateToolbar() && leavePage._canAnimateToolbar(); var enterToolbar = enterPage._getToolbarElement(); var leaveToolbar = leavePage._getToolbarElement(); var isStatic = enterToolbar.hasAttribute('static') || leaveToolbar.hasAttribute('static'); var isMaterial = util$1.hasModifier(enterToolbar, 'material') || util$1.hasModifier(leaveToolbar, 'material'); var isTransparent = util$1.hasModifier(enterToolbar, 'transparent') || util$1.hasModifier(leaveToolbar, 'transparent'); return toolbars && !isStatic && !isMaterial && !isTransparent; } }, { key: '_calculateDelta', value: function _calculateDelta(element, decomposition) { var title = void 0, label = void 0; var pageRect = element.getBoundingClientRect(); if (decomposition.backButtonLabel.classList.contains('back-button__label')) { var labelRect = decomposition.backButtonLabel.getBoundingClientRect(); title = Math.round(pageRect.width / 2 - labelRect.width / 2 - labelRect.left); } else { title = Math.round(pageRect.width / 2 * 0.6); } if (decomposition.backButtonIcon.classList.contains('back-button__icon')) { label = decomposition.backButtonIcon.getBoundingClientRect().right - 2; } return { title: title, label: label }; } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} callback */ }, { key: 'push', value: function push(enterPage, leavePage, callback) { var _this2 = this; this.backgroundMask.remove(); leavePage.parentNode.insertBefore(this.backgroundMask, leavePage); var unblock = get(IOSSlideNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSSlideNavigatorAnimator.prototype), 'block', this).call(this, enterPage); contentReady(enterPage, function () { var enterPageTarget = util$1.findToolbarPage(enterPage) || enterPage; var leavePageTarget = util$1.findToolbarPage(leavePage) || leavePage; var enterPageDecomposition = _this2._decompose(enterPageTarget); var leavePageDecomposition = _this2._decompose(leavePageTarget); var delta = _this2._calculateDelta(leavePage, enterPageDecomposition); var shouldAnimateToolbar = _this2._shouldAnimateToolbar(enterPageTarget, leavePageTarget); if (shouldAnimateToolbar) { Animit.runAll(Animit([enterPageDecomposition.content, enterPageDecomposition.bottomToolbar, enterPageDecomposition.background], _this2.def).default({ transform: translate3d('100%') }, { transform: translate3d() }), Animit(enterPageDecomposition.toolbar, _this2.def).default({ opacity: 0 }, { opacity: 1 }), Animit(enterPageDecomposition.toolbarCenter, _this2.def).default({ transform: translate3d('125%'), opacity: 1 }, { transform: translate3d(), opacity: 1 }), Animit(enterPageDecomposition.backButtonLabel, _this2.def).default({ transform: translate3d(delta.title + 'px'), opacity: 0 }, { transform: translate3d(), opacity: 1, transition: 'opacity ' + _this2.duration + 's linear, transform ' + _this2.duration + 's ' + _this2.timing }), Animit(enterPageDecomposition.other, _this2.def).default({ opacity: 0 }, { css: { opacity: 1 }, timing: 'linear' }), Animit([leavePageDecomposition.content, leavePageDecomposition.bottomToolbar, leavePageDecomposition.background], _this2.def).default({ transform: translate3d(), opacity: 1 }, { transform: translate3d('-25%'), opacity: 0.9 }).queue(function (done) { _this2.backgroundMask.remove(); unblock(); callback(); done(); }), Animit(leavePageDecomposition.toolbarCenter, _this2.def).default({ transform: translate3d(), opacity: 1 }, { transform: translate3d('-' + delta.title + 'px'), opacity: 0, transition: 'opacity ' + _this2.duration + 's linear, transform ' + _this2.duration + 's ' + _this2.timing }), Animit(leavePageDecomposition.backButtonLabel, _this2.def).default({ transform: translate3d(), opacity: 1 }, { transform: translate3d('-' + delta.label + 'px'), opacity: 0 }), Animit(leavePageDecomposition.other, _this2.def).default({ opacity: 1 }, { css: { opacity: 0 }, timing: 'linear' })); } else { Animit.runAll(Animit(enterPage, _this2.def).default({ transform: translate3d('100%') }, { transform: translate3d() }), Animit(leavePage, _this2.def).default({ transform: translate3d(), opacity: 1 }, { transform: translate3d('-25%'), opacity: .9 }).queue(function (done) { _this2.backgroundMask.remove(); unblock(); callback(); done(); })); } }); } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} callback */ }, { key: 'pop', value: function pop(enterPage, leavePage, callback) { var _this3 = this; if (this.isSwiping) { return this.popSwipe(enterPage, leavePage, callback); } this.backgroundMask.remove(); enterPage.parentNode.insertBefore(this.backgroundMask, enterPage); var unblock = get(IOSSlideNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSSlideNavigatorAnimator.prototype), 'block', this).call(this, enterPage); var enterPageTarget = util$1.findToolbarPage(enterPage) || enterPage; var leavePageTarget = util$1.findToolbarPage(leavePage) || leavePage; var enterPageDecomposition = this._decompose(enterPageTarget); var leavePageDecomposition = this._decompose(leavePageTarget); var delta = this._calculateDelta(leavePage, leavePageDecomposition); var shouldAnimateToolbar = this._shouldAnimateToolbar(enterPageTarget, leavePageTarget); if (shouldAnimateToolbar) { Animit.runAll(Animit([enterPageDecomposition.content, enterPageDecomposition.bottomToolbar, enterPageDecomposition.background], this.def).default({ transform: translate3d('-25%'), opacity: .9 }, { transform: translate3d(), opacity: 1 }), Animit(enterPageDecomposition.toolbarCenter, this.def).default({ transform: translate3d('-' + delta.title + 'px'), opacity: 0 }, { transform: translate3d(), opacity: 1, transition: 'opacity ' + this.duration + 's linear, transform ' + this.duration + 's ' + this.timing }), Animit(enterPageDecomposition.backButtonLabel, this.def).default({ transform: translate3d('-' + delta.label + 'px') }, { transform: translate3d() }), Animit(enterPageDecomposition.other, this.def).default({ opacity: 0 }, { css: { opacity: 1 }, timing: 'linear' }), Animit([leavePageDecomposition.content, leavePageDecomposition.bottomToolbar, leavePageDecomposition.background], this.def).default({ transform: translate3d() }, { transform: translate3d('100%') }).wait(0).queue(function (done) { _this3.backgroundMask.remove(); unblock(); callback(); done(); }), Animit(leavePageDecomposition.toolbar, this.def).default({ opacity: 1 }, { opacity: 0 }), Animit(leavePageDecomposition.toolbarCenter, this.def).default({ transform: translate3d() }, { transform: translate3d('125%') }), Animit(leavePageDecomposition.backButtonLabel, this.def).default({ transform: translate3d(), opacity: 1 }, { transform: translate3d(delta.title + 'px'), opacity: 0, transition: 'opacity ' + this.duration + 's linear, transform ' + this.duration + 's ' + this.timing })); } else { Animit.runAll(Animit(enterPage, this.def).default({ transform: translate3d('-25%'), opacity: .9 }, { transform: translate3d(), opacity: 1 }), Animit(leavePage, this.def).default({ transform: translate3d() }, { transform: translate3d('100%') }).queue(function (done) { _this3.backgroundMask.remove(); unblock(); callback(); done(); })); } } }]); return IOSSlideNavigatorAnimator; }(IOSSwipeNavigatorAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Lift screen transition. */ var IOSLiftNavigatorAnimator = function (_NavigatorAnimator) { inherits(IOSLiftNavigatorAnimator, _NavigatorAnimator); function IOSLiftNavigatorAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'cubic-bezier(.1, .7, .1, 1)' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.4 : _ref$duration; classCallCheck(this, IOSLiftNavigatorAnimator); var _this = possibleConstructorReturn(this, (IOSLiftNavigatorAnimator.__proto__ || Object.getPrototypeOf(IOSLiftNavigatorAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); _this.backgroundMask = util$1.createElement('<div style="position: absolute; width: 100%; height: 100%;' + 'background: linear-gradient(black, white);"></div>'); return _this; } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} callback */ createClass(IOSLiftNavigatorAnimator, [{ key: 'push', value: function push(enterPage, leavePage, callback) { var _this2 = this; this.backgroundMask.remove(); leavePage.parentNode.insertBefore(this.backgroundMask, leavePage); var unblock = get(IOSLiftNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSLiftNavigatorAnimator.prototype), 'block', this).call(this, enterPage); Animit.runAll(Animit(enterPage, this.def).default({ transform: 'translate3D(0, 100%, 0)' }, { transform: 'translate3D(0, 0, 0)' }), Animit(leavePage, this.def).default({ transform: 'translate3D(0, 0, 0)', opacity: 1 }, { transform: 'translate3D(0, -10%, 0)', opacity: .9 }).queue(function (done) { _this2.backgroundMask.remove(); unblock(); callback(); done(); })); } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} callback */ }, { key: 'pop', value: function pop(enterPage, leavePage, callback) { var _this3 = this; this.backgroundMask.remove(); enterPage.parentNode.insertBefore(this.backgroundMask, enterPage); var unblock = get(IOSLiftNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSLiftNavigatorAnimator.prototype), 'block', this).call(this, enterPage); Animit.runAll(Animit(enterPage, this.def).default({ transform: 'translate3D(0, -43px, 0)', opacity: .9 }, { transform: 'translate3D(0, 0, 0)', opacity: 1 }).queue(function (done) { _this3.backgroundMask.remove(); unblock(); callback(); done(); }), Animit(leavePage, this.def).default({ transform: 'translate3D(0, 0, 0)' }, { transform: 'translate3D(0, 100%, 0)' })); } }]); return IOSLiftNavigatorAnimator; }(NavigatorAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var transform = 'translate3d(0, 0, 0)'; /** * Fade-in screen transition. */ var IOSFadeNavigatorAnimator = function (_NavigatorAnimator) { inherits(IOSFadeNavigatorAnimator, _NavigatorAnimator); function IOSFadeNavigatorAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'linear' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.4 : _ref$duration; classCallCheck(this, IOSFadeNavigatorAnimator); return possibleConstructorReturn(this, (IOSFadeNavigatorAnimator.__proto__ || Object.getPrototypeOf(IOSFadeNavigatorAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} callback */ createClass(IOSFadeNavigatorAnimator, [{ key: 'push', value: function push(enterPage, leavePage, callback) { var unblock = get(IOSFadeNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSFadeNavigatorAnimator.prototype), 'block', this).call(this, enterPage); Animit.runAll(Animit(enterPage, this.def).default({ transform: transform, opacity: 0 }, { transform: transform, opacity: 1 }).queue(function (done) { unblock(); callback(); done(); })); } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} done */ }, { key: 'pop', value: function pop(enterPage, leavePage, callback) { var unblock = get(IOSFadeNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(IOSFadeNavigatorAnimator.prototype), 'block', this).call(this, enterPage); Animit.runAll(Animit(leavePage, this.def).default({ transform: transform, opacity: 1 }, { transform: transform, opacity: 0 }).queue(function (done) { unblock(); callback(); done(); })); } }]); return IOSFadeNavigatorAnimator; }(NavigatorAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Slide animator for navigator transition. */ var MDSlideNavigatorAnimator = function (_NavigatorAnimator) { inherits(MDSlideNavigatorAnimator, _NavigatorAnimator); function MDSlideNavigatorAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.3 : _ref$duration; classCallCheck(this, MDSlideNavigatorAnimator); var _this = possibleConstructorReturn(this, (MDSlideNavigatorAnimator.__proto__ || Object.getPrototypeOf(MDSlideNavigatorAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); _this.blackMaskOpacity = 0.4; _this.backgroundMask = util$1.createElement('<div style="position: absolute; width: 100%; height: 100%; z-index: 2;' + 'background-color: black; opacity: 0;"></div>'); return _this; } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} callback */ createClass(MDSlideNavigatorAnimator, [{ key: 'push', value: function push(enterPage, leavePage, callback) { var _this2 = this; this.backgroundMask.remove(); leavePage.parentElement.insertBefore(this.backgroundMask, leavePage.nextSibling); var unblock = get(MDSlideNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDSlideNavigatorAnimator.prototype), 'block', this).call(this, enterPage); Animit.runAll(Animit(this.backgroundMask, this.def).default({ transform: 'translate3d(0, 0, 0)', opacity: 0 }, { opacity: this.blackMaskOpacity }).queue(function (done) { _this2.backgroundMask.remove(); done(); }), Animit(enterPage, this.def).default({ transform: 'translate3d(100%, 0, 0)' }, { transform: 'translate3d(0, 0, 0)' }), Animit(leavePage, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(-45%, 0, 0)' }).queue(function (done) { unblock(); callback(); done(); })); } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} callback */ }, { key: 'pop', value: function pop(enterPage, leavePage, callback) { var _this3 = this; this.backgroundMask.remove(); enterPage.parentNode.insertBefore(this.backgroundMask, enterPage.nextSibling); var unblock = get(MDSlideNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDSlideNavigatorAnimator.prototype), 'block', this).call(this, enterPage); Animit.runAll(Animit(this.backgroundMask, this.def).default({ transform: 'translate3d(0, 0, 0)', opacity: this.blackMaskOpacity }, { opacity: 0 }).queue(function (done) { _this3.backgroundMask.remove(); done(); }), Animit(enterPage, this.def).default({ transform: 'translate3d(-45%, 0, 0)', opacity: .9 }, { transform: 'translate3d(0, 0, 0)', opacity: 1 }), Animit(leavePage, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(100%, 0, 0)' }).queue(function (done) { unblock(); callback(); done(); })); } }]); return MDSlideNavigatorAnimator; }(NavigatorAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Lift screen transition. */ var MDLiftNavigatorAnimator = function (_NavigatorAnimator) { inherits(MDLiftNavigatorAnimator, _NavigatorAnimator); function MDLiftNavigatorAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'cubic-bezier(.1, .7, .1, 1)' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0.05 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.4 : _ref$duration; classCallCheck(this, MDLiftNavigatorAnimator); var _this = possibleConstructorReturn(this, (MDLiftNavigatorAnimator.__proto__ || Object.getPrototypeOf(MDLiftNavigatorAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); _this.backgroundMask = util$1.createElement('<div style="position: absolute; width: 100%; height: 100%;' + 'background-color: black;"></div>'); return _this; } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} callback */ createClass(MDLiftNavigatorAnimator, [{ key: 'push', value: function push(enterPage, leavePage, callback) { var _this2 = this; this.backgroundMask.remove(); leavePage.parentNode.insertBefore(this.backgroundMask, leavePage); var unblock = get(MDLiftNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDLiftNavigatorAnimator.prototype), 'block', this).call(this, enterPage); var maskClear = Animit(this.backgroundMask).wait(this.delay + this.duration).queue(function (done) { _this2.backgroundMask.remove(); done(); }); Animit.runAll(maskClear, Animit(enterPage, this.def).default({ transform: 'translate3d(0, 100%, 0)' }, { transform: 'translate3d(0, 0, 0)' }), Animit(leavePage, this.def).default({ opacity: 1 }, { opacity: .4 }).queue(function (done) { unblock(); callback(); done(); })); } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} callback */ }, { key: 'pop', value: function pop(enterPage, leavePage, callback) { var _this3 = this; this.backgroundMask.remove(); enterPage.parentNode.insertBefore(this.backgroundMask, enterPage); var unblock = get(MDLiftNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDLiftNavigatorAnimator.prototype), 'block', this).call(this, enterPage); Animit.runAll(Animit(this.backgroundMask).wait(this.delay + this.duration).queue(function (done) { _this3.backgroundMask.remove(); done(); }), Animit(enterPage, this.def).default({ opacity: .4 }, { opacity: 1 }).queue(function (done) { unblock(); callback(); done(); }), Animit(leavePage, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(0, 100%, 0)' })); } }]); return MDLiftNavigatorAnimator; }(NavigatorAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Fade-in + Lift screen transition. */ var MDFadeNavigatorAnimator = function (_NavigatorAnimator) { inherits(MDFadeNavigatorAnimator, _NavigatorAnimator); function MDFadeNavigatorAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'cubic-bezier(0.4, 0, 0.2, 1)' : _ref$timing, _ref$timingPop = _ref.timingPop, timingPop = _ref$timingPop === undefined ? 'cubic-bezier(0.4, 0, 1, 1)' : _ref$timingPop, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.2 : _ref$duration; classCallCheck(this, MDFadeNavigatorAnimator); var _this = possibleConstructorReturn(this, (MDFadeNavigatorAnimator.__proto__ || Object.getPrototypeOf(MDFadeNavigatorAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); _this.timingPop = timingPop; return _this; } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} callback */ createClass(MDFadeNavigatorAnimator, [{ key: 'push', value: function push(enterPage, leavePage, callback) { var unblock = get(MDFadeNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDFadeNavigatorAnimator.prototype), 'block', this).call(this, enterPage); Animit.runAll(Animit(enterPage, this.def).default({ transform: 'translate3D(0, 42px, 0)', opacity: 0 }, { transform: 'translate3D(0, 0, 0)', opacity: 1 }).queue(function (done) { unblock(); callback(); done(); })); } /** * @param {Object} enterPage * @param {Object} leavePage * @param {Function} done */ }, { key: 'pop', value: function pop(enterPage, leavePage, callback) { var unblock = get(MDFadeNavigatorAnimator.prototype.__proto__ || Object.getPrototypeOf(MDFadeNavigatorAnimator.prototype), 'block', this).call(this, enterPage); Animit.runAll(Animit(leavePage, this.def).default({ transform: 'translate3D(0, 0, 0)', opacity: 1 }, { css: { transform: 'translate3D(0, 38px, 0)', opacity: 0 }, timing: this.timingPop }).queue(function (done) { unblock(); callback(); done(); })); } }]); return MDFadeNavigatorAnimator; }(NavigatorAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var NoneNavigatorAnimator = function (_NavigatorAnimator) { inherits(NoneNavigatorAnimator, _NavigatorAnimator); function NoneNavigatorAnimator(options) { classCallCheck(this, NoneNavigatorAnimator); return possibleConstructorReturn(this, (NoneNavigatorAnimator.__proto__ || Object.getPrototypeOf(NoneNavigatorAnimator)).call(this, options)); } createClass(NoneNavigatorAnimator, [{ key: 'push', value: function push(enterPage, leavePage, callback) { callback(); } }, { key: 'pop', value: function pop(enterPage, leavePage, callback) { callback(); } }]); return NoneNavigatorAnimator; }(NavigatorAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var _animatorDict$5 = { 'default': function _default() { return platform.isAndroid() ? MDFadeNavigatorAnimator : IOSSlideNavigatorAnimator; }, 'slide': function slide() { return platform.isAndroid() ? MDSlideNavigatorAnimator : IOSSlideNavigatorAnimator; }, 'lift': function lift() { return platform.isAndroid() ? MDLiftNavigatorAnimator : IOSLiftNavigatorAnimator; }, 'fade': function fade() { return platform.isAndroid() ? MDFadeNavigatorAnimator : IOSFadeNavigatorAnimator; }, 'slide-ios': IOSSlideNavigatorAnimator, 'slide-md': MDSlideNavigatorAnimator, 'lift-ios': IOSLiftNavigatorAnimator, 'lift-md': MDLiftNavigatorAnimator, 'fade-ios': IOSFadeNavigatorAnimator, 'fade-md': MDFadeNavigatorAnimator, 'none': NoneNavigatorAnimator }; var rewritables = { /** * @param {Element} navigatorSideElement * @param {Function} callback */ ready: function ready(navigatorElement, callback) { callback(); } }; var verifyPageElement = function verifyPageElement(el) { return el.nodeName !== 'ONS-PAGE' && util$1.throw('Only page elements can be children of navigator'); }; /** * @element ons-navigator * @category navigation * @description * [en] * A component that provides page stack management and navigation. Stack navigation is the most common navigation pattern for mobile apps. * * When a page is pushed on top of the stack it is displayed with a transition animation. When the user returns to the previous page the top page will be popped from the top of the stack and hidden with an opposite transition animation. * [/en] * [ja][/ja] * @codepen yrhtv * @tutorial vanilla/Reference/navigator * @guide lifecycle.html#events * [en]Overview of page events[/en] * [ja]Overview of page events[/ja] * @seealso ons-toolbar * [en]The `<ons-toolbar>` component is used to display a toolbar on the top of a page.[/en] * [ja][/ja] * @seealso ons-back-button * [en]The `<ons-back-button>` component lets the user return to the previous page.[/en] * [ja][/ja] * @example * <ons-navigator id="navigator"> * <ons-page> * <ons-toolbar> * <div class="center"> * Title * </div> * </ons-toolbar> * <p> * <ons-button * onclick="document.getElementById('navigator').pushPage('page.html')"> * Push page * </ons-button> * </p> * </ons-page> * </ons-navigator> * * <template id="page.html"> * <ons-page> * <ons-toolbar> * <div class="left"> * <ons-back-button>Back</ons-back-button> * </div> * <div class="center"> * Another page * </div> * </ons-toolbar> * </ons-page> * </template> */ var NavigatorElement = function (_BaseElement) { inherits(NavigatorElement, _BaseElement); createClass(NavigatorElement, [{ key: 'animatorFactory', /** * @attribute page * @initonly * @type {String} * @description * [en]First page to show when navigator is initialized.[/en] * [ja]ナビゲーターが初期化された時に表示するページを指定します。[/ja] */ /** * @attribute swipeable * @type {Boolean} * @description * [en]Enable iOS "swipe to pop" feature.[/en] * [ja][/ja] */ /** * @attribute swipe-target-width * @type {String} * @default 20px * @description * [en]The width of swipeable area calculated from the edge (in pixels). Use this to enable swipe only when the finger touch on the screen edge.[/en] * [ja]スワイプの判定領域をピクセル単位で指定します。画面の端から指定した距離に達するとページが表示されます。[/ja] */ /** * @attribute swipe-threshold * @type {Number} * @default 0.2 * @description * [en]Specify how much the page needs to be swiped before popping. A value between `0` and `1`.[/en] * [ja][/ja] */ /** * @attribute animation * @type {String} * @default default * @description * [en] * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`. * * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"` depending on the platform. * [/en] * [ja][/ja] */ /** * @attribute animation-options * @type {Expression} * @description * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/en] * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`[/ja] */ /** * @event prepush * @description * [en]Fired just before a page is pushed.[/en] * [ja]pageがpushされる直前に発火されます。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.navigator * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Object} event.currentPage * [en]Current page object.[/en] * [ja]現在のpageオブジェクト。[/ja] * @param {Function} event.cancel * [en]Call this function to cancel the push.[/en] * [ja]この関数を呼び出すと、push処理がキャンセルされます。[/ja] */ /** * @event prepop * @description * [en]Fired just before a page is popped.[/en] * [ja]pageがpopされる直前に発火されます。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.navigator * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Object} event.currentPage * [en]Current page object.[/en] * [ja]現在のpageオブジェクト。[/ja] * @param {Function} event.cancel * [en]Call this function to cancel the pop.[/en] * [ja]この関数を呼び出すと、pageのpopがキャンセルされます。[/ja] */ /** * @event postpush * @description * [en]Fired just after a page is pushed.[/en] * [ja]pageがpushされてアニメーションが終了してから発火されます。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.navigator * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Object} event.enterPage * [en]Object of the next page.[/en] * [ja]pushされたpageオブジェクト。[/ja] * @param {Object} event.leavePage * [en]Object of the previous page.[/en] * [ja]以前のpageオブジェクト。[/ja] */ /** * @event postpop * @description * [en]Fired just after a page is popped.[/en] * [ja]pageがpopされてアニメーションが終わった後に発火されます。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.navigator * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Object} event.enterPage * [en]Object of the next page.[/en] * [ja]popされて表示されるページのオブジェクト。[/ja] * @param {Object} event.leavePage * [en]Object of the previous page.[/en] * [ja]popされて消えるページのオブジェクト。[/ja] */ get: function get$$1() { return this._animatorFactory; } }]); function NavigatorElement() { classCallCheck(this, NavigatorElement); var _this = possibleConstructorReturn(this, (NavigatorElement.__proto__ || Object.getPrototypeOf(NavigatorElement)).call(this)); _this._isRunning = false; _this._initialized = false; _this._pageLoader = defaultPageLoader; _this._pageMap = new WeakMap(); _this._updateAnimatorFactory(); return _this; } /** * @property pageLoader * @type {PageLoader} * @description * [en]PageLoader instance. It can be overriden to change the way pages are loaded by this element. Useful for lib developers.[/en] * [ja]PageLoaderインスタンスを格納しています。[/ja] */ createClass(NavigatorElement, [{ key: '_getPageTarget', value: function _getPageTarget() { return this._page || this.getAttribute('page'); } /** * @property page * @type {*} * @description * [en]Specify the page to be loaded during initialization. This value takes precedence over the `page` attribute. Useful for lib developers.[/en] * [ja]初期化時に読み込むページを指定します。`page`属性で指定した値よりも`page`プロパティに指定した値を優先します。[/ja] */ }, { key: 'connectedCallback', value: function connectedCallback() { var _this2 = this; this.onDeviceBackButton = this._onDeviceBackButton.bind(this); if (!platform.isAndroid() || this.getAttribute('swipeable') === 'force') { var swipeAnimator = void 0; this._swipe = new SwipeReveal({ element: this, getThreshold: function getThreshold() { return Math.max(0.2, parseFloat(_this2.getAttribute('swipe-threshold')) || 0); }, swipeMax: function swipeMax() { _this2._onSwipe && _this2._onSwipe(1, { duration: swipeAnimator.durationSwipe, timing: swipeAnimator.timingSwipe }); _this2[_this2.swipeMax ? 'swipeMax' : 'popPage']({ animator: swipeAnimator }); swipeAnimator = null; }, swipeMid: function swipeMid(distance, width) { _this2._onSwipe && _this2._onSwipe(distance / width); swipeAnimator.translate(distance, width, _this2.topPage.previousElementSibling, _this2.topPage); }, swipeMin: function swipeMin() { _this2._onSwipe && _this2._onSwipe(0, { duration: swipeAnimator.durationRestore, timing: swipeAnimator.timingSwipe }); swipeAnimator.restore(_this2.topPage.previousElementSibling, _this2.topPage); swipeAnimator = null; }, ignoreSwipe: function ignoreSwipe(event, distance) { // Basic conditions if (!_this2._isRunning && _this2.children.length > 1) { // Area or directional issues var area = parseInt(_this2.getAttribute('swipe-target-width') || 25, 10); if (event.gesture.direction === 'right' && area > distance) { // Swipes on ons-back-button and its children var isBB = function isBB(el) { return (/ons-back-button/i.test(el.tagName) ); }; if (!isBB(event.target) && !util$1.findParent(event.target, isBB, function (p) { return (/ons-page/i.test(p.tagName) ); })) { // Animator is swipeable var animation = (_this2.topPage.pushedOptions || {}).animation || _this2.animatorFactory._animation; var Animator = _animatorDict$5[animation] instanceof Function ? _animatorDict$5[animation].call() : _animatorDict$5[animation]; if (typeof Animator !== 'undefined' && Animator.swipeable) { swipeAnimator = new Animator(); // Prepare for the swipe return false; } } } } return true; // Ignore swipe } }); this.attributeChangedCallback('swipeable'); } if (this._initialized) { return; } this._initialized = true; var deferred = util$1.defer(); this.loaded = deferred.promise; rewritables.ready(this, function () { var show = !util$1.hasAnyComponentAsParent(_this2); var options = { animation: 'none', show: show }; if (_this2.pages.length === 0 && _this2._getPageTarget()) { _this2.pushPage(_this2._getPageTarget(), options).then(function () { return deferred.resolve(); }); } else if (_this2.pages.length > 0) { for (var i = 0; i < _this2.pages.length; i++) { verifyPageElement(_this2.pages[i]); } if (_this2.topPage) { contentReady(_this2.topPage, function () { return setTimeout(function () { deferred.resolve(); show && _this2.topPage._show(); _this2._updateLastPageBackButton(); }, 0); }); } } else { contentReady(_this2, function () { if (_this2.pages.length === 0 && _this2._getPageTarget()) { _this2.pushPage(_this2._getPageTarget(), options).then(function () { return deferred.resolve(); }); } else { deferred.resolve(); } }); } }); } }, { key: '_updateAnimatorFactory', value: function _updateAnimatorFactory() { this._animatorFactory = new AnimatorFactory({ animators: _animatorDict$5, baseClass: NavigatorAnimator, baseClassName: 'NavigatorAnimator', defaultAnimation: this.getAttribute('animation') }); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this._backButtonHandler.destroy(); this._backButtonHandler = null; this._swipe && this._swipe.dispose(); this._swipe = null; } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'animation': this._updateAnimatorFactory(); break; case 'swipeable': this._swipe && this._swipe.update(); break; } } /** * @method popPage * @signature popPage([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en] * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`. * * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"`. * [/en] * [ja][/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja] * @param {Function} [options.callback] * [en]Function that is called when the transition has ended.[/en] * [ja]このメソッドによる画面遷移が終了した際に呼び出される関数オブジェクトを指定します。[/ja] * @param {Object} [options.data] * [en]Custom data that will be stored in the new page element.[/en] * [ja][/ja] * @param {Number} [options.times] * [en]Number of pages to be popped. Only one animation will be shown.[/en] * [ja][/ja] * @return {Promise} * [en]Promise which resolves to the revealed page.[/en] * [ja]明らかにしたページを解決するPromiseを返します。[/ja] * @description * [en]Pops the current page from the page stack. The previous page will be displayed.[/en] * [ja]現在表示中のページをページスタックから取り除きます。一つ前のページに戻ります。[/ja] */ }, { key: 'popPage', value: function popPage() { var _this3 = this; var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var _preparePageAndOption = this._preparePageAndOptions(null, options); options = _preparePageAndOption.options; if (util$1.isInteger(options.times) && options.times > 1) { this._removePages(options.times); } var popUpdate = function popUpdate() { return new Promise(function (resolve) { _this3._pageLoader.unload(_this3.pages[_this3.pages.length - 1]); resolve(); }); }; return this._popPage(options, popUpdate); } }, { key: '_popPage', value: function _popPage(options) { var _this4 = this; var update = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () { return Promise.resolve(); }; if (this._isRunning) { return Promise.reject('popPage is already running.'); } if (this.pages.length <= 1) { return Promise.reject('ons-navigator\'s page stack is empty.'); } if (this._emitPrePopEvent()) { return Promise.reject('Canceled in prepop event.'); } var length = this.pages.length; this._isRunning = true; this.pages[length - 2].updateBackButton(length - 2 > 0); return new Promise(function (resolve) { var leavePage = _this4.pages[length - 1]; var enterPage = _this4.pages[length - 2]; options = util$1.extend({}, _this4.options || {}, leavePage.pushedOptions || {}, options); if (options.data) { enterPage.data = util$1.extend({}, enterPage.data || {}, options.data || {}); } var done = function done() { update().then(function () { _this4._isRunning = false; enterPage._show(); util$1.triggerElementEvent(_this4, 'postpop', { leavePage: leavePage, enterPage: enterPage, navigator: _this4 }); options.callback && options.callback(enterPage); resolve(enterPage); }); }; leavePage._hide(); enterPage.style.display = ''; var animator = options.animator || _this4._animatorFactory.newAnimator(options); animator.pop(_this4.pages[length - 2], _this4.pages[length - 1], done); }).catch(function () { return _this4._isRunning = false; }); } /** * @method pushPage * @signature pushPage(page, [options]) * @param {String} page * [en]Page URL. Can be either a HTML document or a template defined with the `<template>` tag.[/en] * [ja]pageのURLか、もしくは`<template>`で宣言したテンプレートのid属性の値を指定できます。[/ja] * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.page] * [en]Page URL. Only necessary if `page` parameter is null or undefined.[/en] * [ja][/ja] * @param {String} [options.pageHTML] * [en]HTML code that will be computed as a new page. Overwrites `page` parameter.[/en] * [ja][/ja] * @param {String} [options.animation] * [en] * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`. * * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"`. * [/en] * [ja][/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja] * @param {Function} [options.callback] * [en]Function that is called when the transition has ended.[/en] * [ja]pushPage()による画面遷移が終了した時に呼び出される関数オブジェクトを指定します。[/ja] * @param {Object} [options.data] * [en]Custom data that will be stored in the new page element.[/en] * [ja][/ja] * @return {Promise} * [en]Promise which resolves to the pushed page.[/en] * [ja]追加したページを解決するPromiseを返します。[/ja] * @description * [en]Pushes the specified page into the stack.[/en] * [ja]指定したpageを新しいページスタックに追加します。新しいページが表示されます。[/ja] */ }, { key: 'pushPage', value: function pushPage(page) { var _this5 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var _preparePageAndOption2 = this._preparePageAndOptions(page, options); page = _preparePageAndOption2.page; options = _preparePageAndOption2.options; var prepare = function prepare(pageElement) { verifyPageElement(pageElement); _this5._pageMap.set(pageElement, page); pageElement = util$1.extend(pageElement, { data: options.data }); pageElement.style.visibility = 'hidden'; }; if (options.pageHTML) { return this._pushPage(options, function () { return new Promise(function (resolve) { instantPageLoader.load({ page: options.pageHTML, parent: _this5, params: options.data }, function (pageElement) { prepare(pageElement); resolve(); }); }); }); } return this._pushPage(options, function () { return new Promise(function (resolve) { _this5._pageLoader.load({ page: page, parent: _this5, params: options.data }, function (pageElement) { prepare(pageElement); resolve(); }); }); }); } }, { key: '_pushPage', value: function _pushPage() { var _this6 = this; var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var update = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () { return Promise.resolve(); }; if (this._isRunning) { return Promise.reject('pushPage is already running.'); } if (this._emitPrePushEvent()) { return Promise.reject('Canceled in prepush event.'); } this._isRunning = true; var animationOptions = AnimatorFactory.parseAnimationOptionsString(this.getAttribute('animation-options')); options = util$1.extend({}, this.options || {}, { animationOptions: animationOptions }, options); var animator = this._animatorFactory.newAnimator(options); return update().then(function () { var pageLength = _this6.pages.length; var enterPage = _this6.pages[pageLength - 1]; var leavePage = options.leavePage || _this6.pages[pageLength - 2]; verifyPageElement(enterPage); enterPage.updateBackButton(pageLength > (options._replacePage ? 2 : 1)); enterPage.pushedOptions = util$1.extend({}, enterPage.pushedOptions || {}, options || {}); enterPage.data = util$1.extend({}, enterPage.data || {}, options.data || {}); enterPage.unload = enterPage.unload || options.unload; return new Promise(function (resolve) { var done = function done() { _this6._isRunning = false; options.show !== false && setImmediate(function () { return enterPage._show(); }); util$1.triggerElementEvent(_this6, 'postpush', { leavePage: leavePage, enterPage: enterPage, navigator: _this6 }); if (leavePage) { leavePage.style.display = 'none'; } options.callback && options.callback(enterPage); resolve(enterPage); }; enterPage.style.visibility = ''; if (leavePage) { leavePage._hide(); animator.push(enterPage, leavePage, done); } else { done(); } }); }).catch(function (error) { _this6._isRunning = false; throw error; }); } /** * @method replacePage * @signature replacePage(page, [options]) * @return {Promise} * [en]Promise which resolves to the new page.[/en] * [ja]新しいページを解決するPromiseを返します。[/ja] * @description * [en]Replaces the current top page with the specified one. Extends `pushPage()` parameters.[/en] * [ja]現在表示中のページをを指定したページに置き換えます。[/ja] */ }, { key: 'replacePage', value: function replacePage(page) { var _this7 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return this.pushPage(page, options).then(function (resolvedValue) { if (_this7.pages.length > 1) { _this7._pageLoader.unload(_this7.pages[_this7.pages.length - 2]); } _this7._updateLastPageBackButton(); return Promise.resolve(resolvedValue); }); } /** * @method insertPage * @signature insertPage(index, page, [options]) * @param {Number} index * [en]The index where it should be inserted.[/en] * [ja]スタックに挿入する位置のインデックスを指定します。[/ja] * @return {Promise} * [en]Promise which resolves to the inserted page.[/en] * [ja]指定したページを解決するPromiseを返します。[/ja] * @description * [en]Insert the specified page into the stack with at a position defined by the `index` argument. Extends `pushPage()` parameters.[/en] * [ja]指定したpageをページスタックのindexで指定した位置に追加します。[/ja] */ }, { key: 'insertPage', value: function insertPage(index, page) { var _this8 = this; var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var _preparePageAndOption3 = this._preparePageAndOptions(page, options); page = _preparePageAndOption3.page; options = _preparePageAndOption3.options; index = this._normalizeIndex(index); if (index >= this.pages.length) { return this.pushPage(page, options); } page = typeof options.pageHTML === 'string' ? options.pageHTML : page; var loader = typeof options.pageHTML === 'string' ? instantPageLoader : this._pageLoader; return new Promise(function (resolve) { loader.load({ page: page, parent: _this8 }, function (pageElement) { verifyPageElement(pageElement); _this8._pageMap.set(pageElement, page); pageElement = util$1.extend(pageElement, { data: options.data, pushedOptions: options }); options.animationOptions = util$1.extend({}, AnimatorFactory.parseAnimationOptionsString(_this8.getAttribute('animation-options')), options.animationOptions || {}); pageElement.style.display = 'none'; _this8.insertBefore(pageElement, _this8.pages[index]); _this8.topPage.updateBackButton(true); setTimeout(function () { pageElement = null; resolve(_this8.pages[index]); }, 1000 / 60); }); }); } /** * @method removePage * @signature removePage(index, [options]) * @param {Number} index * [en]The index where it should be removed.[/en] * [ja]スタックから削除するページのインデックスを指定します。[/ja] * @return {Promise} * [en]Promise which resolves to the revealed page.[/en] * [ja]削除によって表示されたページを解決するPromiseを返します。[/ja] * @description * [en]Remove the specified page at a position in the stack defined by the `index` argument. Extends `popPage()` parameters.[/en] * [ja]指定したインデックスにあるページを削除します。[/ja] */ }, { key: 'removePage', value: function removePage(index) { var _this9 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; index = this._normalizeIndex(index); if (index < this.pages.length - 1) { return new Promise(function (resolve) { var leavePage = _this9.pages[index]; var enterPage = _this9.topPage; _this9._pageMap.delete(leavePage); _this9._pageLoader.unload(leavePage); if (_this9.pages.length === 1) { // edge case _this9.topPage.updateBackButton(false); } resolve(enterPage); }); } else { return this.popPage(options); } } /** * @method resetToPage * @signature resetToPage(page, [options]) * @return {Promise} * [en]Promise which resolves to the new top page.[/en] * [ja]新しいトップページを解決するPromiseを返します。[/ja] * @param {Boolean} [options.pop] * [en]Performs 'pop' effect if `true` instead of 'push' or none. This also sets `options.animation` value to `default` instead of `none`.[/en] * [ja][/ja] * @description * [en]Clears page stack and adds the specified page to the stack. Extends `pushPage()` parameters.[/en] * [ja]ページスタックをリセットし、指定したページを表示します。[/ja] */ }, { key: 'resetToPage', value: function resetToPage(page) { var _this10 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var _preparePageAndOption4 = this._preparePageAndOptions(page, options); page = _preparePageAndOption4.page; options = _preparePageAndOption4.options; if (!options.animator && !options.animation && !options.pop) { options.animation = 'none'; } if (!options.page && !options.pageHTML && this._getPageTarget()) { page = options.page = this._getPageTarget(); } if (options.pop) { this._removePages(); return this.insertPage(0, page, { data: options.data }).then(function () { return _this10.popPage(options); }); } // Tip: callback runs before resolved promise var callback = options.callback; options.callback = function (newPage) { _this10._removePages(); newPage.updateBackButton(false); callback && callback(newPage); }; return this.pushPage(page, options); } /** * @method bringPageTop * @signature bringPageTop(item, [options]) * @param {String|Number} item * [en]Page URL or index of an existing page in navigator's stack.[/en] * [ja]ページのURLかもしくはons-navigatorのページスタックのインデックス値を指定します。[/ja] * @return {Promise} * [en]Promise which resolves to the new top page.[/en] * [ja]新しいトップページを解決するPromiseを返します。[/ja] * @description * [en]Brings the given page to the top of the page stack if it already exists or pushes it into the stack if doesn't. Extends `pushPage()` parameters.[/en] * [ja]指定したページをページスタックの一番上に移動します。もし指定したページが無かった場合新しくpushされます。[/ja] */ }, { key: 'bringPageTop', value: function bringPageTop(item) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (['number', 'string'].indexOf(typeof item === 'undefined' ? 'undefined' : _typeof(item)) === -1) { util$1.throw('First argument must be a page name or the index of an existing page. You supplied ' + item); } var index = typeof item === 'number' ? this._normalizeIndex(item) : this._lastIndexOfPage(item); var page = this.pages[index]; if (index < 0) { return this.pushPage(item, options); } var _preparePageAndOption5 = this._preparePageAndOptions(page, options); options = _preparePageAndOption5.options; if (index === this.pages.length - 1) { return Promise.resolve(page); } if (!page) { util$1.throw('Failed to find item ' + item); } if (this._isRunning) { return Promise.reject('pushPage is already running.'); } if (this._emitPrePushEvent()) { return Promise.reject('Canceled in prepush event.'); } page.style.display = ''; page.style.visibility = 'hidden'; page.parentNode.appendChild(page); return this._pushPage(options); } }, { key: '_preparePageAndOptions', value: function _preparePageAndOptions(page) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) != 'object') { util$1.throw('options must be an object. You supplied ' + options); } if ((page === null || page === undefined) && options.page) { page = options.page; } options = util$1.extend({}, this.options || {}, options, { page: page }); return { page: page, options: options }; } }, { key: '_removePages', value: function _removePages(times) { var pages = this.pages; var until = times === undefined ? 0 : pages.length - times; until = until < 0 ? 1 : until; for (var i = pages.length - 2; i >= until; i--) { this._pageMap.delete(pages[i]); this._pageLoader.unload(pages[i]); } } }, { key: '_updateLastPageBackButton', value: function _updateLastPageBackButton() { var index = this.pages.length - 1; if (index >= 0) { this.pages[index].updateBackButton(index > 0); } } }, { key: '_normalizeIndex', value: function _normalizeIndex(index) { return index >= 0 ? index : Math.abs(this.pages.length + index) % this.pages.length; } }, { key: '_onDeviceBackButton', value: function _onDeviceBackButton(event) { if (this.pages.length > 1) { this.popPage(); } else { event.callParentHandler(); } } }, { key: '_lastIndexOfPage', value: function _lastIndexOfPage(pageName) { var index = void 0; for (index = this.pages.length - 1; index >= 0; index--) { if (pageName === this._pageMap.get(this.pages[index])) { break; } } return index; } }, { key: '_emitPreEvent', value: function _emitPreEvent(name) { var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var isCanceled = false; util$1.triggerElementEvent(this, 'pre' + name, util$1.extend({ navigator: this, currentPage: this.pages[this.pages.length - 1], cancel: function cancel() { return isCanceled = true; } }, data)); return isCanceled; } }, { key: '_emitPrePushEvent', value: function _emitPrePushEvent() { return this._emitPreEvent('push'); } }, { key: '_emitPrePopEvent', value: function _emitPrePopEvent() { var l = this.pages.length; return this._emitPreEvent('pop', { leavePage: this.pages[l - 1], enterPage: this.pages[l - 2] }); } // TODO: 書き直す }, { key: '_createPageElement', value: function _createPageElement(templateHTML) { var pageElement = util$1.createElement(internal$1.normalizePageHTML(templateHTML)); verifyPageElement(pageElement); return pageElement; } /** * @property onDeviceBackButton * @type {Object} * @description * [en]Back-button handler.[/en] * [ja]バックボタンハンドラ。[/ja] */ }, { key: '_show', value: function _show() { var _this11 = this; this.loaded.then(function () { return _this11.topPage && _this11.topPage._show(); }); } }, { key: '_hide', value: function _hide() { this.topPage && this.topPage._hide(); } }, { key: '_destroy', value: function _destroy() { for (var i = this.pages.length - 1; i >= 0; i--) { this._pageLoader.unload(this.pages[i]); } this.remove(); } /** * @param {String} name * @param {Function} Animator */ }, { key: 'pageLoader', get: function get$$1() { return this._pageLoader; }, set: function set$$1(pageLoader) { if (!(pageLoader instanceof PageLoader)) { util$1.throwPageLoader(); } this._pageLoader = pageLoader; } }, { key: 'page', get: function get$$1() { return this._page; }, set: function set$$1(page) { this._page = page; } }, { key: 'onDeviceBackButton', get: function get$$1() { return this._backButtonHandler; }, set: function set$$1(callback) { if (this._backButtonHandler) { this._backButtonHandler.destroy(); } this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback); } /** * @property topPage * @readonly * @type {HTMLElement} * @description * [en]Current top page element. Use this method to access options passed by `pushPage()`-like methods.[/en] * [ja]現在のページを取得します。pushPage()やresetToPage()メソッドの引数を取得できます。[/ja] */ }, { key: 'topPage', get: function get$$1() { var last = this.lastElementChild; while (last && last.tagName !== 'ONS-PAGE') { last = last.previousElementSibling; } return last; } /** * @property pages * @readonly * @type {Array} * @description * [en]Copy of the navigator's page stack.[/en] * [ja][/ja] */ }, { key: 'pages', get: function get$$1() { return util$1.arrayFrom(this.children).filter(function (element) { return element.tagName === 'ONS-PAGE'; }); } /** * @property onSwipe * @type {Function} * @description * [en]Hook called whenever the user slides the navigator (swipe-to-pop). It gets a decimal ratio (0-1) and an animationOptions object as arguments.[/en] * [ja][/ja] */ }, { key: 'onSwipe', get: function get$$1() { return this._onSwipe; }, set: function set$$1(value) { if (value && !(value instanceof Function)) { util$1.throw('"onSwipe" must be a function'); } this._onSwipe = value; } /** * @property options * @type {Object} * @description * [en]Default options object. Attributes have priority over this property.[/en] * [ja][/ja] */ /** * @property options.animation * @type {String} * @description * [en] * Animation name. Available animations are `"slide"`, `"lift"`, `"fade"` and `"none"`. * These are platform based animations. For fixed animations, add `"-ios"` or `"-md"` suffix to the animation name. E.g. `"lift-ios"`, `"lift-md"`. Defaults values are `"slide-ios"` and `"fade-md"`. * [/en] * [ja][/ja] */ /** * @property options.animationOptions * @type {String} * @description * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}` [/ja] */ /** * @property options.callback * @type {String} * @description * [en]Function that is called when the transition has ended.[/en] * [ja]このメソッドによる画面遷移が終了した際に呼び出される関数オブジェクトを指定します。[/ja] */ }, { key: 'options', get: function get$$1() { return this._options; }, set: function set$$1(object) { this._options = object; } }, { key: '_isRunning', set: function set$$1(value) { this.setAttribute('_is-running', value ? 'true' : 'false'); }, get: function get$$1() { return JSON.parse(this.getAttribute('_is-running')); } }], [{ key: 'registerAnimator', value: function registerAnimator(name, Animator) { if (!(Animator.prototype instanceof NavigatorAnimator)) { util$1.throwAnimator('Navigator'); } _animatorDict$5[name] = Animator; } }, { key: 'observedAttributes', get: function get$$1() { return ['animation', 'swipeable']; } }, { key: 'animators', get: function get$$1() { return _animatorDict$5; } }, { key: 'NavigatorAnimator', get: function get$$1() { return NavigatorAnimator; } }, { key: 'events', get: function get$$1() { return ['prepush', 'postpush', 'prepop', 'postpop']; } }, { key: 'rewritables', get: function get$$1() { return rewritables; } }]); return NavigatorElement; }(BaseElement); onsElements.Navigator = NavigatorElement; customElements.define('ons-navigator', NavigatorElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$10 = 'toolbar'; var scheme$18 = { '': 'toolbar--*', '.toolbar__left': 'toolbar--*__left', '.toolbar__center': 'toolbar--*__center', '.toolbar__right': 'toolbar--*__right' }; /** * @element ons-toolbar * @category page * @modifier material * [en]Material Design toolbar.[/en] * [ja][/ja] * @modifier transparent * [en]Transparent toolbar.[/en] * [ja]透明な背景を持つツールバーを表示します。[/ja] * @modifier cover-content * [en]Displays the toolbar on top of the page's content. Should be combined with `transparent` modifier.[/en] * [ja][/ja] * @modifier noshadow * [en]Toolbar without shadow.[/en] * [ja]ツールバーに影を付けずに表示します。[/ja] * @description * [en] * Toolbar component that can be used with navigation. * * Left, center and right containers can be specified by class names. * * This component will automatically display as a Material Design toolbar when running on Android devices. * [/en] * [ja]ナビゲーションで使用するツールバー用コンポーネントです。クラス名により、左、中央、右のコンテナを指定できます。[/ja] * @codepen aHmGL * @tutorial vanilla/Reference/toolbar * @guide compilation.html#toolbar-compilation [en]Adding a toolbar[/en][ja]ツールバーの追加[/ja] * @seealso ons-bottom-toolbar * [en]The `<ons-bottom-toolbar>` displays a toolbar on the bottom of the page.[/en] * [ja]ons-bottom-toolbarコンポーネント[/ja] * @seealso ons-back-button * [en]The `<ons-back-button>` component displays a back button inside the toolbar.[/en] * [ja]ons-back-buttonコンポーネント[/ja] * @seealso ons-toolbar-button * [en]The `<ons-toolbar-button>` component displays a toolbar button inside the toolbar.[/en] * [ja]ons-toolbar-buttonコンポーネント[/ja] * @example * <ons-page> * <ons-toolbar> * <div class="left"> * <ons-back-button> * Back * </ons-back-button> * </div> * <div class="center"> * Title * </div> * <div class="right"> * <ons-toolbar-button> * <ons-icon icon="md-menu"></ons-icon> * </ons-toolbar-button> * </div> * </ons-toolbar> * </ons-page> */ var ToolbarElement = function (_BaseElement) { inherits(ToolbarElement, _BaseElement); /** * @attribute inline * @initonly * @description * [en]Display the toolbar as an inline element.[/en] * [ja]ツールバーをインラインに置きます。スクロール領域内にそのまま表示されます。[/ja] */ /** * @attribute static * @description * [en]Static toolbars are not animated by `ons-navigator` when pushing or popping pages. This can be useful to improve performance in some situations.[/en] * [ja][/ja] */ /** * @attribute modifier * @description * [en]The appearance of the toolbar.[/en] * [ja]ツールバーの表現を指定します。[/ja] */ function ToolbarElement() { classCallCheck(this, ToolbarElement); var _this = possibleConstructorReturn(this, (ToolbarElement.__proto__ || Object.getPrototypeOf(ToolbarElement)).call(this)); contentReady(_this, function () { _this._compile(); }); return _this; } createClass(ToolbarElement, [{ key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$10, scheme$18); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$18); break; } } /** * @method setVisibility * @signature setVisibility(visible) * @param {Boolean} visible * [en]Set to true to show the toolbar, false to hide it[/en] * [ja][/ja] * @description * [en]Shows the toolbar if visible is true, otherwise hides it.[/en] * [ja][/ja] */ }, { key: 'setVisibility', value: function setVisibility(visible) { var _this2 = this; contentReady(this, function () { _this2.style.display = visible ? '' : 'none'; if (_this2.parentNode) { var siblingBackground = util$1.findChild(_this2.parentNode, '.page__background'); if (siblingBackground) { siblingBackground.style.top = visible ? null : 0; } var siblingContent = util$1.findChild(_this2.parentNode, '.page__content'); if (siblingContent) { siblingContent.style.top = visible ? null : 0; } } }); } /** * @method show * @signature show() * @description * [en]Show the toolbar.[/en] * [ja][/ja] */ }, { key: 'show', value: function show() { this.setVisibility(true); } /** * @method hide * @signature hide() * @description * [en]Hide the toolbar.[/en] * [ja][/ja] */ }, { key: 'hide', value: function hide() { this.setVisibility(false); } /** * @return {HTMLElement} */ }, { key: '_getToolbarLeftItemsElement', value: function _getToolbarLeftItemsElement() { return this.querySelector('.left') || internal$1.nullElement; } /** * @return {HTMLElement} */ }, { key: '_getToolbarCenterItemsElement', value: function _getToolbarCenterItemsElement() { return this.querySelector('.center') || internal$1.nullElement; } /** * @return {HTMLElement} */ }, { key: '_getToolbarRightItemsElement', value: function _getToolbarRightItemsElement() { return this.querySelector('.right') || internal$1.nullElement; } /** * @return {HTMLElement} */ }, { key: '_getToolbarBackButtonLabelElement', value: function _getToolbarBackButtonLabelElement() { return this.querySelector('ons-back-button .back-button__label') || internal$1.nullElement; } /** * @return {HTMLElement} */ }, { key: '_getToolbarBackButtonIconElement', value: function _getToolbarBackButtonIconElement() { return this.querySelector('ons-back-button .back-button__icon') || internal$1.nullElement; } }, { key: '_compile', value: function _compile() { autoStyle.prepare(this); this.classList.add(defaultClassName$10); this._ensureToolbarItemElements(); ModifierUtil.initModifier(this, scheme$18); } }, { key: '_ensureToolbarItemElements', value: function _ensureToolbarItemElements() { for (var i = this.childNodes.length - 1; i >= 0; i--) { // case of not element if (this.childNodes[i].nodeType != 1) { this.removeChild(this.childNodes[i]); } } var center = this._ensureToolbarElement('center'); center.classList.add('toolbar__title'); if (this.children.length !== 1 || !this.children[0].classList.contains('center')) { var left = this._ensureToolbarElement('left'); var right = this._ensureToolbarElement('right'); if (this.children[0] !== left || this.children[1] !== center || this.children[2] !== right) { this.appendChild(left); this.appendChild(center); this.appendChild(right); } } } }, { key: '_ensureToolbarElement', value: function _ensureToolbarElement(name) { if (util$1.findChild(this, '.toolbar__' + name)) { var _element = util$1.findChild(this, '.toolbar__' + name); _element.classList.add(name); return _element; } var element = util$1.findChild(this, '.' + name) || util$1.create('.' + name); element.classList.add('toolbar__' + name); return element; } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'class']; } }]); return ToolbarElement; }(BaseElement); onsElements.Toolbar = ToolbarElement; customElements.define('ons-toolbar', ToolbarElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$9 = 'page'; var scheme$17 = { '': 'page--*', '.page__content': 'page--*__content', '.page__background': 'page--*__background' }; /** * @element ons-page * @category page * @modifier material * [en]Material Design style[/en] * [ja][/ja] * @description * [en] * This component defines the root of each page. If the content is large it will become scrollable. * * A navigation bar can be added to the top of the page using the `<ons-toolbar>` element. * [/en] * [ja]ページ定義のためのコンポーネントです。このコンポーネントの内容はスクロールが許可されます。[/ja] * @tutorial vanilla/Reference/page * @guide lifecycle.html#events * [en]Overview of page events[/en] * [ja]Overview of page events[/ja] * @guide fundamentals.html#managing-pages * [en]Managing multiple pages[/en] * [ja]複数のページを管理する[/ja] * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @seealso ons-toolbar * [en]Use the `<ons-toolbar>` element to add a navigation bar to the top of the page.[/en] * [ja][/ja] * @example * <ons-page> * <ons-toolbar> * <div class="left"> * <ons-back-button>Back</ons-back-button> * </div> * <div class="center">Title</div> * <div class="right"> * <ons-toolbar-button> * <ons-icon icon="md-menu"></ons-icon> * </ons-toolbar-button> * </div> * </ons-toolbar> * * <p>Page content</p> * </ons-page> * * @example * <script> * myApp.handler = function(done) { * loadMore().then(done); * } * </script> * * <ons-page on-infinite-scroll="myApp.handler"> * <ons-toolbar> * <div class="center">List</div> * </ons-toolbar> * * <ons-list> * <ons-list-item>#1</ons-list-item> * <ons-list-item>#2</ons-list-item> * <ons-list-item>#3</ons-list-item> * ... * </ons-list> * </ons-page> */ var PageElement = function (_BaseElement) { inherits(PageElement, _BaseElement); /** * @event init * @description * [en]Fired right after the page is attached.[/en] * [ja]ページがアタッチされた後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] */ /** * @event show * @description * [en]Fired right after the page is shown.[/en] * [ja]ページが表示された後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] */ /** * @event hide * @description * [en]Fired right after the page is hidden.[/en] * [ja]ページが隠れた後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] */ /** * @event destroy * @description * [en]Fired right before the page is destroyed.[/en] * [ja]ページが破棄される前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] */ /** * @attribute modifier * @type {String} * @description * [en]Specify modifier name to specify custom styles.[/en] * [ja]スタイル定義をカスタマイズするための名前を指定します。[/ja] */ /** * @attribute on-infinite-scroll * @type {String} * @description * [en]Path of the function to be executed on infinite scrolling. Example: `app.loadData`. The function receives a done callback that must be called when it's finished.[/en] * [ja][/ja] */ function PageElement() { classCallCheck(this, PageElement); var _this = possibleConstructorReturn(this, (PageElement.__proto__ || Object.getPrototypeOf(PageElement)).call(this)); _this._deriveHooks(); _this._defaultClassName = defaultClassName$9; _this.classList.add(defaultClassName$9); _this._initialized = false; contentReady(_this, function () { _this._compile(); _this._isShown = false; _this._contentElement = _this._getContentElement(); _this._backgroundElement = _this._getBackgroundElement(); }); return _this; } createClass(PageElement, [{ key: '_compile', value: function _compile() { var _this2 = this; autoStyle.prepare(this); var toolbar = util$1.findChild(this, 'ons-toolbar'); var background = util$1.findChild(this, '.page__background') || util$1.findChild(this, '.background') || document.createElement('div'); background.classList.add('page__background'); this.insertBefore(background, !toolbar && this.firstChild || toolbar && toolbar.nextSibling); var content = util$1.findChild(this, '.page__content') || util$1.findChild(this, '.content') || document.createElement('div'); content.classList.add('page__content'); if (!content.parentElement) { util$1.arrayFrom(this.childNodes).forEach(function (node) { if (node.nodeType !== 1 || _this2._elementShouldBeMoved(node)) { content.appendChild(node); // Can trigger detached connectedCallbacks } }); } this._tryToFillStatusBar(content); // Must run before child pages try to fill status bar. this.insertBefore(content, background.nextSibling); // Can trigger attached connectedCallbacks if ((!toolbar || !util$1.hasModifier(toolbar, 'transparent')) && content.children.length === 1 && util$1.isPageControl(content.children[0])) { this._defaultClassName += ' page--wrapper'; this.attributeChangedCallback('class'); } var bottomToolbar = util$1.findChild(this, 'ons-bottom-toolbar'); if (bottomToolbar) { this._defaultClassName += ' page-with-bottom-toolbar'; this.attributeChangedCallback('class'); } ModifierUtil.initModifier(this, scheme$17); } }, { key: '_elementShouldBeMoved', value: function _elementShouldBeMoved(el) { if (el.classList.contains('page__background')) { return false; } var tagName = el.tagName.toLowerCase(); if (tagName === 'ons-fab') { return !el.hasAttribute('position'); } var fixedElements = ['script', 'ons-toolbar', 'ons-bottom-toolbar', 'ons-modal', 'ons-speed-dial', 'ons-dialog', 'ons-alert-dialog', 'ons-popover', 'ons-action-sheet']; return el.hasAttribute('inline') || fixedElements.indexOf(tagName) === -1; } }, { key: '_tryToFillStatusBar', value: function _tryToFillStatusBar() { var _this3 = this; var content = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this._contentElement; internal$1.autoStatusBarFill(function () { util$1.toggleAttribute(_this3, 'status-bar-fill', !util$1.findParent(_this3, function (e) { return e.hasAttribute('status-bar-fill'); }) // Not already filled && (_this3._canAnimateToolbar(content) || !util$1.findChild(content, util$1.isPageControl)) // Has toolbar or cannot delegate ); }); } }, { key: '_canAnimateToolbar', value: function _canAnimateToolbar() { var content = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this._contentElement; if (util$1.findChild(this, 'ons-toolbar')) { return true; } return !!util$1.findChild(content, function (el) { return util$1.match(el, 'ons-toolbar') && !el.hasAttribute('inline'); }); } }, { key: 'connectedCallback', value: function connectedCallback() { var _this4 = this; if (!util$1.isAttached(this)) { // Avoid detached calls return; } contentReady(this, function () { _this4._tryToFillStatusBar(); // Ensure status bar when the element was compiled before connected if (_this4.hasAttribute('on-infinite-scroll')) { _this4.attributeChangedCallback('on-infinite-scroll', null, _this4.getAttribute('on-infinite-scroll')); } if (!_this4._initialized) { _this4._initialized = true; setImmediate(function () { _this4.onInit && _this4.onInit(); util$1.triggerElementEvent(_this4, 'init'); }); if (!util$1.hasAnyComponentAsParent(_this4)) { setImmediate(function () { return _this4._show(); }); } } }); } }, { key: 'updateBackButton', value: function updateBackButton(show) { if (this.backButton) { show ? this.backButton.show() : this.backButton.hide(); } } }, { key: '_onScroll', value: function _onScroll() { var _this5 = this; var c = this._contentElement, overLimit = (c.scrollTop + c.clientHeight) / c.scrollHeight >= this._infiniteScrollLimit; if (this._onInfiniteScroll && !this._loadingContent && overLimit) { this._loadingContent = true; this._onInfiniteScroll(function () { return _this5._loadingContent = false; }); } } /** * @property onDeviceBackButton * @type {Object} * @description * [en]Back-button handler.[/en] * [ja]バックボタンハンドラ。[/ja] */ }, { key: '_getContentElement', value: function _getContentElement() { var result = util$1.findChild(this, '.page__content'); if (result) { return result; } util$1.throw('Fail to get ".page__content" element'); } }, { key: '_getBackgroundElement', value: function _getBackgroundElement() { var result = util$1.findChild(this, '.page__background'); if (result) { return result; } util$1.throw('Fail to get ".page__background" element'); } }, { key: '_getBottomToolbarElement', value: function _getBottomToolbarElement() { return util$1.findChild(this, 'ons-bottom-toolbar') || internal$1.nullElement; } }, { key: '_getToolbarElement', value: function _getToolbarElement() { return util$1.findChild(this, 'ons-toolbar') || document.createElement('ons-toolbar'); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { var _this6 = this; switch (name) { case 'class': util$1.restoreClass(this, this._defaultClassName, scheme$17); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$17); break; case 'on-infinite-scroll': if (current === null) { this.onInfiniteScroll = null; } else { this.onInfiniteScroll = function (done) { var f = util$1.findFromPath(current); _this6.onInfiniteScroll = f; f(done); }; } break; } } }, { key: '_show', value: function _show() { if (!this._isShown && util$1.isAttached(this)) { this._isShown = true; this.setAttribute('shown', ''); this.onShow && this.onShow(); util$1.triggerElementEvent(this, 'show'); util$1.propagateAction(this, '_show'); } } }, { key: '_hide', value: function _hide() { if (this._isShown) { this._isShown = false; this.removeAttribute('shown'); this.onHide && this.onHide(); util$1.triggerElementEvent(this, 'hide'); util$1.propagateAction(this, '_hide'); } } }, { key: '_destroy', value: function _destroy() { this._hide(); this.onDestroy && this.onDestroy(); util$1.triggerElementEvent(this, 'destroy'); if (this.onDeviceBackButton) { this.onDeviceBackButton.destroy(); } util$1.propagateAction(this, '_destroy'); this.remove(); } }, { key: '_deriveHooks', value: function _deriveHooks() { var _this7 = this; this.constructor.events.forEach(function (event) { var key = 'on' + event.charAt(0).toUpperCase() + event.slice(1); Object.defineProperty(_this7, key, { configurable: true, enumerable: true, get: function get$$1() { return _this7['_' + key]; }, set: function set$$1(value) { if (!(value instanceof Function)) { util$1.throw('"' + key + '" hook must be a function'); } _this7['_' + key] = value.bind(_this7); } }); }); } }, { key: 'name', set: function set$$1(str) { this.setAttribute('name', str); }, get: function get$$1() { return this.getAttribute('name'); } }, { key: 'backButton', get: function get$$1() { return this.querySelector('ons-back-button'); } /** * @property onInfiniteScroll * @description * [en]Function to be executed when scrolling to the bottom of the page. The function receives a done callback as an argument that must be called when it's finished.[/en] * [ja][/ja] */ }, { key: 'onInfiniteScroll', set: function set$$1(value) { var _this8 = this; if (value && !(value instanceof Function)) { util$1.throw('"onInfiniteScroll" must be function or null'); } contentReady(this, function () { if (!value) { _this8._contentElement.removeEventListener('scroll', _this8._boundOnScroll); } else if (!_this8._onInfiniteScroll) { _this8._infiniteScrollLimit = 0.9; _this8._boundOnScroll = _this8._onScroll.bind(_this8); setImmediate(function () { return _this8._contentElement.addEventListener('scroll', _this8._boundOnScroll); }); } _this8._onInfiniteScroll = value; }); }, get: function get$$1() { return this._onInfiniteScroll; } }, { key: 'onDeviceBackButton', get: function get$$1() { return this._backButtonHandler; }, set: function set$$1(callback) { if (this._backButtonHandler) { this._backButtonHandler.destroy(); } this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback); } }, { key: 'scrollTop', get: function get$$1() { return this._contentElement.scrollTop; }, set: function set$$1(newValue) { this._contentElement.scrollTop = newValue; } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'on-infinite-scroll', 'class']; } }, { key: 'events', get: function get$$1() { return ['init', 'show', 'hide', 'destroy']; } /** * @property data * @type {*} * @description * [en]User's custom data passed to `pushPage()`-like methods.[/en] * [ja][/ja] */ }]); return PageElement; }(BaseElement); onsElements.Page = PageElement; customElements.define('ons-page', PageElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var PopoverAnimator = function (_BaseAnimator) { inherits(PopoverAnimator, _BaseAnimator); /** * @param {Object} options * @param {String} options.timing * @param {Number} options.duration * @param {Number} options.delay */ function PopoverAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'cubic-bezier(.1, .7, .4, 1)' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.2 : _ref$duration; classCallCheck(this, PopoverAnimator); return possibleConstructorReturn(this, (PopoverAnimator.__proto__ || Object.getPrototypeOf(PopoverAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } createClass(PopoverAnimator, [{ key: 'show', value: function show(popover, callback) { callback(); } }, { key: 'hide', value: function hide(popover, callback) { callback(); } }, { key: '_animate', value: function _animate(element, _ref2) { var from = _ref2.from, to = _ref2.to, options = _ref2.options, callback = _ref2.callback, _ref2$restore = _ref2.restore, restore = _ref2$restore === undefined ? false : _ref2$restore, animation = _ref2.animation; options = util$1.extend({}, this.options, options); if (animation) { from = animation.from; to = animation.to; } animation = Animit(element); if (restore) { animation = animation.saveStyle(); } animation = animation.queue(from).wait(this.delay).queue({ css: to, duration: this.duration, timing: this.timing }); if (restore) { animation = animation.restoreStyle(); } if (callback) { animation = animation.queue(function (done) { callback(); done(); }); } return animation; } }, { key: '_animateAll', value: function _animateAll(element, animations) { var _this2 = this; Object.keys(animations).forEach(function (key) { return _this2._animate(element[key], animations[key]).play(); }); } }]); return PopoverAnimator; }(BaseAnimator); var fade = { out: { from: { opacity: 1.0 }, to: { opacity: 0 } }, in: { from: { opacity: 0 }, to: { opacity: 1.0 } } }; var MDFadePopoverAnimator = function (_PopoverAnimator) { inherits(MDFadePopoverAnimator, _PopoverAnimator); function MDFadePopoverAnimator() { classCallCheck(this, MDFadePopoverAnimator); return possibleConstructorReturn(this, (MDFadePopoverAnimator.__proto__ || Object.getPrototypeOf(MDFadePopoverAnimator)).apply(this, arguments)); } createClass(MDFadePopoverAnimator, [{ key: 'show', value: function show(popover, callback) { this._animateAll(popover, { _mask: fade.in, _popover: { animation: fade.in, restore: true, callback: callback } }); } }, { key: 'hide', value: function hide(popover, callback) { this._animateAll(popover, { _mask: fade.out, _popover: { animation: fade.out, restore: true, callback: callback } }); } }]); return MDFadePopoverAnimator; }(PopoverAnimator); var IOSFadePopoverAnimator = function (_MDFadePopoverAnimato) { inherits(IOSFadePopoverAnimator, _MDFadePopoverAnimato); function IOSFadePopoverAnimator() { classCallCheck(this, IOSFadePopoverAnimator); return possibleConstructorReturn(this, (IOSFadePopoverAnimator.__proto__ || Object.getPrototypeOf(IOSFadePopoverAnimator)).apply(this, arguments)); } createClass(IOSFadePopoverAnimator, [{ key: 'show', value: function show(popover, callback) { this._animateAll(popover, { _mask: fade.in, _popover: { from: { transform: 'scale3d(1.3, 1.3, 1.0)', opacity: 0 }, to: { transform: 'scale3d(1.0, 1.0, 1.0)', opacity: 1.0 }, restore: true, callback: callback } }); } }]); return IOSFadePopoverAnimator; }(MDFadePopoverAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$19 = { '.popover': 'popover--*', '.popover-mask': 'popover-mask--*', '.popover__content': 'popover--*__content', '.popover__arrow': 'popover--*__arrow' }; var _animatorDict$6 = { 'default': function _default() { return platform.isAndroid() ? MDFadePopoverAnimator : IOSFadePopoverAnimator; }, 'none': PopoverAnimator, 'fade-ios': IOSFadePopoverAnimator, 'fade-md': MDFadePopoverAnimator }; var positions = { up: 'bottom', left: 'right', down: 'top', right: 'left' }; /** * @element ons-popover * @category dialog * @description * [en] * A component that displays a popover next to an element. The popover can be used to display extra information about a component or a tooltip. * * To use the element it can either be attached directly to the `<body>` element or dynamically created from a template using the `ons.createPopover(template)` utility function and the `<template>` tag. * * Another common way to use the popover is to display a menu when a button on the screen is tapped. For Material Design, popover looks exactly as a dropdown menu. * [/en] * [ja]ある要素を対象とするポップオーバーを表示するコンポーネントです。[/ja] * @codepen ZYYRKo * @tutorial vanilla/Reference/popover * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @example * <ons-button onclick="showPopover(this)"> * Click me! * </ons-button> * * <ons-popover direction="down" id="popover"> * <p>This is a popover!</p> * </ons-popover> * * <script> * var showPopover = function(element) { * var popover = document.getElementById('popover'); * popover.show(element); * }; * </script> */ var PopoverElement = function (_BaseDialogElement) { inherits(PopoverElement, _BaseDialogElement); /** * @event preshow * @description * [en]Fired just before the popover is displayed.[/en] * [ja]ポップオーバーが表示される直前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.popover * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Call this function to stop the popover from being shown.[/en] * [ja]この関数を呼び出すと、ポップオーバーの表示がキャンセルされます。[/ja] */ /** * @event postshow * @description * [en]Fired just after the popover is displayed.[/en] * [ja]ポップオーバーが表示された直後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.popover * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @event prehide * @description * [en]Fired just before the popover is hidden.[/en] * [ja]ポップオーバーが隠れる直前に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.popover * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Call this function to stop the popover from being hidden.[/en] * [ja]この関数を呼び出すと、ポップオーバーが隠れる処理をキャンセルします。[/ja] */ /** * @event posthide * @description * [en]Fired just after the popover is hidden.[/en] * [ja]ポップオーバーが隠れた後に発火します。[/ja] * @param {Object} event [en]Event object.[/en] * @param {Object} event.popover * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @attribute modifier * @type {String} * @description * [en]The appearance of the popover.[/en] * [ja]ポップオーバーの表現を指定します。[/ja] */ /** * @attribute direction * @type {String} * @description * [en] * A space separated list of directions. If more than one direction is specified, * it will be chosen automatically. Valid directions are `"up"`, `"down"`, `"left"` and `"right"`. * [/en] * [ja] * ポップオーバーを表示する方向を空白区切りで複数指定できます。 * 指定できる方向は、"up", "down", "left", "right"の4つです。空白区切りで複数指定することもできます。 * 複数指定された場合、対象とする要素に合わせて指定した値から自動的に選択されます。 * [/ja] */ /** * @attribute cancelable * @description * [en]If this attribute is set the popover can be closed by tapping the background or by pressing the back button.[/en] * [ja]この属性があると、ポップオーバーが表示された時に、背景やバックボタンをタップした時にをポップオーバー閉じます。[/ja] */ /** * @attribute cover-target * @description * [en]If set the popover will cover the target on the screen.[/en] * [ja][/ja] */ /** * @attribute animation * @type {String} * @description * [en]The animation used when showing an hiding the popover. Can be either `"none"`, `"default"`, `"fade-ios"` or `"fade-md"`.[/en] * [ja]ポップオーバーを表示する際のアニメーション名を指定します。[/ja] */ /** * @attribute animation-options * @type {Expression} * @description * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. {duration: 0.2, delay: 1, timing: 'ease-in'}[/ja] */ /** * @attribute mask-color * @type {Color} * @description * [en]Color of the background mask. Default is `"rgba(0, 0, 0, 0.2)"`.[/en] * [ja]背景のマスクの色を指定します。デフォルトは"rgba(0, 0, 0, 0.2)"です。[/ja] */ function PopoverElement() { classCallCheck(this, PopoverElement); var _this = possibleConstructorReturn(this, (PopoverElement.__proto__ || Object.getPrototypeOf(PopoverElement)).call(this)); _this._boundOnChange = _this._onChange.bind(_this); contentReady(_this, function () { _this._compile(); _this.style.display = 'none'; }); return _this; } createClass(PopoverElement, [{ key: '_updateAnimatorFactory', value: function _updateAnimatorFactory() { return new AnimatorFactory({ animators: _animatorDict$6, baseClass: PopoverAnimator, baseClassName: 'PopoverAnimator', defaultAnimation: this.getAttribute('animation') || 'default' }); } }, { key: '_toggleStyle', value: function _toggleStyle(shouldShow) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (shouldShow) { this.style.display = 'block'; this._currentTarget = options.target; this._positionPopover(options.target); } else { this.style.display = 'none'; this._clearStyles(); } } }, { key: '_positionPopover', value: function _positionPopover(target) { var radius = this._radius, contentElement = this._content, margin = this._margin; var safeAreaLengths = iPhoneXPatch.getSafeAreaLengths(); var safeAreaRect = iPhoneXPatch.getSafeAreaDOMRect(); var targetRect = target.getBoundingClientRect(); var isMD = util$1.hasModifier(this, 'material'); var cover = isMD && this.hasAttribute('cover-target'); var parent = util$1.findParent(this, 'ons-page') || document.body; var parentDimensions = parent.getBoundingClientRect(); var maxPositions = { top: Math.max(parentDimensions.top, safeAreaRect.top), left: Math.max(parentDimensions.left, safeAreaRect.left), bottom: Math.min(parentDimensions.bottom, safeAreaRect.bottom), right: Math.min(parentDimensions.right, safeAreaRect.right) }; // Distance from each side of the safe area (with margin) to the target element var targetDistance = { top: targetRect.top - (maxPositions.top + margin), left: targetRect.left - (maxPositions.left + margin), bottom: maxPositions.bottom - margin - targetRect.bottom, right: maxPositions.right - margin - targetRect.right }; // Distance from each side of the safe area (with margin) to the geometric center of the target element var targetCenterDistanceFrom = { top: targetRect.top + Math.round(targetRect.height / 2) - (maxPositions.top + margin), left: targetRect.left + Math.round(targetRect.width / 2) - (maxPositions.left + margin), bottom: maxPositions.bottom - margin - targetRect.bottom + Math.round(targetRect.height / 2), right: maxPositions.right - margin - targetRect.right + Math.round(targetRect.width / 2) }; var _calculateDirections2 = this._calculateDirections(targetDistance), vertical = _calculateDirections2.vertical, primaryDirection = _calculateDirections2.primary, secondaryDirection = _calculateDirections2.secondary; this._currentDirection = primaryDirection; util$1.addModifier(this, primaryDirection); var sizeName = vertical ? 'width' : 'height'; // Get .popover__content size var contentSize = function (style) { return { width: parseInt(style.getPropertyValue('width'), 10), height: parseInt(style.getPropertyValue('height'), 10) }; }(window.getComputedStyle(contentElement)); // Setting .popover position. var targetAndArrowLength = cover ? 0 : (vertical ? targetRect.height : targetRect.width) + (isMD ? 0 : 14); var primaryOffset = Math.max(safeAreaLengths[primaryDirection] + margin, safeAreaLengths[primaryDirection] + margin + targetDistance[primaryDirection] + targetAndArrowLength); var secondaryOffset = Math.max(safeAreaLengths[secondaryDirection] + margin, safeAreaLengths[secondaryDirection] + margin + targetCenterDistanceFrom[secondaryDirection] - contentSize[sizeName] / 2); this._popover.style[primaryDirection] = primaryOffset + 'px'; this._popover.style[secondaryDirection] = secondaryOffset + 'px'; // Setting .popover__arrow position. this._arrow.style[secondaryDirection] = Math.max(radius, safeAreaLengths[secondaryDirection] + margin + targetCenterDistanceFrom[secondaryDirection] - secondaryOffset) + 'px'; } }, { key: '_calculateDirections', value: function _calculateDirections(distance) { var options = (this.getAttribute('direction') || 'up down left right').split(/\s+/).map(function (e) { return positions[e]; }); var primary = options.sort(function (a, b) { return distance[a] - distance[b]; })[0]; var vertical = 'top' == primary || 'bottom' == primary; var secondary = void 0; if (vertical) { secondary = distance.left < distance.right ? 'left' : 'right'; } else { secondary = distance.top < distance.bottom ? 'top' : 'bottom'; } return { vertical: vertical, primary: primary, secondary: secondary }; } }, { key: '_clearStyles', value: function _clearStyles() { var _this2 = this; this._currentDirection = null; ['top', 'bottom', 'left', 'right'].forEach(function (e) { _this2._arrow.style[e] = _this2._content.style[e] = _this2._popover.style[e] = ''; util$1.removeModifier(_this2, e); }); } }, { key: '_onChange', value: function _onChange() { var _this3 = this; setImmediate(function () { if (_this3._currentTarget) { _this3._positionPopover(_this3._currentTarget); } }); } }, { key: '_compile', value: function _compile() { autoStyle.prepare(this); if (this._popover && this._mask) { return; } var hasDefaultContainer = this._popover && this._content; if (hasDefaultContainer) { if (!this._mask) { var mask = document.createElement('div'); mask.classList.add('popover-mask'); this.insertBefore(mask, this.firstChild); } if (!this._arrow) { var arrow = document.createElement('div'); arrow.classList.add('popover__arrow'); this._popover.appendChild(arrow); } } else { var template = util$1.createFragment('\n <div class="popover-mask"></div>\n <div class="popover">\n <div class="popover__content"></div>\n <div class="popover__arrow"></div>\n </div>\n '); var content = template.querySelector('.popover__content'); while (this.childNodes[0]) { content.appendChild(this.childNodes[0]); } this.appendChild(template); } // FIXME! if (this.hasAttribute('style')) { this._popover.setAttribute('style', this.getAttribute('style')); this.removeAttribute('style'); } ModifierUtil.initModifier(this, this._scheme); } /** * @method show * @signature show(target, [options]) * @param {String|Event|HTMLElement} target * [en]Target element. Can be either a CSS selector, an event object or a DOM element. It can be also provided as 'options.target' instead. [/en] * [ja]ポップオーバーのターゲットとなる要素を指定します。CSSセレクタかeventオブジェクトかDOM要素のいずれかを渡せます。[/ja] * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Use one of `"fade-ios"`, `"fade-md"`, `"none"` and `"default"`.[/en] * [ja]アニメーション名を指定します。"fade-ios", "fade-md", "none", "default"のいずれかを指定できます。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja] * @param {Function} [options.callback] * [en]This function is called after the popover has been revealed.[/en] * [ja]ポップオーバーが表示され終わった後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Open the popover and point it at a target. The target can be either an event, a CSS selector or a DOM element..[/en] * [ja]対象とする要素にポップオーバーを表示します。target引数には、$eventオブジェクトやDOMエレメントやCSSセレクタを渡すことが出来ます。[/ja] * @return {Promise} * [en]Resolves to the displayed element[/en] * [ja][/ja] */ }, { key: 'show', value: function show(target) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // Copy options and include options.target if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && !(target instanceof Event) && !(target instanceof HTMLElement)) { options = _extends({}, target); } else { options = _extends({}, options, { target: target }); } if (typeof options.target === 'string') { options.target = document.querySelector(options.target); } else if (options.target instanceof Event) { options.target = options.target.target; } if (!(options.target instanceof HTMLElement)) { util$1.throw('Invalid target type or undefined'); } return get(PopoverElement.prototype.__proto__ || Object.getPrototypeOf(PopoverElement.prototype), 'show', this).call(this, options); } /** * @method hide * @signature hide([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Use one of `"fade-ios"`, `"fade-md"`, `"none"` and `"default"`.[/en] * [ja]アニメーション名を指定します。"fade-ios", "fade-md", "none", "default"のいずれかを指定できます。[/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja] * @param {Function} [options.callback] * [en]This functions is called after the popover has been hidden.[/en] * [ja]ポップオーバーが隠れた後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Close the popover.[/en] * [ja]ポップオーバーを閉じます。[/ja] * @return {Promise} * [en]Resolves to the hidden element[/en] * [ja][/ja] */ /** * @property visible * @readonly * @type {Boolean} * @description * [en]Whether the element is visible or not.[/en] * [ja]要素が見える場合に`true`。[/ja] */ /** * @property cancelable * @type {Boolean} * @description * [en] * A boolean value that specifies whether the popover is cancelable or not. * * When the popover is cancelable it can be closed by tapping the background or by pressing the back button on Android devices. * [/en] * [ja][/ja] */ /** * @property onDeviceBackButton * @type {Object} * @description * [en]Back-button handler.[/en] * [ja]バックボタンハンドラ。[/ja] */ }, { key: 'connectedCallback', value: function connectedCallback() { var _this4 = this; get(PopoverElement.prototype.__proto__ || Object.getPrototypeOf(PopoverElement.prototype), 'connectedCallback', this).call(this); window.addEventListener('resize', this._boundOnChange, false); this._margin = this._margin || parseInt(window.getComputedStyle(this).getPropertyValue('top')); this._margin = this._margin || 6; // Fix for iframes contentReady(this, function () { _this4._radius = parseInt(window.getComputedStyle(_this4._content).getPropertyValue('border-top-left-radius')); }); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { get(PopoverElement.prototype.__proto__ || Object.getPrototypeOf(PopoverElement.prototype), 'disconnectedCallback', this).call(this); window.removeEventListener('resize', this._boundOnChange, false); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'direction') { return this._boundOnChange(); } else if (name === 'modifier') { this._currentDirection && util$1.addModifier(this, this._currentDirection); } get(PopoverElement.prototype.__proto__ || Object.getPrototypeOf(PopoverElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current); } /** * @param {String} name * @param {PopoverAnimator} Animator */ }, { key: '_scheme', get: function get$$1() { return scheme$19; } }, { key: '_mask', get: function get$$1() { return util$1.findChild(this, '.popover-mask'); } }, { key: '_popover', get: function get$$1() { return util$1.findChild(this, '.popover'); } }, { key: '_content', get: function get$$1() { return util$1.findChild(this._popover, '.popover__content'); } }, { key: '_arrow', get: function get$$1() { return util$1.findChild(this._popover, '.popover__arrow'); } }], [{ key: 'registerAnimator', value: function registerAnimator(name, Animator) { if (!(Animator.prototype instanceof PopoverAnimator)) { util$1.throwAnimator('Popover'); } _animatorDict$6[name] = Animator; } }, { key: 'observedAttributes', get: function get$$1() { return [].concat(toConsumableArray(get(PopoverElement.__proto__ || Object.getPrototypeOf(PopoverElement), 'observedAttributes', this)), ['direction']); } }, { key: 'animators', get: function get$$1() { return _animatorDict$6; } }, { key: 'PopoverAnimator', get: function get$$1() { return PopoverAnimator; } }]); return PopoverElement; }(BaseDialogElement); onsElements.Popover = PopoverElement; customElements.define('ons-popover', PopoverElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$20 = { '.progress-bar': 'progress-bar--*', '.progress-bar__primary': 'progress-bar--*__primary', '.progress-bar__secondary': 'progress-bar--*__secondary' }; var template = util$1.createElement('\n <div class="progress-bar">\n <div class="progress-bar__secondary"></div>\n <div class="progress-bar__primary"></div>\n </div>\n'); var INDET = 'indeterminate'; /** * @element ons-progress-bar * @category visual * @modifier material * [en]Display a Material Design progress bar.[/en] * [ja]マテリアルデザインのスタイルでプログレスバーを表示します。[/ja] * @description * [en] * The component is used to display a linear progress bar. It can either display a progress bar that shows the user how much of a task has been completed. In the case where the percentage is not known it can be used to display an animated progress bar so the user can see that an operation is in progress. * [/en] * [ja][/ja] * @codepen zvQbGj * @tutorial vanilla/Reference/progress * @seealso ons-progress-circular * [en]The `<ons-progress-circular>` component displays a circular progress indicator.[/en] * [ja][/ja] * @example * <ons-progress-bar * value="55" * secondary-value="87"> * </ons-progress-bar> * * <ons-progress-bar * indeterminate> * </ons-progress-bar> */ var ProgressBarElement = function (_BaseElement) { inherits(ProgressBarElement, _BaseElement); /** * @attribute modifier * @type {String} * @description * [en]Change the appearance of the progress indicator.[/en] * [ja]プログレスインジケータの見た目を変更します。[/ja] */ /** * @attribute value * @type {Number} * @description * [en]Current progress. Should be a value between 0 and 100.[/en] * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja] */ /** * @attribute secondary-value * @type {Number} * @description * [en]Current secondary progress. Should be a value between 0 and 100.[/en] * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja] */ /** * @attribute indeterminate * @description * [en]If this attribute is set, an infinite looping animation will be shown.[/en] * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja] */ function ProgressBarElement() { classCallCheck(this, ProgressBarElement); var _this = possibleConstructorReturn(this, (ProgressBarElement.__proto__ || Object.getPrototypeOf(ProgressBarElement)).call(this)); contentReady(_this, function () { return _this._compile(); }); return _this; } createClass(ProgressBarElement, [{ key: '_compile', value: function _compile() { if (!this._isCompiled()) { this._template = template.cloneNode(true); } else { this._template = util$1.findChild(this, '.progress-bar'); } this._primary = util$1.findChild(this._template, '.progress-bar__primary'); this._secondary = util$1.findChild(this._template, '.progress-bar__secondary'); this._updateDeterminate(); this._updateValue(); this.appendChild(this._template); autoStyle.prepare(this); ModifierUtil.initModifier(this, scheme$20); } }, { key: '_isCompiled', value: function _isCompiled() { if (!util$1.findChild(this, '.progress-bar')) { return false; } var barElement = util$1.findChild(this, '.progress-bar'); if (!util$1.findChild(barElement, '.progress-bar__secondary')) { return false; } if (!util$1.findChild(barElement, '.progress-bar__primary')) { return false; } return true; } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'modifier') { ModifierUtil.onModifierChanged(last, current, this, scheme$20); this.hasAttribute(INDET) && this._updateDeterminate(); } else if (name === 'value' || name === 'secondary-value') { this._updateValue(); } else if (name === INDET) { this._updateDeterminate(); } } }, { key: '_updateDeterminate', value: function _updateDeterminate() { var _this2 = this; contentReady(this, function () { return util$1.toggleModifier(_this2, INDET, { force: _this2.hasAttribute(INDET) }); }); } }, { key: '_updateValue', value: function _updateValue() { var _this3 = this; contentReady(this, function () { _this3._primary.style.width = _this3.hasAttribute('value') ? _this3.getAttribute('value') + '%' : '0%'; _this3._secondary.style.width = _this3.hasAttribute('secondary-value') ? _this3.getAttribute('secondary-value') + '%' : '0%'; }); } /** * @property value * @type {Number} * @description * [en]Current progress. Should be a value between 0 and 100.[/en] * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja] */ }, { key: 'value', set: function set$$1(value) { if (typeof value !== 'number' || value < 0 || value > 100) { util$1.throw('Invalid value'); } this.setAttribute('value', Math.floor(value)); }, get: function get$$1() { return parseInt(this.getAttribute('value') || '0'); } /** * @property secondaryValue * @type {Number} * @description * [en]Current secondary progress. Should be a value between 0 and 100.[/en] * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja] */ }, { key: 'secondaryValue', set: function set$$1(value) { if (typeof value !== 'number' || value < 0 || value > 100) { util$1.throw('Invalid value'); } this.setAttribute('secondary-value', Math.floor(value)); }, get: function get$$1() { return parseInt(this.getAttribute('secondary-value') || '0'); } /** * @property indeterminate * @type {Boolean} * @description * [en]If this property is `true`, an infinite looping animation will be shown.[/en] * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja] */ }, { key: 'indeterminate', set: function set$$1(value) { if (value) { this.setAttribute(INDET, ''); } else { this.removeAttribute(INDET); } }, get: function get$$1() { return this.hasAttribute(INDET); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'value', 'secondary-value', INDET]; } }]); return ProgressBarElement; }(BaseElement); onsElements.ProgressBar = ProgressBarElement; customElements.define('ons-progress-bar', ProgressBarElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$21 = { '.progress-circular': 'progress-circular--*', '.progress-circular__background': 'progress-circular--*__background', '.progress-circular__primary': 'progress-circular--*__primary', '.progress-circular__secondary': 'progress-circular--*__secondary' }; var template$1 = util$1.createElement('\n <svg class="progress-circular">\n <circle class="progress-circular__background" />\n <circle class="progress-circular__secondary" cx="50%" cy="50%" r="40%" />\n <circle class="progress-circular__primary" cx="50%" cy="50%" r="40%" />\n </svg>\n'); var INDET$1 = 'indeterminate'; /** * @element ons-progress-circular * @category visual * @description * [en] * This component displays a circular progress indicator. It can either be used to show how much of a task has been completed or to show a looping animation to indicate that an operation is currently running. * [/en] * [ja][/ja] * @codepen EVzMjR * @tutorial vanilla/Reference/progress-circular * @seealso ons-progress-bar * [en]The `<ons-progress-bar>` component displays a bar progress indicator.[/en] * [ja][/ja] * @example * <ons-progress-circular * value="55" * secondary-value="87"> * </ons-progress-circular> * * <ons-progress-circular * indeterminate> * </ons-progress-circular> */ var ProgressCircularElement = function (_BaseElement) { inherits(ProgressCircularElement, _BaseElement); /** * @attribute modifier * @type {String} * @description * [en]Change the appearance of the progress indicator.[/en] * [ja]プログレスインジケータの見た目を変更します。[/ja] */ /** * @attribute value * @type {Number} * @description * [en]Current progress. Should be a value between 0 and 100.[/en] * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja] */ /** * @attribute secondary-value * @type {Number} * @description * [en]Current secondary progress. Should be a value between 0 and 100.[/en] * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja] */ /** * @attribute indeterminate * @description * [en]If this attribute is set, an infinite looping animation will be shown.[/en] * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja] */ function ProgressCircularElement() { classCallCheck(this, ProgressCircularElement); var _this = possibleConstructorReturn(this, (ProgressCircularElement.__proto__ || Object.getPrototypeOf(ProgressCircularElement)).call(this)); contentReady(_this, function () { return _this._compile(); }); return _this; } createClass(ProgressCircularElement, [{ key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'modifier') { ModifierUtil.onModifierChanged(last, current, this, scheme$21); this.hasAttribute(INDET$1) && this._updateDeterminate(); } else if (name === 'value' || name === 'secondary-value') { this._updateValue(); } else if (name === INDET$1) { this._updateDeterminate(); } } }, { key: '_updateDeterminate', value: function _updateDeterminate() { var _this2 = this; contentReady(this, function () { return util$1.toggleModifier(_this2, INDET$1, { force: _this2.hasAttribute(INDET$1) }); }); } }, { key: '_updateValue', value: function _updateValue() { var _this3 = this; if (this.hasAttribute('value')) { contentReady(this, function () { var per = Math.ceil(_this3.getAttribute('value') * 251.32 * 0.01); _this3._primary.style['stroke-dasharray'] = per + '%, 251.32%'; }); } if (this.hasAttribute('secondary-value')) { contentReady(this, function () { var per = Math.ceil(_this3.getAttribute('secondary-value') * 251.32 * 0.01); _this3._secondary.style.display = null; _this3._secondary.style['stroke-dasharray'] = per + '%, 251.32%'; }); } else { contentReady(this, function () { _this3._secondary.style.display = 'none'; }); } } /** * @property value * @type {Number} * @description * [en]Current progress. Should be a value between 0 and 100.[/en] * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja] */ }, { key: '_compile', value: function _compile() { if (this._isCompiled()) { this._template = util$1.findChild(this, '.progress-circular'); } else { this._template = template$1.cloneNode(true); } this._primary = util$1.findChild(this._template, '.progress-circular__primary'); this._secondary = util$1.findChild(this._template, '.progress-circular__secondary'); this._updateDeterminate(); this._updateValue(); this.appendChild(this._template); autoStyle.prepare(this); ModifierUtil.initModifier(this, scheme$21); } }, { key: '_isCompiled', value: function _isCompiled() { if (!util$1.findChild(this, '.progress-circular')) { return false; } var svg = util$1.findChild(this, '.progress-circular'); if (!util$1.findChild(svg, '.progress-circular__secondary')) { return false; } if (!util$1.findChild(svg, '.progress-circular__primary')) { return false; } return true; } }, { key: 'value', set: function set$$1(value) { if (typeof value !== 'number' || value < 0 || value > 100) { util$1.throw('Invalid value'); } this.setAttribute('value', Math.floor(value)); }, get: function get$$1() { return parseInt(this.getAttribute('value') || '0'); } /** * @property secondaryValue * @type {Number} * @description * [en]Current secondary progress. Should be a value between 0 and 100.[/en] * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja] */ }, { key: 'secondaryValue', set: function set$$1(value) { if (typeof value !== 'number' || value < 0 || value > 100) { util$1.throw('Invalid value'); } this.setAttribute('secondary-value', Math.floor(value)); }, get: function get$$1() { return parseInt(this.getAttribute('secondary-value') || '0'); } /** * @property indeterminate * @type {Boolean} * @description * [en]If this property is `true`, an infinite looping animation will be shown.[/en] * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja] */ }, { key: 'indeterminate', set: function set$$1(value) { if (value) { this.setAttribute(INDET$1, ''); } else { this.removeAttribute(INDET$1); } }, get: function get$$1() { return this.hasAttribute(INDET$1); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'value', 'secondary-value', INDET$1]; } }]); return ProgressCircularElement; }(BaseElement); onsElements.ProgressCircular = ProgressCircularElement; customElements.define('ons-progress-circular', ProgressCircularElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var STATE_INITIAL = 'initial'; var STATE_PREACTION = 'preaction'; var STATE_ACTION = 'action'; var throwType = function throwType(el, type) { return util$1.throw('"' + el + '" must be ' + type); }; /** * @element ons-pull-hook * @category control * @description * [en] * Component that adds **Pull to refresh** functionality to an `<ons-page>` element. * * It can be used to perform a task when the user pulls down at the top of the page. A common usage is to refresh the data displayed in a page. * [/en] * [ja][/ja] * @codepen WbJogM * @tutorial vanilla/Reference/pull-hook * @example * <ons-page> * <ons-pull-hook> * Release to refresh * </ons-pull-hook> * </ons-page> * * <script> * document.querySelector('ons-pull-hook').onAction = function(done) { * setTimeout(done, 1000); * }; * </script> */ var PullHookElement = function (_BaseElement) { inherits(PullHookElement, _BaseElement); /** * @event changestate * @description * [en]Fired when the state is changed. The state can be either "initial", "preaction" or "action".[/en] * [ja]コンポーネントの状態が変わった場合に発火します。状態は、"initial", "preaction", "action"のいずれかです。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクト。[/ja] * @param {Object} event.pullHook * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {String} event.state * [en]Current state.[/en] * [ja]現在の状態名を参照できます。[/ja] */ /** * @attribute disabled * @description * [en]If this attribute is set the "pull-to-refresh" functionality is disabled.[/en] * [ja]この属性がある時、disabled状態になりアクションが実行されなくなります[/ja] */ /** * @attribute height * @type {String} * @description * [en]Specify the height of the component. When pulled down further than this value it will switch to the "preaction" state. The default value is "64px".[/en] * [ja]コンポーネントの高さを指定します。この高さ以上にpull downすると"preaction"状態に移行します。デフォルトの値は"64px"です。[/ja] */ /** * @attribute threshold-height * @type {String} * @description * [en]Specify the threshold height. The component automatically switches to the "action" state when pulled further than this value. The default value is "96px". A negative value will disable this property. If this value is lower than the height, it will skip "preaction" state.[/en] * [ja]閾値となる高さを指定します。この値で指定した高さよりもpull downすると、このコンポーネントは自動的に"action"状態に移行します。[/ja] */ /** * @attribute fixed-content * @description * [en]If this attribute is set the content of the page will not move when pulling.[/en] * [ja]この属性がある時、プルフックが引き出されている時にもコンテンツは動きません。[/ja] */ function PullHookElement() { classCallCheck(this, PullHookElement); var _this = possibleConstructorReturn(this, (PullHookElement.__proto__ || Object.getPrototypeOf(PullHookElement)).call(this)); _this._shouldFixScroll = util$1.globals.isUIWebView; _this._onDrag = _this._onDrag.bind(_this); _this._onDragStart = _this._onDragStart.bind(_this); _this._onDragEnd = _this._onDragEnd.bind(_this); _this._onScroll = _this._onScroll.bind(_this); _this._setState(STATE_INITIAL, true); _this._hide(); // Fix for transparent toolbar transitions return _this; } createClass(PullHookElement, [{ key: '_setStyle', value: function _setStyle() { var height = this.height + 'px'; styler(this, { height: height, lineHeight: height }); this.style.display === '' && this._show(); } }, { key: '_onScroll', value: function _onScroll(event) { var element = this._pageElement; if (element.scrollTop < 0) { element.scrollTop = 0; } } }, { key: '_canConsumeGesture', value: function _canConsumeGesture(gesture) { return gesture.direction === 'up' || gesture.direction === 'down'; } }, { key: '_onDragStart', value: function _onDragStart(event) { var _this2 = this; if (!event.gesture || this.disabled) { return; } var tapY = event.gesture.center.clientY + this._pageElement.scrollTop; var maxY = window.innerHeight; // Only use drags that start near the pullHook to reduce flickerings var draggableAreaRatio = this._shouldFixScroll ? .8 : 1; this._ignoreDrag = event.consumed || tapY > maxY * draggableAreaRatio; if (!this._ignoreDrag) { var consume = event.consume; event.consume = function () { consume && consume(); _this2._ignoreDrag = true; // This elements resizes .page__content so it is safer // to hide it when other components are dragged. _this2._hide(); }; if (this._canConsumeGesture(event.gesture)) { consume && consume(); event.consumed = true; this._show(); // Not enough due to 'dragLockAxis' } } this._startScroll = this._pageElement.scrollTop; } }, { key: '_onDrag', value: function _onDrag(event) { var _this3 = this; if (!event.gesture || this.disabled || this._ignoreDrag || !this._canConsumeGesture(event.gesture)) { return; } // Necessary due to 'dragLockAxis' (25px) if (this.style.display === 'none') { this._show(); } event.stopPropagation(); var tapY = event.gesture.center.clientY + this._pageElement.scrollTop; var maxY = window.innerHeight; // Hack to make it work on Android 4.4 WebView and iOS UIWebView. Scrolls manually // near the top of the page so there will be no inertial scroll when scrolling down. // Allowing default scrolling will kill all 'touchmove' events. if (this._shouldFixScroll) { this._pageElement.scrollTop = this._startScroll - event.gesture.deltaY; // Allow inertia when scrolling down below 50% of the view to reduce flickerings if (event.gesture.interimDirection !== 'up' || tapY <= maxY * .5) { event.gesture.preventDefault(); } } var scroll = Math.max(event.gesture.deltaY - this._startScroll, 0); if (scroll !== this._currentTranslation) { var th = this.thresholdHeight; if (th > 0 && scroll >= th) { event.gesture.stopDetect(); setImmediate(function () { return _this3._finish(); }); } else if (scroll >= this.height) { this._setState(STATE_PREACTION); } else { this._setState(STATE_INITIAL); } this._translateTo(scroll); } } }, { key: '_onDragEnd', value: function _onDragEnd(event) { if (!event.gesture || this.disabled || this._ignoreDrag) { return; } event.stopPropagation(); if (this._currentTranslation > 0) { var scroll = this._currentTranslation; if (scroll > this.height) { this._finish(); } else { this._translateTo(0, { animate: true }); } } } /** * @property onAction * @type {Function} * @description * [en]This will be called in the `action` state if it exists. The function will be given a `done` callback as it's first argument.[/en] * [ja][/ja] */ }, { key: '_finish', value: function _finish() { var _this4 = this; this._setState(STATE_ACTION); this._translateTo(this.height, { animate: true }); var action = this.onAction || function (done) { return done(); }; action(function () { _this4._translateTo(0, { animate: true }); _this4._setState(STATE_INITIAL); }); } /** * @property height * @type {Number} * @description * [en]The height of the pull hook in pixels. The default value is `64px`.[/en] * [ja][/ja] */ }, { key: '_setState', value: function _setState(state, noEvent) { var lastState = this.state; this.setAttribute('state', state); if (!noEvent && lastState !== this.state) { util$1.triggerElementEvent(this, 'changestate', { pullHook: this, state: state, lastState: lastState }); } } /** * @property state * @readonly * @type {String} * @description * [en]Current state of the element.[/en] * [ja][/ja] */ }, { key: '_show', value: function _show() { var _this5 = this; // Run asyncrhonously to avoid conflicts with Animit's style clean setImmediate(function () { _this5.style.display = ''; if (_this5._pageElement) { _this5._pageElement.style.marginTop = '-' + _this5.height + 'px'; } }); } }, { key: '_hide', value: function _hide() { this.style.display = 'none'; if (this._pageElement) { this._pageElement.style.marginTop = ''; } } /** * @param {Number} scroll * @param {Object} options * @param {Function} [options.callback] */ }, { key: '_translateTo', value: function _translateTo(scroll) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (this._currentTranslation == 0 && scroll == 0) { return; } this._currentTranslation = scroll; var opt = options.animate ? { duration: .3, timing: 'cubic-bezier(.1, .7, .1, 1)' } : {}; this._onPull && this._onPull((scroll / this.height).toFixed(2), opt); var scrollElement = this.hasAttribute('fixed-content') ? this : this._pageElement; Animit(scrollElement).queue({ transform: 'translate3d(0px, ' + scroll + 'px, 0px)' }, opt).play(function () { scroll === 0 && styler.clear(scrollElement, 'transition transform'); options.callback instanceof Function && options.callback(); }); } }, { key: '_disableDragLock', value: function _disableDragLock() { // e2e tests need it this._dragLockDisabled = true; this._setupListeners(true); } }, { key: '_setupListeners', value: function _setupListeners(add) { var _this6 = this; var scrollToggle = function scrollToggle(action) { return _this6._pageElement[action + 'EventListener']('scroll', _this6._onScroll, false); }; var gdToggle = function gdToggle(action) { var passive = { passive: true }; _this6._gestureDetector[action]('drag', _this6._onDrag, passive); _this6._gestureDetector[action]('dragstart', _this6._onDragStart, passive); _this6._gestureDetector[action]('dragend', _this6._onDragEnd, passive); }; if (this._gestureDetector) { gdToggle('off'); this._gestureDetector.dispose(); this._gestureDetector = null; } scrollToggle('remove'); if (add) { this._gestureDetector = new GestureDetector(this._pageElement, { dragMinDistance: 1, dragDistanceCorrection: false, dragLockToAxis: !this._dragLockDisabled, passive: !this._shouldFixScroll }); gdToggle('on'); scrollToggle('add'); } } }, { key: 'connectedCallback', value: function connectedCallback() { this._currentTranslation = 0; this._pageElement = this.parentNode; this._setupListeners(true); this._setStyle(); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this._hide(); this._setupListeners(false); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'height' && this._pageElement) { this._setStyle(); } } }, { key: 'onAction', get: function get$$1() { return this._onAction; }, set: function set$$1(value) { if (value && !(value instanceof Function)) { throwType('onAction', 'function or null'); } this._onAction = value; } /** * @property onPull * @type {Function} * @description * [en]Hook called whenever the user pulls the element. It gets the pulled distance ratio (scroll / height) and an animationOptions object as arguments.[/en] * [ja][/ja] */ }, { key: 'onPull', get: function get$$1() { return this._onPull; }, set: function set$$1(value) { if (value && !(value instanceof Function)) { throwType('onPull', 'function or null'); } this._onPull = value; } }, { key: 'height', set: function set$$1(value) { if (!util$1.isInteger(value)) { throwType('height', 'integer'); } this.setAttribute('height', value + 'px'); }, get: function get$$1() { return parseInt(this.getAttribute('height') || '64', 10); } /** * @property thresholdHeight * @type {Number} * @description * [en]The thresholdHeight of the pull hook in pixels. The default value is `96px`.[/en] * [ja][/ja] */ }, { key: 'thresholdHeight', set: function set$$1(value) { if (!util$1.isInteger(value)) { throwType('thresholdHeight', 'integer'); } this.setAttribute('threshold-height', value + 'px'); }, get: function get$$1() { return parseInt(this.getAttribute('threshold-height') || '96', 10); } }, { key: 'state', get: function get$$1() { return this.getAttribute('state'); } /** * @property pullDistance * @readonly * @type {Number} * @description * [en]The current number of pixels the pull hook has moved.[/en] * [ja]現在のプルフックが引き出された距離をピクセル数。[/ja] */ }, { key: 'pullDistance', get: function get$$1() { return this._currentTranslation; } /** * @property disabled * @type {Boolean} * @description * [en]Whether the element is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ }, { key: 'disabled', set: function set$$1(value) { return util$1.toggleAttribute(this, 'disabled', value); }, get: function get$$1() { return this.hasAttribute('disabled'); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['height']; } }, { key: 'events', get: function get$$1() { return ['changestate']; } }]); return PullHookElement; }(BaseElement); onsElements.PullHook = PullHookElement; customElements.define('ons-pull-hook', PullHookElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$22 = { '': 'range--*', '.range__input': 'range--*__input', '.range__focus-ring': 'range--*__focus-ring' }; var activeClassToken = 'range__input--active'; /** * @element ons-range * @category form * @modifier material * [en]Material Design slider[/en] * [ja][/ja] * @description * [en] * Range input component. Used to display a draggable slider. * * Works very similar to the `<input type="range">` element. * [/en] * [ja][/ja] * @codepen xZQomM * @tutorial vanilla/Reference/range * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @seealso ons-input * [en]The `<ons-input>` component is used to display text inputs, radio buttons and checkboxes.[/en] * [ja][/ja] * @example * <ons-range value="20"></ons-range> * <ons-range modifier="material" value="10"></range> */ var RangeElement = function (_BaseInputElement) { inherits(RangeElement, _BaseInputElement); function RangeElement() { classCallCheck(this, RangeElement); var _this = possibleConstructorReturn(this, (RangeElement.__proto__ || Object.getPrototypeOf(RangeElement)).call(this)); _this._onMouseDown = _this._onMouseDown.bind(_this); _this._onMouseUp = _this._onMouseUp.bind(_this); _this._onTouchStart = _this._onTouchStart.bind(_this); _this._onTouchEnd = _this._onTouchEnd.bind(_this); _this._onInput = _this._update.bind(_this); _this._onDragstart = _this._onDragstart.bind(_this); _this._onDragend = _this._onDragend.bind(_this); return _this; } createClass(RangeElement, [{ key: '_compile', value: function _compile() { get(RangeElement.prototype.__proto__ || Object.getPrototypeOf(RangeElement.prototype), '_compile', this).call(this); this._updateDisabled(this.hasAttribute('disabled')); } /* Inherited props */ }, { key: '_update', value: function _update() { var input = this._input; var focusRing = this._focusRing; input.style.backgroundSize = 100 * this._ratio + '% 2px'; focusRing.value = this.value; // NOTE: "_zero" attribute is used for CSS styling. if (input.min === '' && input.value === '0' || input.min === input.value) { input.setAttribute('_zero', ''); } else { input.removeAttribute('_zero'); } ['min', 'max'].forEach(function (attr) { return focusRing[attr] = input[attr]; }); } }, { key: '_onMouseDown', /* Own props */ value: function _onMouseDown(e) { var _this2 = this; this._input.classList.add(activeClassToken); setImmediate(function () { return _this2._input.focus(); }); } }, { key: '_onTouchStart', value: function _onTouchStart(e) { this._onMouseDown(); } }, { key: '_onMouseUp', value: function _onMouseUp(e) { this._input.classList.remove(activeClassToken); } }, { key: '_onTouchEnd', value: function _onTouchEnd(e) { this._onMouseUp(e); } }, { key: '_onDragstart', value: function _onDragstart(e) { e.consumed = true; e.gesture.stopPropagation(); this._input.classList.add(activeClassToken); this.addEventListener('drag', this._onDrag); } }, { key: '_onDrag', value: function _onDrag(e) { e.stopPropagation(); } }, { key: '_onDragend', value: function _onDragend(e) { this._input.classList.remove(activeClassToken); this.removeEventListener('drag', this._onDrag); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'disabled') { this._updateDisabled(current); } get(RangeElement.prototype.__proto__ || Object.getPrototypeOf(RangeElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current); } /** * @param {boolean} disabled */ }, { key: '_updateDisabled', value: function _updateDisabled(disabled) { if (disabled) { this.classList.add('range--disabled'); } else { this.classList.remove('range--disabled'); } } }, { key: 'connectedCallback', value: function connectedCallback() { this._setupListeners(true); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this._setupListeners(false); } }, { key: '_setupListeners', value: function _setupListeners(add) { var action = (add ? 'add' : 'remove') + 'EventListener'; util$1[action](this, 'touchstart', this._onTouchStart, { passive: true }); this[action]('mousedown', this._onMouseDown); this[action]('mouseup', this._onMouseUp); this[action]('touchend', this._onTouchEnd); this[action]('dragstart', this._onDragstart); this[action]('dragend', this._onDragend); this[action]('input', this._onInput); } /** * @attribute disabled * @description * [en]Whether the element is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the element is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ /** * @property value * @type {Number} * @description * [en]Current value.[/en] * [ja][/ja] */ }, { key: '_scheme', get: function get$$1() { return scheme$22; } }, { key: '_template', get: function get$$1() { return '\n <input type="' + this.type + '" class="' + this._defaultClassName + '__input">\n <input type="range" class="range__focus-ring" tabIndex="-1">\n '; } }, { key: '_defaultClassName', get: function get$$1() { return 'range'; } }, { key: 'type', get: function get$$1() { return 'range'; } }, { key: '_focusRing', get: function get$$1() { return this.children[1]; } }, { key: '_ratio', get: function get$$1() { // Returns the current ratio. var min = this._input.min === '' ? 0 : parseInt(this._input.min); var max = this._input.max === '' ? 100 : parseInt(this._input.max); return (this.value - min) / (max - min); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['disabled'].concat(toConsumableArray(BaseInputElement.observedAttributes)); } }]); return RangeElement; }(BaseInputElement); onsElements.Range = RangeElement; customElements.define('ons-range', RangeElement); /* Copyright 2013-2016 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @class AnimatorCSS - implementation of Animator class using css transitions */ var AnimatorCSS = function () { createClass(AnimatorCSS, [{ key: 'animate', /** * @method animate * @desc main animation function * @param {Element} element * @param {Object} finalCSS * @param {number} [duration=200] - duration in milliseconds * @return {Object} result * @return {Function} result.then(callback) - sets a callback to be executed after the animation has stopped * @return {Function} result.stop(options) - stops the animation; if options.stopNext is true then it doesn't call the callback * @return {Function} result.finish(ms) - finishes the animation in the specified time in milliseconds * @return {Function} result.speed(ms) - sets the animation speed so that it finishes as if the original duration was the one specified here * @example * ```` * var result = animator.animate(el, {opacity: 0.5}, 1000); * * el.addEventListener('click', function(e){ * result.speed(200).then(function(){ * console.log('done'); * }); * }, 300); * ```` */ value: function animate(el, final) { var duration = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 200; var start = new Date().getTime(), initial = {}, stopped = false, next = false, timeout = false, properties = Object.keys(final); var updateStyles = function updateStyles() { var s = window.getComputedStyle(el); properties.forEach(s.getPropertyValue.bind(s)); s = el.offsetHeight; }; var result = { stop: function stop() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; timeout && clearTimeout(timeout); var k = Math.min(1, (new Date().getTime() - start) / duration); properties.forEach(function (i) { el.style[i] = (1 - k) * initial[i] + k * final[i] + (i == 'opacity' ? '' : 'px'); }); el.style.transitionDuration = '0s'; if (options.stopNext) { next = false; } else if (!stopped) { stopped = true; next && next(); } return result; }, then: function then(cb) { next = cb; if (stopped) { next && next(); } return result; }, speed: function speed(newDuration) { if (internal$1.config.animationsDisabled) { newDuration = 0; } if (!stopped) { timeout && clearTimeout(timeout); var passed = new Date().getTime() - start; var k = passed / duration; var remaining = newDuration * (1 - k); properties.forEach(function (i) { el.style[i] = (1 - k) * initial[i] + k * final[i] + (i == 'opacity' ? '' : 'px'); }); updateStyles(); start = el.speedUpTime; duration = remaining; el.style.transitionDuration = duration / 1000 + 's'; properties.forEach(function (i) { el.style[i] = final[i] + (i == 'opacity' ? '' : 'px'); }); timeout = setTimeout(result.stop, remaining); } return result; }, finish: function finish() { var milliseconds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50; var k = (new Date().getTime() - start) / duration; result.speed(milliseconds / (1 - k)); return result; } }; if (el.hasAttribute('disabled') || stopped || internal$1.config.animationsDisabled) { return result; } var style = window.getComputedStyle(el); properties.forEach(function (e) { var v = parseFloat(style.getPropertyValue(e)); initial[e] = isNaN(v) ? 0 : v; }); if (!stopped) { el.style.transitionProperty = properties.join(','); el.style.transitionDuration = duration / 1000 + 's'; properties.forEach(function (e) { el.style[e] = final[e] + (e == 'opacity' ? '' : 'px'); }); } timeout = setTimeout(result.stop, duration); this._onStopAnimations(el, result.stop); return result; } }]); function AnimatorCSS() { classCallCheck(this, AnimatorCSS); this._queue = []; this._index = 0; } createClass(AnimatorCSS, [{ key: '_onStopAnimations', value: function _onStopAnimations(el, listener) { var queue = this._queue; var i = this._index++; queue[el] = queue[el] || []; queue[el][i] = function (options) { delete queue[el][i]; if (queue[el] && queue[el].length == 0) { delete queue[el]; } return listener(options); }; } /** * @method stopAnimations * @desc stops active animations on a specified element * @param {Element|Array} element - element or array of elements * @param {Object} [options={}] * @param {Boolean} [options.stopNext] - the callbacks after the animations won't be called if this option is true */ }, { key: 'stopAnimations', value: function stopAnimations(el) { var _this = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (Array.isArray(el)) { return el.forEach(function (el) { _this.stopAnimations(el, options); }); } (this._queue[el] || []).forEach(function (e) { e(options || {}); }); } /** * @method stopAll * @desc stops all active animations * @param {Object} [options={}] * @param {Boolean} [options.stopNext] - the callbacks after the animations won't be called if this option is true */ }, { key: 'stopAll', value: function stopAll() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; this.stopAnimations(Object.keys(this._queue), options); } /** * @method fade * @desc fades the element (short version for animate(el, {opacity: 0})) * @param {Element} element * @param {number} [duration=200] */ }, { key: 'fade', value: function fade(el) { var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200; return this.animate(el, { opacity: 0 }, duration); } }]); return AnimatorCSS; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$11 = 'ripple'; var scheme$23 = { '': 'ripple--*', '.ripple__wave': 'ripple--*__wave', '.ripple__background': 'ripple--*__background' }; /** * @element ons-ripple * @category visual * @description * [en] * Adds a Material Design "ripple" effect to an element. The ripple effect will spread from the position where the user taps. * * Some elements such as `<ons-button>` and `<ons-fab>` support a `ripple` attribute. * [/en] * [ja]マテリアルデザインのリップル効果をDOM要素に追加します。[/ja] * @codepen wKQWdZ * @tutorial vanilla/Reference/ripple * @modifier light-gray * [en]Change the color of effects to light gray.[/en] * [ja]エフェクトの色が明るい灰色になります。[/ja] * @guide theming.html#cross-platform-styling-autostyling * [en]Cross platform styling[/en] * [ja]Cross platform styling[/ja] * @example * <div class="my-div"> * <ons-ripple></ons-ripple> * </div> * * @example * <ons-button ripple>Click me!</ons-button> */ var RippleElement = function (_BaseElement) { inherits(RippleElement, _BaseElement); /** * @attribute color * @type {String} * @description * [en]Color of the ripple effect.[/en] * [ja]リップルエフェクトの色を指定します。[/ja] */ /** * @attribute modifier * @type {String} * @description * [en]The appearance of the ripple effect.[/en] * [ja]エフェクトの表現を指定します。[/ja] */ /** * @attribute background * @type {String} * @description * [en]Color of the background.[/en] * [ja]背景の色を設定します。[/ja] */ /** * @attribute size * @type {String} * @description * [en]Sizing of the wave on ripple effect. Set "cover" or "contain". Default is "cover".[/en] * [ja]エフェクトのサイズを指定します。"cover"もしくは"contain"を指定します。デフォルトは"cover"です。[/ja] */ /** * @attribute center * @type {Boolean} * @description * [en]If this attribute presents, change the position of wave effect to center of the target element.[/en] * [ja]この要素を設定すると、エフェクトの位置が要素の真ん中から始まります。[/ja] */ /** * @attribute disabled * @description * [en]If this attribute is set, the ripple effect will be disabled.[/en] * [ja]この属性が設定された場合、リップルエフェクトは無効になります。[/ja] */ function RippleElement() { classCallCheck(this, RippleElement); var _this = possibleConstructorReturn(this, (RippleElement.__proto__ || Object.getPrototypeOf(RippleElement)).call(this)); _this._onTap = _this._onTap.bind(_this); _this._onHold = _this._onHold.bind(_this); _this._onDragStart = _this._onDragStart.bind(_this); _this._onRelease = _this._onRelease.bind(_this); contentReady(_this, function () { return _this._compile(); }); _this._animator = new AnimatorCSS(); ['color', 'center', 'start-radius', 'background', 'modifier'].forEach(function (e) { _this.attributeChangedCallback(e, null, _this.getAttribute(e)); }); return _this; } createClass(RippleElement, [{ key: '_compile', value: function _compile() { this.classList.add(defaultClassName$11); this._wave = this.getElementsByClassName('ripple__wave')[0]; this._background = this.getElementsByClassName('ripple__background')[0]; if (!(this._background && this._wave)) { this._wave = util$1.create('.ripple__wave'); this._background = util$1.create('.ripple__background'); this.appendChild(this._wave); this.appendChild(this._background); } ModifierUtil.initModifier(this, scheme$23); } }, { key: '_getEffectSize', value: function _getEffectSize() { var sizes = ['cover', 'contain']; if (this.hasAttribute('size')) { var size = this.getAttribute('size'); if (sizes.indexOf(size) !== -1) { return size; } } return 'cover'; } }, { key: '_calculateCoords', value: function _calculateCoords(e) { var x = void 0, y = void 0, h = void 0, w = void 0, r = void 0; var b = this.getBoundingClientRect(); var size = this._getEffectSize(); var error = function error() { return util$1.throw('Ripple invalid state'); }; if (this._center) { x = b.width / 2; y = b.height / 2; if (size === 'cover') { r = Math.sqrt(x * x + y * y); } else if (size === 'contain') { r = Math.min(x, y); } else { error(); } } else { x = (typeof e.clientX === 'number' ? e.clientX : e.changedTouches[0].clientX) - b.left; y = (typeof e.clientY === 'number' ? e.clientY : e.changedTouches[0].clientY) - b.top; h = Math.max(y, b.height - y); w = Math.max(x, b.width - x); if (size === 'cover') { r = Math.sqrt(h * h + w * w); } else if (size === 'contain') { r = Math.min(Math.round(h / 2), Math.round(w / 2)); } else { error(); } } return { x: x, y: y, r: r }; } }, { key: '_rippleAnimation', value: function _rippleAnimation(e) { var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300; var _animator = this._animator, _wave = this._wave, _background = this._background, _minR = this._minR; var _calculateCoords2 = this._calculateCoords(e), x = _calculateCoords2.x, y = _calculateCoords2.y, r = _calculateCoords2.r; _animator.stopAll({ stopNext: 1 }); _animator.animate(_background, { opacity: 1 }, duration); util$1.extend(_wave.style, { opacity: 1, top: y - _minR + 'px', left: x - _minR + 'px', width: 2 * _minR + 'px', height: 2 * _minR + 'px' }); return _animator.animate(_wave, { top: y - r, left: x - r, height: 2 * r, width: 2 * r }, duration); } }, { key: '_updateParent', value: function _updateParent() { if (!this._parentUpdated && this.parentNode) { var computedStyle = window.getComputedStyle(this.parentNode); if (computedStyle.getPropertyValue('position') === 'static') { this.parentNode.style.position = 'relative'; } this._parentUpdated = true; } } }, { key: '_onTap', value: function _onTap(e) { var _this2 = this; if (!this.disabled && !e.ripple) { e.ripple = true; this._updateParent(); this._rippleAnimation(e.gesture.srcEvent).then(function () { _this2._animator.fade(_this2._wave); _this2._animator.fade(_this2._background); }); } } }, { key: '_onHold', value: function _onHold(e) { if (!this.disabled && !e.ripple) { e.ripple = true; this._updateParent(); this._holding = this._rippleAnimation(e.gesture.srcEvent, 2000); document.addEventListener('release', this._onRelease); } } }, { key: '_onRelease', value: function _onRelease(e) { var _this3 = this; if (this._holding && !e.ripple) { e.ripple = true; this._holding.speed(300).then(function () { _this3._animator.stopAll({ stopNext: true }); _this3._animator.fade(_this3._wave); _this3._animator.fade(_this3._background); }); this._holding = false; } document.removeEventListener('release', this._onRelease); } }, { key: '_onDragStart', value: function _onDragStart(e) { if (this._holding) { return this._onRelease(e); } if (['left', 'right'].indexOf(e.gesture.direction) != -1) { this._onTap(e); } } }, { key: 'connectedCallback', value: function connectedCallback() { this._parentNode = this.parentNode; if (internal$1.config.animationsDisabled) { this.disabled = true; } else { this._parentNode.addEventListener('tap', this._onTap); this._parentNode.addEventListener('hold', this._onHold); this._parentNode.addEventListener('dragstart', this._onDragStart); } } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { var pn = this._parentNode || this.parentNode; pn.removeEventListener('tap', this._onTap); pn.removeEventListener('hold', this._onHold); pn.removeEventListener('dragstart', this._onDragStart); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { var _this4 = this; switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$11, scheme$23); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$23); break; case 'start-radius': this._minR = Math.max(0, parseFloat(current) || 0); break; case 'color': if (current) { contentReady(this, function () { _this4._wave.style.background = current; if (!_this4.hasAttribute('background')) { _this4._background.style.background = current; } }); } break; case 'background': if (current || last) { if (current === 'none') { contentReady(this, function () { _this4._background.setAttribute('disabled', 'disabled'); _this4._background.style.background = 'transparent'; }); } else { contentReady(this, function () { if (_this4._background.hasAttribute('disabled')) { _this4._background.removeAttribute('disabled'); } _this4._background.style.background = current; }); } } break; case 'center': if (name === 'center') { this._center = current != null && current != 'false'; } break; } } /** * @property disabled * @type {Boolean} * @description * [en]Whether the element is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ }, { key: 'disabled', set: function set$$1(value) { return util$1.toggleAttribute(this, 'disabled', value); }, get: function get$$1() { return this.hasAttribute('disabled'); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['start-radius', 'color', 'background', 'center', 'class', 'modifier']; } }]); return RippleElement; }(BaseElement); onsElements.Ripple = RippleElement; customElements.define('ons-ripple', RippleElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-row * @category grid * @description * [en]Represents a row in the grid system. Use with `<ons-col>` to layout components.[/en] * [ja]グリッドシステムにて行を定義します。ons-colとともに使用し、コンポーネントの配置に使用します。[/ja] * @codepen GgujC {wide} * @guide features.html * [en]Layouting guide[/en] * [ja]レイアウト調整[/ja] * @seealso ons-col * [en]The `<ons-col>` component is used as children of `<ons-row>`.[/en] * [ja]ons-colコンポーネント[/ja] * @note * [en]For Android 4.3 and earlier, and iOS6 and earlier, when using mixed alignment with ons-row and ons-col, they may not be displayed correctly. You can use only one vertical-align.[/en] * [ja]Android 4.3以前、もしくはiOS 6以前のOSの場合、ons-rowとons-colを組み合わせてそれぞれのons-col要素のvertical-align属性の値に別々の値を指定すると、描画が崩れる場合があります。vertical-align属性の値には一つの値だけを指定できます。[/ja] * @example * <ons-row> * <ons-col width="50px"><ons-icon icon="fa-twitter"></ons-icon></ons-col> * <ons-col>Text</ons-col> * </ons-row> */ /** * @attribute vertical-align * @type {String} * @description * [en]Short hand attribute for aligning vertically. Valid values are top, bottom, and center.[/en] * [ja]縦に整列するために指定します。top、bottom、centerのいずれかを指定できます。[/ja] */ var RowElement = function (_BaseElement) { inherits(RowElement, _BaseElement); function RowElement() { classCallCheck(this, RowElement); return possibleConstructorReturn(this, (RowElement.__proto__ || Object.getPrototypeOf(RowElement)).apply(this, arguments)); } return RowElement; }(BaseElement); onsElements.Row = RowElement; customElements.define('ons-row', RowElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$12 = 'segment'; var scheme$24 = { '': 'segment--*', '.segment__item': 'segment--*__item', '.segment__input': 'segment--*__input', '.segment__button': 'segment--*__button' }; var generateId$1 = function () { var i = 0; return function () { return 'ons-segment-gen-' + i++; }; }(); /** * @element ons-segment * @category control * @modifier material * [en]Material Design segment[/en] * [ja][/ja] * @description * [en] * Segment component. Use this component to have a button bar with automatic styles that switch on click of another button. * * Will automatically display as a Material Design segment on Android. * [/en] * [ja][/ja] * @codepen hLayx * @tutorial vanilla/Reference/segment * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja] * @example * <ons-segment> * <ons-button>Label 1</ons-button> * <ons-button>Label 2</ons-button> * <ons-button>Label 3</ons-button> * </ons-segment> */ var SegmentElement = function (_BaseElement) { inherits(SegmentElement, _BaseElement); /** * @event postchange * @description * [en]Fires after the active button is changed.[/en] * [ja][/ja] * @param {Object} event * [en]Event object.[/en] * [ja][/ja] * @param {Number} event.index * [en]Tapped button index.[/en] * [ja][/ja] * @param {Object} event.segmentItem * [en]Segment item object.[/en] * [ja][/ja] */ /** * @attribute modifier * @type {String} * @description * [en]The appearance of the segment.[/en] * [ja][/ja] */ /** * @attribute tabbar-id * @initonly * @type {String} * @description * [en]ID of the tabbar element to "connect" to the segment. Must be inside the same page.[/en] * [ja][/ja] */ /** * @attribute active-index * @initonly * @default 0 * @type {Number} * @description * [en]Index of the first active button, only works if there is no connected tabbar (in which case the active tab sets the active button).[/en] * [ja][/ja] */ /** * @attribute disabled * @description * [en]Specify if segment should be disabled.[/en] * [ja]ボタンを無効化する場合は指定します。[/ja] */ function SegmentElement() { classCallCheck(this, SegmentElement); var _this = possibleConstructorReturn(this, (SegmentElement.__proto__ || Object.getPrototypeOf(SegmentElement)).call(this)); _this._segmentId = generateId$1(); _this._tabbar = null; _this._onChange = _this._onChange.bind(_this); _this._onTabbarPreChange = _this._onTabbarPreChange.bind(_this); contentReady(_this, function () { _this._compile(); setImmediate(function () { return _this._lastActiveIndex = _this._tabbar ? _this._tabbar.getActiveTabIndex() : _this.getActiveButtonIndex(); }); }); return _this; } createClass(SegmentElement, [{ key: '_compile', value: function _compile() { autoStyle.prepare(this); this.classList.add(defaultClassName$12); for (var index = this.children.length - 1; index >= 0; index--) { var item = this.children[index]; item.classList.add('segment__item'); var input = util$1.findChild(item, '.segment__input') || util$1.create('input.segment__input'); input.type = 'radio'; input.value = index; input.name = input.name || this._segmentId; input.checked = !this.hasAttribute('tabbar-id') && index === (parseInt(this.getAttribute('active-index')) || 0); var button = util$1.findChild(item, '.segment__button') || util$1.create('.segment__button'); if (button.parentElement !== item) { while (item.firstChild) { button.appendChild(item.firstChild); } } item.appendChild(input); item.appendChild(button); } ModifierUtil.initModifier(this, scheme$24); } }, { key: 'connectedCallback', value: function connectedCallback() { var _this2 = this; contentReady(this, function () { if (_this2.hasAttribute('tabbar-id')) { var page = util$1.findParent(_this2, 'ons-page'); _this2._tabbar = page && page.querySelector('#' + _this2.getAttribute('tabbar-id')); if (!_this2._tabbar || _this2._tabbar.tagName !== 'ONS-TABBAR') { util$1.throw('No tabbar with id ' + _this2.getAttribute('tabbar-id') + ' was found.'); } _this2._tabbar.setAttribute('hide-tabs', ''); setImmediate(function () { return _this2._setChecked(_this2._tabbar.getActiveTabIndex()); }); _this2._tabbar.addEventListener('prechange', _this2._onTabbarPreChange); } }); this.addEventListener('change', this._onChange); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { var _this3 = this; contentReady(this, function () { if (_this3._tabbar) { _this3._tabbar.removeEventListener('prechange', _this3._onTabbarPreChange); _this3._tabbar = null; } }); this.removeEventListener('change', this._onChange); } }, { key: '_setChecked', value: function _setChecked(index) { this.children[index].firstElementChild.checked = true; } /** * @method setActiveButton * @signature setActiveButton(index, [options]) * @param {Number} index * [en]Button index.[/en] * [ja][/ja] * @param {Object} [options] * [en]Parameter object, works only if there is a connected tabbar. Supports the same options as `ons-tabbar`'s `setActiveTab` method.[/en] * [ja][/ja] * @description * [en]Make button with the specified index active. If there is a connected tabbar it shows the corresponding tab page. In this case animations and their options can be specified by the second parameter.[/en] * [ja][/ja] * @return {Promise} * [en]Resolves to the selected index or to the new page element if there is a connected tabbar.[/en] * [ja][/ja] */ }, { key: 'setActiveButton', value: function setActiveButton(index, options) { if (this._tabbar) { return this._tabbar.setActiveTab(index, options); } this._setChecked(index); this._postChange(index); return Promise.resolve(index); } /** * @method getActiveButtonIndex * @signature getActiveButtonIndex() * @return {Number} * [en]The index of the currently active button.[/en] * [ja][/ja] * @description * [en]Returns button index of current active button. If active button is not found, returns -1.[/en] * [ja][/ja] */ }, { key: 'getActiveButtonIndex', value: function getActiveButtonIndex() { for (var i = this.children.length - 1; i >= 0; i--) { // Array.findIndex if (this.children[i].firstElementChild.checked) { return i; } } return -1; } }, { key: '_onChange', value: function _onChange(event) { event.stopPropagation(); this._tabbar ? this._tabbar.setActiveTab(this.getActiveButtonIndex(), { reject: false }) : this._postChange(this.getActiveButtonIndex()); } }, { key: '_onTabbarPreChange', value: function _onTabbarPreChange(event) { var _this4 = this; setImmediate(function () { if (!event.detail.canceled) { _this4._setChecked(event.index); _this4._postChange(event.index); } }); } }, { key: '_postChange', value: function _postChange(index) { util$1.triggerElementEvent(this, 'postchange', { index: index, activeIndex: index, lastActiveIndex: this._lastActiveIndex, segmentItem: this.children[index] }); this._lastActiveIndex = index; } /** * @property disabled * @type {Boolean} * @description * [en]Whether the segment is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$12, scheme$24); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$24); break; } } }, { key: 'disabled', set: function set$$1(value) { return util$1.toggleAttribute(this, 'disabled', value); }, get: function get$$1() { return this.hasAttribute('disabled'); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['class', 'modifier']; } }, { key: 'events', get: function get$$1() { return ['postchange']; } }]); return SegmentElement; }(BaseElement); onsElements.Segment = SegmentElement; customElements.define('ons-segment', SegmentElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$25 = { '': 'select-* select--*', '.select-input': 'select-input--*' }; var defaultClassName$13 = 'select'; var INPUT_ATTRIBUTES$1 = ['autofocus', 'disabled', 'form', 'multiple', 'name', 'required', 'size']; /** * @element ons-select * @category form * @modifier material * [en]Displays a Material Design select input.[/en] * [ja][/ja] * @modifier underbar * [en]Displays a horizontal line underneath a select input.[/en] * [ja][/ja] * @description * [en] * Select component. If you want to place a select with an ID of `my-id` on a page, use `<ons-select select-id="my-id">`. * * The component will automatically display as a Material Design select on Android. * * Most attributes that can be used for a normal `<select>` element can also be used on the `<ons-select>` element. * [/en] * [ja]セレクトボックスを表示するコンポーネントです。`select` 要素に使用できる属性の多くが `ons-select` 要素でも利用できます。[/ja] * @codepen hLayx * @tutorial vanilla/Reference/select * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @guide theming.html#cross-platform-styling-autostyling [en]Information about cross platform styling[/en][ja]Information about cross platform styling[/ja] * @example * <ons-select> * <option value="1">1</option> * <option value="2">2nd</option> * <option value="3">3rd option</option> * </ons-select> */ var SelectElement = function (_BaseElement) { inherits(SelectElement, _BaseElement); /** * @attribute autofocus * @type {Boolean} * @default false * @description * [en]Element automatically gains focus on page load.[/en] * [ja]ページロード時にこのセレクトボックスにフォーカスが移るようにします。[/ja] */ /** * @attribute disabled * @type {Boolean} * @default false * @description * [en]Specify if select input should be disabled.[/en] * [ja]このセレクトボックスを無効化する場合に指定します。[/ja] */ /** * @attribute form * @type {String} * @description * [en]Associate a select element to an existing form on the page, even if not nested.[/en] * [ja]このセレクトボックスを、指定した `form` 要素に紐付けます。セレクトボックスを `form` 要素の外側に配置する際に使用します。[/ja] */ /** * @attribute multiple * @type {Boolean} * @default false * @description * [en]If this attribute is defined, multiple options can be selected at once.[/en] * [ja]選択肢の複数選択を有効にします。[/ja] */ /** * @attribute name * @type {String} * @description * [en]Name the select element, useful for instance if it is part of a form.[/en] * [ja]このセレクトボックスの名前を指定します。通常 `form` 要素と共に使用します。[/ja] */ /** * @attribute required * @type {Boolean} * @description * [en]Make the select input required for submitting the form it is part of.[/en] * [ja]このセレクトボックスを入力必須にする場合に指定します。通常 `form` 要素と共に使用します。[/ja] */ /** * @attribute select-id * @type {String} * @description * [en]ID given to the inner select, useful for dynamic manipulation.[/en] * [ja]このセレクトボックスが内部に持つ select 要素に与える ID を指定します。セレクトボックスの内容を動的に変更する必要がある場合に使用します。[/ja] */ /** * @attribute size * @type {Number} * @default 1 * @description * [en]How many options are displayed; if there are more than the size then a scroll appears to navigate them.[/en] * [ja]一度に表示する選択肢の個数を指定します。選択肢がこの属性で指定した個数よりも多い場合、スクロールが有効になります。[/ja] */ function SelectElement() { classCallCheck(this, SelectElement); var _this = possibleConstructorReturn(this, (SelectElement.__proto__ || Object.getPrototypeOf(SelectElement)).call(this)); contentReady(_this, function () { return _this._compile(); }); _this._deriveGetters(); return _this; } createClass(SelectElement, [{ key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { var _this2 = this; switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$13, scheme$25); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$25); break; } if (INPUT_ATTRIBUTES$1.indexOf(name) >= 0) { contentReady(this, function () { return _this2._updateBoundAttributes(); }); } } }, { key: '_updateBoundAttributes', value: function _updateBoundAttributes() { var _this3 = this; INPUT_ATTRIBUTES$1.forEach(function (attr) { if (_this3.hasAttribute(attr)) { _this3._select.setAttribute(attr, _this3.getAttribute(attr)); } else { _this3._select.removeAttribute(attr); } }); } /** * @property length * @description * [en]Number of options in the select box.[/en] * [ja]このセレクトボックスに含まれる選択肢の個数を返します。 `select` 要素[/ja] */ /** * @property options * @description * [en]Several options for handling the select DOM object.[/en] * [ja]このセレクトボックスに含まれる `option` 要素の配列を返します。[/ja] */ /** * @property selectedIndex * @description * [en]Index of the currently selected option.[/en] * [ja]現在選択されている選択肢のインデックスを返します。[/ja] */ /** * @property value * @description * [en]Value of the currently selected option.[/en] * [ja]現在選択されている選択肢の値を返します。[/ja] */ }, { key: '_compile', value: function _compile() { autoStyle.prepare(this); this.classList.add(defaultClassName$13); var sel = this._select || document.createElement('select'); if (!sel.id && this.hasAttribute('select-id')) { sel.id = this.getAttribute('select-id'); } sel.classList.add('select-input'); if (!this._select) { util$1.arrayFrom(this.childNodes).forEach(function (element) { return sel.appendChild(element); }); this.appendChild(sel); } ModifierUtil.initModifier(this, scheme$25); } }, { key: '_deriveGetters', value: function _deriveGetters() { var _this4 = this; ['disabled', 'length', 'multiple', 'name', 'options', 'selectedIndex', 'size', 'value', 'form', 'type'].forEach(function (key) { Object.defineProperty(_this4, key, { configurable: true, enumerable: true, get: function get$$1() { return _this4._select[key]; }, set: ['form', 'type'].indexOf(key) === -1 ? function (value) { return contentReady(_this4, function () { return _this4._select[key] = value; }); } : undefined }); }); } }, { key: 'add', value: function add(option) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; this._select.add(option, index); } }, { key: 'remove', value: function remove(index) { this._select.remove(index); } }, { key: '_select', get: function get$$1() { return this.querySelector('select'); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'class'].concat(INPUT_ATTRIBUTES$1); } }]); return SelectElement; }(BaseElement); onsElements.Select = SelectElement; customElements.define('ons-select', SelectElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$14 = 'fab fab--mini speed-dial__item'; var scheme$26 = { '': 'fab--* speed-dial__item--*' }; /** * @element ons-speed-dial-item * @category control * @description * [en] * This component displays the child elements of the Material Design Speed dial component. * [/en] * [ja] * Material DesignのSpeed dialの子要素を表現する要素です。 * [/ja] * @codepen dYQYLg * @tutorial vanilla/Reference/speed-dial * @seealso ons-speed-dial * [en]The `<ons-speed-dial>` component.[/en] * [ja]ons-speed-dialコンポーネント[/ja] * @seealso ons-fab * [en]ons-fab component[/en] * [ja]ons-fabコンポーネント[/ja] * @example * <ons-speed-dial position="left bottom"> * <ons-fab> * <ons-icon icon="fa-twitter"></ons-icon> * </ons-fab> * <ons-speed-dial-item>A</ons-speed-dial-item> * <ons-speed-dial-item>B</ons-speed-dial-item> * <ons-speed-dial-item>C</ons-speed-dial-item> * </ons-speed-dial> */ var SpeedDialItemElement = function (_BaseElement) { inherits(SpeedDialItemElement, _BaseElement); /** * @attribute modifier * @type {String} * @description * [en]The appearance of the component.[/en] * [ja]このコンポーネントの表現を指定します。[/ja] */ /** * @attribute ripple * @description * [en]If this attribute is defined, the button will have a ripple effect when tapped.[/en] * [ja][/ja] */ function SpeedDialItemElement() { classCallCheck(this, SpeedDialItemElement); var _this = possibleConstructorReturn(this, (SpeedDialItemElement.__proto__ || Object.getPrototypeOf(SpeedDialItemElement)).call(this)); _this._compile(); _this._boundOnClick = _this._onClick.bind(_this); return _this; } createClass(SpeedDialItemElement, [{ key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$14, scheme$26); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$26); util$1.addModifier(this, 'mini'); break; case 'ripple': this._updateRipple(); } } }, { key: 'connectedCallback', value: function connectedCallback() { this.addEventListener('click', this._boundOnClick, false); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this.removeEventListener('click', this._boundOnClick, false); } }, { key: '_updateRipple', value: function _updateRipple() { util$1.updateRipple(this); } }, { key: '_onClick', value: function _onClick(e) { e.stopPropagation(); } }, { key: '_compile', value: function _compile() { var _this2 = this; autoStyle.prepare(this); defaultClassName$14.split(/\s+/).forEach(function (token) { return _this2.classList.add(token); }); util$1.addModifier(this, 'mini'); this._updateRipple(); ModifierUtil.initModifier(this, scheme$26); } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'ripple', 'class']; } }]); return SpeedDialItemElement; }(BaseElement); onsElements.SpeedDialItem = SpeedDialItemElement; customElements.define('ons-speed-dial-item', SpeedDialItemElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$15 = 'speed-dial'; var scheme$27 = { '': 'speed-dial--*' }; /** * @element ons-speed-dial * @category control * @description * [en] * Element that displays a Material Design Speed Dialog component. It is useful when there are more than one primary action that can be performed in a page. * * The Speed dial looks like a `<ons-fab>` element but will expand a menu when tapped. * [/en] * [ja][/ja] * @codepen dYQYLg * @tutorial vanilla/Reference/speed-dial * @seealso ons-speed-dial-item * [en]The `<ons-speed-dial-item>` represents a menu item.[/en] * [ja]ons-speed-dial-itemコンポーネント[/ja] * @seealso ons-fab * [en]ons-fab component[/en] * [ja]ons-fabコンポーネント[/ja] * @example * <ons-speed-dial position="left bottom"> * <ons-fab> * <ons-icon icon="fa-twitter"></ons-icon> * </ons-fab> * <ons-speed-dial-item>A</ons-speed-dial-item> * <ons-speed-dial-item>B</ons-speed-dial-item> * <ons-speed-dial-item>C</ons-speed-dial-item> * </ons-speed-dial> */ var SpeedDialElement = function (_BaseElement) { inherits(SpeedDialElement, _BaseElement); /** * @event open * @description * [en]Fired when the menu items are shown.[/en] * [ja][/ja] */ /** * @event close * @description * [en]Fired when the menu items are hidden.[/en] * [ja][/ja] */ /** * @attribute modifier * @type {String} * @description * [en]The appearance of the component.[/en] * [ja]このコンポーネントの表現を指定します。[/ja] */ /** * @attribute ripple * @description * [en]If this attribute is defined, the button will have a ripple effect when tapped.[/en] * [ja][/ja] */ /** * @attribute position * @type {String} * @description * [en] * Specify the vertical and horizontal position of the component. * I.e. to display it in the top right corner specify "right top". * Choose from "right", "left", "top" and "bottom". * [/en] * [ja] * この要素を表示する左右と上下の位置を指定します。 * 例えば、右上に表示する場合には"right top"を指定します。 * 左右と上下の位置の指定には、rightとleft、topとbottomがそれぞれ指定できます。 * [/ja] */ /** * @attribute direction * @type {String} * @description * [en]Specify the direction the items are displayed. Possible values are "up", "down", "left" and "right".[/en] * [ja] * 要素が表示する方向を指定します。up, down, left, rightが指定できます。 * [/ja] */ /** * @attribute disabled * @description * [en]Specify if button should be disabled.[/en] * [ja]無効化する場合に指定します。[/ja] */ function SpeedDialElement() { classCallCheck(this, SpeedDialElement); var _this = possibleConstructorReturn(this, (SpeedDialElement.__proto__ || Object.getPrototypeOf(SpeedDialElement)).call(this)); contentReady(_this, function () { _this._compile(); }); _this._itemShown = false; _this._boundOnClick = _this._onClick.bind(_this); return _this; } createClass(SpeedDialElement, [{ key: '_compile', value: function _compile() { this.classList.add(defaultClassName$15); autoStyle.prepare(this); this._updateRipple(); ModifierUtil.initModifier(this, scheme$27); if (this.hasAttribute('direction')) { this._updateDirection(this.getAttribute('direction')); } else { this._updateDirection('up'); } this._updatePosition(); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { var _this2 = this; switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$15, scheme$27); break; case 'modifier': ModifierUtil.onModifierChanged(last, current, this, scheme$27); break; case 'ripple': contentReady(this, function () { return _this2._updateRipple(); }); break; case 'direction': contentReady(this, function () { return _this2._updateDirection(current); }); break; case 'position': contentReady(this, function () { return _this2._updatePosition(); }); break; } } }, { key: 'connectedCallback', value: function connectedCallback() { this.addEventListener('click', this._boundOnClick, false); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this.removeEventListener('click', this._boundOnClick, false); } }, { key: '_onClick', value: function _onClick(e) { if (this.onClick) { this.onClick.apply(this); return Promise.resolve(); } else if (!this.disabled && this.visible) { return this.toggleItems(); } } }, { key: '_show', value: function _show() { if (!this.inline) { return this.show(); } return Promise.resolve(); } }, { key: '_hide', value: function _hide() { var _this3 = this; return new Promise(function (resolve) { if (!_this3.inline) { setImmediate(function () { return _this3.hide().then(resolve); }); } else { resolve(); } }); } }, { key: '_updateRipple', value: function _updateRipple() { if (this._fab) { this.hasAttribute('ripple') ? this._fab.setAttribute('ripple', '') : this._fab.removeAttribute('ripple'); } } }, { key: '_updateDirection', value: function _updateDirection(direction) { var children = this.items; for (var i = 0; i < children.length; i++) { styler(children[i], { transitionDelay: 25 * i + 'ms', bottom: 'auto', right: 'auto', top: 'auto', left: 'auto' }); } switch (direction) { case 'up': for (var _i = 0; _i < children.length; _i++) { children[_i].style.bottom = 72 + 56 * _i + 'px'; children[_i].style.right = '8px'; } break; case 'down': for (var _i2 = 0; _i2 < children.length; _i2++) { children[_i2].style.top = 72 + 56 * _i2 + 'px'; children[_i2].style.left = '8px'; } break; case 'left': for (var _i3 = 0; _i3 < children.length; _i3++) { children[_i3].style.top = '8px'; children[_i3].style.right = 72 + 56 * _i3 + 'px'; } break; case 'right': for (var _i4 = 0; _i4 < children.length; _i4++) { children[_i4].style.top = '8px'; children[_i4].style.left = 72 + 56 * _i4 + 'px'; } break; default: util$1.throw('Argument must be one of up, down, left or right.'); } } }, { key: '_updatePosition', value: function _updatePosition() { var position = this.getAttribute('position'); this.classList.remove('fab--top__left', 'fab--bottom__right', 'fab--bottom__left', 'fab--top__right', 'fab--top__center', 'fab--bottom__center'); switch (position) { case 'top right': case 'right top': this.classList.add('fab--top__right'); break; case 'top left': case 'left top': this.classList.add('fab--top__left'); break; case 'bottom right': case 'right bottom': this.classList.add('fab--bottom__right'); break; case 'bottom left': case 'left bottom': this.classList.add('fab--bottom__left'); break; case 'center top': case 'top center': this.classList.add('fab--top__center'); break; case 'center bottom': case 'bottom center': this.classList.add('fab--bottom__center'); break; default: break; } } }, { key: '_getTranslate', value: function _getTranslate() { var isBottom = (this.getAttribute('position') || '').indexOf('bottom') >= 0; var translate = isBottom ? 'translate3d(0px, -' + (util$1.globals.fabOffset || 0) + 'px, 0px) ' : ''; return translate; } /** * @method show * @signature show() * @description * [en]Show the speed dial.[/en] * [ja]Speed dialを表示します。[/ja] */ }, { key: 'show', value: function show() { this._fab.show(); styler(this, { transform: this._getTranslate }); return Promise.resolve(); } /** * @method hide * @signature hide() * @description * [en]Hide the speed dial.[/en] * [ja]Speed dialを非表示にします。[/ja] */ }, { key: 'hide', value: function hide() { var _this4 = this; return this.hideItems().then(function () { return _this4._fab.hide(); }); } /** * @method showItems * @signature showItems() * @description * [en]Show the speed dial items.[/en] * [ja]Speed dialの子要素を表示します。[/ja] */ }, { key: 'showItems', value: function showItems() { if (this.hasAttribute('direction')) { this._updateDirection(this.getAttribute('direction')); } else { this._updateDirection('up'); } var totalDelay = 0; if (!this._itemShown) { var children = this.items; for (var i = 0; i < children.length; i++) { var delay = 25 * i; totalDelay += delay; styler(children[i], { transform: 'scale(1)', transitionDelay: delay + 'ms' }); } totalDelay += 50; this._itemShown = true; util$1.triggerElementEvent(this, 'open'); } var deferred = util$1.defer(); setTimeout(deferred.resolve, totalDelay); return deferred.promise; } /** * @method hideItems * @signature hideItems() * @description * [en]Hide the speed dial items.[/en] * [ja]Speed dialの子要素を非表示にします。[/ja] */ }, { key: 'hideItems', value: function hideItems() { var totalDelay = 0; if (this._itemShown) { var children = this.items; for (var i = 0; i < children.length; i++) { var delay = 25 * (children.length - i); totalDelay += delay; styler(children[i], { transform: 'scale(0)', transitionDelay: delay + 'ms' }); } totalDelay += 50; this._itemShown = false; util$1.triggerElementEvent(this, 'close'); } var deferred = util$1.defer(); setTimeout(deferred.resolve, totalDelay); return deferred.promise; } /** * @property disabled * @type {Boolean} * @description * [en]Whether the element is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ }, { key: 'isOpen', /** * @method isOpen * @signature isOpen() * @description * [en]Returns whether the menu is open or not.[/en] * [ja][/ja] */ value: function isOpen() { return this._itemShown; } /** * @method toggle * @signature toggle() * @description * [en]Toggle visibility.[/en] * [ja]Speed dialの表示非表示を切り替えます。[/ja] */ }, { key: 'toggle', value: function toggle() { return this.visible ? this.hide() : this.show(); } /** * @method toggleItems * @signature toggleItems() * @description * [en]Toggle item visibility.[/en] * [ja]Speed dialの子要素の表示非表示を切り替えます。[/ja] */ }, { key: 'toggleItems', value: function toggleItems() { return this.isOpen() ? this.hideItems() : this.showItems(); } }, { key: 'items', get: function get$$1() { return util$1.arrayFrom(this.querySelectorAll('ons-speed-dial-item')); } }, { key: '_fab', get: function get$$1() { return util$1.findChild(this, 'ons-fab'); } }, { key: 'disabled', set: function set$$1(value) { if (value) { this.hideItems(); } util$1.arrayFrom(this.children).forEach(function (e) { util$1.match(e, '.fab') && util$1.toggleAttribute(e, 'disabled', value); }); return util$1.toggleAttribute(this, 'disabled', value); }, get: function get$$1() { return this.hasAttribute('disabled'); } /** * @property inline * @readonly * @type {Boolean} * @description * [en]Whether the element is inline or not.[/en] * [ja]インライン要素の場合に`true`。[/ja] */ }, { key: 'inline', get: function get$$1() { return this.hasAttribute('inline'); } /** * @property visible * @readonly * @type {Boolean} * @description * [en]Whether the element is visible or not.[/en] * [ja]要素が見える場合に`true`。[/ja] */ }, { key: 'visible', get: function get$$1() { return this._fab.visible && this.style.display !== 'none'; } }], [{ key: 'observedAttributes', get: function get$$1() { return ['class', 'modifier', 'ripple', 'direction', 'position']; } }, { key: 'events', get: function get$$1() { return ['open', 'close']; } }]); return SpeedDialElement; }(BaseElement); onsElements.SpeedDial = SpeedDialElement; customElements.define('ons-speed-dial', SpeedDialElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var rewritables$1 = { /** * @param {Element} element * @param {Function} callback */ ready: function ready(element, callback) { setImmediate(callback); } }; /** * @element ons-splitter-content * @category menu * @description * [en] * The `<ons-splitter-content>` element is used as a child element of `<ons-splitter>`. * * It contains the main content of the page while `<ons-splitter-side>` contains the list. * [/en] * [ja]ons-splitter-content要素は、ons-splitter要素の子要素として利用します。[/ja] * @codepen rOQOML * @tutorial vanilla/Reference/splitter * @guide fundamentals.html#managing-pages * [en]Managing multiple pages.[/en] * [ja]複数のページを管理する[/ja] * @seealso ons-splitter * [en]The `<ons-splitter>` component is the parent element.[/en] * [ja]ons-splitterコンポーネント[/ja] * @seealso ons-splitter-side * [en]The `<ons-splitter-side>` component contains the menu.[/en] * [ja]ons-splitter-sideコンポーネント[/ja] * @example * <ons-splitter> * <ons-splitter-content> * ... * </ons-splitter-content> * * <ons-splitter-side side="left" width="80%" collapse> * ... * </ons-splitter-side> * </ons-splitter> */ var SplitterContentElement = function (_BaseElement) { inherits(SplitterContentElement, _BaseElement); /** * @attribute page * @type {String} * @description * [en] * The url of the content page. If this attribute is used the content will be loaded from a `<template>` tag or a remote file. * * It is also possible to put `<ons-page>` element as a child of the element. * [/en] * [ja]ons-splitter-content要素に表示するページのURLを指定します。[/ja] */ function SplitterContentElement() { classCallCheck(this, SplitterContentElement); var _this = possibleConstructorReturn(this, (SplitterContentElement.__proto__ || Object.getPrototypeOf(SplitterContentElement)).call(this)); _this._page = null; _this._pageLoader = defaultPageLoader; contentReady(_this, function () { rewritables$1.ready(_this, function () { var page = _this._getPageTarget(); if (page) { _this.load(page); } }); }); return _this; } createClass(SplitterContentElement, [{ key: 'connectedCallback', value: function connectedCallback() { if (!util$1.match(this.parentNode, 'ons-splitter')) { util$1.throw('"ons-splitter-content" must have "ons-splitter" as parent'); } } }, { key: '_getPageTarget', value: function _getPageTarget() { return this._page || this.getAttribute('page'); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() {} }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) {} /** * @property page * @type {HTMLElement} * @description * [en]The page to load in the splitter content.[/en] * [ja]この要素内に表示するページを指定します。[/ja] */ }, { key: 'load', /** * @method load * @signature load(page, [options]) * @param {String} page, [options] * [en]Page URL. Can be either an HTML document or an `<template>` id.[/en] * [ja]pageのURLか、`<template>`で宣言したテンプレートのid属性の値を指定します。[/ja] * @param {Object} [options] * @param {Function} [options.callback] * @description * [en]Show the page specified in `page` in the content.[/en] * [ja]指定したURLをメインページを読み込みます。[/ja] * @return {Promise} * [en]Resolves to the new `<ons-page>` element[/en] * [ja]`<ons-page>`要素を解決するPromiseオブジェクトを返します。[/ja] */ value: function load(page) { var _this2 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; this._page = page; var callback = options.callback || function () {}; return new Promise(function (resolve) { var oldContent = _this2._content || null; _this2._pageLoader.load({ page: page, parent: _this2 }, function (pageElement) { if (oldContent) { _this2._pageLoader.unload(oldContent); oldContent = null; } setImmediate(function () { return _this2._show(); }); callback(pageElement); resolve(pageElement); }); }); } }, { key: '_show', value: function _show() { if (this._content) { this._content._show(); } } }, { key: '_hide', value: function _hide() { if (this._content) { this._content._hide(); } } }, { key: '_destroy', value: function _destroy() { if (this._content) { this._pageLoader.unload(this._content); } this.remove(); } }, { key: 'page', get: function get$$1() { return this._page; } /** * @param {*} page */ , set: function set$$1(page) { this._page = page; } }, { key: '_content', get: function get$$1() { return this.children[0]; } /** * @property pageLoader * @type {Function} * @description * [en]Page element loaded in the splitter content.[/en] * [ja]この要素内に表示するページを指定します。[/ja] */ }, { key: 'pageLoader', get: function get$$1() { return this._pageLoader; }, set: function set$$1(loader) { if (!(loader instanceof PageLoader)) { util$1.throwPageLoader(); } this._pageLoader = loader; } }], [{ key: 'observedAttributes', get: function get$$1() { return []; } }, { key: 'rewritables', get: function get$$1() { return rewritables$1; } }]); return SplitterContentElement; }(BaseElement); onsElements.SplitterContent = SplitterContentElement; customElements.define('ons-splitter-content', SplitterContentElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var SplitterMaskElement = function (_BaseElement) { inherits(SplitterMaskElement, _BaseElement); function SplitterMaskElement() { classCallCheck(this, SplitterMaskElement); var _this = possibleConstructorReturn(this, (SplitterMaskElement.__proto__ || Object.getPrototypeOf(SplitterMaskElement)).call(this)); _this._boundOnClick = _this._onClick.bind(_this); contentReady(_this, function () { if (_this.parentNode._sides.every(function (side) { return side.mode === 'split'; })) { _this.setAttribute('style', 'display: none !important'); } }); return _this; } createClass(SplitterMaskElement, [{ key: '_onClick', value: function _onClick(event) { if (this.onClick instanceof Function) { this.onClick(); } else if (util$1.match(this.parentNode, 'ons-splitter')) { this.parentNode._sides.forEach(function (side) { return side.close('left').catch(function () {}); }); } event.stopPropagation(); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) {} }, { key: 'connectedCallback', value: function connectedCallback() { this.addEventListener('click', this._boundOnClick); util$1.iosMaskScrollFix(this, true); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this.removeEventListener('click', this._boundOnClick); util$1.iosMaskScrollFix(this, false); } }], [{ key: 'observedAttributes', get: function get$$1() { return []; } }]); return SplitterMaskElement; }(BaseElement); onsElements.SplitterMask = SplitterMaskElement; customElements.define('ons-splitter-mask', SplitterMaskElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var SplitterAnimator$1 = function (_BaseAnimator) { inherits(SplitterAnimator, _BaseAnimator); function SplitterAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'cubic-bezier(.1, .7, .1, 1)' : _ref$timing, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.3 : _ref$duration, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay; classCallCheck(this, SplitterAnimator); return possibleConstructorReturn(this, (SplitterAnimator.__proto__ || Object.getPrototypeOf(SplitterAnimator)).call(this, { timing: timing, duration: duration, delay: delay })); } createClass(SplitterAnimator, [{ key: 'updateOptions', value: function updateOptions() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; util$1.extend(this, { timing: this.timing, duration: this.duration, delay: this.delay }, options); } /** * @param {Element} sideElement */ }, { key: 'activate', value: function activate(sideElement) { var _this2 = this; var splitter = sideElement.parentNode; contentReady(splitter, function () { _this2._side = sideElement; _this2._oppositeSide = splitter.right !== sideElement && splitter.right || splitter.left !== sideElement && splitter.left; _this2._content = splitter.content; _this2._mask = splitter.mask; }); } }, { key: 'deactivate', value: function deactivate() { this.clearTransition(); this._mask && this.clearMask(); this._content = this._side = this._oppositeSide = this._mask = null; } }, { key: 'clearTransition', value: function clearTransition() { var _this3 = this; 'side mask content'.split(/\s+/).forEach(function (e) { return _this3['_' + e] && styler.clear(_this3['_' + e], 'transform transition'); }); } }, { key: 'clearMask', value: function clearMask() { // Check if the other side needs the mask before clearing if (!this._oppositeSide || this._oppositeSide.mode === 'split' || !this._oppositeSide.isOpen) { this._mask.style.opacity = ''; this._mask.style.display = 'none'; } } /** * @param {Number} distance */ }, { key: 'translate', value: function translate(distance) {} /** * @param {Function} done */ }, { key: 'open', value: function open(done) { done(); } /** * @param {Function} done */ }, { key: 'close', value: function close(done) { done(); } }, { key: 'minus', get: function get$$1() { return this._side.side === 'right' ? '-' : ''; } }]); return SplitterAnimator; }(BaseAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var OverlaySplitterAnimator = function (_SplitterAnimator) { inherits(OverlaySplitterAnimator, _SplitterAnimator); function OverlaySplitterAnimator() { classCallCheck(this, OverlaySplitterAnimator); return possibleConstructorReturn(this, (OverlaySplitterAnimator.__proto__ || Object.getPrototypeOf(OverlaySplitterAnimator)).apply(this, arguments)); } createClass(OverlaySplitterAnimator, [{ key: 'translate', value: function translate(distance) { this._mask.style.display = 'block'; // Avoid content clicks Animit(this._side).queue({ transform: 'translate3d(' + (this.minus + distance) + 'px, 0, 0)' }).play(); } /** * @param {Function} done */ }, { key: 'open', value: function open(done) { Animit.runAll(Animit(this._side).wait(this.delay).queue({ transform: 'translate3d(' + this.minus + '100%, 0, 0)' }, this.def).queue(function (callback) { callback(); done && done(); }), Animit(this._mask).wait(this.delay).queue({ display: 'block' }).queue({ opacity: '1' }, { duration: this.duration, timing: 'linear' })); } /** * @param {Function} done */ }, { key: 'close', value: function close(done) { Animit.runAll(Animit(this._side).wait(this.delay).queue({ transform: 'translate3d(0, 0, 0)' }, this.def).queue(function (callback) { done && done(); callback(); }), Animit(this._mask).wait(this.delay).queue({ opacity: '0' }, { duration: this.duration, timing: 'linear' }).queue({ display: 'none' })); } }]); return OverlaySplitterAnimator; }(SplitterAnimator$1); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var PushSplitterAnimator = function (_SplitterAnimator) { inherits(PushSplitterAnimator, _SplitterAnimator); function PushSplitterAnimator() { classCallCheck(this, PushSplitterAnimator); return possibleConstructorReturn(this, (PushSplitterAnimator.__proto__ || Object.getPrototypeOf(PushSplitterAnimator)).apply(this, arguments)); } createClass(PushSplitterAnimator, [{ key: '_getSlidingElements', value: function _getSlidingElements() { var slidingElements = [this._side, this._content]; if (this._oppositeSide && this._oppositeSide.mode === 'split') { slidingElements.push(this._oppositeSide); } return slidingElements; } }, { key: 'translate', value: function translate(distance) { if (!this._slidingElements) { this._slidingElements = this._getSlidingElements(); } this._mask.style.display = 'block'; // Avoid content clicks Animit(this._slidingElements).queue({ transform: 'translate3d(' + (this.minus + distance) + 'px, 0, 0)' }).play(); } /** * @param {Function} done */ }, { key: 'open', value: function open(done) { var _this2 = this; var max = this._side.offsetWidth; this._slidingElements = this._getSlidingElements(); Animit.runAll(Animit(this._slidingElements).wait(this.delay).queue({ transform: 'translate3d(' + (this.minus + max) + 'px, 0, 0)' }, this.def).queue(function (callback) { _this2._slidingElements = null; callback(); done && done(); }), Animit(this._mask).wait(this.delay).queue({ display: 'block' })); } /** * @param {Function} done */ }, { key: 'close', value: function close(done) { var _this3 = this; this._slidingElements = this._getSlidingElements(); Animit.runAll(Animit(this._slidingElements).wait(this.delay).queue({ transform: 'translate3d(0, 0, 0)' }, this.def).queue(function (callback) { _this3._slidingElements = null; get(PushSplitterAnimator.prototype.__proto__ || Object.getPrototypeOf(PushSplitterAnimator.prototype), 'clearTransition', _this3).call(_this3); done && done(); callback(); }), Animit(this._mask).wait(this.delay).queue({ display: 'none' })); } }]); return PushSplitterAnimator; }(SplitterAnimator$1); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var RevealSplitterAnimator = function (_SplitterAnimator) { inherits(RevealSplitterAnimator, _SplitterAnimator); function RevealSplitterAnimator() { classCallCheck(this, RevealSplitterAnimator); return possibleConstructorReturn(this, (RevealSplitterAnimator.__proto__ || Object.getPrototypeOf(RevealSplitterAnimator)).apply(this, arguments)); } createClass(RevealSplitterAnimator, [{ key: '_getSlidingElements', value: function _getSlidingElements() { var slidingElements = [this._content, this._mask]; if (this._oppositeSide && this._oppositeSide.mode === 'split') { slidingElements.push(this._oppositeSide); } return slidingElements; } }, { key: 'activate', value: function activate(sideElement) { get(RevealSplitterAnimator.prototype.__proto__ || Object.getPrototypeOf(RevealSplitterAnimator.prototype), 'activate', this).call(this, sideElement); if (sideElement.mode === 'collapse') { this._setStyles(sideElement); } } }, { key: 'deactivate', value: function deactivate() { this._side && this._unsetStyles(this._side); get(RevealSplitterAnimator.prototype.__proto__ || Object.getPrototypeOf(RevealSplitterAnimator.prototype), 'deactivate', this).call(this); } }, { key: '_setStyles', value: function _setStyles(sideElement) { styler(sideElement, { left: sideElement.side === 'right' ? 'auto' : 0, right: sideElement.side === 'right' ? 0 : 'auto', zIndex: 0, backgroundColor: 'black', transform: this._generateBehindPageStyle(0).container.transform, display: 'none' }); var splitter = sideElement.parentElement; contentReady(splitter, function () { return splitter.content && styler(splitter.content, { boxShadow: '0 0 12px 0 rgba(0, 0, 0, 0.2)' }); }); } }, { key: '_unsetStyles', value: function _unsetStyles(sideElement) { styler.clear(sideElement, 'left right zIndex backgroundColor display'); if (sideElement._content) { sideElement._content.style.opacity = ''; } // Check if the other side needs the common styles if (!this._oppositeSide || this._oppositeSide.mode === 'split') { sideElement.parentElement.content && styler.clear(sideElement.parentElement.content, 'boxShadow'); } } }, { key: '_generateBehindPageStyle', value: function _generateBehindPageStyle(distance) { var max = this.maxWidth; var behindDistance = (distance - max) / max * 10; behindDistance = isNaN(behindDistance) ? 0 : Math.max(Math.min(behindDistance, 0), -10); var behindTransform = 'translate3d(' + (this.minus ? -1 : 1) * behindDistance + '%, 0, 0)'; var opacity = 1 + behindDistance / 100; return { content: { opacity: opacity }, container: { transform: behindTransform } }; } }, { key: 'translate', value: function translate(distance) { this._side.style.display = ''; this._side.style.zIndex = 1; this.maxWidth = this.maxWidth || this._getMaxWidth(); var menuStyle = this._generateBehindPageStyle(Math.min(distance, this.maxWidth)); if (!this._slidingElements) { this._slidingElements = this._getSlidingElements(); } this._mask.style.display = 'block'; // Avoid content clicks Animit.runAll(Animit(this._slidingElements).queue({ transform: 'translate3d(' + (this.minus + distance) + 'px, 0, 0)' }), Animit(this._side._content).queue(menuStyle.content), Animit(this._side).queue(menuStyle.container)); } /** * @param {Function} done */ }, { key: 'open', value: function open(done) { var _this2 = this; this._side.style.display = ''; this._side.style.zIndex = 1; this.maxWidth = this.maxWidth || this._getMaxWidth(); var menuStyle = this._generateBehindPageStyle(this.maxWidth); this._slidingElements = this._getSlidingElements(); setTimeout(function () { // Fix: Time to update previous translate3d after changing style.display Animit.runAll(Animit(_this2._slidingElements).wait(_this2.delay).queue({ transform: 'translate3d(' + (_this2.minus + _this2.maxWidth) + 'px, 0, 0)' }, _this2.def), Animit(_this2._mask).wait(_this2.delay).queue({ display: 'block' }), Animit(_this2._side._content).wait(_this2.delay).queue(menuStyle.content, _this2.def), Animit(_this2._side).wait(_this2.delay).queue(menuStyle.container, _this2.def).queue(function (callback) { _this2._slidingElements = null; callback(); done && done(); })); }, 1000 / 60); } /** * @param {Function} done */ }, { key: 'close', value: function close(done) { var _this3 = this; var menuStyle = this._generateBehindPageStyle(0); this._slidingElements = this._getSlidingElements(); Animit.runAll(Animit(this._slidingElements).wait(this.delay).queue({ transform: 'translate3d(0, 0, 0)' }, this.def), Animit(this._mask).wait(this.delay).queue({ display: 'none' }), Animit(this._side._content).wait(this.delay).queue(menuStyle.content, this.def), Animit(this._side).wait(this.delay).queue(menuStyle.container, this.def).queue(function (callback) { _this3._slidingElements = null; _this3._side.style.zIndex = 0; _this3._side.style.display = 'none'; _this3._side._content.style.opacity = ''; done && done(); callback(); })); } }, { key: '_getMaxWidth', value: function _getMaxWidth() { return this._side.offsetWidth; } }]); return RevealSplitterAnimator; }(SplitterAnimator$1); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var _animatorDict$7 = { default: OverlaySplitterAnimator, overlay: OverlaySplitterAnimator, push: PushSplitterAnimator, reveal: RevealSplitterAnimator }; /** * @element ons-splitter * @category menu * @description * [en] * A component that enables responsive layout by implementing both a two-column layout and a sliding menu layout. * * It can be configured to automatically expand into a column layout on large screens and collapse the menu on smaller screens. When the menu is collapsed the user can open it by swiping. * [/en] * [ja][/ja] * @codepen rOQOML * @tutorial vanilla/Reference/splitter * @guide fundamentals.html#managing-pages * [en]Managing multiple pages.[/en] * [ja]複数のページを管理する[/ja] * @seealso ons-splitter-content * [en]The `<ons-splitter-content>` component contains the main content of the page.[/en] * [ja]ons-splitter-contentコンポーネント[/ja] * @seealso ons-splitter-side * [en]The `<ons-splitter-side>` component contains the menu.[/en] * [ja]ons-splitter-sideコンポーネント[/ja] * @example * <ons-splitter id="splitter"> * <ons-splitter-content> * ... * </ons-splitter-content> * * <ons-splitter-side side="left" width="80%" collapse swipeable> * ... * </ons-splitter-side> * </ons-splitter> * * <script> * var splitter = document.getElementById('splitter'); * splitter.left.open(); * </script> */ var SplitterElement = function (_BaseElement) { inherits(SplitterElement, _BaseElement); createClass(SplitterElement, [{ key: '_getSide', value: function _getSide(side) { var element = util$1.findChild(this, function (e) { return util$1.match(e, 'ons-splitter-side') && e.getAttribute('side') === side; }); return element; } /** * @property left * @readonly * @type {HTMLElement} * @description * [en]Left `<ons-splitter-side>` element.[/en] * [ja][/ja] */ }, { key: '_onDeviceBackButton', value: function _onDeviceBackButton(event) { this._sides.some(function (s) { return s.isOpen ? s.close() : false; }) || event.callParentHandler(); } }, { key: '_onModeChange', value: function _onModeChange(e) { var _this2 = this; if (e.target.parentNode) { contentReady(this, function () { _this2._layout(); }); } } }, { key: '_layout', value: function _layout() { var _this3 = this; this._sides.forEach(function (side) { if (_this3.content) { _this3.content.style[side.side] = side.mode === 'split' ? side.style.width : 0; } }); } }, { key: 'left', get: function get$$1() { return this._getSide('left'); } /** * @property right * @readonly * @type {HTMLElement} * @description * [en]Right `<ons-splitter-side>` element.[/en] * [ja][/ja] */ }, { key: 'right', get: function get$$1() { return this._getSide('right'); } /** * @property side * @readonly * @type {HTMLElement} * @description * [en]First `<ons-splitter-side>` element regardless the actual side.[/en] * [ja][/ja] */ }, { key: 'side', get: function get$$1() { return util$1.findChild(this, 'ons-splitter-side'); } }, { key: '_sides', get: function get$$1() { return [this.left, this.right].filter(function (e) { return e; }); } /** * @property content * @readonly * @type {HTMLElement} * @description * [en]The `<ons-splitter-content>` element.[/en] * [ja][/ja] */ }, { key: 'content', get: function get$$1() { return util$1.findChild(this, 'ons-splitter-content'); } }, { key: 'topPage', get: function get$$1() { return this.content._content; } }, { key: 'mask', get: function get$$1() { return util$1.findChild(this, 'ons-splitter-mask'); } /** * @property onDeviceBackButton * @type {Object} * @description * [en]Back-button handler.[/en] * [ja]バックボタンハンドラ。[/ja] */ }, { key: 'onDeviceBackButton', get: function get$$1() { return this._backButtonHandler; }, set: function set$$1(callback) { if (this._backButtonHandler) { this._backButtonHandler.destroy(); } this._backButtonHandler = deviceBackButtonDispatcher.createHandler(this, callback); } }]); function SplitterElement() { classCallCheck(this, SplitterElement); var _this = possibleConstructorReturn(this, (SplitterElement.__proto__ || Object.getPrototypeOf(SplitterElement)).call(this)); _this._onModeChange = _this._onModeChange.bind(_this); contentReady(_this, function () { !_this.mask && _this.appendChild(document.createElement('ons-splitter-mask')); _this._layout(); }); return _this; } createClass(SplitterElement, [{ key: 'connectedCallback', value: function connectedCallback() { this.onDeviceBackButton = this._onDeviceBackButton.bind(this); this.addEventListener('modechange', this._onModeChange, false); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this._backButtonHandler.destroy(); this._backButtonHandler = null; this.removeEventListener('modechange', this._onModeChange, false); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) {} }, { key: '_show', value: function _show() { util$1.propagateAction(this, '_show'); } }, { key: '_hide', value: function _hide() { util$1.propagateAction(this, '_hide'); } }, { key: '_destroy', value: function _destroy() { util$1.propagateAction(this, '_destroy'); this.remove(); } }], [{ key: 'registerAnimator', value: function registerAnimator(name, Animator) { if (!(Animator instanceof SplitterAnimator)) { util$1.throwAnimator('Splitter'); } _animatorDict$7[name] = Animator; } }, { key: 'SplitterAnimator', get: function get$$1() { return SplitterAnimator; } }, { key: 'animators', get: function get$$1() { return _animatorDict$7; } }]); return SplitterElement; }(BaseElement); onsElements.Splitter = SplitterElement; customElements.define('ons-splitter', SplitterElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var SPLIT_MODE = 'split'; var COLLAPSE_MODE = 'collapse'; var CLOSED_STATE = 'closed'; var OPEN_STATE = 'open'; var CHANGING_STATE = 'changing'; var rewritables$2 = { /** * @param {Element} splitterSideElement * @param {Function} callback */ ready: function ready(splitterSideElement, callback) { setImmediate(callback); } }; var CollapseDetection = function () { function CollapseDetection(element, target) { classCallCheck(this, CollapseDetection); this._element = element; this._onChange = this._onChange.bind(this); target && this.changeTarget(target); } createClass(CollapseDetection, [{ key: 'changeTarget', value: function changeTarget(target) { this.disable(); this._target = target; if (target) { this._orientation = ['portrait', 'landscape'].indexOf(target) !== -1; this.activate(); } } }, { key: '_match', value: function _match(value) { if (this._orientation) { return this._target === (value.isPortrait ? 'portrait' : 'landscape'); } return value.matches; } }, { key: '_onChange', value: function _onChange(value) { this._element._updateMode(this._match(value) ? COLLAPSE_MODE : SPLIT_MODE); } }, { key: 'activate', value: function activate() { if (this._orientation) { orientation.on('change', this._onChange); this._onChange({ isPortrait: orientation.isPortrait() }); } else { this._queryResult = window.matchMedia(this._target); this._queryResult.addListener(this._onChange); this._onChange(this._queryResult); } } }, { key: 'disable', value: function disable() { if (this._orientation) { orientation.off('change', this._onChange); } else if (this._queryResult) { this._queryResult.removeListener(this._onChange); this._queryResult = null; } } }]); return CollapseDetection; }(); /** * @element ons-splitter-side * @category menu * @description * [en] * The `<ons-splitter-side>` element is used as a child element of `<ons-splitter>`. * * It will be displayed on either the left or right side of the `<ons-splitter-content>` element. * * It supports two modes: collapsed and split. When it's in collapsed mode it will be hidden from view and can be displayed when the user swipes the screen or taps a button. In split mode the element is always shown. It can be configured to automatically switch between the two modes depending on the screen size. * [/en] * [ja]ons-splitter-side要素は、ons-splitter要素の子要素として利用します。[/ja] * @codepen rOQOML * @tutorial vanilla/Reference/splitter * @guide fundamentals.html#managing-pages * [en]Managing multiple pages.[/en] * [ja]複数のページを管理する[/ja] * @seealso ons-splitter * [en]The `<ons-splitter>` is the parent component.[/en] * [ja]ons-splitterコンポーネント[/ja] * @seealso ons-splitter-content * [en]The `<ons-splitter-content>` component contains the main content of the page.[/en] * [ja]ons-splitter-contentコンポーネント[/ja] * @example * <ons-splitter> * <ons-splitter-content> * ... * </ons-splitter-content> * * <ons-splitter-side side="left" width="80%" collapse> * ... * </ons-splitter-side> * </ons-splitter> */ var SplitterSideElement = function (_BaseElement) { inherits(SplitterSideElement, _BaseElement); /** * @event modechange * @description * [en]Fired just after the component's mode changes.[/en] * [ja]この要素のモードが変化した際に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクトです。[/ja] * @param {Object} event.side * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {String} event.mode * [en]Returns the current mode. Can be either `"collapse"` or `"split"`.[/en] * [ja]現在のモードを返します。[/ja] */ /** * @event preopen * @description * [en]Fired just before the sliding menu is opened.[/en] * [ja]スライディングメニューが開く前に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクトです。[/ja] * @param {Function} event.cancel * [en]Call to cancel opening sliding menu.[/en] * [ja]スライディングメニューが開くのをキャンセルします。[/ja] * @param {Object} event.side * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @event postopen * @description * [en]Fired just after the sliding menu is opened.[/en] * [ja]スライディングメニューが開いた後に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクトです。[/ja] * @param {Object} event.side * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @event preclose * @description * [en]Fired just before the sliding menu is closed.[/en] * [ja]スライディングメニューが閉じる前に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクトです。[/ja] * @param {Object} event.side * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] * @param {Function} event.cancel * [en]Call to cancel opening sliding-menu.[/en] * [ja]スライディングメニューが閉じるのをキャンセルします。[/ja] */ /** * @event postclose * @description * [en]Fired just after the sliding menu is closed.[/en] * [ja]スライディングメニューが閉じた後に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクトです。[/ja] * @param {Object} event.side * [en]Component object.[/en] * [ja]コンポーネントのオブジェクト。[/ja] */ /** * @attribute animation * @type {String} * @default default * @description * [en]Specify the animation. Use one of `overlay`, `push`, `reveal` or `default`.[/en] * [ja]アニメーションを指定します。"overlay", "push", "reveal", "default"のいずれかを指定できます。[/ja] */ /** * @attribute animation-options * @type {Expression} * @description * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. {duration: 0.2, delay: 1, timing: 'ease-in'}[/ja] */ /** * @attribute open-threshold * @type {Number} * @default 0.3 * @description * [en]Specify how much the menu needs to be swiped before opening. A value between `0` and `1`.[/en] * [ja]どのくらいスワイプすればスライディングメニューを開くかどうかの割合を指定します。0から1の間の数値を指定します。スワイプの距離がここで指定した数値掛けるこの要素の幅よりも大きければ、スワイプが終わった時にこの要素を開きます。デフォルトは0.3です。[/ja] */ /** * @attribute collapse * @type {String} * @description * [en] * Specify the collapse behavior. Valid values are `"portrait"`, `"landscape"` or a media query. * The strings `"portrait"` and `"landscape"` means the view will collapse when device is in landscape or portrait orientation. * If the value is a media query, the view will collapse when the media query resolves to `true`. * If the value is not defined, the view always be in `"collapse"` mode. * [/en] * [ja] * 左側のページを非表示にする条件を指定します。portrait, landscape、width #pxもしくはメディアクエリの指定が可能です。 * portraitもしくはlandscapeを指定すると、デバイスの画面が縦向きもしくは横向きになった時に適用されます。 * メディアクエリを指定すると、指定したクエリに適合している場合に適用されます。 * 値に何も指定しない場合には、常にcollapseモードになります。 * [/ja] */ /** * @attribute swipe-target-width * @type {String} * @description * [en]The width of swipeable area calculated from the edge (in pixels). Use this to enable swipe only when the finger touch on the screen edge.[/en] * [ja]スワイプの判定領域をピクセル単位で指定します。画面の端から指定した距離に達するとページが表示されます。[/ja] */ /** * @attribute width * @type {String} * @description * [en]Can be specified in either pixels or as a percentage, e.g. `90%` or `200px`.[/en] * [ja]この要素の横幅を指定します。pxと%での指定が可能です。eg. 90%, 200px[/ja] */ /** * @attribute side * @type {String} * @default left * @description * [en]Specify which side of the screen the `<ons-splitter-side>` element is located. Possible values are `"left"` and `"right"`.[/en] * [ja]この要素が左か右かを指定します。指定できる値は"left"か"right"のみです。[/ja] */ /** * @attribute mode * @type {String} * @description * [en]Current mode. Possible values are `"collapse"` or `"split"`. This attribute is read only.[/en] * [ja]現在のモードが設定されます。"collapse"もしくは"split"が指定されます。この属性は読み込み専用です。[/ja] */ /** * @attribute page * @initonly * @type {String} * @description * [en]The URL of the menu page.[/en] * [ja]ons-splitter-side要素に表示するページのURLを指定します。[/ja] */ /** * @attribute swipeable * @type {Boolean} * @description * [en]Whether to enable swipe interaction on collapse mode.[/en] * [ja]collapseモード時にスワイプ操作を有効にする場合に指定します。[/ja] */ function SplitterSideElement() { classCallCheck(this, SplitterSideElement); var _this = possibleConstructorReturn(this, (SplitterSideElement.__proto__ || Object.getPrototypeOf(SplitterSideElement)).call(this)); _this._page = null; _this._state = CLOSED_STATE; _this._lock = new DoorLock(); _this._pageLoader = defaultPageLoader; _this._collapseDetection = new CollapseDetection(_this); _this._animatorFactory = new AnimatorFactory({ animators: SplitterElement.animators, baseClass: SplitterAnimator$1, baseClassName: 'SplitterAnimator', defaultAnimation: _this.getAttribute('animation') }); contentReady(_this, function () { // These attributes are used early by the parent element _this.attributeChangedCallback('width'); if (!_this.hasAttribute('side')) { _this.setAttribute('side', 'left'); } rewritables$2.ready(_this, function () { var page = _this._page || _this.getAttribute('page'); page && _this.load(page); }); }); return _this; } createClass(SplitterSideElement, [{ key: 'connectedCallback', value: function connectedCallback() { var _this2 = this; if (!util$1.match(this.parentNode, 'ons-splitter')) { util$1.throw('Parent must be an ons-splitter element'); } this._swipe = new SwipeReveal({ element: this, elementHandler: this.parentElement, swipeMax: function swipeMax() { _this2._onSwipe && _this2._onSwipe(1, _this2._animationOpt); _this2.open(); }, swipeMid: function swipeMid(distance, width) { _this2._onSwipe && _this2._onSwipe(distance / width); _this2._animator.translate(distance); }, swipeMin: function swipeMin() { _this2._onSwipe && _this2._onSwipe(0, _this2._animationOpt); _this2.close(); }, getThreshold: function getThreshold() { return Math.max(0, Math.min(1, parseFloat(_this2.getAttribute('open-threshold')) || 0.3)); }, getSide: function getSide() { return _this2.side; }, isInitialState: function isInitialState() { var closed = _this2._state === CLOSED_STATE; _this2._state = CHANGING_STATE; return closed; }, ignoreSwipe: function ignoreSwipe(event, distance) { var isOpen = _this2.isOpen; var validDrag = function validDrag(d) { return _this2.side === 'left' ? d === 'left' && isOpen || d === 'right' && !isOpen : d === 'left' && !isOpen || d === 'right' && isOpen; }; var area = Math.max(0, parseInt(_this2.getAttribute('swipe-target-width'), 10) || 0); return _this2._mode === SPLIT_MODE || _this2._lock.isLocked() || _this2._isOtherSideOpen() || !validDrag(event.gesture.direction) || !isOpen && area !== 0 && distance > area; } }); this.attributeChangedCallback('swipeable'); contentReady(this, function () { _this2.constructor.observedAttributes.forEach(function (attr) { return _this2.attributeChangedCallback(attr, null, _this2.getAttribute(attr)); }); }); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this._swipe && this._swipe.dispose(); this._animator = this._animationOpt = this._swipe = null; } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { switch (name) { case 'swipeable': this._swipe && this._swipe.update(); break; case 'width': current = this.getAttribute('width'); // Sometimes undefined. CE bug? this.style.width = /^\d+(px|%)$/.test(current) ? current : '80%'; break; default: this[util$1.camelize('_update-' + name)](current); } } }, { key: '_emitEvent', value: function _emitEvent(name) { if (name.slice(0, 3) !== 'pre') { return util$1.triggerElementEvent(this, name, { side: this }); } var isCanceled = false; util$1.triggerElementEvent(this, name, { side: this, cancel: function cancel() { return isCanceled = true; } }); return isCanceled; } }, { key: '_isOtherSideOpen', value: function _isOtherSideOpen() { var _this3 = this; return !!util$1.findChild(this.parentElement, function (el) { return el instanceof _this3.constructor && el !== _this3 && el._mode === COLLAPSE_MODE && el.isOpen; }); } }, { key: '_updateCollapse', value: function _updateCollapse() { var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('collapse'); if (value === null || value === 'split') { this._collapseDetection.disable(); return this._updateMode(SPLIT_MODE); } if (value === '' || value === 'collapse') { this._collapseDetection.disable(); return this._updateMode(COLLAPSE_MODE); } this._collapseDetection.changeTarget(value); } }, { key: '_updateMode', value: function _updateMode(mode) { if (mode !== this._mode) { this._mode = mode; this.setAttribute('mode', mode); // readonly attribute for the users if (mode === SPLIT_MODE) { this._animator && this._animator.deactivate(); this._state = CLOSED_STATE; } else { this._animator && this._animator.activate(this); this._state === OPEN_STATE && this._animator.open(); } util$1.triggerElementEvent(this, 'modechange', { side: this, mode: mode }); } } }, { key: '_updateAnimation', value: function _updateAnimation() { var animation = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('animation'); if (this.parentNode) { this._animator && this._animator.deactivate(); this._animator = this._animatorFactory.newAnimator({ animation: animation }); this._animator.activate(this); this._animationOpt = { timing: this._animator.duration, duration: this._animator.duration }; } } }, { key: '_updateAnimationOptions', value: function _updateAnimationOptions() { var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('animation-options'); this._animator.updateOptions(AnimatorFactory.parseAnimationOptionsString(value)); } /** * @property page * @type {*} * @description * [en]Page location to load in the splitter side.[/en] * [ja]この要素内に表示するページを指定します。[/ja] */ }, { key: 'open', /** * @method open * @signature open([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {Function} [options.callback] * [en]This function will be called after the menu has been opened.[/en] * [ja]メニューが開いた後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Open menu in collapse mode.[/en] * [ja]collapseモードになっているons-splitter-side要素を開きます。[/ja] * @return {Promise} * [en]Resolves to the splitter side element or false if not in collapse mode[/en] * [ja][/ja] */ value: function open(options) { return this.toggle(options, true); } /** * @method close * @signature close([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {Function} [options.callback] * [en]This function will be called after the menu has been closed.[/en] * [ja]メニューが閉じた後に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en]Close menu in collapse mode.[/en] * [ja]collapseモードになっているons-splitter-side要素を閉じます。[/ja] * @return {Promise} * [en]Resolves to the splitter side element or false if not in collapse mode[/en] * [ja][/ja] */ }, { key: 'close', value: function close(options) { return this.toggle(options, false); } /** * @method toggle * @signature toggle([options]) * @param {Object} [options] * @description * [en]Opens if it's closed. Closes if it's open.[/en] * [ja]開けている場合は要素を閉じますそして開けている場合は要素を開きます。[/ja] * @return {Promise} * [en]Resolves to the splitter side element or false if not in collapse mode[/en] * [ja][/ja] */ }, { key: 'toggle', value: function toggle() { var _this4 = this; var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var force = arguments[1]; var shouldOpen = typeof force === 'boolean' ? force : !this.isOpen; var action = shouldOpen ? 'open' : 'close'; var FINAL_STATE = shouldOpen ? OPEN_STATE : CLOSED_STATE; if (this._mode === SPLIT_MODE) { return Promise.resolve(false); } if (this._state === FINAL_STATE) { return Promise.resolve(this); } if (this._lock.isLocked()) { return Promise.reject('Another splitter-side action is already running.'); } if (shouldOpen && this._isOtherSideOpen()) { return Promise.reject('Another menu is already open.'); } if (this._emitEvent('pre' + action)) { return Promise.reject('Canceled in pre' + action + ' event.'); } var unlock = this._lock.lock(); this._state = CHANGING_STATE; if (options.animation) { this._updateAnimation(options.animation); } return new Promise(function (resolve) { _this4._animator[action](function () { util$1.iosPageScrollFix(shouldOpen); _this4._state = FINAL_STATE; unlock(); _this4._emitEvent('post' + action); options.callback instanceof Function && options.callback(_this4); resolve(_this4); }); }); } /** * @method load * @signature load(page, [options]) * @param {String} page * [en]Page URL. Can be either an HTML document or a `<template>`.[/en] * [ja]pageのURLか、`<template>`で宣言したテンプレートのid属性の値を指定します。[/ja] * @param {Object} [options] * @param {Function} [options.callback] * @description * [en]Show the page specified in pageUrl in the right section[/en] * [ja]指定したURLをメインページを読み込みます。[/ja] * @return {Promise} * [en]Resolves to the new page element[/en] * [ja][/ja] */ }, { key: 'load', value: function load(page) { var _this5 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; this._page = page; var callback = options.callback || function () {}; return new Promise(function (resolve) { var oldContent = _this5._content || null; _this5._pageLoader.load({ page: page, parent: _this5 }, function (pageElement) { if (oldContent) { _this5._pageLoader.unload(oldContent); oldContent = null; } setImmediate(function () { return _this5._show(); }); callback(pageElement); resolve(pageElement); }); }); } }, { key: '_show', value: function _show() { if (this._content) { this._content._show(); } } }, { key: '_hide', value: function _hide() { if (this._content) { this._content._hide(); } } }, { key: '_destroy', value: function _destroy() { if (this._content) { this._pageLoader.unload(this._content); } this.remove(); } }, { key: 'side', get: function get$$1() { return this.getAttribute('side') === 'right' ? 'right' : 'left'; } }, { key: 'page', get: function get$$1() { return this._page; } /** * @param {*} page */ , set: function set$$1(page) { this._page = page; } }, { key: '_content', get: function get$$1() { return this.children[0]; } /** * @property pageLoader * @description * [en][/en] * [ja][/ja] */ }, { key: 'pageLoader', get: function get$$1() { return this._pageLoader; }, set: function set$$1(loader) { if (!(loader instanceof PageLoader)) { util$1.throwPageLoader(); } this._pageLoader = loader; } /** * @property mode * @readonly * @type {String} * @description * [en]Current mode. Possible values are "split", "collapse", "closed", "open" or "changing".[/en] * [ja][/ja] */ }, { key: 'mode', get: function get$$1() { return this._mode; } /** * @property onSwipe * @type {Function} * @description * [en]Hook called whenever the user slides the splitter. It gets a decimal ratio (0-1) and an animationOptions object as arguments.[/en] * [ja][/ja] */ }, { key: 'onSwipe', get: function get$$1() { return this._onSwipe; }, set: function set$$1(value) { if (value && !(value instanceof Function)) { util$1.throw('"onSwipe" must be a function'); } this._onSwipe = value; } /** * @property isOpen * @type {Boolean} * @readonly * @description * [en]This value is `true` when the menu is open.[/en] * [ja][/ja] */ }, { key: 'isOpen', get: function get$$1() { return this._mode === COLLAPSE_MODE && this._state !== CLOSED_STATE; } }], [{ key: 'observedAttributes', get: function get$$1() { return ['animation', 'width', 'collapse', 'swipeable', 'animation-options']; } }, { key: 'events', get: function get$$1() { return ['preopen', 'postopen', 'preclose', 'postclose', 'modechange']; } }, { key: 'rewritables', get: function get$$1() { return rewritables$2; } }]); return SplitterSideElement; }(BaseElement); onsElements.SplitterSide = SplitterSideElement; customElements.define('ons-splitter-side', SplitterSideElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$28 = { '': 'switch--*', '.switch__input': 'switch--*__input', '.switch__handle': 'switch--*__handle', '.switch__toggle': 'switch--*__toggle' }; var locations = { ios: [1, 21], material: [0, 16] }; /** * @element ons-switch * @category form * @description * [en] * Switch component. The switch can be toggled both by dragging and tapping. * * Will automatically displays a Material Design switch on Android devices. * [/en] * [ja]スイッチを表示するコンポーネントです。[/ja] * @modifier material * [en]Material Design switch[/en] * [ja][/ja] * @codepen LpXZQQ * @tutorial vanilla/Reference/switch * @guide theming.html#modifiers [en]More details about the `modifier` attribute[/en][ja]modifier属性の使い方[/ja] * @example * <ons-switch checked></ons-switch> * <ons-switch disabled></ons-switch> * <ons-switch modifier="material"></ons-switch> */ var SwitchElement = function (_BaseCheckboxElement) { inherits(SwitchElement, _BaseCheckboxElement); function SwitchElement() { classCallCheck(this, SwitchElement); var _this = possibleConstructorReturn(this, (SwitchElement.__proto__ || Object.getPrototypeOf(SwitchElement)).call(this)); contentReady(_this, function () { _this.attributeChangedCallback('modifier', null, _this.getAttribute('modifier')); }); _this._onChange = _this._onChange.bind(_this); _this._onRelease = _this._onRelease.bind(_this); _this._lastTimeStamp = 0; return _this; } createClass(SwitchElement, [{ key: '_getPosition', /* Own props */ value: function _getPosition(e) { var l = this._locations; return Math.min(l[1], Math.max(l[0], this._startX + e.gesture.deltaX)); } }, { key: '_emitChangeEvent', value: function _emitChangeEvent() { util$1.triggerElementEvent(this, 'change', { value: this.checked, switch: this, isInteractive: true }); } }, { key: '_onChange', value: function _onChange(event) { if (event && event.stopPropagation) { event.stopPropagation(); } this._emitChangeEvent(); } }, { key: '_onClick', value: function _onClick(ev) { if (ev.target.classList.contains(this.defaultElementClass + '__touch') || ev.timeStamp - this._lastTimeStamp < 50 // Prevent second click triggered by <label> ) { ev.preventDefault(); } this._lastTimeStamp = ev.timeStamp; } }, { key: '_onHold', value: function _onHold(e) { if (!this.disabled) { ModifierUtil.addModifier(this, 'active'); document.addEventListener('release', this._onRelease); } } }, { key: '_onDragStart', value: function _onDragStart(e) { if (this.disabled || ['left', 'right'].indexOf(e.gesture.direction) === -1) { ModifierUtil.removeModifier(this, 'active'); return; } e.consumed = true; ModifierUtil.addModifier(this, 'active'); this._startX = this._locations[this.checked ? 1 : 0]; // - e.gesture.deltaX; this.addEventListener('drag', this._onDrag); document.addEventListener('release', this._onRelease); } }, { key: '_onDrag', value: function _onDrag(e) { e.stopPropagation(); this._handle.style.left = this._getPosition(e) + 'px'; } }, { key: '_onRelease', value: function _onRelease(e) { var l = this._locations; var position = this._getPosition(e); var previousValue = this.checked; this.checked = position >= (l[0] + l[1]) / 2; if (this.checked !== previousValue) { this._emitChangeEvent(); } this.removeEventListener('drag', this._onDrag); document.removeEventListener('release', this._onRelease); this._handle.style.left = ''; ModifierUtil.removeModifier(this, 'active'); } }, { key: 'click', value: function click() { var ev = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (!this.disabled) { this.checked = !this.checked; this._emitChangeEvent(); this._lastTimeStamp = ev.timeStamp || 0; } } }, { key: 'connectedCallback', value: function connectedCallback() { var _this2 = this; contentReady(this, function () { _this2._input.addEventListener('change', _this2._onChange); }); this.addEventListener('dragstart', this._onDragStart); this.addEventListener('hold', this._onHold); this.addEventListener('tap', this.click); this.addEventListener('click', this._onClick); this._gestureDetector = new GestureDetector(this, { dragMinDistance: 1, holdTimeout: 251, passive: true }); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { var _this3 = this; contentReady(this, function () { _this3._input.removeEventListener('change', _this3._onChange); }); this.removeEventListener('dragstart', this._onDragStart); this.removeEventListener('hold', this._onHold); this.removeEventListener('tap', this.click); this.removeEventListener('click', this._onClick); if (this._gestureDetector) { this._gestureDetector.dispose(); } } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'modifier') { var md = (current || '').indexOf('material') !== -1; this._locations = locations[md ? 'material' : 'ios']; } get(SwitchElement.prototype.__proto__ || Object.getPrototypeOf(SwitchElement.prototype), 'attributeChangedCallback', this).call(this, name, last, current); } /** * @event change * @description * [en]Fired when the switch is toggled.[/en] * [ja]ON/OFFが変わった時に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクト。[/ja] * @param {Object} event.switch * [en]Switch object.[/en] * [ja]イベントが発火したSwitchオブジェクトを返します。[/ja] * @param {Boolean} event.value * [en]Current value.[/en] * [ja]現在の値を返します。[/ja] * @param {Boolean} event.isInteractive * [en]True if the change was triggered by the user clicking on the switch.[/en] * [ja]タップやクリックなどのユーザの操作によって変わった場合にはtrueを返します。[/ja] */ /** * @attribute modifier * @type {String} * @description * [en]The appearance of the switch.[/en] * [ja]スイッチの表現を指定します。[/ja] */ /** * @attribute disabled * @description * [en]Whether the switch is be disabled.[/en] * [ja]スイッチを無効の状態にする場合に指定します。[/ja] */ /** * @attribute checked * @description * [en]Whether the switch is checked.[/en] * [ja]スイッチがONの状態にするときに指定します。[/ja] */ /** * @attribute input-id * @type {String} * @description * [en]Specify the `id` attribute of the inner `<input>` element. This is useful when using `<label for="...">` elements.[/en] * [ja][/ja] */ /** * @property checked * @type {Boolean} * @description * [en]This value is `true` if the switch is checked.[/en] * [ja]スイッチがONの場合に`true`。[/ja] */ /** * @property value * @type {String} * @description * [en]The current value of the input.[/en] * [ja][/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the element is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ /** * @property checkbox * @readonly * @type {HTMLElement} * @description * [en]The underlying checkbox element.[/en] * [ja]コンポーネント内部のcheckbox要素になります。[/ja] */ }, { key: '_scheme', get: function get$$1() { return scheme$28; } }, { key: '_defaultClassName', get: function get$$1() { return 'switch'; } }, { key: '_template', get: function get$$1() { return '\n <input type="' + this.type + '" class="' + this._defaultClassName + '__input">\n <div class="' + this._defaultClassName + '__toggle">\n <div class="' + this._defaultClassName + '__handle">\n <div class="' + this._defaultClassName + '__touch"></div>\n </div>\n </div>\n '; } }, { key: 'type', get: function get$$1() { return 'checkbox'; } }, { key: '_handle', get: function get$$1() { return this.querySelector('.' + this._defaultClassName + '__handle'); } }, { key: 'checkbox', get: function get$$1() { return this._input; } }], [{ key: 'observedAttributes', get: function get$$1() { return [].concat(toConsumableArray(get(SwitchElement.__proto__ || Object.getPrototypeOf(SwitchElement), 'observedAttributes', this)), ['modifier']); } }]); return SwitchElement; }(BaseCheckboxElement); onsElements.Switch = SwitchElement; customElements.define('ons-switch', SwitchElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$30 = { '.tabbar__content': 'tabbar--*__content', '.tabbar__border': 'tabbar--*__border', '.tabbar': 'tabbar--*' }; var rewritables$3 = { /** * @param {Element} tabbarElement * @param {Function} callback */ ready: function ready(tabbarElement, callback) { callback(); } }; var lerp = function lerp(x0, x1, t) { return (1 - t) * x0 + t * x1; }; /** * @element ons-tabbar * @category tabbar * @description * [en]A component to display a tab bar on the bottom of a page. Used with `<ons-tab>` to manage pages using tabs.[/en] * [ja]タブバーをページ下部に表示するためのコンポーネントです。ons-tabと組み合わせて使うことで、ページを管理できます。[/ja] * @codepen pGuDL * @tutorial vanilla/Reference/tabbar * @modifier material * [en]A tabbar in Material Design.[/en] * [ja][/ja] * @modifier autogrow * [en]Tabs automatically grow depending on their content instead of having a fixed width.[/en] * [ja][/ja] * @modifier top-border * [en]Shows a static border-bottom in tabs for iOS top tabbars.[/en] * [ja][/ja] * @guide fundamentals.html#managing-pages * [en]Managing multiple pages.[/en] * [ja]複数のページを管理する[/ja] * @seealso ons-tab * [en]The `<ons-tab>` component.[/en] * [ja]ons-tabコンポーネント[/ja] * @seealso ons-page * [en]The `<ons-page>` component.[/en] * [ja]ons-pageコンポーネント[/ja] * @example * <ons-tabbar> * <ons-tab * page="home.html" * label="Home" * active> * </ons-tab> * <ons-tab * page="settings.html" * label="Settings" * active> * </ons-tab> * </ons-tabbar> * * <template id="home.html"> * ... * </template> * * <template id="settings.html"> * ... * </template> */ var TabbarElement = function (_BaseElement) { inherits(TabbarElement, _BaseElement); /** * @event prechange * @description * [en]Fires just before the tab is changed.[/en] * [ja]アクティブなタブが変わる前に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクト。[/ja] * @param {Number} event.index * [en]Current index.[/en] * [ja]現在アクティブになっているons-tabのインデックスを返します。[/ja] * @param {Object} event.tabItem * [en]Tab item object.[/en] * [ja]tabItemオブジェクト。[/ja] * @param {Function} event.cancel * [en]Call this function to cancel the change event.[/en] * [ja]この関数を呼び出すと、アクティブなタブの変更がキャンセルされます。[/ja] */ /** * @event postchange * @description * [en]Fires just after the tab is changed.[/en] * [ja]アクティブなタブが変わった後に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクト。[/ja] * @param {Number} event.index * [en]Current index.[/en] * [ja]現在アクティブになっているons-tabのインデックスを返します。[/ja] * @param {Object} event.tabItem * [en]Tab item object.[/en] * [ja]tabItemオブジェクト。[/ja] */ /** * @event reactive * @description * [en]Fires if the already open tab is tapped again.[/en] * [ja]すでにアクティブになっているタブがもう一度タップやクリックされた場合に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクト。[/ja] * @param {Number} event.index * [en]Current index.[/en] * [ja]現在アクティブになっているons-tabのインデックスを返します。[/ja] * @param {Object} event.tabItem * [en]Tab item object.[/en] * [ja]tabItemオブジェクト。[/ja] */ /** * @attribute animation * @type {String} * @default none * @description * [en]If this attribute is set to `"none"` the transitions will not be animated.[/en] * [ja][/ja] */ /** * @attribute animation-options * @type {Expression} * @description * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. {duration: 0.2, delay: 1, timing: 'ease-in'}[/ja] */ /** * @attribute position * @initonly * @type {String} * @default bottom * @description * [en]Tabbar's position. Available values are `"bottom"` and `"top"`. Use `"auto"` to choose position depending on platform (bottom for iOS flat design, top for Material Design).[/en] * [ja]タブバーの位置を指定します。"bottom"もしくは"top"を選択できます。デフォルトは"bottom"です。[/ja] */ /** * @attribute swipeable * @description * [en]If this attribute is set the tab bar can be scrolled by drag or swipe.[/en] * [ja]この属性がある時、タブバーをスワイプやドラッグで移動できるようになります。[/ja] */ /** * @attribute ignore-edge-width * @type {Number} * @default 20 * @description * [en]Distance in pixels from both edges. Swiping on these areas will prioritize parent components such as `ons-splitter` or `ons-navigator`.[/en] * [ja][/ja] */ /** * @attribute hide-tabs * @description * [en]Whether to hide the tabs.[/en] * [ja]タブを非表示にする場合に指定します。[/ja] */ /** * @attribute tab-border * @description * [en]If this attribute is set the tabs show a dynamic bottom border. Only works for iOS flat design since the border is always visible in Material Design.[/en] * [ja][/ja] */ /** * @attribute modifier * @type {String} * @description * [en]The appearance of the tabbar.[/en] * [ja]タブバーの表現を指定します。[/ja] */ function TabbarElement() { classCallCheck(this, TabbarElement); var _this = possibleConstructorReturn(this, (TabbarElement.__proto__ || Object.getPrototypeOf(TabbarElement)).call(this)); _this._loadInactive = util$1.defer(); // Improves #2324 contentReady(_this, function () { return _this._compile(); }); return _this; } createClass(TabbarElement, [{ key: 'connectedCallback', value: function connectedCallback() { var _this2 = this; if (!this._swiper) { this._swiper = new Swiper({ getElement: function getElement() { return _this2._contentElement; }, getInitialIndex: function getInitialIndex() { return _this2.getAttribute('activeIndex') || _this2.getAttribute('active-index'); }, getAutoScrollRatio: this._getAutoScrollRatio.bind(this), getBubbleWidth: function getBubbleWidth() { return parseInt(_this2.getAttribute('ignore-edge-width') || 25, 10); }, isAutoScrollable: function isAutoScrollable() { return true; }, preChangeHook: this._onPreChange.bind(this), postChangeHook: this._onPostChange.bind(this), refreshHook: this._onRefresh.bind(this), scrollHook: this._onScroll.bind(this) }); contentReady(this, function () { _this2._tabbarBorder = util$1.findChild(_this2._tabbarElement, '.tabbar__border'); _this2._swiper.init({ swipeable: _this2.hasAttribute('swipeable') }); }); } contentReady(this, function () { _this2._updatePosition(); if (!util$1.findParent(_this2, 'ons-page', function (p) { return p === document.body; })) { _this2._show(); // This tabbar is the top component } }); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { if (this._swiper && this._swiper.initialized) { this._swiper.dispose(); this._swiper = null; this._tabbarBorder = null; this._tabsRect = null; } } }, { key: '_normalizeEvent', value: function _normalizeEvent(event) { return _extends({}, event, { index: event.activeIndex, tabItem: this.tabs[event.activeIndex] }); } }, { key: '_onPostChange', value: function _onPostChange(event) { event = this._normalizeEvent(event); util$1.triggerElementEvent(this, 'postchange', event); var page = event.tabItem.pageElement; page && page._show(); } }, { key: '_onPreChange', value: function _onPreChange(event) { event = this._normalizeEvent(event); event.cancel = function () { return event.canceled = true; }; util$1.triggerElementEvent(this, 'prechange', event); if (!event.canceled) { var _event = event, activeIndex = _event.activeIndex, lastActiveIndex = _event.lastActiveIndex; var tabs = this.tabs; tabs[activeIndex].setActive(true); if (lastActiveIndex >= 0) { var prevTab = tabs[lastActiveIndex]; prevTab.setActive(false); prevTab.pageElement && prevTab.pageElement._hide(); } } return event.canceled; } }, { key: '_onScroll', value: function _onScroll(index) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (this._tabbarBorder) { this._tabbarBorder.style.transition = 'all ' + (options.duration || 0) + 's ' + (options.timing || ''); if (this._autogrow && this._tabsRect.length > 0) { var a = Math.floor(index), b = Math.ceil(index), r = index % 1; this._tabbarBorder.style.width = lerp(this._tabsRect[a].width, this._tabsRect[b].width, r) + 'px'; this._tabbarBorder.style.transform = 'translate3d(' + lerp(this._tabsRect[a].left, this._tabsRect[b].left, r) + 'px, 0, 0)'; } else { this._tabbarBorder.style.transform = 'translate3d(' + index * 100 + '%, 0, 0)'; } } this._onSwipe && this._onSwipe(index, options); } }, { key: '_onRefresh', value: function _onRefresh() { this._autogrow = util$1.hasModifier(this, 'autogrow'); this._tabsRect = this.tabs.map(function (tab) { return tab.getBoundingClientRect(); }); if (this._tabbarBorder) { this._tabbarBorder.style.display = this.hasAttribute('tab-border') || util$1.hasModifier(this, 'material') ? 'block' : 'none'; var index = this.getActiveTabIndex(); if (this._tabsRect.length > 0 && index >= 0) { this._tabbarBorder.style.width = this._tabsRect[index].width + 'px'; } } } }, { key: '_getAutoScrollRatio', value: function _getAutoScrollRatio(matches, velocity, size) { var ratio = .6; // Base ratio var modifier = size / 300 * (matches ? -1 : 1); // Based on screen size return Math.min(1, Math.max(0, ratio + velocity * modifier)); } }, { key: '_compile', value: function _compile() { autoStyle.prepare(this); var content = this._contentElement || util$1.create('.tabbar__content'); content.classList.add('ons-tabbar__content'); var tabbar = this._tabbarElement || util$1.create('.tabbar'); tabbar.classList.add('ons-tabbar__footer'); if (!tabbar.parentNode) { while (this.firstChild) { tabbar.appendChild(this.firstChild); } } var activeIndex = Number(this.getAttribute('activeIndex')); // 0 by default if (tabbar.children.length > activeIndex && !util$1.findChild(tabbar, '[active]')) { tabbar.children[activeIndex].setAttribute('active', ''); } this._tabbarBorder = util$1.findChild(tabbar, '.tabbar__border') || util$1.create('.tabbar__border'); tabbar.appendChild(this._tabbarBorder); tabbar.classList.add('ons-swiper-tabbar'); // Hides material border !content.children[0] && content.appendChild(document.createElement('div')); !content.children[1] && content.appendChild(document.createElement('div')); content.appendChild = content.appendChild.bind(content.children[0]); content.insertBefore = content.insertBefore.bind(content.children[0]); this.appendChild(content); this.appendChild(tabbar); // Triggers ons-tab connectedCallback ModifierUtil.initModifier(this, scheme$30); } }, { key: '_updatePosition', value: function _updatePosition() { var _this3 = this; var position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.getAttribute('position'); var top = this._top = position === 'top' || position === 'auto' && util$1.hasModifier(this, 'material'); var action = top ? util$1.addModifier : util$1.removeModifier; action(this, 'top'); var page = util$1.findParent(this, 'ons-page'); if (page) { contentReady(page, function () { var p = 0; if (page.children[0] && util$1.match(page.children[0], 'ons-toolbar')) { action(page.children[0], 'noshadow'); p = 1; // Visual fix for some devices } var content = page._getContentElement(); var cs = window.getComputedStyle(page._getContentElement(), null); _this3.style.top = top ? parseInt(cs.getPropertyValue('padding-top'), 10) - p + 'px' : ''; // Refresh content top - Fix for iOS 8 content.style.top = cs.top; content.style.top = ''; }); } internal$1.autoStatusBarFill(function () { var filled = util$1.findParent(_this3, function (e) { return e.hasAttribute('status-bar-fill'); }); util$1.toggleAttribute(_this3, 'status-bar-fill', top && !filled); }); } }, { key: 'setActiveTab', /** * @method setActiveTab * @signature setActiveTab(index, [options]) * @param {Number} index * [en]Tab index.[/en] * [ja]タブのインデックスを指定します。[/ja] * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {Function} [options.callback] * [en]Function that runs when the new page has loaded.[/en] * [ja][/ja] * @param {String} [options.animation] * [en]If this option is "none", the transition won't slide.[/en] * [ja][/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja] * @description * [en]Show specified tab page. Animations and their options can be specified by the second parameter.[/en] * [ja]指定したインデックスのタブを表示します。アニメーションなどのオプションを指定できます。[/ja] * @return {Promise} * [en]A promise that resolves to the new page element.[/en] * [ja][/ja] */ value: function setActiveTab(nextIndex) { var _this4 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var prevIndex = this.getActiveTabIndex(); var prevTab = this.tabs[prevIndex], nextTab = this.tabs[nextIndex]; if (!nextTab) { return Promise.reject('Specified index does not match any tab.'); } if (nextIndex === prevIndex) { util$1.triggerElementEvent(this, 'reactive', { index: nextIndex, activeIndex: nextIndex, tabItem: nextTab }); return Promise.resolve(nextTab.pageElement); } // FIXME: nextTab.loaded is broken in Zone.js promises (Angular2) var nextPage = nextTab.pageElement; return (nextPage ? Promise.resolve(nextPage) : nextTab.loaded).then(function (nextPage) { return _this4._swiper.setActiveIndex(nextIndex, _extends({ reject: true }, options, { animation: prevTab && nextPage ? options.animation || _this4.getAttribute('animation') : 'none', animationOptions: util$1.extend({ duration: .3, timing: 'cubic-bezier(.4, .7, .5, 1)' }, _this4.hasAttribute('animation-options') ? util$1.animationOptionsParse(_this4.getAttribute('animation-options')) : {}, options.animationOptions || {}) })).then(function () { options.callback instanceof Function && options.callback(nextPage); return nextPage; }); }); } /** * @method setTabbarVisibility * @signature setTabbarVisibility(visible) * @param {Boolean} visible * @description * [en]Used to hide or show the tab bar.[/en] * [ja][/ja] */ }, { key: 'setTabbarVisibility', value: function setTabbarVisibility(visible) { var _this5 = this; contentReady(this, function () { _this5._contentElement.style[_this5._top ? 'top' : 'bottom'] = visible ? '' : '0px'; _this5._tabbarElement.style.display = visible ? '' : 'none'; visible && _this5._onRefresh(); }); } }, { key: 'show', value: function show() { this.setTabbarVisibility(true); } }, { key: 'hide', value: function hide() { this.setTabbarVisibility(false); } /** * @property visible * @readonly * @type {Boolean} * @description * [en]Whether the tabbar is visible or not.[/en] * [ja]タブバーが見える場合に`true`。[/ja] */ }, { key: 'getActiveTabIndex', /** * @method getActiveTabIndex * @signature getActiveTabIndex() * @return {Number} * [en]The index of the currently active tab.[/en] * [ja]現在アクティブになっているタブのインデックスを返します。[/ja] * @description * [en]Returns tab index on current active tab. If active tab is not found, returns -1.[/en] * [ja]現在アクティブになっているタブのインデックスを返します。現在アクティブなタブがない場合には-1を返します。[/ja] */ value: function getActiveTabIndex() { var tabs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.tabs; for (var i = 0; i < tabs.length; i++) { if (tabs[i] && tabs[i].tagName === 'ONS-TAB' && tabs[i].isActive()) { return i; } } return -1; } }, { key: '_show', value: function _show() { var _this6 = this; this._swiper.show(); setImmediate(function () { var tabs = _this6.tabs; var activeIndex = _this6.getActiveTabIndex(tabs); _this6._loadInactive.resolve(); if (tabs.length > 0 && activeIndex >= 0) { tabs[activeIndex].loaded.then(function (el) { return el && setImmediate(function () { return el._show(); }); }); } }); } }, { key: '_hide', value: function _hide() { this._swiper.hide(); var topPage = this.topPage; topPage && topPage._hide(); } }, { key: '_destroy', value: function _destroy() { this.tabs.forEach(function (tab) { return tab.remove(); }); this.remove(); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { if (name === 'modifier') { ModifierUtil.onModifierChanged(last, current, this, scheme$30); var isTop = function isTop(m) { return (/(^|\s+)top($|\s+)/i.test(m) ); }; isTop(last) !== isTop(current) && this._updatePosition(); } else if (name === 'position') { util$1.isAttached(this) && this._updatePosition(); } else if (name === 'swipeable') { this._swiper && this._swiper.updateSwipeable(this.hasAttribute('swipeable')); } else if (name === 'hide-tabs') { this.setTabbarVisibility(!this.hasAttribute('hide-tabs') || current === 'false'); } } }, { key: '_tabbarElement', get: function get$$1() { return util$1.findChild(this, '.tabbar'); } }, { key: '_contentElement', get: function get$$1() { return util$1.findChild(this, '.tabbar__content'); } }, { key: '_targetElement', get: function get$$1() { var content = this._contentElement; return content && content.children[0] || null; } }, { key: 'topPage', get: function get$$1() { var tabs = this.tabs, index = this.getActiveTabIndex(); return tabs[index] ? tabs[index].pageElement || this.pages[0] || null : null; } }, { key: 'pages', get: function get$$1() { return util$1.arrayFrom(this._targetElement.children); } }, { key: 'tabs', get: function get$$1() { return Array.prototype.filter.call(this._tabbarElement.children, function (e) { return e.tagName === 'ONS-TAB'; }); } }, { key: 'visible', get: function get$$1() { return this._tabbarElement.style.display !== 'none'; } /** * @property swipeable * @type {Boolean} * @description * [en]Enable swipe interaction.[/en] * [ja]swipeableであればtrueを返します。[/ja] */ }, { key: 'swipeable', get: function get$$1() { return this.hasAttribute('swipeable'); }, set: function set$$1(value) { return util$1.toggleAttribute(this, 'swipeable', value); } /** * @property onSwipe * @type {Function} * @description * [en]Hook called whenever the user slides the tabbar. It gets a decimal index and an animationOptions object as arguments.[/en] * [ja][/ja] */ }, { key: 'onSwipe', get: function get$$1() { return this._onSwipe; }, set: function set$$1(value) { if (value && !(value instanceof Function)) { util$1.throw('"onSwipe" must be a function'); } this._onSwipe = value; } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'position', 'swipeable', 'tab-border', 'hide-tabs']; } }, { key: 'rewritables', get: function get$$1() { return rewritables$3; } }, { key: 'events', get: function get$$1() { return ['prechange', 'postchange', 'reactive']; } }]); return TabbarElement; }(BaseElement); onsElements.Tabbar = TabbarElement; customElements.define('ons-tabbar', TabbarElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var defaultClassName$16 = 'tabbar__item'; var scheme$29 = { '': 'tabbar--*__item', '.tabbar__button': 'tabbar--*__button' }; /** * @element ons-tab * @category tabbar * @description * [en]Represents a tab inside tab bar. Each `<ons-tab>` represents a page.[/en] * [ja] * タブバーに配置される各アイテムのコンポーネントです。それぞれのons-tabはページを表します。 * ons-tab要素の中には、タブに表示されるコンテンツを直接記述することが出来ます。 * [/ja] * @codepen pGuDL * @tutorial vanilla/Reference/tabbar * @guide fundamentals.html#managing-pages * [en]Managing multiple pages.[/en] * [ja]複数のページを管理する[/ja]] * @guide appsize.html#removing-icon-packs [en]Removing icon packs.[/en][ja][/ja] * @guide faq.html#how-can-i-use-custom-icon-packs [en]Adding custom icon packs.[/en][ja][/ja] * @seealso ons-tabbar * [en]ons-tabbar component[/en] * [ja]ons-tabbarコンポーネント[/ja] * @seealso ons-page * [en]ons-page component[/en] * [ja]ons-pageコンポーネント[/ja] * @seealso ons-icon * [en]ons-icon component[/en] * [ja]ons-iconコンポーネント[/ja] * @example * <ons-tabbar> * <ons-tab * page="home.html" * label="Home" * active> * </ons-tab> * <ons-tab * page="settings.html" * label="Settings" * active> * </ons-tab> * </ons-tabbar> * * <template id="home.html"> * ... * </template> * * <template id="settings.html"> * ... * </template> */ var TabElement = function (_BaseElement) { inherits(TabElement, _BaseElement); /** * @attribute page * @initonly * @type {String} * @description * [en]The page that is displayed when the tab is tapped.[/en] * [ja]ons-tabが参照するページへのURLを指定します。[/ja] */ /** * @attribute icon * @type {String} * @description * [en] * The icon name for the tab. Can specify the same icon name as `<ons-icon>`. Check [See also](#seealso) section for more information. * [/en] * [ja] * アイコン名を指定します。ons-iconと同じアイコン名を指定できます。 * 個別にアイコンをカスタマイズする場合は、background-imageなどのCSSスタイルを用いて指定できます。 * [/ja] */ /** * @attribute active-icon * @type {String} * @description * [en]The name of the icon when the tab is active.[/en] * [ja]アクティブの際のアイコン名を指定します。[/ja] */ /** * @attribute label * @type {String} * @description * [en]The label of the tab item.[/en] * [ja]アイコン下に表示されるラベルを指定します。[/ja] */ /** * @attribute badge * @type {String} * @description * [en]Display a notification badge on top of the tab.[/en] * [ja]バッジに表示する内容を指定します。[/ja] */ /** * @attribute active * @description * [en]This attribute should be set to the tab that is active by default.[/en] * [ja][/ja] */ function TabElement() { classCallCheck(this, TabElement); var _this = possibleConstructorReturn(this, (TabElement.__proto__ || Object.getPrototypeOf(TabElement)).call(this)); if (['label', 'icon', 'badge'].some(_this.hasAttribute.bind(_this))) { _this._compile(); } else { contentReady(_this, function () { return _this._compile(); }); } _this._pageLoader = defaultPageLoader; _this._onClick = _this._onClick.bind(_this); return _this; } createClass(TabElement, [{ key: '_compile', value: function _compile() { autoStyle.prepare(this); this.classList.add(defaultClassName$16); if (this._button) { return; } var button = util$1.create('button.tabbar__button'); while (this.childNodes[0]) { button.appendChild(this.childNodes[0]); } var input = util$1.create('input', { display: 'none' }); input.type = 'radio'; this.appendChild(input); this.appendChild(button); this._updateButtonContent(); ModifierUtil.initModifier(this, scheme$29); this._updateRipple(); } }, { key: '_updateRipple', value: function _updateRipple() { this._button && util$1.updateRipple(this._button, this.hasAttribute('ripple')); } }, { key: '_updateButtonContent', value: function _updateButtonContent() { var _this2 = this; var button = this._button; var iconWrapper = this._icon; if (this.hasAttribute('icon')) { iconWrapper = iconWrapper || util$1.createElement('<div class="tabbar__icon"><ons-icon></ons-icon></div>'); var icon = iconWrapper.children[0]; var fix = function (last) { return function () { return icon.attributeChangedCallback('icon', last, _this2.getAttribute('icon')); }; }(icon.getAttribute('icon')); icon.setAttribute('icon', this.getAttribute(this.isActive() ? 'active-icon' : 'icon')); iconWrapper.parentElement !== button && button.insertBefore(iconWrapper, button.firstChild); // dirty fix for https://github.com/OnsenUI/OnsenUI/issues/1654 icon.attributeChangedCallback instanceof Function ? fix() : setImmediate(function () { return icon.attributeChangedCallback instanceof Function && fix(); }); } else { iconWrapper && iconWrapper.remove(); } ['label', 'badge'].forEach(function (attr, index) { var prop = _this2.querySelector('.tabbar__' + attr); if (_this2.hasAttribute(attr)) { prop = prop || util$1.create('.tabbar__' + attr + (attr === 'badge' ? ' notification' : '')); prop.textContent = _this2.getAttribute(attr); prop.parentElement !== button && button.appendChild(prop); } else { prop && prop.remove(); } }); } }, { key: '_onClick', value: function _onClick() { if (this.onClick instanceof Function) { this.onClick(); } else { this._tabbar.setActiveTab(this.index, { reject: false }); } } }, { key: 'setActive', value: function setActive() { var active = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; this._input.checked = active; this.classList.toggle('active', active); util$1.toggleAttribute(this, 'active', active); if (this.hasAttribute('icon') && this.hasAttribute('active-icon')) { this._icon.children[0].setAttribute('icon', this.getAttribute(active ? 'active-icon' : 'icon')); } } }, { key: '_loadPageElement', value: function _loadPageElement(parent, page) { var _this3 = this; this._hasLoaded = true; return new Promise(function (resolve) { _this3._pageLoader.load({ parent: parent, page: page }, function (pageElement) { parent.replaceChild(pageElement, parent.children[_this3.index]); // Ensure position _this3._loadedPage = pageElement; resolve(pageElement); }); }); } }, { key: 'isActive', /** * @return {Boolean} */ value: function isActive() { return this.classList.contains('active'); } }, { key: 'disconnectedCallback', value: function disconnectedCallback() { this.removeEventListener('click', this._onClick, false); if (this._loadedPage) { this._hasLoaded = false; this.loaded = null; } } }, { key: 'connectedCallback', value: function connectedCallback() { var _this4 = this; this.addEventListener('click', this._onClick, false); if (!util$1.isAttached(this) || this.loaded) { return; // ons-tabbar compilation may trigger this } var deferred = util$1.defer(); this.loaded = deferred.promise; contentReady(this, function () { var index = _this4.index; var tabbar = _this4._tabbar; if (!tabbar) { util$1.throw('Tab elements must be children of Tabbar'); } if (tabbar.hasAttribute('modifier')) { util$1.addModifier(_this4, tabbar.getAttribute('modifier')); } if (!_this4._hasLoaded) { if (_this4.hasAttribute('active')) { _this4.setActive(true); tabbar.setAttribute('activeIndex', index); } if (index === tabbar.tabs.length - 1) { tabbar._onRefresh(); setImmediate(function () { return tabbar._onRefresh(); }); } TabbarElement.rewritables.ready(tabbar, function () { var pageTarget = _this4.page || _this4.getAttribute('page'); if (!_this4.pageElement && pageTarget) { var parentTarget = tabbar._targetElement; var dummyPage = util$1.create('div', { height: '100%', width: '100%', visibility: 'hidden' }); parentTarget.insertBefore(dummyPage, parentTarget.children[index]); // Ensure position var load = function load() { return _this4._loadPageElement(parentTarget, pageTarget).then(deferred.resolve); }; return _this4.isActive() ? load() : tabbar._loadInactive.promise.then(load); } return deferred.resolve(_this4.pageElement); }); } }); } }, { key: 'attributeChangedCallback', value: function attributeChangedCallback(name, last, current) { var _this5 = this; switch (name) { case 'class': util$1.restoreClass(this, defaultClassName$16, scheme$29); break; case 'modifier': contentReady(this, function () { return ModifierUtil.onModifierChanged(last, current, _this5, scheme$29); }); break; case 'ripple': contentReady(this, function () { return _this5._updateRipple(); }); break; case 'icon': case 'label': case 'badge': contentReady(this, function () { return _this5._updateButtonContent(); }); break; case 'page': this.page = current || ''; break; } } }, { key: 'pageLoader', set: function set$$1(loader) { if (!(loader instanceof PageLoader)) { util$1.throwPageLoader(); } this._pageLoader = loader; }, get: function get$$1() { return this._pageLoader; } }, { key: '_input', get: function get$$1() { return util$1.findChild(this, 'input'); } }, { key: '_button', get: function get$$1() { return util$1.findChild(this, '.tabbar__button'); } }, { key: '_icon', get: function get$$1() { return this.querySelector('.tabbar__icon'); } }, { key: '_tabbar', get: function get$$1() { return util$1.findParent(this, 'ons-tabbar'); } }, { key: 'index', get: function get$$1() { return Array.prototype.indexOf.call(this.parentElement.children, this); } }, { key: 'pageElement', get: function get$$1() { // It has been loaded by ons-tab if (this._loadedPage) { return this._loadedPage; } // Manually attached to DOM, 1 per tab var tabbar = this._tabbar; if (tabbar.pages.length === tabbar.tabs.length) { return tabbar.pages[this.index]; } // Loaded in another way return null; } }], [{ key: 'observedAttributes', get: function get$$1() { return ['modifier', 'ripple', 'icon', 'label', 'page', 'badge', 'class']; } }]); return TabElement; }(BaseElement); onsElements.Tab = TabElement; customElements.define('ons-tab', TabElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var ToastAnimator = function (_BaseAnimator) { inherits(ToastAnimator, _BaseAnimator); /** * @param {Object} options * @param {String} options.timing * @param {Number} options.duration * @param {Number} options.delay */ function ToastAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'linear' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.2 : _ref$duration; classCallCheck(this, ToastAnimator); return possibleConstructorReturn(this, (ToastAnimator.__proto__ || Object.getPrototypeOf(ToastAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } /** * @param {HTMLElement} modal * @param {Function} callback */ createClass(ToastAnimator, [{ key: 'show', value: function show(modal, callback) { callback(); } /** * @param {HTMLElement} modal * @param {Function} callback */ }, { key: 'hide', value: function hide(modal, callback) { callback(); } }]); return ToastAnimator; }(BaseAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * iOS style animator for dialog. */ var FadeToastAnimator = function (_ToastAnimator) { inherits(FadeToastAnimator, _ToastAnimator); function FadeToastAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'linear' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.3 : _ref$duration; classCallCheck(this, FadeToastAnimator); return possibleConstructorReturn(this, (FadeToastAnimator.__proto__ || Object.getPrototypeOf(FadeToastAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); } /** * @param {HTMLElement} toast * @param {Function} callback */ createClass(FadeToastAnimator, [{ key: 'show', value: function show(toast, callback) { callback = callback ? callback : function () {}; Animit(toast, this.def).default({ opacity: 0 }, { opacity: 1 }).queue(function (done) { callback(); done(); }).play(); } /** * @param {HTMLElement} toast * @param {Function} callback */ }, { key: 'hide', value: function hide(toast, callback) { callback = callback ? callback : function () {}; Animit(toast, this.def).default({ opacity: 1 }, { opacity: 0 }).queue(function (done) { callback(); done(); }).play(); } }]); return FadeToastAnimator; }(ToastAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Ascend Toast Animator. */ var AscendToastAnimator = function (_ToastAnimator) { inherits(AscendToastAnimator, _ToastAnimator); function AscendToastAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'ease' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.25 : _ref$duration; classCallCheck(this, AscendToastAnimator); var _this = possibleConstructorReturn(this, (AscendToastAnimator.__proto__ || Object.getPrototypeOf(AscendToastAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); _this.messageDelay = _this.duration * 0.4 + _this.delay; // Delay message opacity change if (platform.isAndroid()) { _this.ascension = 48; // Toasts are always 1 line } else { if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) { _this.ascension = 98; // 64 + 34 } else if (iPhoneXPatch.isIPhoneXLandscapePatchActive()) { _this.ascension = 85; // 64 + 21 } else { _this.ascension = 64; } } return _this; } /** * @param {HTMLElement} toast * @param {Function} callback */ createClass(AscendToastAnimator, [{ key: 'show', value: function show(toast, callback) { toast = toast._toast; util$1.globals.fabOffset = this.ascension; Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, ' + this.ascension + 'px, 0)' }, { transform: 'translate3d(0, 0, 0)' }).queue(function (done) { callback && callback(); done(); }), Animit(this._getFabs()).wait(this.delay).queue({ transform: 'translate3d(0, -' + this.ascension + 'px, 0) scale(1)' }, this.def), Animit(util$1.arrayFrom(toast.children), this.def).default({ opacity: 0 }, { opacity: 1 })); } /** * @param {HTMLElement} toast * @param {Function} callback */ }, { key: 'hide', value: function hide(toast, callback) { toast = toast._toast; util$1.globals.fabOffset = 0; Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, 0, 0)' }, { transform: 'translate3d(0, ' + this.ascension + 'px, 0)' }).queue(function (done) { callback && callback(); done(); }), Animit(this._getFabs(), this.def).wait(this.delay).queue({ transform: 'translate3d(0, 0, 0) scale(1)' }, this.def), Animit(util$1.arrayFrom(toast.children), this.def).default({ opacity: 1 }, { opacity: 0 })); } }, { key: '_getFabs', value: function _getFabs() { return util$1.arrayFrom(document.querySelectorAll('ons-fab[position~=bottom], ons-speed-dial[position~=bottom]')).filter(function (fab) { return fab.visible; }); } }]); return AscendToastAnimator; }(ToastAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Lift-fade Toast Animator */ var LiftToastAnimator = function (_ToastAnimator) { inherits(LiftToastAnimator, _ToastAnimator); function LiftToastAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'ease' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.35 : _ref$duration; classCallCheck(this, LiftToastAnimator); var _this = possibleConstructorReturn(this, (LiftToastAnimator.__proto__ || Object.getPrototypeOf(LiftToastAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); _this.bodyHeight = document.body.clientHeight; // avoid Forced Synchronous Layout if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) { _this.liftAmount = 'calc(100% + 34px)'; } else if (iPhoneXPatch.isIPhoneXLandscapePatchActive()) { _this.liftAmount = 'calc(100% + 21px)'; } else { _this.liftAmount = '100%'; } return _this; } /** * @param {HTMLElement} toast * @param {Function} callback */ createClass(LiftToastAnimator, [{ key: 'show', value: function show(toast, callback) { toast = toast._toast; Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, ' + this.liftAmount + ', 0)', opacity: 0 }, { transform: 'translate3d(0, 0, 0)', opacity: 1 }).queue(function (done) { callback && callback(); done(); })); } /** * @param {HTMLElement} toast * @param {Function} callback */ }, { key: 'hide', value: function hide(toast, callback) { toast = toast._toast; Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, 0, 0)', opacity: 1 }, { transform: 'translate3d(0, ' + this.liftAmount + ', 0)', opacity: 0 }).queue(function (done) { callback && callback(); done(); })); } }, { key: '_updatePosition', value: function _updatePosition(toast) { if (parseInt(toast.style.top, 10) === 0) { toast.style.top = toast.style.bottom = ''; } } }]); return LiftToastAnimator; }(ToastAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Fall-fade Toast Animator */ var FallToastAnimator = function (_ToastAnimator) { inherits(FallToastAnimator, _ToastAnimator); function FallToastAnimator() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, _ref$timing = _ref.timing, timing = _ref$timing === undefined ? 'ease' : _ref$timing, _ref$delay = _ref.delay, delay = _ref$delay === undefined ? 0 : _ref$delay, _ref$duration = _ref.duration, duration = _ref$duration === undefined ? 0.35 : _ref$duration; classCallCheck(this, FallToastAnimator); var _this = possibleConstructorReturn(this, (FallToastAnimator.__proto__ || Object.getPrototypeOf(FallToastAnimator)).call(this, { timing: timing, delay: delay, duration: duration })); if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) { _this.fallAmount = 'calc(-100% - 44px)'; } else { _this.fallAmount = '-100%'; } return _this; } /** * @param {HTMLElement} toast * @param {Function} callback */ createClass(FallToastAnimator, [{ key: 'show', value: function show(toast, callback) { toast = toast._toast; this._updatePosition(toast); Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, ' + this.fallAmount + ', 0)', opacity: 0 }, { transform: 'translate3d(0, 0, 0)', opacity: 1 }).queue(function (done) { callback && callback(); done(); })); } /** * @param {HTMLElement} toast * @param {Function} callback */ }, { key: 'hide', value: function hide(toast, callback) { var _this2 = this; toast = toast._toast; this._updatePosition(toast); Animit.runAll(Animit(toast, this.def).default({ transform: 'translate3d(0, 0, 0)', opacity: 1 }, { transform: 'translate3d(0, ' + this.fallAmount + ', 0)', opacity: 0 }).queue(function (done) { _this2._updatePosition(toast, true); callback && callback(); done(); })); } }, { key: '_updatePosition', value: function _updatePosition(toast, cleanUp) { var correctTop = void 0; if (iPhoneXPatch.isIPhoneXPortraitPatchActive()) { correctTop = '44px'; } else { correctTop = '0'; } if (toast.style.top !== correctTop) { toast.style.top = correctTop; toast.style.bottom = 'initial'; } } }]); return FallToastAnimator; }(ToastAnimator); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var scheme$31 = { '.toast': 'toast--*', '.toast__message': 'toast--*__message', '.toast__button': 'toast--*__button' }; var defaultClassName$17 = 'toast'; var _animatorDict$8 = { 'default': platform.isAndroid() ? AscendToastAnimator : LiftToastAnimator, 'fade': FadeToastAnimator, 'ascend': AscendToastAnimator, 'lift': LiftToastAnimator, 'fall': FallToastAnimator, 'none': ToastAnimator }; /** * @element ons-toast * @category dialog * @description * [en] * The Toast or Snackbar component is useful for displaying dismissable information or simple actions at (normally) the bottom of the page. * * This component does not block user input, allowing the app to continue its flow. For simple toasts, consider `ons.notification.toast` instead. * [/en] * [ja][/ja] * @tutorial vanilla/Reference/toast * @seealso ons-alert-dialog * [en]The `<ons-alert-dialog>` component is preferred for displaying undismissable information.[/en] * [ja][/ja] */ var ToastElement = function (_BaseDialogElement) { inherits(ToastElement, _BaseDialogElement); /** * @attribute animation * @type {String} * @default default * @description * [en]The animation used when showing and hiding the toast. Can be either `"default"`, `"ascend"` (Android), `"lift"` (iOS), `"fall"`, `"fade"` or `"none"`.[/en] * [ja][/ja] */ /** * @attribute animation-options * @type {Expression} * @description * [en]Specify the animation's duration, timing and delay with an object literal. E.g. `{duration: 0.2, delay: 1, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, timing, delayをオブジェクトリテラルで指定します。e.g. <code>{duration: 0.2, delay: 1, timing: 'ease-in'}</code>[/ja] */ function ToastElement() { classCallCheck(this, ToastElement); var _this = possibleConstructorReturn(this, (ToastElement.__proto__ || Object.getPrototypeOf(ToastElement)).call(this)); _this._defaultDBB = null; contentReady(_this, function () { return _this._compile(); }); return _this; } createClass(ToastElement, [{ key: '_updateAnimatorFactory', value: function _updateAnimatorFactory() { // Reset position style this._toast && (this._toast.style.top = this._toast.style.bottom = ''); return new AnimatorFactory({ animators: _animatorDict$8, baseClass: ToastAnimator, baseClassName: 'ToastAnimator', defaultAnimation: this.getAttribute('animation') }); } /** * @property onDeviceBackButton * @type {Object} * @description * [en]Back-button handler.[/en] * [ja]バックボタンハンドラ。[/ja] */ }, { key: '_compile', value: function _compile() { autoStyle.prepare(this); this.style.display = 'none'; this.style.zIndex = 10000; // Lower than dialogs var messageClassName = 'toast__message'; var buttonClassName = 'toast__button'; var toast = util$1.findChild(this, '.' + defaultClassName$17); if (!toast) { toast = document.createElement('div'); toast.classList.add(defaultClassName$17); while (this.childNodes[0]) { toast.appendChild(this.childNodes[0]); } } var button = util$1.findChild(toast, '.' + buttonClassName); if (!button) { button = util$1.findChild(toast, function (e) { return util$1.match(e, '.button') || util$1.match(e, 'button'); }); if (button) { button.classList.remove('button'); button.classList.add(buttonClassName); toast.appendChild(button); } } if (!util$1.findChild(toast, '.' + messageClassName)) { var message = util$1.findChild(toast, '.message'); if (!message) { message = document.createElement('div'); for (var i = toast.childNodes.length - 1; i >= 0; i--) { if (toast.childNodes[i] !== button) { message.insertBefore(toast.childNodes[i], message.firstChild); } } } message.classList.add(messageClassName); toast.insertBefore(message, toast.firstChild); } if (toast.parentNode !== this) { this.appendChild(toast); } ModifierUtil.initModifier(this, this._scheme); } /** * @property visible * @readonly * @type {Boolean} * @description * [en]Whether the element is visible or not.[/en] * [ja]要素が見える場合に`true`。[/ja] */ /** * @method show * @signature show([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"default"`, `"ascend"` (Android), `"lift"` (iOS), `"fall"`, `"fade"` or `"none"`.[/en] * [ja][/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja] * @description * [en]Show the element.[/en] * [ja][/ja] * @return {Promise} * [en]Resolves to the displayed element[/en] * [ja][/ja] */ /** * @method toggle * @signature toggle([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"default"`, `"ascend"` (Android), `"lift"` (iOS), `"fall"`, `"fade"` or `"none"`.[/en] * [ja][/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja] * @description * [en]Toggle toast visibility.[/en] * [ja][/ja] */ /** * @method hide * @signature hide([options]) * @param {Object} [options] * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクト。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `"default"`, `"ascend"` (Android), `"lift"` (iOS), `"fall"`, `"fade"` or `"none"`.[/en] * [ja][/ja] * @param {String} [options.animationOptions] * [en]Specify the animation's duration, delay and timing. E.g. `{duration: 0.2, delay: 0.4, timing: 'ease-in'}`.[/en] * [ja]アニメーション時のduration, delay, timingを指定します。e.g. {duration: 0.2, delay: 0.4, timing: 'ease-in'}[/ja] * @description * [en]Hide toast.[/en] * [ja][/ja] * @return {Promise} * [en]Resolves to the hidden element[/en] * [ja][/ja] */ /** * @param {String} name * @param {Function} Animator */ }, { key: '_scheme', get: function get$$1() { return scheme$31; } }, { key: '_toast', get: function get$$1() { return util$1.findChild(this, '.' + defaultClassName$17); } }], [{ key: 'registerAnimator', value: function registerAnimator(name, Animator) { if (!(Animator.prototype instanceof ToastAnimator)) { util$1.throw('"Animator" param must inherit OnsToastElement.ToastAnimator'); } _animatorDict$8[name] = Animator; } }, { key: 'animators', get: function get$$1() { return _animatorDict$8; } }, { key: 'ToastAnimator', get: function get$$1() { return ToastAnimator; } }]); return ToastElement; }(BaseDialogElement); onsElements.Toast = ToastElement; customElements.define('ons-toast', ToastElement); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @element ons-toolbar-button * @category page * @modifier material * [en]Material Design toolbar button.[/en] * [ja][/ja] * @modifier outline * [en]A button with an outline.[/en] * [ja]アウトラインをもったボタンを表示します。[/ja] * @description * [en]Button component for ons-toolbar and ons-bottom-toolbar.[/en] * [ja]ons-toolbarあるいはons-bottom-toolbarに設置できるボタン用コンポーネントです。[/ja] * @codepen aHmGL * @tutorial vanilla/Reference/page * @guide compilation.html#toolbar-compilation * [en]Adding a toolbar[/en] * [ja]ツールバーの追加[/ja] * @seealso ons-toolbar * [en]The `<ons-toolbar>` component displays a navigation bar at the top of a page.[/en] * [ja]ons-toolbarコンポーネント[/ja] * @seealso ons-back-button * [en]The `<ons-back-button>` displays a back button in the navigation bar.[/en] * [ja]ons-back-buttonコンポーネント[/ja] * @example * <ons-toolbar> * <div class="left"> * <ons-toolbar-button> * Button * </ons-toolbar-button> * </div> * <div class="center"> * Title * </div> * <div class="right"> * <ons-toolbar-button> * <ons-icon icon="ion-navicon" size="28px"></ons-icon> * </ons-toolbar-button> * </div> * </ons-toolbar> */ var ToolbarButtonElement = function (_BaseButtonElement) { inherits(ToolbarButtonElement, _BaseButtonElement); function ToolbarButtonElement() { classCallCheck(this, ToolbarButtonElement); return possibleConstructorReturn(this, (ToolbarButtonElement.__proto__ || Object.getPrototypeOf(ToolbarButtonElement)).apply(this, arguments)); } createClass(ToolbarButtonElement, [{ key: '_scheme', /** * @attribute modifier * @type {String} * @description * [en]The appearance of the button.[/en] * [ja]ボタンの表現を指定します。[/ja] */ /** * @attribute icon * @type {String} * @description * [en]Creates an `ons-icon` component with this string.[/en] * [ja]`ons-icon`コンポーネントを悪性します。[/ja] */ /** * @attribute disabled * @description * [en]Specify if button should be disabled.[/en] * [ja]ボタンを無効化する場合は指定してください。[/ja] */ /** * @property disabled * @type {Boolean} * @description * [en]Whether the element is disabled or not.[/en] * [ja]無効化されている場合に`true`。[/ja] */ get: function get$$1() { return { '': 'toolbar-button--*' }; } }, { key: '_defaultClassName', get: function get$$1() { return 'toolbar-button'; } }, { key: '_rippleOpt', get: function get$$1() { return [this, undefined, { center: '', 'size': 'contain', 'background': 'transparent' }]; } }]); return ToolbarButtonElement; }(BaseButtonElement); onsElements.ToolbarButton = ToolbarButtonElement; customElements.define('ons-toolbar-button', ToolbarButtonElement); // Add and register Custom Elements setup$1(ons$1); // Setup initial listeners window._superSecretOns = ons$1; return ons$1; }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib25zZW51aS5qcyIsInNvdXJjZXMiOlsiLi4vLi4vY29yZS9zcmMvb25zL2VsZW1lbnRzLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL3N0eWxlci5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9wbGF0Zm9ybS5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9wYWdlLWF0dHJpYnV0ZS1leHByZXNzaW9uLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL2ludGVybmFsL2ludGVybmFsLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnkuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvYXV0b3N0eWxlLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvaW50ZXJuYWwvZGV2aWNlLWJhY2stYnV0dG9uLWRpc3BhdGNoZXIuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvaW50ZXJuYWwvaW5kZXguanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvYW5pbWF0aW9uLW9wdGlvbnMtcGFyc2VyLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL3V0aWwuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvYW5pbWl0LmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL2dlc3R1cmUtZGV0ZWN0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvY29udGVudC1yZWFkeS5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9pbnRlcm5hbC90b2FzdC1xdWV1ZS5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9ub3RpZmljYXRpb24uanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvYWN0aW9uLXNoZWV0LmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL21pY3JvZXZlbnQuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvb3JpZW50YXRpb24uanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvbW9kaWZpZXIuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvc29mdHdhcmUta2V5Ym9hcmQuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvZG9vcmxvY2suanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvcGFnZS1sb2FkZXIuanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvaW5kZXguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG9uc2VudWkvZmFzdGNsaWNrL2xpYi9mYXN0Y2xpY2suanMiLCIuLi8uLi9jb3JlL3NyYy9wb2x5ZmlsbHMvcG9seWZpbGwtc3dpdGNoZXMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19nbG9iYWwuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19jb3JlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9faXMtb2JqZWN0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fYW4tb2JqZWN0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fZmFpbHMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19kZXNjcmlwdG9ycy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2RvbS1jcmVhdGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pZTgtZG9tLWRlZmluZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3RvLXByaW1pdGl2ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX29iamVjdC1kcC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3Byb3BlcnR5LWRlc2MuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19oaWRlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9faGFzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fdWlkLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fcmVkZWZpbmUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19hLWZ1bmN0aW9uLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fY3R4LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fZXhwb3J0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fb2JqZWN0LXBpZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2NvZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2lvYmplY3QuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19kZWZpbmVkLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fdG8taW9iamVjdC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX29iamVjdC1nb3BkLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fc2V0LXByb3RvLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lczYub2JqZWN0LnNldC1wcm90b3R5cGUtb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9mbi9vYmplY3Qvc2V0LXByb3RvdHlwZS1vZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3NoYXJlZC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3drcy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2NsYXNzb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNi5vYmplY3QudG8tc3RyaW5nLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fdG8taW50ZWdlci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3N0cmluZy1hdC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2xpYnJhcnkuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pdGVyYXRvcnMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL190by1sZW5ndGguanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL190by1hYnNvbHV0ZS1pbmRleC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2FycmF5LWluY2x1ZGVzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fc2hhcmVkLWtleS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX29iamVjdC1rZXlzLWludGVybmFsLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fZW51bS1idWcta2V5cy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX29iamVjdC1rZXlzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fb2JqZWN0LWRwcy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2h0bWwuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19vYmplY3QtY3JlYXRlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fc2V0LXRvLXN0cmluZy10YWcuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pdGVyLWNyZWF0ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX3RvLW9iamVjdC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX29iamVjdC1ncG8uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pdGVyLWRlZmluZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM2LnN0cmluZy5pdGVyYXRvci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2FkZC10by11bnNjb3BhYmxlcy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2l0ZXItc3RlcC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM2LmFycmF5Lml0ZXJhdG9yLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy93ZWIuZG9tLml0ZXJhYmxlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fcmVkZWZpbmUtYWxsLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fYW4taW5zdGFuY2UuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pdGVyLWNhbGwuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pcy1hcnJheS1pdGVyLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19mb3Itb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19zZXQtc3BlY2llcy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX21ldGEuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL192YWxpZGF0ZS1jb2xsZWN0aW9uLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fY29sbGVjdGlvbi1zdHJvbmcuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19pdGVyLWRldGVjdC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2luaGVyaXQtaWYtcmVxdWlyZWQuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19jb2xsZWN0aW9uLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lczYuc2V0LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fYXJyYXktZnJvbS1pdGVyYWJsZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2NvbGxlY3Rpb24tdG8tanNvbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM3LnNldC50by1qc29uLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fc2V0LWNvbGxlY3Rpb24tb2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNy5zZXQub2YuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19zZXQtY29sbGVjdGlvbi1mcm9tLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lczcuc2V0LmZyb20uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9mbi9zZXQuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNi5tYXAuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNy5tYXAudG8tanNvbi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM3Lm1hcC5vZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM3Lm1hcC5mcm9tLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvZm4vbWFwLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9faXMtYXJyYXkuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19hcnJheS1zcGVjaWVzLWNvbnN0cnVjdG9yLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fYXJyYXktc3BlY2llcy1jcmVhdGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19hcnJheS1tZXRob2RzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fb2JqZWN0LWdvcHMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL19vYmplY3QtYXNzaWduLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9fY29sbGVjdGlvbi13ZWFrLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lczYud2Vhay1tYXAuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzNy53ZWFrLW1hcC5vZi5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM3LndlYWstbWFwLmZyb20uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9mbi93ZWFrLW1hcC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvX2NyZWF0ZS1wcm9wZXJ0eS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXM2LmFycmF5LmZyb20uanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvY29yZS1qcy9mbi9hcnJheS9mcm9tLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BvbnNlbnVpL2N1c3RvbS1lbGVtZW50cy9zcmMvVXRpbGl0aWVzLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BvbnNlbnVpL2N1c3RvbS1lbGVtZW50cy9zcmMvQ3VzdG9tRWxlbWVudFN0YXRlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BvbnNlbnVpL2N1c3RvbS1lbGVtZW50cy9zcmMvQ3VzdG9tRWxlbWVudEludGVybmFscy5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL0RvY3VtZW50Q29uc3RydWN0aW9uT2JzZXJ2ZXIuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG9uc2VudWkvY3VzdG9tLWVsZW1lbnRzL3NyYy9EZWZlcnJlZC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL0N1c3RvbUVsZW1lbnRSZWdpc3RyeS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL1BhdGNoL05hdGl2ZS5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL0FscmVhZHlDb25zdHJ1Y3RlZE1hcmtlci5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL1BhdGNoL0hUTUxFbGVtZW50LmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BvbnNlbnVpL2N1c3RvbS1lbGVtZW50cy9zcmMvUGF0Y2gvSW50ZXJmYWNlL1BhcmVudE5vZGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG9uc2VudWkvY3VzdG9tLWVsZW1lbnRzL3NyYy9QYXRjaC9Eb2N1bWVudC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL1BhdGNoL05vZGUuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvQG9uc2VudWkvY3VzdG9tLWVsZW1lbnRzL3NyYy9QYXRjaC9JbnRlcmZhY2UvQ2hpbGROb2RlLmpzIiwiLi4vLi4vbm9kZV9tb2R1bGVzL0BvbnNlbnVpL2N1c3RvbS1lbGVtZW50cy9zcmMvUGF0Y2gvRWxlbWVudC5qcyIsIi4uLy4uL25vZGVfbW9kdWxlcy9Ab25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL2N1c3RvbS1lbGVtZW50cy5qcyIsIi4uLy4uL2NvcmUvc3JjL3BvbHlmaWxscy9NdXRhdGlvbk9ic2VydmVyQDAuNy4yMi9NdXRhdGlvbk9ic2VydmVyLmpzIiwiLi4vLi4vY29yZS9zcmMvcG9seWZpbGxzL3NldEltbWVkaWF0ZUAxLjAuMittb2Qvc2V0SW1tZWRpYXRlLmpzIiwiLi4vLi4vY29yZS9zcmMvcG9seWZpbGxzL2luZGV4LmpzIiwiLi4vLi4vY29yZS9zcmMvdmVuZG9yL3ZpZXdwb3J0LmpzIiwiLi4vLi4vY29yZS9zcmMvc2V0dXAuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9iYXNlL2Jhc2UtZWxlbWVudC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy10ZW1wbGF0ZS5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1pZi5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9iYXNlLWFuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvb25zL2lwaG9uZXgtcGF0Y2guanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtYWN0aW9uLXNoZWV0L2FuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvYmFzZS9iYXNlLWRpYWxvZy5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1hY3Rpb24tc2hlZXQvaW5kZXguanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9iYXNlL2Jhc2UtYnV0dG9uLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWFjdGlvbi1zaGVldC1idXR0b24uanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtYWxlcnQtZGlhbG9nL2FuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWFsZXJ0LWRpYWxvZy9pbmRleC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1hbGVydC1kaWFsb2ctYnV0dG9uLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWJhY2stYnV0dG9uLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWJvdHRvbS10b29sYmFyLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWJ1dHRvbi5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1jYXJkLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWNhcm91c2VsLWl0ZW0uanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvaW50ZXJuYWwvc3dpcGVyLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWNhcm91c2VsLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWNvbC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1kaWFsb2cvYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtZGlhbG9nL2luZGV4LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWZhYi5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1nZXN0dXJlLWRldGVjdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWljb24uanMiLCIuLi8uLi9jb3JlL3NyYy9vbnMvaW50ZXJuYWwvbGF6eS1yZXBlYXQuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbGF6eS1yZXBlYXQuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbGlzdC1oZWFkZXIuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbGlzdC10aXRsZS5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1saXN0LWl0ZW0vYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbGlzdC1pdGVtL2luZGV4LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLWxpc3QuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9iYXNlL2Jhc2UtaW5wdXQuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtaW5wdXQuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9iYXNlL2Jhc2UtY2hlY2tib3guanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtY2hlY2tib3guanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtcmFkaW8uanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtc2VhcmNoLWlucHV0LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLW1vZGFsL2FuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLW1vZGFsL2ZhZGUtYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbW9kYWwvbGlmdC1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1tb2RhbC9pbmRleC5qcyIsIi4uLy4uL2NvcmUvc3JjL29ucy9pbnRlcm5hbC9zd2lwZS1yZXZlYWwuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbmF2aWdhdG9yL2FuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLW5hdmlnYXRvci9pb3Mtc3dpcGUtYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbmF2aWdhdG9yL2lvcy1zbGlkZS1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3IvaW9zLWxpZnQtYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtbmF2aWdhdG9yL2lvcy1mYWRlLWFuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLW5hdmlnYXRvci9tZC1zbGlkZS1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3IvbWQtbGlmdC1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3IvbWQtZmFkZS1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3Ivbm9uZS1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3IvaW5kZXguanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtdG9vbGJhci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1wYWdlLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXBvcG92ZXIvYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtcG9wb3Zlci9pbmRleC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1wcm9ncmVzcy1iYXIuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtcHJvZ3Jlc3MtY2lyY3VsYXIuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtcHVsbC1ob29rLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXJhbmdlLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXJpcHBsZS9hbmltYXRvci1jc3MuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtcmlwcGxlL2luZGV4LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXJvdy5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zZWdtZW50LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXNlbGVjdC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zcGVlZC1kaWFsLWl0ZW0uanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtc3BlZWQtZGlhbC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zcGxpdHRlci1jb250ZW50LmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXNwbGl0dGVyLW1hc2suanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtc3BsaXR0ZXIvYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtc3BsaXR0ZXIvb3ZlcmxheS1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zcGxpdHRlci9wdXNoLWFuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXNwbGl0dGVyL3JldmVhbC1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zcGxpdHRlci9pbmRleC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy1zcGxpdHRlci1zaWRlLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXN3aXRjaC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy10YWJiYXIvaW5kZXguanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtdGFiLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXRvYXN0L2FuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXRvYXN0L2ZhZGUtYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtdG9hc3QvYXNjZW5kLWFuaW1hdG9yLmpzIiwiLi4vLi4vY29yZS9zcmMvZWxlbWVudHMvb25zLXRvYXN0L2xpZnQtYW5pbWF0b3IuanMiLCIuLi8uLi9jb3JlL3NyYy9lbGVtZW50cy9vbnMtdG9hc3QvZmFsbC1hbmltYXRvci5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy10b2FzdC9pbmRleC5qcyIsIi4uLy4uL2NvcmUvc3JjL2VsZW1lbnRzL29ucy10b29sYmFyLWJ1dHRvbi5qcyIsIi4uLy4uL2NvcmUvc3JjL2luZGV4LnVtZC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZGVmYXVsdCB7IH07XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5cbi8qKlxuICogQWRkIHZlbmRvciBwcmVmaXguXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqL1xuY29uc3QgcHJlZml4ID0gKGZ1bmN0aW9uKCkge1xuICBjb25zdCBzdHlsZXMgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsICcnKTtcbiAgY29uc3QgcHJlZml4ID0gKEFycmF5LnByb3RvdHlwZS5zbGljZVxuICAgIC5jYWxsKHN0eWxlcylcbiAgICAuam9pbignJylcbiAgICAubWF0Y2goLy0obW96fHdlYmtpdHxtcyktLykgfHwgKHN0eWxlcy5PTGluayA9PT0gJycgJiYgWycnLCAnbyddKVxuICApWzFdO1xuXG4gIHJldHVybiBmdW5jdGlvbihuYW1lKSB7XG4gICAgcmV0dXJuICctJyArIHByZWZpeCArICctJyArIHV0aWwuaHlwaGVuYXRlKG5hbWUpO1xuICB9O1xufSkoKTtcblxuXG4vKipcbiAqIE1pbmltYWwgdXRpbGl0eSBsaWJyYXJ5IGZvciBtYW5pcHVsYXRpbmcgZWxlbWVudCdzIHN0eWxlLlxuICogU2V0IGVsZW1lbnQncyBzdHlsZS5cbiAqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdHlsZXNcbiAqIEByZXR1cm4ge0VsZW1lbnR9XG4gKi9cbmNvbnN0IHN0eWxlciA9IGZ1bmN0aW9uKGVsZW1lbnQsIHN0eWxlKSB7XG4gIE9iamVjdC5rZXlzKHN0eWxlKS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgIGlmIChrZXkgaW4gZWxlbWVudC5zdHlsZSkge1xuICAgICAgZWxlbWVudC5zdHlsZVtrZXldID0gc3R5bGVba2V5XTtcbiAgICB9IGVsc2UgaWYgKHByZWZpeChrZXkpIGluIGVsZW1lbnQuc3R5bGUpIHtcbiAgICAgIGVsZW1lbnQuc3R5bGVbcHJlZml4KGtleSldID0gc3R5bGVba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgdXRpbC53YXJuKCdObyBzdWNoIHN0eWxlIHByb3BlcnR5OiAnICsga2V5KTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gZWxlbWVudDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge1N0cmluZ30gc3R5bGVzIFNwYWNlLXNlcGFyYXRlZCBDU1MgcHJvcGVydGllcyB0byByZW1vdmVcbiAqL1xuc3R5bGVyLmNsZWFyID0gZnVuY3Rpb24oZWxlbWVudCwgc3R5bGVzID0gJycpIHtcbiAgY29uc3QgY2xlYXJsaXN0ID0gc3R5bGVzLnNwbGl0KC9cXHMrLykucmVkdWNlKChyLCBzKSA9PiByLmNvbmNhdChbdXRpbC5oeXBoZW5hdGUocyksIHByZWZpeChzKV0pLCBbXSksXG4gICAga2V5cyA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSBlbGVtZW50LnN0eWxlLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgY29uc3Qga2V5ID0gZWxlbWVudC5zdHlsZVtpXTtcbiAgICBpZiAoY2xlYXJsaXN0Lmxlbmd0aCA9PT0gMCB8fCBjbGVhcmxpc3Quc29tZShzID0+IGtleS5pbmRleE9mKHMpID09PSAwKSkge1xuICAgICAga2V5cy5wdXNoKGtleSk7IC8vIFN0b3JlIHRoZSBrZXkgdG8gZml4IFNhZmFyaSBzdHlsZSBpbmRleGVzXG4gICAgfVxuICB9XG5cbiAga2V5cy5mb3JFYWNoKGtleSA9PiBlbGVtZW50LnN0eWxlW2tleV0gPSAnJyk7XG4gIGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdzdHlsZScpID09PSAnJyAmJiBlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnc3R5bGUnKTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IHN0eWxlcjtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbi8vIFNhdmUgSFRNTEVsZW1lbnQgb2JqZWN0IGJlZm9yZSBDdXN0b20gRWxlbWVudHMgcG9seWZpbGwgcGF0Y2ggZ2xvYmFsIEhUTUxFbGVtZW50LlxuY29uc3QgTmF0aXZlSFRNTEVsZW1lbnQgPSB3aW5kb3cuSFRNTEVsZW1lbnQ7XG5cbi8qKlxuICogQG9iamVjdCBvbnMucGxhdGZvcm1cbiAqIEBjYXRlZ29yeSB1dGlsXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVV0aWxpdHkgbWV0aG9kcyB0byBkZXRlY3QgY3VycmVudCBwbGF0Zm9ybS5bL2VuXVxuICogICBbamFd54++5Zyo5a6f6KGM44GV44KM44Gm44GE44KL44OX44Op44OD44OI44OV44Kp44O844Og44KS5qSc55+l44GZ44KL44Gf44KB44Gu44Om44O844OG44Kj44Oq44OG44Kj44Oh44K944OD44OJ44KS5Y+O44KB44Gf44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAqL1xuY2xhc3MgUGxhdGZvcm0ge1xuXG4gIC8qKlxuICAgKiBBbGwgZWxlbWVudHMgd2lsbCBiZSByZW5kZXJlZCBhcyBpZiB0aGUgYXBwIHdhcyBydW5uaW5nIG9uIHRoaXMgcGxhdGZvcm0uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqL1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLl9zZWxlY3RlZFBsYXRmb3JtID0gbnVsbDtcbiAgICB0aGlzLl9pZ25vcmVQbGF0Zm9ybVNlbGVjdCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2VsZWN0XG4gICAqIEBzaWduYXR1cmUgc2VsZWN0KHBsYXRmb3JtKVxuICAgKiBAcGFyYW0gIHtzdHJpbmd9IHBsYXRmb3JtIE5hbWUgb2YgdGhlIHBsYXRmb3JtLlxuICAgKiAgIFtlbl1Qb3NzaWJsZSB2YWx1ZXMgYXJlOiBcIm9wZXJhXCIsIFwiZmlyZWZveFwiLCBcInNhZmFyaVwiLCBcImNocm9tZVwiLCBcImllXCIsIFwiYW5kcm9pZFwiLCBcImJsYWNrYmVycnlcIiwgXCJpb3NcIiBvciBcIndwXCIuWy9lbl1cbiAgICogICBbamFdXCJvcGVyYVwiLCBcImZpcmVmb3hcIiwgXCJzYWZhcmlcIiwgXCJjaHJvbWVcIiwgXCJpZVwiLCBcImFuZHJvaWRcIiwgXCJibGFja2JlcnJ5XCIsIFwiaW9zXCIsIFwid3BcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TZXRzIHRoZSBwbGF0Zm9ybSB1c2VkIHRvIHJlbmRlciB0aGUgZWxlbWVudHMuIFVzZWZ1bCBmb3IgdGVzdGluZy5bL2VuXVxuICAgKiAgIFtqYV3opoHntKDjgpLmj4/nlLvjgZnjgovjgZ/jgoHjgavliKnnlKjjgZnjgovjg5fjg6njg4Pjg4jjg5Xjgqnjg7zjg6DlkI3jgpLoqK3lrprjgZfjgb7jgZnjgILjg4bjgrnjg4jjgavkvr/liKnjgafjgZnjgIJbL2phXVxuICAgKi9cbiAgc2VsZWN0KHBsYXRmb3JtKSB7XG4gICAgaWYgKHR5cGVvZiBwbGF0Zm9ybSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHRoaXMuX3NlbGVjdGVkUGxhdGZvcm0gPSBwbGF0Zm9ybS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICBfZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpIHtcbiAgICByZXR1cm4gdGhpcy5faWdub3JlUGxhdGZvcm1TZWxlY3QgPyBudWxsIDogdGhpcy5fc2VsZWN0ZWRQbGF0Zm9ybTtcbiAgfVxuXG4gIF9ydW5PbkFjdHVhbFBsYXRmb3JtKGZuKSB7XG4gICAgdGhpcy5faWdub3JlUGxhdGZvcm1TZWxlY3QgPSB0cnVlO1xuICAgIGNvbnN0IHJlc3VsdCA9IGZuKCk7XG4gICAgdGhpcy5faWdub3JlUGxhdGZvcm1TZWxlY3QgPSBmYWxzZTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gR2VuZXJhbFxuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNXZWJWaWV3XG4gICAqIEBzaWduYXR1cmUgaXNXZWJWaWV3KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciBhcHAgaXMgcnVubmluZyBpbiBDb3Jkb3ZhLlsvZW5dXG4gICAqICAgW2phXUNvcmRvdmHlhoXjgaflrp/ooYzjgZXjgozjgabjgYTjgovjgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNXZWJWaWV3KCkge1xuICAgIGlmIChkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnbG9hZGluZycgfHwgZG9jdW1lbnQucmVhZHlTdGF0ZSA9PSAndW5pbml0aWFsaXplZCcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaXNXZWJWaWV3KCkgbWV0aG9kIGlzIGF2YWlsYWJsZSBhZnRlciBkb20gY29udGVudHMgbG9hZGVkLicpO1xuICAgIH1cblxuICAgIHJldHVybiAhISh3aW5kb3cuY29yZG92YSB8fCB3aW5kb3cucGhvbmVnYXAgfHwgd2luZG93LlBob25lR2FwKTtcbiAgfVxuXG4gIC8vLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBpT1MgZGV2aWNlc1xuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNJUGhvbmVcbiAgICogQHNpZ25hdHVyZSBpc0lQaG9uZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGRldmljZSBpcyBpUGhvbmUuWy9lbl1cbiAgICogICBbamFdaVBob25l5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSVBob25lKCkge1xuICAgIHJldHVybiAvaVBob25lL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzSVBob25lWFxuICAgKiBAc2lnbmF0dXJlIGlzSVBob25lWCgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGRldmljZSBpcyBpUGhvbmUgWCwgWFMsIFhTIE1heCwgb3IgWFIuWy9lbl1cbiAgICogICBbamFdaVBob25lIFgg44KEIFhT44CBWFMgTWF444CB44G+44Gf44GvIFhSIOS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0lQaG9uZVgoKSB7XG4gICAgLy8gaU9TIFdlYlZpZXdzIG9uIHRoZSBzYW1lIGlPUyB2ZXJzaW9uIGhhdmUgdGhlIHNhbWUgdXNlciBhZ2VudC5cbiAgICAvLyBXZSBjYW5ub3QgYXZvaWQgdXNpbmcgd2luZG93LnNjcmVlbi5cbiAgICAvLyBXZSBhbHNvIGNhbm5vdCB1c2UgY29yZG92YS1wbHVnaW4tZGV2aWNlIHNpbmNlIGl0cyBiZWhhdmlvciBpcyBkaWZmZXJlbnQgYmV0d2VlbiBzaW11bGF0b3JzIGFuZCByZWFsIGRldmljZXMuXG4gICAgLy8gVGhpcyB3b3JrcyB3ZWxsIGJvdGggaW4gaU9TIFNhZmFyaSBhbmQgKFVJfFdLKVdlYlZpZXcgb2YgaVBob25lIFguXG4gICAgcmV0dXJuIHRoaXMuaXNJUGhvbmUoKSAmJlxuICAgICAgKHdpbmRvdy5zY3JlZW4ud2lkdGggPT09IDM3NSAmJiB3aW5kb3cuc2NyZWVuLmhlaWdodCA9PT0gODEyIHx8IC8vIFgsIFhTIHBvcnRyYWl0XG4gICAgICAgd2luZG93LnNjcmVlbi53aWR0aCA9PT0gODEyICYmIHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID09PSAzNzUgfHwgLy8gWCwgWFMgbGFuZHNjYXBlXG4gICAgICAgd2luZG93LnNjcmVlbi53aWR0aCA9PT0gNDE0ICYmIHdpbmRvdy5zY3JlZW4uaGVpZ2h0ID09PSA4OTYgfHwgLy8gWFMgTWF4LCBYUiBwb3J0cmFpdFxuICAgICAgIHdpbmRvdy5zY3JlZW4ud2lkdGggPT09IDg5NiAmJiB3aW5kb3cuc2NyZWVuLmhlaWdodCA9PT0gNDE0KTsgLy8gWFMgTWF4LCBYUiBsYW5kc2NhcGVcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzSVBhZFxuICAgKiBAc2lnbmF0dXJlIGlzSVBhZCgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGRldmljZSBpcyBpUGFkLlsvZW5dXG4gICAqICAgW2phXWlQYWTkuIrjgaflrp/ooYzjgZXjgozjgabjgYTjgovjgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNJUGFkKCkge1xuICAgIHJldHVybiAvaVBhZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSVBvZCgpIHtcbiAgICByZXR1cm4gL2lQb2QvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICB9XG5cbiAgLy8tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIGlPUyB2ZXJzaW9uc1xuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNJT1NcbiAgICogQHNpZ25hdHVyZSBpc0lPUyhbZm9yY2VBY3R1YWxQbGF0Zm9ybV0pXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gZm9yY2VBY3R1YWxQbGF0Zm9ybVxuICAgKiAgIFtlbl1JZiB0cnVlLCBzZWxlY3RlZCBwbGF0Zm9ybSBpcyBpZ25vcmVkIGFuZCB0aGUgYWN0dWFsIHBsYXRmb3JtIGlzIHJldHVybmVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIE9TIGlzIGlPUy4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdaU9T5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSU9TKGZvcmNlQWN0dWFsUGxhdGZvcm0pIHtcbiAgICBpZiAoIWZvcmNlQWN0dWFsUGxhdGZvcm0gJiYgdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpID09PSAnaW9zJztcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRldmljZSA9PT0gJ29iamVjdCcgJiYgIS9icm93c2VyL2kudGVzdChkZXZpY2UucGxhdGZvcm0pKSB7XG4gICAgICByZXR1cm4gL2lPUy9pLnRlc3QoZGV2aWNlLnBsYXRmb3JtKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIC9pUGhvbmV8aVBhZHxpUG9kL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc0lPUzdhYm92ZVxuICAgKiBAc2lnbmF0dXJlIGlzSU9TN2Fib3ZlKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgaU9TIHZlcnNpb24gaXMgNyBvciBhYm92ZS5bL2VuXVxuICAgKiAgIFtqYV1pT1M35Lul5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzSU9TN2Fib3ZlKCkge1xuICAgIGlmICh0eXBlb2YgZGV2aWNlID09PSAnb2JqZWN0JyAmJiAhL2Jyb3dzZXIvaS50ZXN0KGRldmljZS5wbGF0Zm9ybSkpIHtcbiAgICAgIHJldHVybiAoL2lPUy9pLnRlc3QoZGV2aWNlLnBsYXRmb3JtKSAmJiAocGFyc2VJbnQoZGV2aWNlLnZlcnNpb24uc3BsaXQoJy4nKVswXSkgPj0gNykpO1xuICAgIH0gZWxzZSBpZiAoL2lQaG9uZXxpUGFkfGlQb2QvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpKSB7XG4gICAgICBjb25zdCB2ZXIgPSAobmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvXFxiWzAtOV0rX1swLTldKyg/Ol9bMC05XSspP1xcYi8pIHx8IFsnJ10pWzBdLnJlcGxhY2UoL18vZywgJy4nKTtcbiAgICAgIHJldHVybiAocGFyc2VJbnQodmVyLnNwbGl0KCcuJylbMF0pID49IDcpO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gaU9TIGJyb3dzZXJzXG4gIC8vLS0tLS0tLS0tLS0tLS0tLVxuICAvKipcbiAgICogQG1ldGhvZCBpc0lPU1NhZmFyaVxuICAgKiBAc2lnbmF0dXJlIGlzSU9TU2FmYXJpKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciBhcHAgaXMgcnVubmluZyBpbiBpT1MgU2FmYXJpLlsvZW5dXG4gICAqICAgW2phXWlPUyBTYWZhcmnjgaflrp/ooYzjgZXjgozjgabjgYTjgovjgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaXNJT1NTYWZhcmkoKSB7XG4gICAgY29uc3QgbmF2aWdhdG9yID0gd2luZG93Lm5hdmlnYXRvcjtcbiAgICBjb25zdCB1YSA9IG5hdmlnYXRvci51c2VyQWdlbnQ7XG5cbiAgICByZXR1cm4gISEodGhpcy5pc0lPUygpICYmIHVhLmluZGV4T2YoJ1NhZmFyaScpICE9PSAtMSAmJiB1YS5pbmRleE9mKCdWZXJzaW9uJykgIT09IC0xICYmICFuYXZpZ2F0b3Iuc3RhbmRhbG9uZSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc1dLV2ViVmlld1xuICAgKiBAc2lnbmF0dXJlIGlzV0tXZWJWaWV3KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciBhcHAgaXMgcnVubmluZyBpbiBXS1dlYlZpZXcuWy9lbl1cbiAgICogICBbamFdV0tXZWJWaWV344Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzV0tXZWJWaWV3KCkge1xuICAgIGNvbnN0IGx0ZTkgPSAvY29uc3RydWN0b3IvaS50ZXN0KE5hdGl2ZUhUTUxFbGVtZW50KTtcbiAgICByZXR1cm4gISEodGhpcy5pc0lPUygpICYmIHdpbmRvdy53ZWJraXQgJiYgd2luZG93LndlYmtpdC5tZXNzYWdlSGFuZGxlcnMgJiYgd2luZG93LmluZGV4ZWREQiAmJiAhbHRlOSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc1VJV2ViVmlld1xuICAgKiBAc2lnbmF0dXJlIGlzVUlXZWJWaWV3KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciBhcHAgaXMgcnVubmluZyBpbiBVSVdlYlZpZXcuWy9lbl1cbiAgICogICBbamFdVUlXZWJWaWV344Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzVUlXZWJWaWV3KCkge1xuICAgIHJldHVybiAhISh0aGlzLmlzSU9TKCkgJiYgIXRoaXMuaXNJT1NTYWZhcmkoKSAmJiAhdGhpcy5pc1dLV2ViVmlldygpKTtcbiAgfVxuXG4gIC8vLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBBbmRyb2lkIGRldmljZXNcbiAgLy8tLS0tLS0tLS0tLS0tLS0tXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzQW5kcm9pZFBob25lXG4gICAqIEBzaWduYXR1cmUgaXNBbmRyb2lkUGhvbmUoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBkZXZpY2UgaXMgQW5kcm9pZCBwaG9uZS5bL2VuXVxuICAgKiAgIFtqYV1BbmRyb2lk5pC65biv5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzQW5kcm9pZFBob25lKCkge1xuICAgIHJldHVybiAvQW5kcm9pZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiYgL01vYmlsZS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc0FuZHJvaWRUYWJsZXRcbiAgICogQHNpZ25hdHVyZSBpc0FuZHJvaWRUYWJsZXQoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBkZXZpY2UgaXMgQW5kcm9pZCB0YWJsZXQuWy9lbl1cbiAgICogICBbamFdQW5kcm9pZOOCv+ODluODrOODg+ODiOS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0FuZHJvaWRUYWJsZXQoKSB7XG4gICAgcmV0dXJuIC9BbmRyb2lkL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSAmJiAhL01vYmlsZS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gIH1cblxuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gQW5kcm9pZCB2ZXJzaW9uc1xuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNBbmRyb2lkXG4gICAqIEBzaWduYXR1cmUgaXNBbmRyb2lkKFtmb3JjZUFjdHVhbFBsYXRmb3JtXSlcbiAgICogQHBhcmFtIHtCb29sZWFufSBmb3JjZUFjdHVhbFBsYXRmb3JtXG4gICAqICAgW2VuXUlmIHRydWUsIHNlbGVjdGVkIHBsYXRmb3JtIGlzIGlnbm9yZWQgYW5kIHRoZSBhY3R1YWwgcGxhdGZvcm0gaXMgcmV0dXJuZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgT1MgaXMgQW5kcm9pZC4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdQW5kcm9pZOS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0FuZHJvaWQoZm9yY2VBY3R1YWxQbGF0Zm9ybSkge1xuICAgIGlmICghZm9yY2VBY3R1YWxQbGF0Zm9ybSAmJiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkgPT09ICdhbmRyb2lkJztcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRldmljZSA9PT0gJ29iamVjdCcgJiYgIS9icm93c2VyL2kudGVzdChkZXZpY2UucGxhdGZvcm0pKSB7XG4gICAgICByZXR1cm4gL0FuZHJvaWQvaS50ZXN0KGRldmljZS5wbGF0Zm9ybSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAvQW5kcm9pZC9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG4gICAgfVxuICB9XG5cbiAgLy8tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIE90aGVyIGRldmljZXNcbiAgLy8tLS0tLS0tLS0tLS0tLS0tXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzV1BcbiAgICogQHNpZ25hdHVyZSBpc1dQKFtmb3JjZUFjdHVhbFBsYXRmb3JtXSlcbiAgICogQHBhcmFtIHtCb29sZWFufSBmb3JjZUFjdHVhbFBsYXRmb3JtXG4gICAqICAgW2VuXUlmIHRydWUsIHNlbGVjdGVkIHBsYXRmb3JtIGlzIGlnbm9yZWQgYW5kIHRoZSBhY3R1YWwgcGxhdGZvcm0gaXMgcmV0dXJuZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgT1MgaXMgV2luZG93cyBwaG9uZS4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzV1AoZm9yY2VBY3R1YWxQbGF0Zm9ybSkge1xuICAgIGlmICghZm9yY2VBY3R1YWxQbGF0Zm9ybSAmJiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkgPT09ICd3cCc7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBkZXZpY2UgPT09ICdvYmplY3QnICYmICEvYnJvd3Nlci9pLnRlc3QoZGV2aWNlLnBsYXRmb3JtKSkge1xuICAgICAgcmV0dXJuIC9XaW4zMk5UfFdpbkNFL2kudGVzdChkZXZpY2UucGxhdGZvcm0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gL1dpbmRvd3MgUGhvbmV8SUVNb2JpbGV8V1BEZXNrdG9wL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc0JsYWNrQmVycnlcbiAgICogQHNpZ25hdHVyZSBpc0JsYWNrQmVycnkoW2ZvcmNlQWN0dWFsUGxhdGZvcm1dKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGZvcmNlQWN0dWFsUGxhdGZvcm1cbiAgICogICBbZW5dSWYgdHJ1ZSwgc2VsZWN0ZWQgcGxhdGZvcm0gaXMgaWdub3JlZCBhbmQgdGhlIGFjdHVhbCBwbGF0Zm9ybSBpcyByZXR1cm5lZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBkZXZpY2UgaXMgQmxhY2tCZXJyeS4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdQmxhY2tCZXJyeeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0JsYWNrQmVycnkoZm9yY2VBY3R1YWxQbGF0Zm9ybSkge1xuICAgIGlmICghZm9yY2VBY3R1YWxQbGF0Zm9ybSAmJiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkgPT09ICdibGFja2JlcnJ5JztcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRldmljZSA9PT0gJ29iamVjdCcgJiYgIS9icm93c2VyL2kudGVzdChkZXZpY2UucGxhdGZvcm0pKSB7XG4gICAgICByZXR1cm4gL0JsYWNrQmVycnkvaS50ZXN0KGRldmljZS5wbGF0Zm9ybSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAvQmxhY2tCZXJyeXxSSU0gVGFibGV0IE9TfEJCMTAvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuICAgIH1cbiAgfVxuXG4gIC8vLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBPdGhlciBicm93c2Vyc1xuICAvLy0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNPcGVyYVxuICAgKiBAc2lnbmF0dXJlIGlzT3BlcmEoW2ZvcmNlQWN0dWFsUGxhdGZvcm1dKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGZvcmNlQWN0dWFsUGxhdGZvcm1cbiAgICogICBbZW5dSWYgdHJ1ZSwgc2VsZWN0ZWQgcGxhdGZvcm0gaXMgaWdub3JlZCBhbmQgdGhlIGFjdHVhbCBwbGF0Zm9ybSBpcyByZXR1cm5lZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIE9wZXJhLiBCeSBkZWZhdWx0IHdpbGwgcmV0dXJuIG1hbnVhbGx5IHNlbGVjdGVkIHBsYXRmb3JtIGlmIGl0IGlzIHNldC5bL2VuXVxuICAgKiAgIFtqYV1PcGVyYeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc09wZXJhKGZvcmNlQWN0dWFsUGxhdGZvcm0pIHtcbiAgICBpZiAoIWZvcmNlQWN0dWFsUGxhdGZvcm0gJiYgdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpID09PSAnb3BlcmEnO1xuICAgIH1cblxuICAgIHJldHVybiAoISF3aW5kb3cub3BlcmEgfHwgbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgT1BSLycpID49IDApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNGaXJlZm94XG4gICAqIEBzaWduYXR1cmUgaXNGaXJlZm94KFtmb3JjZUFjdHVhbFBsYXRmb3JtXSlcbiAgICogQHBhcmFtIHtCb29sZWFufSBmb3JjZUFjdHVhbFBsYXRmb3JtXG4gICAqICAgW2VuXUlmIHRydWUsIHNlbGVjdGVkIHBsYXRmb3JtIGlzIGlnbm9yZWQgYW5kIHRoZSBhY3R1YWwgcGxhdGZvcm0gaXMgcmV0dXJuZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgYnJvd3NlciBpcyBGaXJlZm94LiBCeSBkZWZhdWx0IHdpbGwgcmV0dXJuIG1hbnVhbGx5IHNlbGVjdGVkIHBsYXRmb3JtIGlmIGl0IGlzIHNldC5bL2VuXVxuICAgKiAgIFtqYV1GaXJlZm945LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzRmlyZWZveChmb3JjZUFjdHVhbFBsYXRmb3JtKSB7XG4gICAgaWYgKCFmb3JjZUFjdHVhbFBsYXRmb3JtICYmIHRoaXMuX2dldFNlbGVjdGVkUGxhdGZvcm0oKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldFNlbGVjdGVkUGxhdGZvcm0oKSA9PT0gJ2ZpcmVmb3gnO1xuICAgIH1cblxuICAgIHJldHVybiAodHlwZW9mIEluc3RhbGxUcmlnZ2VyICE9PSAndW5kZWZpbmVkJyk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc1NhZmFyaVxuICAgKiBAc2lnbmF0dXJlIGlzU2FmYXJpKFtmb3JjZUFjdHVhbFBsYXRmb3JtXSlcbiAgICogQHBhcmFtIHtCb29sZWFufSBmb3JjZUFjdHVhbFBsYXRmb3JtXG4gICAqICAgW2VuXUlmIHRydWUsIHNlbGVjdGVkIHBsYXRmb3JtIGlzIGlnbm9yZWQgYW5kIHRoZSBhY3R1YWwgcGxhdGZvcm0gaXMgcmV0dXJuZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgd2hldGhlciB0aGUgYnJvd3NlciBpcyBTYWZhcmkuIEJ5IGRlZmF1bHQgd2lsbCByZXR1cm4gbWFudWFsbHkgc2VsZWN0ZWQgcGxhdGZvcm0gaWYgaXQgaXMgc2V0LlsvZW5dXG4gICAqICAgW2phXVNhZmFyaeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc1NhZmFyaShmb3JjZUFjdHVhbFBsYXRmb3JtKSB7XG4gICAgaWYgKCFmb3JjZUFjdHVhbFBsYXRmb3JtICYmIHRoaXMuX2dldFNlbGVjdGVkUGxhdGZvcm0oKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2dldFNlbGVjdGVkUGxhdGZvcm0oKSA9PT0gJ3NhZmFyaSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwod2luZG93LkhUTUxFbGVtZW50KS5pbmRleE9mKCdDb25zdHJ1Y3RvcicpID4gMCkgfHwgKGZ1bmN0aW9uIChwKSB7IHJldHVybiBwLnRvU3RyaW5nKCkgPT09ICdbb2JqZWN0IFNhZmFyaVJlbW90ZU5vdGlmaWNhdGlvbl0nIH0pKCF3aW5kb3dbJ3NhZmFyaSddIHx8IHNhZmFyaS5wdXNoTm90aWZpY2F0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzQ2hyb21lXG4gICAqIEBzaWduYXR1cmUgaXNDaHJvbWUoW2ZvcmNlQWN0dWFsUGxhdGZvcm1dKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGZvcmNlQWN0dWFsUGxhdGZvcm1cbiAgICogICBbZW5dSWYgdHJ1ZSwgc2VsZWN0ZWQgcGxhdGZvcm0gaXMgaWdub3JlZCBhbmQgdGhlIGFjdHVhbCBwbGF0Zm9ybSBpcyByZXR1cm5lZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIENocm9tZS4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdQ2hyb21l5LiK44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIGlzQ2hyb21lKGZvcmNlQWN0dWFsUGxhdGZvcm0pIHtcbiAgICBpZiAoIWZvcmNlQWN0dWFsUGxhdGZvcm0gJiYgdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpID09PSAnY2hyb21lJztcbiAgICB9XG5cbiAgICByZXR1cm4gKCEhd2luZG93LmNocm9tZSAmJiAhKCEhd2luZG93Lm9wZXJhIHx8IG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIE9QUi8nKSA+PSAwKSAmJiAhKG5hdmlnYXRvci51c2VyQWdlbnQuaW5kZXhPZignIEVkZ2UvJykgPj0gMCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaXNJRVxuICAgKiBAc2lnbmF0dXJlIGlzSUUoW2ZvcmNlQWN0dWFsUGxhdGZvcm1dKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGZvcmNlQWN0dWFsUGxhdGZvcm1cbiAgICogICBbZW5dSWYgdHJ1ZSwgc2VsZWN0ZWQgcGxhdGZvcm0gaXMgaWdub3JlZCBhbmQgdGhlIGFjdHVhbCBwbGF0Zm9ybSBpcyByZXR1cm5lZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBicm93c2VyIGlzIEludGVybmV0IEV4cGxvcmVyLiBCeSBkZWZhdWx0IHdpbGwgcmV0dXJuIG1hbnVhbGx5IHNlbGVjdGVkIHBsYXRmb3JtIGlmIGl0IGlzIHNldC5bL2VuXVxuICAgKiAgIFtqYV1JbnRlcm5ldCBFeHBsb3JlcuS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0lFKGZvcmNlQWN0dWFsUGxhdGZvcm0pIHtcbiAgICBpZiAoIWZvcmNlQWN0dWFsUGxhdGZvcm0gJiYgdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpID09PSAnaWUnO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZSB8fCAhIWRvY3VtZW50LmRvY3VtZW50TW9kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGlzRWRnZVxuICAgKiBAc2lnbmF0dXJlIGlzRWRnZShbZm9yY2VBY3R1YWxQbGF0Zm9ybV0pXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gZm9yY2VBY3R1YWxQbGF0Zm9ybVxuICAgKiAgIFtlbl1JZiB0cnVlLCBzZWxlY3RlZCBwbGF0Zm9ybSBpcyBpZ25vcmVkIGFuZCB0aGUgYWN0dWFsIHBsYXRmb3JtIGlzIHJldHVybmVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGJyb3dzZXIgaXMgRWRnZS4gQnkgZGVmYXVsdCB3aWxsIHJldHVybiBtYW51YWxseSBzZWxlY3RlZCBwbGF0Zm9ybSBpZiBpdCBpcyBzZXQuWy9lbl1cbiAgICogICBbamFdRWRnZeS4iuOBp+Wun+ihjOOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0VkZ2UoZm9yY2VBY3R1YWxQbGF0Zm9ybSkge1xuICAgIGlmICghZm9yY2VBY3R1YWxQbGF0Zm9ybSAmJiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLl9nZXRTZWxlY3RlZFBsYXRmb3JtKCkgPT09ICdlZGdlJztcbiAgICB9XG5cbiAgICByZXR1cm4gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCcgRWRnZS8nKSA+PSAwO1xuICB9XG5cbiAgLy8tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIFV0aWxpdHkgZnVuY3Rpb25zXG4gIC8vLS0tLS0tLS0tLS0tLS0tLVxuICAvKipcbiAgICogQHJldHVybiB7U3RyaW5nfVxuICAgKi9cbiAgZ2V0TW9iaWxlT1MoKSB7XG4gICAgaWYgKHRoaXMuaXNBbmRyb2lkKCkpIHtcbiAgICAgIHJldHVybiAnYW5kcm9pZCc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHRoaXMuaXNJT1MoKSkge1xuICAgICAgcmV0dXJuICdpb3MnO1xuICAgIH1cbiAgICBlbHNlIGlmICh0aGlzLmlzV1AoKSkge1xuICAgICAgcmV0dXJuICd3cCc7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgcmV0dXJuICdvdGhlcic7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge1N0cmluZ31cbiAgICovXG4gIGdldElPU0RldmljZSgpIHtcbiAgICBpZiAodGhpcy5pc0lQaG9uZSgpKSB7XG4gICAgICByZXR1cm4gJ2lwaG9uZSc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHRoaXMuaXNJUGFkKCkpIHtcbiAgICAgIHJldHVybiAnaXBhZCc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHRoaXMuaXNJUG9kKCkpIHtcbiAgICAgIHJldHVybiAnaXBvZCc7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgcmV0dXJuICduYSc7XG4gICAgfVxuICB9XG59XG5cblxuZXhwb3J0IGRlZmF1bHQgbmV3IFBsYXRmb3JtKCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi9wbGF0Zm9ybSc7XG5pbXBvcnQgdXRpbCBmcm9tICcuL3V0aWwnO1xuXG5jb25zdCBlcnJvciA9IG1lc3NhZ2UgPT4gdXRpbC50aHJvdyhgSW4gUGFnZUF0dHJpYnV0ZUV4cHJlc3Npb246ICR7bWVzc2FnZX1gKTtcblxuY29uc3QgcGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24gPSB7XG4gIF92YXJpYWJsZXM6IHt9LFxuXG4gIC8qKlxuICAgKiBEZWZpbmUgYSB2YXJpYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgdmFyaWFibGVcbiAgICogQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IHZhbHVlIFZhbHVlIG9mIHRoZSB2YXJpYWJsZS4gQ2FuIGJlIGEgc3RyaW5nIG9yIGEgZnVuY3Rpb24uIFRoZSBmdW5jdGlvbiBtdXN0IHJldHVybiBhIHN0cmluZy5cbiAgICogQHBhcmFtIHtCb29sZWFufSBvdmVyd3JpdGUgSWYgdGhpcyB2YWx1ZSBpcyBmYWxzZSwgYW4gZXJyb3Igd2lsbCBiZSB0aHJvd24gd2hlbiB0cnlpbmcgdG8gZGVmaW5lIGEgdmFyaWFibGUgdGhhdCBoYXMgYWxyZWFkeSBiZWVuIGRlZmluZWQuXG4gICAqL1xuICBkZWZpbmVWYXJpYWJsZTogZnVuY3Rpb24obmFtZSwgdmFsdWUsIG92ZXJ3cml0ZT1mYWxzZSkge1xuICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIGVycm9yKCdWYXJpYWJsZSBuYW1lIG11c3QgYmUgYSBzdHJpbmcnKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyAmJiB0eXBlb2YgdmFsdWUgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGVycm9yKCdWYXJpYWJsZSB2YWx1ZSBtdXN0IGJlIGEgc3RyaW5nIG9yIGEgZnVuY3Rpb24nKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodGhpcy5fdmFyaWFibGVzLmhhc093blByb3BlcnR5KG5hbWUpICYmICFvdmVyd3JpdGUpIHtcbiAgICAgIGVycm9yKGBcIiR7bmFtZX1cIiBpcyBhbHJlYWR5IGRlZmluZWRgKTtcbiAgICB9XG4gICAgdGhpcy5fdmFyaWFibGVzW25hbWVdID0gdmFsdWU7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBhIHZhcmlhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBOYW1lIG9mIHRoZSB2YXJpYWJsZS5cbiAgICogQHJldHVybiB7U3RyaW5nfEZ1bmN0aW9ufG51bGx9XG4gICAqL1xuICBnZXRWYXJpYWJsZTogZnVuY3Rpb24obmFtZSkge1xuICAgIGlmICghdGhpcy5fdmFyaWFibGVzLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fdmFyaWFibGVzW25hbWVdO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYSB2YXJpYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgdmFyYWlibGUuXG4gICAqL1xuICByZW1vdmVWYXJpYWJsZTogZnVuY3Rpb24obmFtZSkge1xuICAgIGRlbGV0ZSB0aGlzLl92YXJpYWJsZXNbbmFtZV07XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdldCBhbGwgdmFyaWFibGVzLlxuICAgKlxuICAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICAqL1xuICBnZXRBbGxWYXJpYWJsZXM6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl92YXJpYWJsZXM7XG4gIH0sXG4gIF9wYXJzZVBhcnQ6IGZ1bmN0aW9uKHBhcnQpIHtcbiAgICBsZXQgYyxcbiAgICAgIGluSW50ZXJwb2xhdGlvbiA9IGZhbHNlLFxuICAgICAgY3VycmVudEluZGV4ID0gMDtcblxuICAgIGNvbnN0IHRva2VucyA9IFtdO1xuXG4gICAgaWYgKHBhcnQubGVuZ3RoID09PSAwKSB7XG4gICAgICBlcnJvcignVW5hYmxlIHRvIHBhcnNlIGVtcHR5IHN0cmluZycpO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydC5sZW5ndGg7IGkrKykge1xuICAgICAgYyA9IHBhcnQuY2hhckF0KGkpO1xuXG4gICAgICBpZiAoYyA9PT0gJyQnICYmIHBhcnQuY2hhckF0KGkgKyAxKSA9PT0gJ3snKSB7XG4gICAgICAgIGlmIChpbkludGVycG9sYXRpb24pIHtcbiAgICAgICAgICBlcnJvcignTmVzdGVkIGludGVycG9sYXRpb24gbm90IHN1cHBvcnRlZCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdG9rZW4gPSBwYXJ0LnN1YnN0cmluZyhjdXJyZW50SW5kZXgsIGkpO1xuICAgICAgICBpZiAodG9rZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHRva2Vucy5wdXNoKHBhcnQuc3Vic3RyaW5nKGN1cnJlbnRJbmRleCwgaSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY3VycmVudEluZGV4ID0gaTtcbiAgICAgICAgaW5JbnRlcnBvbGF0aW9uID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKGMgPT09ICd9Jykge1xuICAgICAgICBpZiAoIWluSW50ZXJwb2xhdGlvbikge1xuICAgICAgICAgIGVycm9yKCd9IG11c3QgYmUgcHJlY2VlZGVkIGJ5ICR7Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0b2tlbiA9IHBhcnQuc3Vic3RyaW5nKGN1cnJlbnRJbmRleCwgaSArIDEpO1xuICAgICAgICBpZiAodG9rZW4ubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHRva2Vucy5wdXNoKHBhcnQuc3Vic3RyaW5nKGN1cnJlbnRJbmRleCwgaSArIDEpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGN1cnJlbnRJbmRleCA9IGkgKyAxO1xuICAgICAgICBpbkludGVycG9sYXRpb24gPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaW5JbnRlcnBvbGF0aW9uKSB7XG4gICAgICBlcnJvcignVW50ZXJtaW5hdGVkIGludGVycG9sYXRpb24nKTtcbiAgICB9XG5cbiAgICB0b2tlbnMucHVzaChwYXJ0LnN1YnN0cmluZyhjdXJyZW50SW5kZXgsIHBhcnQubGVuZ3RoKSk7XG5cbiAgICByZXR1cm4gdG9rZW5zO1xuICB9LFxuICBfcmVwbGFjZVRva2VuOiBmdW5jdGlvbih0b2tlbikge1xuICAgIGNvbnN0IHJlID0gL15cXCR7KC4qPyl9JC8sXG4gICAgICBtYXRjaCA9IHRva2VuLm1hdGNoKHJlKTtcblxuICAgIGlmIChtYXRjaCkge1xuICAgICAgY29uc3QgbmFtZSA9IG1hdGNoWzFdLnRyaW0oKTtcbiAgICAgIGNvbnN0IHZhcmlhYmxlID0gdGhpcy5nZXRWYXJpYWJsZShuYW1lKTtcblxuICAgICAgaWYgKHZhcmlhYmxlID09PSBudWxsKSB7XG4gICAgICAgIGVycm9yKGBWYXJpYWJsZSBcIiR7bmFtZX1cIiBkb2VzIG5vdCBleGlzdGApO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAodHlwZW9mIHZhcmlhYmxlID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gdmFyaWFibGU7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgY29uc3QgcnYgPSB2YXJpYWJsZSgpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgcnYgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgZXJyb3IoJ011c3QgcmV0dXJuIGEgc3RyaW5nJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcnY7XG4gICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgcmV0dXJuIHRva2VuO1xuICAgIH1cbiAgfSxcbiAgX3JlcGxhY2VUb2tlbnM6IGZ1bmN0aW9uKHRva2Vucykge1xuICAgIHJldHVybiB0b2tlbnMubWFwKHRoaXMuX3JlcGxhY2VUb2tlbi5iaW5kKHRoaXMpKTtcbiAgfSxcbiAgX3BhcnNlRXhwcmVzc2lvbjogZnVuY3Rpb24oZXhwcmVzc2lvbikge1xuICAgIHJldHVybiBleHByZXNzaW9uLnNwbGl0KCcsJylcbiAgICAgIC5tYXAoXG4gICAgICAgIGZ1bmN0aW9uKHBhcnQpIHtcbiAgICAgICAgICByZXR1cm4gcGFydC50cmltKCk7XG4gICAgICAgIH1cbiAgICAgIClcbiAgICAgIC5tYXAodGhpcy5fcGFyc2VQYXJ0LmJpbmQodGhpcykpXG4gICAgICAubWFwKHRoaXMuX3JlcGxhY2VUb2tlbnMuYmluZCh0aGlzKSlcbiAgICAgIC5tYXAoKHBhcnQpID0+IHBhcnQuam9pbignJykpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBFdmFsdWF0ZSBhbiBleHByZXNzaW9uLlxuICAgKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXhwcmVzc2lvbiBBbiBwYWdlIGF0dHJpYnV0ZSBleHByZXNzaW9uLlxuICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICovXG4gIGV2YWx1YXRlOiBmdW5jdGlvbihleHByZXNzaW9uKSB7XG4gICAgaWYgKCFleHByZXNzaW9uKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3BhcnNlRXhwcmVzc2lvbihleHByZXNzaW9uKTtcbiAgfVxufTtcblxuLy8gRGVmaW5lIGRlZmF1bHQgdmFyaWFibGVzLlxucGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24uZGVmaW5lVmFyaWFibGUoJ21vYmlsZU9TJywgcGxhdGZvcm0uZ2V0TW9iaWxlT1MoKSk7XG5wYWdlQXR0cmlidXRlRXhwcmVzc2lvbi5kZWZpbmVWYXJpYWJsZSgnaU9TRGV2aWNlJywgcGxhdGZvcm0uZ2V0SU9TRGV2aWNlKCkpO1xucGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24uZGVmaW5lVmFyaWFibGUoJ3J1bnRpbWUnLCAoKSA9PiB7XG4gIHJldHVybiBwbGF0Zm9ybS5pc1dlYlZpZXcoKSA/ICdjb3Jkb3ZhJyA6ICdicm93c2VyJztcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBwYWdlQXR0cmlidXRlRXhwcmVzc2lvbjtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uL3BsYXRmb3JtJztcbmltcG9ydCBwYWdlQXR0cmlidXRlRXhwcmVzc2lvbiBmcm9tICcuLi9wYWdlLWF0dHJpYnV0ZS1leHByZXNzaW9uJztcblxuY29uc3QgaW50ZXJuYWwgPSB7fTtcblxuaW50ZXJuYWwuY29uZmlnID0ge1xuICBhdXRvU3RhdHVzQmFyRmlsbDogdHJ1ZSxcbiAgYW5pbWF0aW9uc0Rpc2FibGVkOiBmYWxzZSxcbiAgd2FybmluZ3NEaXNhYmxlZDogZmFsc2Vcbn07XG5cbmludGVybmFsLm51bGxFbGVtZW50ID0gd2luZG93LmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4vKipcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKi9cbmludGVybmFsLmlzRW5hYmxlZEF1dG9TdGF0dXNCYXJGaWxsID0gKCkgPT4ge1xuICByZXR1cm4gISFpbnRlcm5hbC5jb25maWcuYXV0b1N0YXR1c0JhckZpbGw7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfSBodG1sXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKi9cbmludGVybmFsLm5vcm1hbGl6ZVBhZ2VIVE1MID0gaHRtbCA9PiAoJycgKyBodG1sKS50cmltKCk7XG5cbmludGVybmFsLndhaXRET01Db250ZW50TG9hZGVkID0gY2FsbGJhY2sgPT4ge1xuICBpZiAod2luZG93LmRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdsb2FkaW5nJyB8fCB3aW5kb3cuZG9jdW1lbnQucmVhZHlTdGF0ZSA9PSAndW5pbml0aWFsaXplZCcpIHtcbiAgICBjb25zdCB3cmFwcGVkQ2FsbGJhY2sgPSAoKSA9PiB7XG4gICAgICBjYWxsYmFjaygpO1xuICAgICAgd2luZG93LmRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCB3cmFwcGVkQ2FsbGJhY2spO1xuICAgIH07XG4gICAgd2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCB3cmFwcGVkQ2FsbGJhY2spO1xuICB9IGVsc2Uge1xuICAgIHNldEltbWVkaWF0ZShjYWxsYmFjayk7XG4gIH1cbn07XG5cbmludGVybmFsLmF1dG9TdGF0dXNCYXJGaWxsID0gYWN0aW9uID0+IHtcbiAgY29uc3Qgb25SZWFkeSA9ICgpID0+IHtcbiAgICBpZiAoaW50ZXJuYWwuc2hvdWxkRmlsbFN0YXR1c0JhcigpKSB7XG4gICAgICBhY3Rpb24oKTtcbiAgICB9XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZGV2aWNlcmVhZHknLCBvblJlYWR5KTtcbiAgfTtcblxuICBpZiAodHlwZW9mIGRldmljZSA9PT0gJ29iamVjdCcpIHtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkZXZpY2VyZWFkeScsIG9uUmVhZHkpO1xuICB9IGVsc2UgaWYgKFsnY29tcGxldGUnLCAnaW50ZXJhY3RpdmUnXS5pbmRleE9mKGRvY3VtZW50LnJlYWR5U3RhdGUpID09PSAtMSkge1xuICAgIGludGVybmFsLndhaXRET01Db250ZW50TG9hZGVkKG9uUmVhZHkpO1xuICB9IGVsc2Uge1xuICAgIG9uUmVhZHkoKTtcbiAgfVxufTtcblxuaW50ZXJuYWwuc2hvdWxkRmlsbFN0YXR1c0JhciA9ICgpID0+IGludGVybmFsLmlzRW5hYmxlZEF1dG9TdGF0dXNCYXJGaWxsKCkgJiZcbiAgKHBsYXRmb3JtLmlzV2ViVmlldygpICYmIHBsYXRmb3JtLmlzSU9TN2Fib3ZlKCkgJiYgIXBsYXRmb3JtLmlzSVBob25lWCgpIHx8IGRvY3VtZW50LmJvZHkucXVlcnlTZWxlY3RvcignLm9ucy1zdGF0dXMtYmFyLW1vY2suaW9zJykpO1xuXG5pbnRlcm5hbC50ZW1wbGF0ZVN0b3JlID0ge1xuICBfc3RvcmFnZToge30sXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBrZXlcbiAgICogQHJldHVybiB7U3RyaW5nL251bGx9IHRlbXBsYXRlXG4gICAqL1xuICBnZXQoa2V5KSB7XG4gICAgcmV0dXJuIGludGVybmFsLnRlbXBsYXRlU3RvcmUuX3N0b3JhZ2Vba2V5XSB8fCBudWxsO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0ZW1wbGF0ZVxuICAgKi9cbiAgc2V0KGtleSwgdGVtcGxhdGUpIHtcbiAgICBpbnRlcm5hbC50ZW1wbGF0ZVN0b3JlLl9zdG9yYWdlW2tleV0gPSB0ZW1wbGF0ZTtcbiAgfVxufTtcblxud2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ190ZW1wbGF0ZWxvYWRlZCcsIGZ1bmN0aW9uKGUpIHtcbiAgaWYgKGUudGFyZ2V0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdvbnMtdGVtcGxhdGUnKSB7XG4gICAgaW50ZXJuYWwudGVtcGxhdGVTdG9yZS5zZXQoZS50ZW1wbGF0ZUlkLCBlLnRlbXBsYXRlKTtcbiAgfVxufSwgZmFsc2UpO1xuXG5pbnRlcm5hbC53YWl0RE9NQ29udGVudExvYWRlZChmdW5jdGlvbigpIHtcbiAgcmVnaXN0ZXIoJ3NjcmlwdFt0eXBlPVwidGV4dC9vbnMtdGVtcGxhdGVcIl0nKTtcbiAgcmVnaXN0ZXIoJ3NjcmlwdFt0eXBlPVwidGV4dC90ZW1wbGF0ZVwiXScpO1xuICByZWdpc3Rlcignc2NyaXB0W3R5cGU9XCJ0ZXh0L25nLXRlbXBsYXRlXCJdJyk7XG4gIHJlZ2lzdGVyKCd0ZW1wbGF0ZScpO1xuXG4gIGZ1bmN0aW9uIHJlZ2lzdGVyKHF1ZXJ5KSB7XG4gICAgY29uc3QgdGVtcGxhdGVzID0gd2luZG93LmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwocXVlcnkpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGVtcGxhdGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpbnRlcm5hbC50ZW1wbGF0ZVN0b3JlLnNldCh0ZW1wbGF0ZXNbaV0uZ2V0QXR0cmlidXRlKCdpZCcpLCB0ZW1wbGF0ZXNbaV0udGV4dENvbnRlbnQgfHwgdGVtcGxhdGVzW2ldLmNvbnRlbnQpO1xuICAgIH1cbiAgfVxufSk7XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKi9cbmludGVybmFsLmdldFRlbXBsYXRlSFRNTEFzeW5jID0gZnVuY3Rpb24ocGFnZSkge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGludGVybmFsLndhaXRET01Db250ZW50TG9hZGVkKCgpID0+IHtcbiAgICAgIGNvbnN0IGNhY2hlID0gaW50ZXJuYWwudGVtcGxhdGVTdG9yZS5nZXQocGFnZSk7XG4gICAgICBpZiAoY2FjaGUpIHtcbiAgICAgICAgaWYgKGNhY2hlIGluc3RhbmNlb2YgRG9jdW1lbnRGcmFnbWVudCkge1xuICAgICAgICAgIHJldHVybiByZXNvbHZlKGNhY2hlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGh0bWwgPSB0eXBlb2YgY2FjaGUgPT09ICdzdHJpbmcnID8gY2FjaGUgOiBjYWNoZVsxXTtcbiAgICAgICAgcmV0dXJuIHJlc29sdmUoaW50ZXJuYWwubm9ybWFsaXplUGFnZUhUTUwoaHRtbCkpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBsb2NhbCA9IHdpbmRvdy5kb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYWdlKTtcbiAgICAgIGlmIChsb2NhbCkge1xuICAgICAgICBjb25zdCBodG1sID0gbG9jYWwudGV4dENvbnRlbnQgfHwgbG9jYWwuY29udGVudDtcbiAgICAgICAgcmV0dXJuIHJlc29sdmUoaHRtbCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgeGhyLm9wZW4oJ0dFVCcsIHBhZ2UsIHRydWUpO1xuICAgICAgeGhyLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBjb25zdCBodG1sID0geGhyLnJlc3BvbnNlVGV4dDtcbiAgICAgICAgaWYgKHhoci5zdGF0dXMgPj0gNDAwICYmIHhoci5zdGF0dXMgPCA2MDApIHtcbiAgICAgICAgICByZWplY3QoaHRtbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gUmVmcmVzaCBzY3JpcHQgdGFnc1xuICAgICAgICAgIGNvbnN0IGZyYWdtZW50ID0gdXRpbC5jcmVhdGVGcmFnbWVudChodG1sKTtcbiAgICAgICAgICB1dGlsLmFycmF5RnJvbShmcmFnbWVudC5xdWVyeVNlbGVjdG9yQWxsKCdzY3JpcHQnKSkuZm9yRWFjaChlbCA9PiB7XG4gICAgICAgICAgICBjb25zdCBzY3JpcHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcbiAgICAgICAgICAgIHNjcmlwdC50eXBlID0gZWwudHlwZSB8fCAndGV4dC9qYXZhc2NyaXB0JztcbiAgICAgICAgICAgIHNjcmlwdC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShlbC50ZXh0IHx8IGVsLnRleHRDb250ZW50IHx8IGVsLmlubmVySFRNTCkpO1xuICAgICAgICAgICAgZWwucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQoc2NyaXB0LCBlbCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpbnRlcm5hbC50ZW1wbGF0ZVN0b3JlLnNldChwYWdlLCBmcmFnbWVudCk7XG4gICAgICAgICAgcmVzb2x2ZShmcmFnbWVudCk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB1dGlsLnRocm93KGBQYWdlIHRlbXBsYXRlIG5vdCBmb3VuZDogJHtwYWdlfWApO1xuICAgICAgfTtcbiAgICAgIHhoci5zZW5kKG51bGwpO1xuICAgIH0pO1xuICB9KTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKi9cbmludGVybmFsLmdldFBhZ2VIVE1MQXN5bmMgPSBmdW5jdGlvbihwYWdlKSB7XG4gIGNvbnN0IHBhZ2VzID0gcGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24uZXZhbHVhdGUocGFnZSk7XG5cbiAgY29uc3QgZ2V0UGFnZSA9IChwYWdlKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBwYWdlICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdNdXN0IHNwZWNpZnkgYSBwYWdlLicpO1xuICAgIH1cblxuICAgIHJldHVybiBpbnRlcm5hbC5nZXRUZW1wbGF0ZUhUTUxBc3luYyhwYWdlKVxuICAgICAgLmNhdGNoKGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgICAgIGlmIChwYWdlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGdldFBhZ2UocGFnZXMuc2hpZnQoKSk7XG4gICAgICB9KTtcbiAgfTtcblxuICByZXR1cm4gZ2V0UGFnZShwYWdlcy5zaGlmdCgpKTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGludGVybmFsO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vdXRpbCc7XG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi4vaW50ZXJuYWwnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBbmltYXRvckZhY3Rvcnkge1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0c1xuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cy5hbmltYXRvcnMgVGhlIGRpY3Rpb25hcnkgZm9yIGFuaW1hdG9yIGNsYXNzZXNcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gb3B0cy5iYXNlQ2xhc3MgVGhlIGJhc2UgY2xhc3Mgb2YgYW5pbWF0b3JzXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0cy5iYXNlQ2xhc3NOYW1lXSBUaGUgbmFtZSBvZiB0aGUgYmFzZSBjbGFzcyBvZiBhbmltYXRvcnNcbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRzLmRlZmF1bHRBbmltYXRpb25dIFRoZSBkZWZhdWx0IGFuaW1hdGlvbiBuYW1lXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0cy5kZWZhdWx0QW5pbWF0aW9uT3B0aW9uc10gVGhlIGRlZmF1bHQgYW5pbWF0aW9uIG9wdGlvbnNcbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdHMpIHtcbiAgICB0aGlzLl9hbmltYXRvcnMgPSBvcHRzLmFuaW1hdG9ycztcbiAgICB0aGlzLl9iYXNlQ2xhc3MgPSBvcHRzLmJhc2VDbGFzcztcbiAgICB0aGlzLl9iYXNlQ2xhc3NOYW1lID0gb3B0cy5iYXNlQ2xhc3NOYW1lIHx8IG9wdHMuYmFzZUNsYXNzLm5hbWU7XG4gICAgdGhpcy5fYW5pbWF0aW9uID0gb3B0cy5kZWZhdWx0QW5pbWF0aW9uIHx8ICdkZWZhdWx0JztcbiAgICB0aGlzLl9hbmltYXRpb25PcHRpb25zID0gb3B0cy5kZWZhdWx0QW5pbWF0aW9uT3B0aW9ucyB8fCB7fTtcblxuICAgIGlmICghdGhpcy5fYW5pbWF0b3JzW3RoaXMuX2FuaW1hdGlvbl0pIHtcbiAgICAgIHV0aWwudGhyb3coJ05vIHN1Y2ggYW5pbWF0aW9uOiAnICsgdGhpcy5fYW5pbWF0aW9uKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IGpzb25TdHJpbmdcbiAgICogQHJldHVybiB7T2JqZWN0L251bGx9XG4gICAqL1xuICBzdGF0aWMgcGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKGpzb25TdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHR5cGVvZiBqc29uU3RyaW5nID09PSAnc3RyaW5nJykge1xuICAgICAgICBjb25zdCByZXN1bHQgPSB1dGlsLmFuaW1hdGlvbk9wdGlvbnNQYXJzZShqc29uU3RyaW5nKTtcbiAgICAgICAgaWYgKHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnICYmIHJlc3VsdCAhPT0gbnVsbCkge1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignXCJhbmltYXRpb24tb3B0aW9uc1wiIGF0dHJpYnV0ZSBtdXN0IGJlIGEgSlNPTiBvYmplY3Qgc3RyaW5nOiAnICsganNvblN0cmluZyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB7fTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdcImFuaW1hdGlvbi1vcHRpb25zXCIgYXR0cmlidXRlIG11c3QgYmUgYSBKU09OIG9iamVjdCBzdHJpbmc6ICcgKyBqc29uU3RyaW5nKTtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICovXG4gIHNldEFuaW1hdGlvbk9wdGlvbnMob3B0aW9ucykge1xuICAgIHRoaXMuX2FuaW1hdGlvbk9wdGlvbnMgPSBvcHRpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dIFRoZSBhbmltYXRpb24gbmFtZVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc10gVGhlIGFuaW1hdGlvbiBvcHRpb25zXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkZWZhdWx0QW5pbWF0b3IgVGhlIGRlZmF1bHQgYW5pbWF0b3IgaW5zdGFuY2VcbiAgICogQHJldHVybiB7T2JqZWN0fSBBbiBhbmltYXRvciBpbnN0YW5jZVxuICAgKi9cbiAgbmV3QW5pbWF0b3Iob3B0aW9ucyA9IHt9LCBkZWZhdWx0QW5pbWF0b3IpIHtcblxuICAgIGxldCBhbmltYXRvciA9IG51bGw7XG5cbiAgICBpZiAob3B0aW9ucy5hbmltYXRpb24gaW5zdGFuY2VvZiB0aGlzLl9iYXNlQ2xhc3MpIHtcbiAgICAgIHJldHVybiBvcHRpb25zLmFuaW1hdGlvbjtcbiAgICB9XG5cbiAgICBsZXQgQW5pbWF0b3IgPSBudWxsO1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmFuaW1hdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgIEFuaW1hdG9yID0gdGhpcy5fYW5pbWF0b3JzW29wdGlvbnMuYW5pbWF0aW9uXTtcbiAgICB9XG5cbiAgICBpZiAoIUFuaW1hdG9yICYmIGRlZmF1bHRBbmltYXRvcikge1xuICAgICAgYW5pbWF0b3IgPSBkZWZhdWx0QW5pbWF0b3I7XG4gICAgfSBlbHNlIHtcbiAgICAgIEFuaW1hdG9yID0gQW5pbWF0b3IgfHwgdGhpcy5fYW5pbWF0b3JzW3RoaXMuX2FuaW1hdGlvbl07XG5cbiAgICAgIGNvbnN0IGFuaW1hdGlvbk9wdHMgPSB1dGlsLmV4dGVuZChcbiAgICAgICAge30sXG4gICAgICAgIHRoaXMuX2FuaW1hdGlvbk9wdGlvbnMsXG4gICAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fSxcbiAgICAgICAgaW50ZXJuYWwuY29uZmlnLmFuaW1hdGlvbnNEaXNhYmxlZCA/IHtkdXJhdGlvbjogMCwgZGVsYXk6IDB9IDoge31cbiAgICAgICk7XG5cbiAgICAgIGFuaW1hdG9yID0gbmV3IEFuaW1hdG9yKGFuaW1hdGlvbk9wdHMpO1xuXG4gICAgICBpZiAodHlwZW9mIGFuaW1hdG9yID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIGFuaW1hdG9yID0gbmV3IGFuaW1hdG9yKGFuaW1hdGlvbk9wdHMpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5ldy1jYXBcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIShhbmltYXRvciBpbnN0YW5jZW9mIHRoaXMuX2Jhc2VDbGFzcykpIHtcbiAgICAgIHV0aWwudGhyb3coYFwiYW5pbWF0b3JcIiBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgJHt0aGlzLl9iYXNlQ2xhc3NOYW1lfWApO1xuICAgIH1cblxuICAgIHJldHVybiBhbmltYXRvcjtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc1BsYXRmb3JtIGZyb20gJy4vcGxhdGZvcm0nO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcblxubGV0IGF1dG9TdHlsZUVuYWJsZWQgPSB0cnVlO1xuXG4vLyBNb2RpZmllcnNcbmNvbnN0IG1vZGlmaWVyc01hcCA9IHtcbiAgJ3F1aWV0JzogJ21hdGVyaWFsLS1mbGF0JyxcbiAgJ2xpZ2h0JzogJ21hdGVyaWFsLS1mbGF0JyxcbiAgJ291dGxpbmUnOiAnbWF0ZXJpYWwtLWZsYXQnLFxuICAnY3RhJzogJycsXG4gICdsYXJnZS0tcXVpZXQnOiAnbWF0ZXJpYWwtLWZsYXQgbGFyZ2UnLFxuICAnbGFyZ2UtLWN0YSc6ICdsYXJnZScsXG4gICdub2JvcmRlcic6ICcnLFxuICAndGFwcGFibGUnOiAnJ1xufTtcblxuY29uc3QgcGxhdGZvcm1zID0ge307XG5cbnBsYXRmb3Jtcy5hbmRyb2lkID0gZWxlbWVudCA9PiB7XG5cbiAgY29uc3QgZWxlbWVudE5hbWUgPSBlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKTtcblxuICBpZiAoIXV0aWwuaGFzTW9kaWZpZXIoZWxlbWVudCwgJ21hdGVyaWFsJykpIHtcbiAgICBjb25zdCBvbGRNb2RpZmllciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpIHx8ICcnO1xuXG4gICAgY29uc3QgbmV3TW9kaWZpZXIgPSBvbGRNb2RpZmllci50cmltKCkuc3BsaXQoL1xccysvKS5tYXAoZSA9PiBtb2RpZmllcnNNYXAuaGFzT3duUHJvcGVydHkoZSkgPyBtb2RpZmllcnNNYXBbZV0gOiBlKTtcbiAgICBuZXdNb2RpZmllci51bnNoaWZ0KCdtYXRlcmlhbCcpO1xuXG4gICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJywgbmV3TW9kaWZpZXIuam9pbignICcpLnRyaW0oKSk7XG4gIH1cblxuICBjb25zdCBlbGVtZW50cyA9IFtcbiAgICAnb25zLWFsZXJ0LWRpYWxvZy1idXR0b24nLFxuICAgICdvbnMtdG9vbGJhci1idXR0b24nLFxuICAgICdvbnMtYmFjay1idXR0b24nLFxuICAgICdvbnMtYnV0dG9uJyxcbiAgICAnb25zLWxpc3QtaXRlbScsXG4gICAgJ29ucy1mYWInLFxuICAgICdvbnMtc3BlZWQtZGlhbCcsXG4gICAgJ29ucy1zcGVlZC1kaWFsLWl0ZW0nLFxuICAgICdvbnMtdGFiJ1xuICBdO1xuXG5cbiAgLy8gRWZmZWN0c1xuICBpZiAoZWxlbWVudHMuaW5kZXhPZihlbGVtZW50TmFtZSkgIT09IC0xXG4gICAgJiYgIWVsZW1lbnQuaGFzQXR0cmlidXRlKCdyaXBwbGUnKVxuICAgICYmICFlbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJ29ucy1yaXBwbGUnKSkge1xuXG4gICAgaWYgKGVsZW1lbnROYW1lID09PSAnb25zLWxpc3QtaXRlbScpIHtcbiAgICAgIGlmIChlbGVtZW50Lmhhc0F0dHJpYnV0ZSgndGFwcGFibGUnKSkge1xuICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgncmlwcGxlJywgJycpO1xuICAgICAgICBlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgndGFwcGFibGUnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3JpcHBsZScsICcnKTtcbiAgICB9XG4gIH1cbn07XG5cbnBsYXRmb3Jtcy5pb3MgPSBlbGVtZW50ID0+IHtcblxuIC8vIE1vZGlmaWVyc1xuIGlmICh1dGlsLnJlbW92ZU1vZGlmaWVyKGVsZW1lbnQsICdtYXRlcmlhbCcpKSB7XG4gICBpZiAodXRpbC5yZW1vdmVNb2RpZmllcihlbGVtZW50LCAnbWF0ZXJpYWwtLWZsYXQnKSkge1xuICAgICB1dGlsLmFkZE1vZGlmaWVyKGVsZW1lbnQsICh1dGlsLnJlbW92ZU1vZGlmaWVyKGVsZW1lbnQsICdsYXJnZScpKSA/ICdsYXJnZS0tcXVpZXQnIDogJ3F1aWV0Jyk7XG4gICB9XG5cbiAgIGlmICghZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJykpIHtcbiAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ21vZGlmaWVyJyk7XG4gICB9XG4gfVxuXG4gLy8gRWZmZWN0c1xuIGlmIChlbGVtZW50Lmhhc0F0dHJpYnV0ZSgncmlwcGxlJykpIHtcbiAgIGlmIChlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29ucy1saXN0LWl0ZW0nKSB7XG4gICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCd0YXBwYWJsZScsICcnKTtcbiAgIH1cblxuICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ3JpcHBsZScpO1xuIH1cbn07XG5cbmNvbnN0IHVubG9ja2VkID0ge1xuICBhbmRyb2lkOiB0cnVlXG59O1xuXG5jb25zdCBnZXRQbGF0Zm9ybSA9IChlbGVtZW50LCBmb3JjZSkgPT4ge1xuICBpZiAoYXV0b1N0eWxlRW5hYmxlZCAmJiAhZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGUtYXV0by1zdHlsaW5nJykpIHtcbiAgICBjb25zdCBtb2JpbGVPUyA9IG9uc1BsYXRmb3JtLmdldE1vYmlsZU9TKCk7XG4gICAgaWYgKHBsYXRmb3Jtcy5oYXNPd25Qcm9wZXJ0eShtb2JpbGVPUykgJiYgKHVubG9ja2VkLmhhc093blByb3BlcnR5KG1vYmlsZU9TKSB8fCBmb3JjZSkpIHtcbiAgICAgIHJldHVybiBtb2JpbGVPUztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59O1xuXG5jb25zdCBwcmVwYXJlID0gKGVsZW1lbnQsIGZvcmNlKSA9PiB7XG4gIGNvbnN0IHAgPSBnZXRQbGF0Zm9ybShlbGVtZW50LCBmb3JjZSk7XG4gIHAgJiYgcGxhdGZvcm1zW3BdKGVsZW1lbnQpO1xufTtcblxuY29uc3QgbWFwTW9kaWZpZXIgPSAobW9kaWZpZXIsIGVsZW1lbnQsIGZvcmNlKSA9PiB7XG4gIGlmIChnZXRQbGF0Zm9ybShlbGVtZW50LCBmb3JjZSkpIHtcbiAgICByZXR1cm4gbW9kaWZpZXIuc3BsaXQoL1xccysvKS5tYXAobSA9PiBtb2RpZmllcnNNYXAuaGFzT3duUHJvcGVydHkobSkgPyBtb2RpZmllcnNNYXBbbV0gOiBtKS5qb2luKCcgJyk7XG4gIH1cbiAgcmV0dXJuIG1vZGlmaWVyO1xufTtcblxuY29uc3QgcmVzdG9yZU1vZGlmaWVyID0gZWxlbWVudCA9PiB7XG4gIGlmIChnZXRQbGF0Zm9ybShlbGVtZW50KSA9PT0gJ2FuZHJvaWQnKSB7XG4gICAgY29uc3QgbW9kaWZpZXIgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSB8fCAnJztcbiAgICBsZXQgbmV3TW9kaWZpZXIgPSBtYXBNb2RpZmllcihtb2RpZmllciwgZWxlbWVudCk7XG5cbiAgICBpZiAoIS8oXnxcXHMrKW1hdGVyaWFsKCR8XFxzKykvaS50ZXN0KG1vZGlmaWVyKSkge1xuICAgICAgbmV3TW9kaWZpZXIgPSAnbWF0ZXJpYWwgJyArIG5ld01vZGlmaWVyO1xuICAgIH1cblxuICAgIGlmIChuZXdNb2RpZmllciAhPT0gbW9kaWZpZXIpIHtcbiAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdtb2RpZmllcicsIG5ld01vZGlmaWVyLnRyaW0oKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuZXhwb3J0IGRlZmF1bHQge1xuICBpc0VuYWJsZWQ6ICgpID0+IGF1dG9TdHlsZUVuYWJsZWQsXG4gIGVuYWJsZTogKCkgPT4gYXV0b1N0eWxlRW5hYmxlZCA9IHRydWUsXG4gIGRpc2FibGU6ICgpID0+IGF1dG9TdHlsZUVuYWJsZWQgPSBmYWxzZSxcbiAgcHJlcGFyZSxcbiAgbWFwTW9kaWZpZXIsXG4gIGdldFBsYXRmb3JtLFxuICByZXN0b3JlTW9kaWZpZXJcbn07XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi91dGlsLmpzJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vYXV0b3N0eWxlLmpzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTW9kaWZpZXJVdGlsIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBsYXN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBjdXJyZW50XG4gICAqL1xuICBzdGF0aWMgZGlmZihsYXN0LCBjdXJyZW50KSB7XG4gICAgbGFzdCA9IG1ha2VEaWN0KCgnJyArIGxhc3QpLnRyaW0oKSk7XG4gICAgY3VycmVudCA9IG1ha2VEaWN0KCgnJyArIGN1cnJlbnQpLnRyaW0oKSk7XG5cbiAgICBjb25zdCByZW1vdmVkID0gT2JqZWN0LmtleXMobGFzdCkucmVkdWNlKChyZXN1bHQsIHRva2VuKSA9PiB7XG4gICAgICBpZiAoIWN1cnJlbnRbdG9rZW5dKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHRva2VuKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSwgW10pO1xuXG4gICAgY29uc3QgYWRkZWQgPSBPYmplY3Qua2V5cyhjdXJyZW50KS5yZWR1Y2UoKHJlc3VsdCwgdG9rZW4pID0+IHtcbiAgICAgIGlmICghbGFzdFt0b2tlbl0pIHtcbiAgICAgICAgcmVzdWx0LnB1c2godG9rZW4pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LCBbXSk7XG5cbiAgICByZXR1cm4ge2FkZGVkLCByZW1vdmVkfTtcblxuICAgIGZ1bmN0aW9uIG1ha2VEaWN0KG1vZGlmaWVyKSB7XG4gICAgICBjb25zdCBkaWN0ID0ge307XG4gICAgICBNb2RpZmllclV0aWwuc3BsaXQobW9kaWZpZXIpLmZvckVhY2godG9rZW4gPT4gZGljdFt0b2tlbl0gPSB0b2tlbik7XG4gICAgICByZXR1cm4gZGljdDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpZmZcbiAgICogQHBhcmFtIHtBcnJheX0gZGlmZi5yZW1vdmVkXG4gICAqIEBwYXJhbSB7QXJyYXl9IGRpZmYuYWRkZWRcbiAgICogQHBhcmFtIHtPYmplY3R9IGNsYXNzTGlzdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdGVtcGxhdGVcbiAgICovXG4gIHN0YXRpYyBhcHBseURpZmZUb0NsYXNzTGlzdChkaWZmLCBjbGFzc0xpc3QsIHRlbXBsYXRlKSB7XG4gICAgZGlmZi5hZGRlZFxuICAgICAgLm1hcChtb2RpZmllciA9PiB0ZW1wbGF0ZS5yZXBsYWNlKC9cXCovZywgbW9kaWZpZXIpKVxuICAgICAgLmZvckVhY2goa2xhc3MgPT4ga2xhc3Muc3BsaXQoL1xccysvKS5mb3JFYWNoKGsgPT4gY2xhc3NMaXN0LmFkZChrKSkpO1xuXG4gICAgZGlmZi5yZW1vdmVkXG4gICAgICAubWFwKG1vZGlmaWVyID0+IHRlbXBsYXRlLnJlcGxhY2UoL1xcKi9nLCBtb2RpZmllcikpXG4gICAgICAuZm9yRWFjaChrbGFzcyA9PiBrbGFzcy5zcGxpdCgvXFxzKy8pLmZvckVhY2goayA9PiBjbGFzc0xpc3QucmVtb3ZlKGspKSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpZmZcbiAgICogQHBhcmFtIHtBcnJheX0gZGlmZi5yZW1vdmVkXG4gICAqIEBwYXJhbSB7QXJyYXl9IGRpZmYuYWRkZWRcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge09iamVjdH0gc2NoZW1lXG4gICAqL1xuICBzdGF0aWMgYXBwbHlEaWZmVG9FbGVtZW50KGRpZmYsIGVsZW1lbnQsIHNjaGVtZSkge1xuICAgIE9iamVjdC5rZXlzKHNjaGVtZSkuZm9yRWFjaChzZWxlY3RvciA9PiB7XG4gICAgICBjb25zdCB0YXJnZXRFbGVtZW50cyA9ICFzZWxlY3RvciB8fCB1dGlsLm1hdGNoKGVsZW1lbnQsIHNlbGVjdG9yKVxuICAgICAgICA/IFtlbGVtZW50XVxuICAgICAgICA6IEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbChcbiAgICAgICAgICAgIGVsZW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvciksXG4gICAgICAgICAgICB0YXJnZXRFbGVtZW50ID0+ICF1dGlsLmZpbmRQYXJlbnQodGFyZ2V0RWxlbWVudCwgZWxlbWVudC50YWdOYW1lLCBwYXJlbnQgPT4gcGFyZW50ID09PSBlbGVtZW50KVxuICAgICAgICAgICk7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGFyZ2V0RWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgTW9kaWZpZXJVdGlsLmFwcGx5RGlmZlRvQ2xhc3NMaXN0KGRpZmYsIHRhcmdldEVsZW1lbnRzW2ldLmNsYXNzTGlzdCwgc2NoZW1lW3NlbGVjdG9yXSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IGxhc3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IGN1cnJlbnRcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge09iamVjdH0gc2NoZW1lXG4gICAqL1xuICBzdGF0aWMgb25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgZWxlbWVudCwgc2NoZW1lKSB7XG4gICAgTW9kaWZpZXJVdGlsLmFwcGx5RGlmZlRvRWxlbWVudChNb2RpZmllclV0aWwuZGlmZihsYXN0LCBjdXJyZW50KSwgZWxlbWVudCwgc2NoZW1lKTtcbiAgICBhdXRvU3R5bGUucmVzdG9yZU1vZGlmaWVyKGVsZW1lbnQpO1xuICB9XG5cbiAgc3RhdGljIHJlZnJlc2goZWxlbWVudCwgc2NoZW1lKSB7XG4gICAgTW9kaWZpZXJVdGlsLmFwcGx5RGlmZlRvRWxlbWVudChNb2RpZmllclV0aWwuZGlmZignJywgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJykgfHwgJycpLCBlbGVtZW50LCBzY2hlbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtPYmplY3R9IHNjaGVtZVxuICAgKi9cbiAgc3RhdGljIGluaXRNb2RpZmllcihlbGVtZW50LCBzY2hlbWUpIHtcbiAgICBjb25zdCBtb2RpZmllciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpO1xuICAgIGlmICh0eXBlb2YgbW9kaWZpZXIgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgTW9kaWZpZXJVdGlsLmFwcGx5RGlmZlRvRWxlbWVudCh7XG4gICAgICByZW1vdmVkOiBbXSxcbiAgICAgIGFkZGVkOiBNb2RpZmllclV0aWwuc3BsaXQobW9kaWZpZXIpXG4gICAgfSwgZWxlbWVudCwgc2NoZW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBzcGxpdChtb2RpZmllcikge1xuICAgIGlmICh0eXBlb2YgbW9kaWZpZXIgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGlmaWVyLnRyaW0oKS5zcGxpdCgvICsvKS5maWx0ZXIodG9rZW4gPT4gdG9rZW4gIT09ICcnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgbW9kaWZpZXIgdG9rZW4gdG8gYW4gZWxlbWVudC5cbiAgICovXG4gIHN0YXRpYyBhZGRNb2RpZmllcihlbGVtZW50LCBtb2RpZmllclRva2VuKSB7XG4gICAgaWYgKCFlbGVtZW50Lmhhc0F0dHJpYnV0ZSgnbW9kaWZpZXInKSkge1xuICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJywgbW9kaWZpZXJUb2tlbik7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHRva2VucyA9IE1vZGlmaWVyVXRpbC5zcGxpdChlbGVtZW50LmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSk7XG4gICAgICBpZiAodG9rZW5zLmluZGV4T2YobW9kaWZpZXJUb2tlbikgPT0gLTEpIHtcbiAgICAgICAgdG9rZW5zLnB1c2gobW9kaWZpZXJUb2tlbik7XG4gICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdtb2RpZmllcicsIHRva2Vucy5qb2luKCcgJykpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgbW9kaWZpZXIgdG9rZW4gZnJvbSBhbiBlbGVtZW50LlxuICAgKi9cbiAgc3RhdGljIHJlbW92ZU1vZGlmaWVyKGVsZW1lbnQsIG1vZGlmaWVyVG9rZW4pIHtcbiAgICBpZiAoZWxlbWVudC5oYXNBdHRyaWJ1dGUoJ21vZGlmaWVyJykpIHtcbiAgICAgIGNvbnN0IHRva2VucyA9IE1vZGlmaWVyVXRpbC5zcGxpdChlbGVtZW50LmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSk7XG4gICAgICBjb25zdCBpbmRleCA9IHRva2Vucy5pbmRleE9mKG1vZGlmaWVyVG9rZW4pO1xuICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgICB0b2tlbnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJywgdG9rZW5zLmpvaW4oJyAnKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vcGxhdGZvcm0nO1xuXG5jb25zdCB1dGlsID0ge1xuICBfcmVhZHk6IGZhbHNlLFxuXG4gIF9kb21Db250ZW50TG9hZGVkOiBmYWxzZSxcblxuICBfb25ET01Db250ZW50TG9hZGVkOiAoKSA9PiB7XG4gICAgdXRpbC5fZG9tQ29udGVudExvYWRlZCA9IHRydWU7XG5cbiAgICBpZiAocGxhdGZvcm0uaXNXZWJWaWV3KCkpIHtcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkZXZpY2VyZWFkeScsICgpID0+IHtcbiAgICAgICAgdXRpbC5fcmVhZHkgPSB0cnVlO1xuICAgICAgfSwgZmFsc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICB1dGlsLl9yZWFkeSA9IHRydWU7XG4gICAgfVxuICB9LFxuXG4gIGFkZEJhY2tCdXR0b25MaXN0ZW5lcjogZnVuY3Rpb24oZm4pIHtcbiAgICBpZiAoIXRoaXMuX2RvbUNvbnRlbnRMb2FkZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhpcyBtZXRob2QgaXMgYXZhaWxhYmxlIGFmdGVyIERPTUNvbnRlbnRMb2FkZWQnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fcmVhZHkpIHtcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdiYWNrYnV0dG9uJywgZm4sIGZhbHNlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2luZG93LmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RldmljZXJlYWR5JywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdiYWNrYnV0dG9uJywgZm4sIGZhbHNlKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfSxcblxuICByZW1vdmVCYWNrQnV0dG9uTGlzdGVuZXI6IGZ1bmN0aW9uKGZuKSB7XG4gICAgaWYgKCF0aGlzLl9kb21Db250ZW50TG9hZGVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgbWV0aG9kIGlzIGF2YWlsYWJsZSBhZnRlciBET01Db250ZW50TG9hZGVkJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3JlYWR5KSB7XG4gICAgICB3aW5kb3cuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignYmFja2J1dHRvbicsIGZuLCBmYWxzZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHdpbmRvdy5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdkZXZpY2VyZWFkeScsIGZ1bmN0aW9uKCkge1xuICAgICAgICB3aW5kb3cuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignYmFja2J1dHRvbicsIGZuLCBmYWxzZSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn07XG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHV0aWwuX29uRE9NQ29udGVudExvYWRlZCgpLCBmYWxzZSk7XG5cbmNvbnN0IEhhbmRsZXJSZXBvc2l0b3J5ID0ge1xuICBfc3RvcmU6IHt9LFxuXG4gIF9nZW5JZDogKCgpID0+IHtcbiAgICBsZXQgaSA9IDA7XG4gICAgcmV0dXJuICgpID0+IGkrKztcbiAgfSkoKSxcblxuICBzZXQ6IGZ1bmN0aW9uKGVsZW1lbnQsIGhhbmRsZXIpIHtcbiAgICBpZiAoZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQpIHtcbiAgICAgIHRoaXMucmVtb3ZlKGVsZW1lbnQpO1xuICAgIH1cbiAgICBjb25zdCBpZCA9IGVsZW1lbnQuZGF0YXNldC5kZXZpY2VCYWNrQnV0dG9uSGFuZGxlcklkID0gSGFuZGxlclJlcG9zaXRvcnkuX2dlbklkKCk7XG4gICAgdGhpcy5fc3RvcmVbaWRdID0gaGFuZGxlcjtcbiAgfSxcblxuICByZW1vdmU6IGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICBpZiAoZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLl9zdG9yZVtlbGVtZW50LmRhdGFzZXQuZGV2aWNlQmFja0J1dHRvbkhhbmRsZXJJZF07XG4gICAgICBkZWxldGUgZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQ7XG4gICAgfVxuICB9LFxuXG4gIGdldDogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGlmICghZWxlbWVudC5kYXRhc2V0LmRldmljZUJhY2tCdXR0b25IYW5kbGVySWQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgaWQgPSBlbGVtZW50LmRhdGFzZXQuZGV2aWNlQmFja0J1dHRvbkhhbmRsZXJJZDtcblxuICAgIGlmICghdGhpcy5fc3RvcmVbaWRdKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fc3RvcmVbaWRdO1xuICB9LFxuXG4gIGhhczogZnVuY3Rpb24oZWxlbWVudCkge1xuICAgIGlmICghZWxlbWVudC5kYXRhc2V0KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaWQgPSBlbGVtZW50LmRhdGFzZXQuZGV2aWNlQmFja0J1dHRvbkhhbmRsZXJJZDtcblxuICAgIHJldHVybiAhIXRoaXMuX3N0b3JlW2lkXTtcbiAgfVxufTtcblxuY2xhc3MgRGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLl9pc0VuYWJsZWQgPSBmYWxzZTtcbiAgICB0aGlzLl9ib3VuZENhbGxiYWNrID0gdGhpcy5fY2FsbGJhY2suYmluZCh0aGlzKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEVuYWJsZSB0byBoYW5kbGUgJ2JhY2tidXR0b24nIGV2ZW50cy5cbiAgICovXG4gIGVuYWJsZSgpIHtcbiAgICBpZiAoIXRoaXMuX2lzRW5hYmxlZCkge1xuICAgICAgdXRpbC5hZGRCYWNrQnV0dG9uTGlzdGVuZXIodGhpcy5fYm91bmRDYWxsYmFjayk7XG4gICAgICB0aGlzLl9pc0VuYWJsZWQgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNhYmxlIHRvIGhhbmRsZSAnYmFja2J1dHRvbicgZXZlbnRzLlxuICAgKi9cbiAgZGlzYWJsZSgpIHtcbiAgICBpZiAodGhpcy5faXNFbmFibGVkKSB7XG4gICAgICB1dGlsLnJlbW92ZUJhY2tCdXR0b25MaXN0ZW5lcih0aGlzLl9ib3VuZENhbGxiYWNrKTtcbiAgICAgIHRoaXMuX2lzRW5hYmxlZCA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGaXJlIGEgJ2JhY2tidXR0b24nIGV2ZW50IG1hbnVhbGx5LlxuICAgKi9cbiAgZmlyZURldmljZUJhY2tCdXR0b25FdmVudCgpIHtcbiAgICBjb25zdCBldmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdFdmVudCcpO1xuICAgIGV2ZW50LmluaXRFdmVudCgnYmFja2J1dHRvbicsIHRydWUsIHRydWUpO1xuICAgIGRvY3VtZW50LmRpc3BhdGNoRXZlbnQoZXZlbnQpO1xuICB9XG5cbiAgX2NhbGxiYWNrKCkge1xuICAgIHRoaXMuX2Rpc3BhdGNoRGV2aWNlQmFja0J1dHRvbkV2ZW50KCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgY3JlYXRlSGFuZGxlcihlbGVtZW50LCBjYWxsYmFjaykge1xuICAgIGlmICghKGVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZWxlbWVudCBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIEhUTUxFbGVtZW50Jyk7XG4gICAgfVxuXG4gICAgaWYgKCEoY2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2FsbGJhY2sgbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBGdW5jdGlvbicpO1xuICAgIH1cblxuICAgIGNvbnN0IGhhbmRsZXIgPSB7XG4gICAgICBfY2FsbGJhY2s6IGNhbGxiYWNrLFxuICAgICAgX2VsZW1lbnQ6IGVsZW1lbnQsXG5cbiAgICAgIGRpc2FibGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICBIYW5kbGVyUmVwb3NpdG9yeS5yZW1vdmUoZWxlbWVudCk7XG4gICAgICB9LFxuXG4gICAgICBzZXRMaXN0ZW5lcjogZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5fY2FsbGJhY2sgPSBjYWxsYmFjaztcbiAgICAgIH0sXG5cbiAgICAgIGVuYWJsZTogZnVuY3Rpb24oKSB7XG4gICAgICAgIEhhbmRsZXJSZXBvc2l0b3J5LnNldChlbGVtZW50LCB0aGlzKTtcbiAgICAgIH0sXG5cbiAgICAgIGlzRW5hYmxlZDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBIYW5kbGVyUmVwb3NpdG9yeS5nZXQoZWxlbWVudCkgPT09IHRoaXM7XG4gICAgICB9LFxuXG4gICAgICBkZXN0cm95OiBmdW5jdGlvbigpIHtcbiAgICAgICAgSGFuZGxlclJlcG9zaXRvcnkucmVtb3ZlKGVsZW1lbnQpO1xuICAgICAgICB0aGlzLl9jYWxsYmFjayA9IHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBoYW5kbGVyLmVuYWJsZSgpO1xuXG4gICAgcmV0dXJuIGhhbmRsZXI7XG4gIH1cblxuICBfZGlzcGF0Y2hEZXZpY2VCYWNrQnV0dG9uRXZlbnQoKSB7XG4gICAgY29uc3QgdHJlZSA9IHRoaXMuX2NhcHR1cmVUcmVlKCk7XG5cbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fZmluZEhhbmRsZXJMZWFmRWxlbWVudCh0cmVlKTtcblxuICAgIGxldCBoYW5kbGVyID0gSGFuZGxlclJlcG9zaXRvcnkuZ2V0KGVsZW1lbnQpO1xuICAgIGhhbmRsZXIuX2NhbGxiYWNrKGNyZWF0ZUV2ZW50KGVsZW1lbnQpKTtcblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUV2ZW50KGVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIF9lbGVtZW50OiBlbGVtZW50LFxuICAgICAgICBjYWxsUGFyZW50SGFuZGxlcjogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgbGV0IHBhcmVudCA9IHRoaXMuX2VsZW1lbnQucGFyZW50Tm9kZTtcblxuICAgICAgICAgIHdoaWxlIChwYXJlbnQpIHtcbiAgICAgICAgICAgIGhhbmRsZXIgPSBIYW5kbGVyUmVwb3NpdG9yeS5nZXQocGFyZW50KTtcbiAgICAgICAgICAgIGlmIChoYW5kbGVyKSB7XG4gICAgICAgICAgICAgIHJldHVybiBoYW5kbGVyLl9jYWxsYmFjayhjcmVhdGVFdmVudChwYXJlbnQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBhcmVudCA9IHBhcmVudC5wYXJlbnROb2RlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7T2JqZWN0fVxuICAgKi9cbiAgX2NhcHR1cmVUcmVlKCkge1xuICAgIHJldHVybiBjcmVhdGVUcmVlKGRvY3VtZW50LmJvZHkpO1xuXG4gICAgZnVuY3Rpb24gY3JlYXRlVHJlZShlbGVtZW50KSB7XG4gICAgICBjb25zdCB0cmVlID0ge1xuICAgICAgICBlbGVtZW50OiBlbGVtZW50LFxuICAgICAgICBjaGlsZHJlbjogQXJyYXkucHJvdG90eXBlLmNvbmNhdC5hcHBseShbXSwgYXJyYXlPZihlbGVtZW50LmNoaWxkcmVuKS5tYXAoZnVuY3Rpb24oY2hpbGRFbGVtZW50KSB7XG5cbiAgICAgICAgICBpZiAoY2hpbGRFbGVtZW50LnN0eWxlLmRpc3BsYXkgPT09ICdub25lJyB8fCBjaGlsZEVsZW1lbnQuX2lzU2hvd24gPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGNoaWxkRWxlbWVudC5jaGlsZHJlbi5sZW5ndGggPT09IDAgJiYgIUhhbmRsZXJSZXBvc2l0b3J5LmhhcyhjaGlsZEVsZW1lbnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gY3JlYXRlVHJlZShjaGlsZEVsZW1lbnQpO1xuXG4gICAgICAgICAgaWYgKHJlc3VsdC5jaGlsZHJlbi5sZW5ndGggPT09IDAgJiYgIUhhbmRsZXJSZXBvc2l0b3J5LmhhcyhyZXN1bHQuZWxlbWVudCkpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gW3Jlc3VsdF07XG4gICAgICAgIH0pKVxuICAgICAgfTtcblxuICAgICAgaWYgKCFIYW5kbGVyUmVwb3NpdG9yeS5oYXModHJlZS5lbGVtZW50KSkge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspe1xuICAgICAgICAgIGNvbnN0IHN1YlRyZWUgPSB0cmVlLmNoaWxkcmVuW2ldO1xuICAgICAgICAgIGlmIChIYW5kbGVyUmVwb3NpdG9yeS5oYXMoc3ViVHJlZS5lbGVtZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuIHN1YlRyZWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0cmVlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFycmF5T2YodGFyZ2V0KSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGFyZ2V0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHRhcmdldFtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gdHJlZVxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIF9maW5kSGFuZGxlckxlYWZFbGVtZW50KHRyZWUpIHtcbiAgICByZXR1cm4gZmluZCh0cmVlKTtcblxuICAgIGZ1bmN0aW9uIGZpbmQobm9kZSkge1xuICAgICAgaWYgKG5vZGUuY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBub2RlLmVsZW1lbnQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChub2RlLmNoaWxkcmVuLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4gZmluZChub2RlLmNoaWxkcmVuWzBdKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5vZGUuY2hpbGRyZW4ubWFwKGZ1bmN0aW9uKGNoaWxkTm9kZSkge1xuICAgICAgICByZXR1cm4gY2hpbGROb2RlLmVsZW1lbnQ7XG4gICAgICB9KS5yZWR1Y2UoZnVuY3Rpb24obGVmdCwgcmlnaHQpIHtcbiAgICAgICAgaWYgKCFsZWZ0KSB7XG4gICAgICAgICAgcmV0dXJuIHJpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGVmdFogPSBwYXJzZUludCh3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShsZWZ0LCAnJykuekluZGV4LCAxMCk7XG4gICAgICAgIGNvbnN0IHJpZ2h0WiA9IHBhcnNlSW50KHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHJpZ2h0LCAnJykuekluZGV4LCAxMCk7XG5cbiAgICAgICAgaWYgKCFpc05hTihsZWZ0WikgJiYgIWlzTmFOKHJpZ2h0WikpIHtcbiAgICAgICAgICByZXR1cm4gbGVmdFogPiByaWdodFogPyBsZWZ0IDogcmlnaHQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhcHR1cmluZyBiYWNrYnV0dG9uLWhhbmRsZXIgaXMgZmFpbHVyZS4nKTtcbiAgICAgIH0sIG51bGwpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBuZXcgRGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIoKTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi9pbnRlcm5hbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4vYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4vbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi9kZXZpY2UtYmFjay1idXR0b24tZGlzcGF0Y2hlcic7XG5cbmludGVybmFsLkFuaW1hdG9yRmFjdG9yeSA9IEFuaW1hdG9yRmFjdG9yeTtcbmludGVybmFsLk1vZGlmaWVyVXRpbCA9IE1vZGlmaWVyVXRpbDtcbmludGVybmFsLmRiYkRpc3BhdGNoZXIgPSBkZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlcjtcblxuZXhwb3J0IGRlZmF1bHQgaW50ZXJuYWw7XG5cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxuY29uc3Qgc3RhcnRzV2l0aCA9IChzLCBjKSA9PiBzLnN1YnN0cigwLCBjLmxlbmd0aCkgPT09IGM7XG5jb25zdCBlbmRzV2l0aCA9IChzLCBjKSA9PiBzLnN1YnN0cihzLmxlbmd0aCAtIGMubGVuZ3RoLCBjLmxlbmd0aCkgPT09IGM7XG5jb25zdCB1bndyYXAgPSBzID0+IHMuc2xpY2UoMSwgLTEpO1xuY29uc3QgaXNPYmplY3RTdHJpbmcgPSBzID0+IHN0YXJ0c1dpdGgocywgJ3snKSAmJiBlbmRzV2l0aChzLCAnfScpO1xuY29uc3QgaXNBcnJheVN0cmluZyA9IHMgPT4gc3RhcnRzV2l0aChzLCAnWycpICYmIGVuZHNXaXRoKHMsICddJyk7XG5jb25zdCBpc1F1b3RlZFN0cmluZyA9IHMgPT4gKHN0YXJ0c1dpdGgocywgJ1xcJycpICYmIGVuZHNXaXRoKHMsICdcXCcnKSkgfHwgKHN0YXJ0c1dpdGgocywgJ1wiJykgJiYgZW5kc1dpdGgocywgJ1wiJykpO1xuXG5jb25zdCBlcnJvciA9ICh0b2tlbiwgc3RyaW5nLCBvcmlnaW5hbFN0cmluZykgPT4ge1xuICB0aHJvdyBuZXcgRXJyb3IoJ1VuZXhwZWN0ZWQgdG9rZW4gXFwnJyArIHRva2VuICsgJ1xcJyBhdCBwb3NpdGlvbiAnICsgKG9yaWdpbmFsU3RyaW5nLmxlbmd0aCAtIHN0cmluZy5sZW5ndGggLSAxKSArICcgaW4gc3RyaW5nOiBcXCcnICsgb3JpZ2luYWxTdHJpbmcgKyAnXFwnJyk7XG59O1xuXG5jb25zdCBwcm9jZXNzVG9rZW4gPSAodG9rZW4sIHN0cmluZywgb3JpZ2luYWxTdHJpbmcpID0+IHtcbiAgaWYgKHRva2VuID09PSAndHJ1ZScgfHwgdG9rZW4gPT09ICdmYWxzZScpIHtcbiAgICByZXR1cm4gdG9rZW4gPT09ICd0cnVlJztcbiAgfSBlbHNlIGlmIChpc1F1b3RlZFN0cmluZyh0b2tlbikpIHtcbiAgICByZXR1cm4gdW53cmFwKHRva2VuKTtcbiAgfSBlbHNlIGlmICghaXNOYU4odG9rZW4pKSB7XG4gICAgcmV0dXJuICsodG9rZW4pO1xuICB9IGVsc2UgaWYgKGlzT2JqZWN0U3RyaW5nKHRva2VuKSkge1xuICAgIHJldHVybiBwYXJzZU9iamVjdCh1bndyYXAodG9rZW4pKTtcbiAgfSBlbHNlIGlmIChpc0FycmF5U3RyaW5nKHRva2VuKSkge1xuICAgIHJldHVybiBwYXJzZUFycmF5KHVud3JhcCh0b2tlbikpO1xuICB9IGVsc2Uge1xuICAgIGVycm9yKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgfVxufTtcblxuY29uc3QgbmV4dFRva2VuID0gKHN0cmluZykgPT4ge1xuICBzdHJpbmcgPSBzdHJpbmcudHJpbSgpO1xuICBsZXQgbGltaXQgPSBzdHJpbmcubGVuZ3RoO1xuXG4gIGlmIChzdHJpbmdbMF0gPT09ICc6JyB8fCBzdHJpbmdbMF0gPT09ICcsJykge1xuXG4gICAgbGltaXQgPSAxO1xuXG4gIH0gZWxzZSBpZiAoc3RyaW5nWzBdID09PSAneycgfHwgc3RyaW5nWzBdID09PSAnWycpIHtcblxuICAgIGNvbnN0IGMgPSBzdHJpbmcuY2hhckNvZGVBdCgwKTtcbiAgICBsZXQgbmVzdGVkT2JqZWN0ID0gMTtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHN0cmluZy5jaGFyQ29kZUF0KGkpID09PSBjKSB7XG4gICAgICAgIG5lc3RlZE9iamVjdCsrO1xuICAgICAgfSBlbHNlIGlmIChzdHJpbmcuY2hhckNvZGVBdChpKSA9PT0gYyArIDIpIHtcbiAgICAgICAgbmVzdGVkT2JqZWN0LS07XG4gICAgICAgIGlmIChuZXN0ZWRPYmplY3QgPT09IDApIHtcbiAgICAgICAgICBsaW1pdCA9IGkgKyAxO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gIH0gZWxzZSBpZiAoc3RyaW5nWzBdID09PSAnXFwnJyB8fCBzdHJpbmdbMF0gPT09ICdcIicpIHtcblxuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoc3RyaW5nW2ldID09PSBzdHJpbmdbMF0pIHtcbiAgICAgICAgbGltaXQgPSBpICsgMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gIH0gZWxzZSB7XG5cbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKFsnICcsICcsJywgJzonXS5pbmRleE9mKHN0cmluZ1tpXSkgIT09IC0xKSB7XG4gICAgICAgIGxpbWl0ID0gaTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gIH1cblxuICByZXR1cm4gc3RyaW5nLnNsaWNlKDAsIGxpbWl0KTtcbn07XG5cbmNvbnN0IHBhcnNlT2JqZWN0ID0gKHN0cmluZykgPT4ge1xuICBjb25zdCBpc1ZhbGlkS2V5ID0ga2V5ID0+IC9eW0EtWl8kXVtBLVowLTlfJF0qJC9pLnRlc3Qoa2V5KTtcblxuICBzdHJpbmcgPSBzdHJpbmcudHJpbSgpO1xuICBjb25zdCBvcmlnaW5hbFN0cmluZyA9IHN0cmluZztcbiAgY29uc3Qgb2JqZWN0ID0ge307XG4gIGxldCByZWFkaW5nS2V5ID0gdHJ1ZSwga2V5LCBwcmV2aW91c1Rva2VuLCB0b2tlbjtcblxuICB3aGlsZSAoc3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICBwcmV2aW91c1Rva2VuID0gdG9rZW47XG4gICAgdG9rZW4gPSBuZXh0VG9rZW4oc3RyaW5nKTtcbiAgICBzdHJpbmcgPSBzdHJpbmcuc2xpY2UodG9rZW4ubGVuZ3RoLCBzdHJpbmcubGVuZ3RoKS50cmltKCk7XG5cbiAgICBpZiAoKHRva2VuID09PSAnOicgJiYgKCFyZWFkaW5nS2V5IHx8ICFwcmV2aW91c1Rva2VuIHx8IHByZXZpb3VzVG9rZW4gPT09ICcsJykpXG4gICAgICAgfHwgKHRva2VuID09PSAnLCcgJiYgcmVhZGluZ0tleSlcbiAgICAgICB8fCAodG9rZW4gIT09ICc6JyAmJiB0b2tlbiAhPT0gJywnICYmIChwcmV2aW91c1Rva2VuICYmIHByZXZpb3VzVG9rZW4gIT09ICcsJyAmJiBwcmV2aW91c1Rva2VuICE9PSAnOicpKSkge1xuICAgICAgZXJyb3IodG9rZW4sIHN0cmluZywgb3JpZ2luYWxTdHJpbmcpO1xuICAgIH0gZWxzZSBpZiAodG9rZW4gPT09ICc6JyAmJiByZWFkaW5nS2V5ICYmIHByZXZpb3VzVG9rZW4pIHtcbiAgICAgIHByZXZpb3VzVG9rZW4gPSBpc1F1b3RlZFN0cmluZyhwcmV2aW91c1Rva2VuKSA/IHVud3JhcChwcmV2aW91c1Rva2VuKSA6IHByZXZpb3VzVG9rZW47XG4gICAgICBpZiAoaXNWYWxpZEtleShwcmV2aW91c1Rva2VuKSkge1xuICAgICAgICBrZXkgPSBwcmV2aW91c1Rva2VuO1xuICAgICAgICByZWFkaW5nS2V5ID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQga2V5IHRva2VuIFxcJycgKyBwcmV2aW91c1Rva2VuICsgJ1xcJyBhdCBwb3NpdGlvbiAwIGluIHN0cmluZzogXFwnJyArIG9yaWdpbmFsU3RyaW5nICsgJ1xcJycpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodG9rZW4gPT09ICcsJyAmJiAhcmVhZGluZ0tleSAmJiBwcmV2aW91c1Rva2VuKSB7XG4gICAgICBvYmplY3Rba2V5XSA9IHByb2Nlc3NUb2tlbihwcmV2aW91c1Rva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgICAgIHJlYWRpbmdLZXkgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGlmICh0b2tlbikge1xuICAgIG9iamVjdFtrZXldID0gcHJvY2Vzc1Rva2VuKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgfVxuXG4gIHJldHVybiBvYmplY3Q7XG59O1xuXG5jb25zdCBwYXJzZUFycmF5ID0gKHN0cmluZykgPT4ge1xuICBzdHJpbmcgPSBzdHJpbmcudHJpbSgpO1xuICBjb25zdCBvcmlnaW5hbFN0cmluZyA9IHN0cmluZztcbiAgY29uc3QgYXJyYXkgPSBbXTtcbiAgbGV0IHByZXZpb3VzVG9rZW4sIHRva2VuO1xuXG4gIHdoaWxlIChzdHJpbmcubGVuZ3RoID4gMCkge1xuICAgIHByZXZpb3VzVG9rZW4gPSB0b2tlbjtcbiAgICB0b2tlbiA9IG5leHRUb2tlbihzdHJpbmcpO1xuICAgIHN0cmluZyA9IHN0cmluZy5zbGljZSh0b2tlbi5sZW5ndGgsIHN0cmluZy5sZW5ndGgpLnRyaW0oKTtcblxuICAgIGlmICh0b2tlbiA9PT0gJywnICYmICghcHJldmlvdXNUb2tlbiB8fCBwcmV2aW91c1Rva2VuID09PSAnLCcpKSB7XG4gICAgICBlcnJvcih0b2tlbiwgc3RyaW5nLCBvcmlnaW5hbFN0cmluZyk7XG4gICAgfSBlbHNlIGlmICh0b2tlbiA9PT0gJywnKSB7XG4gICAgICBhcnJheS5wdXNoKHByb2Nlc3NUb2tlbihwcmV2aW91c1Rva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHRva2VuKSB7XG4gICAgaWYgKHRva2VuICE9PSAnLCcpIHtcbiAgICAgIGFycmF5LnB1c2gocHJvY2Vzc1Rva2VuKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVycm9yKHRva2VuLCBzdHJpbmcsIG9yaWdpbmFsU3RyaW5nKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYXJyYXk7XG59O1xuXG5jb25zdCBwYXJzZSA9IChzdHJpbmcpID0+IHtcbiAgc3RyaW5nID0gc3RyaW5nLnRyaW0oKTtcblxuICBpZiAoaXNPYmplY3RTdHJpbmcoc3RyaW5nKSkge1xuICAgIHJldHVybiBwYXJzZU9iamVjdCh1bndyYXAoc3RyaW5nKSk7XG4gIH0gZWxzZSBpZiAoaXNBcnJheVN0cmluZyhzdHJpbmcpKSB7XG4gICAgcmV0dXJuIHBhcnNlQXJyYXkodW53cmFwKHN0cmluZykpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignUHJvdmlkZWQgc3RyaW5nIG11c3QgYmUgb2JqZWN0IG9yIGFycmF5IGxpa2U6ICcgKyBzdHJpbmcpO1xuICB9XG59O1xuXG5leHBvcnQgZGVmYXVsdCBwYXJzZTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuL2VsZW1lbnRzJztcbmltcG9ydCBzdHlsZXIgZnJvbSAnLi9zdHlsZXInO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4vaW50ZXJuYWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4vaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgYW5pbWF0aW9uT3B0aW9uc1BhcnNlIGZyb20gJy4vYW5pbWF0aW9uLW9wdGlvbnMtcGFyc2VyJztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuL3BsYXRmb3JtJztcblxuY29uc3QgdXRpbCA9IHt9O1xuY29uc3QgZXJyb3JQcmVmaXggPSAnW09uc2VuIFVJXSc7XG5cbnV0aWwuZ2xvYmFscyA9IHtcbiAgZmFiT2Zmc2V0OiAwLFxuICBlcnJvclByZWZpeCxcbiAgc3VwcG9ydHNQYXNzaXZlOiBmYWxzZVxufTtcblxucGxhdGZvcm0uX3J1bk9uQWN0dWFsUGxhdGZvcm0oKCkgPT4ge1xuICB1dGlsLmdsb2JhbHMuYWN0dWFsTW9iaWxlT1MgPSBwbGF0Zm9ybS5nZXRNb2JpbGVPUygpO1xuICB1dGlsLmdsb2JhbHMuaXNVSVdlYlZpZXcgPSBwbGF0Zm9ybS5pc1VJV2ViVmlldygpO1xuICB1dGlsLmdsb2JhbHMuaXNXS1dlYlZpZXcgPSBwbGF0Zm9ybS5pc1dLV2ViVmlldygpO1xufSk7XG5cbnRyeSB7XG4gIGNvbnN0IG9wdHMgPSBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sICdwYXNzaXZlJywge1xuICAgIGdldCgpIHsgdXRpbC5nbG9iYWxzLnN1cHBvcnRzUGFzc2l2ZSA9IHRydWU7IH1cbiAgfSk7XG4gIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCd0ZXN0UGFzc2l2ZScsIG51bGwsIG9wdHMpO1xuICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigndGVzdFBhc3NpdmUnLCBudWxsLCBvcHRzKTtcbn0gY2F0Y2ggKGUpIHsgbnVsbDsgfVxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWwgVGFyZ2V0XG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBFdmVudCBuYW1lXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyIEV2ZW50IGhhbmRsZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0XSBFdmVudCBvcHRpb25zIChwYXNzaXZlLCBjYXB0dXJlLi4uKVxuICogQHBhcmFtIHtCb29sZWFufSBbaXNHRF0gSWYgY29tZXMgZnJvbSBHZXN0dXJlRGV0ZWN0b3IuIEp1c3QgZm9yIHRlc3RpbmcuXG4gKi9cbnV0aWwuYWRkRXZlbnRMaXN0ZW5lciA9IChlbCwgbmFtZSwgaGFuZGxlciwgb3B0LCBpc0dEKSA9PiB7XG4gIGVsLmFkZEV2ZW50TGlzdGVuZXIobmFtZSwgaGFuZGxlciwgdXRpbC5nbG9iYWxzLnN1cHBvcnRzUGFzc2l2ZSA/IG9wdCA6IChvcHQgfHwge30pLmNhcHR1cmUpO1xufTtcbnV0aWwucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IChlbCwgbmFtZSwgaGFuZGxlciwgb3B0LCBpc0dEKSA9PiB7XG4gIGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIobmFtZSwgaGFuZGxlciwgdXRpbC5nbG9iYWxzLnN1cHBvcnRzUGFzc2l2ZSA/IG9wdCA6IChvcHQgfHwge30pLmNhcHR1cmUpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZy9GdW5jdGlvbn0gcXVlcnkgZG90IGNsYXNzIG5hbWUgb3Igbm9kZSBuYW1lIG9yIG1hdGNoZXIgZnVuY3Rpb24uXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAqL1xudXRpbC5wcmVwYXJlUXVlcnkgPSAocXVlcnkpID0+IHtcbiAgcmV0dXJuIHF1ZXJ5IGluc3RhbmNlb2YgRnVuY3Rpb24gPyBxdWVyeSA6IChlbGVtZW50KSA9PiB1dGlsLm1hdGNoKGVsZW1lbnQsIHF1ZXJ5KTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlXG4gKiBAcGFyYW0ge1N0cmluZy9GdW5jdGlvbn0gcyBDU1MgU2VsZWN0b3IuXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG51dGlsLm1hdGNoID0gKGUsIHMpID0+IChlLm1hdGNoZXMgfHwgZS53ZWJraXRNYXRjaGVzU2VsZWN0b3IgfHwgZS5tb3pNYXRjaGVzU2VsZWN0b3IgfHwgZS5tc01hdGNoZXNTZWxlY3RvcikuY2FsbChlLCBzKTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7U3RyaW5nL0Z1bmN0aW9ufSBxdWVyeSBkb3QgY2xhc3MgbmFtZSBvciBub2RlIG5hbWUgb3IgbWF0Y2hlciBmdW5jdGlvbi5cbiAqIEByZXR1cm4ge0hUTUxFbGVtZW50L251bGx9XG4gKi9cbnV0aWwuZmluZENoaWxkID0gKGVsZW1lbnQsIHF1ZXJ5KSA9PiB7XG4gIGNvbnN0IG1hdGNoID0gdXRpbC5wcmVwYXJlUXVlcnkocXVlcnkpO1xuXG4gIC8vIENhdXRpb246IGBlbGVtZW50LmNoaWxkcmVuYCBpcyBgdW5kZWZpbmVkYCBpbiBzb21lIGVudmlyb25tZW50cyBpZiBgZWxlbWVudGAgaXMgYHN2Z2BcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50LmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBub2RlID0gZWxlbWVudC5jaGlsZE5vZGVzW2ldO1xuICAgIGlmIChub2RlLm5vZGVUeXBlICE9PSBOb2RlLkVMRU1FTlRfTk9ERSkgeyAvLyBwcm9jZXNzIG9ubHkgZWxlbWVudCBub2Rlc1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmIChtYXRjaChub2RlKSkge1xuICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7U3RyaW5nL0Z1bmN0aW9ufSBxdWVyeSBkb3QgY2xhc3MgbmFtZSBvciBub2RlIG5hbWUgb3IgbWF0Y2hlciBmdW5jdGlvbi5cbiAqIEByZXR1cm4ge0hUTUxFbGVtZW50L251bGx9XG4gKi9cbnV0aWwuZmluZFBhcmVudCA9IChlbGVtZW50LCBxdWVyeSwgdW50aWwpID0+IHtcbiAgY29uc3QgbWF0Y2ggPSB1dGlsLnByZXBhcmVRdWVyeShxdWVyeSk7XG5cbiAgbGV0IHBhcmVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcbiAgZm9yICg7Oykge1xuICAgIGlmICghcGFyZW50IHx8IHBhcmVudCA9PT0gZG9jdW1lbnQgfHwgcGFyZW50IGluc3RhbmNlb2YgRG9jdW1lbnRGcmFnbWVudCB8fCAodW50aWwgJiYgdW50aWwocGFyZW50KSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gZWxzZSBpZiAobWF0Y2gocGFyZW50KSkge1xuICAgICAgcmV0dXJuIHBhcmVudDtcbiAgICB9XG4gICAgcGFyZW50ID0gcGFyZW50LnBhcmVudE5vZGU7XG4gIH1cbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG51dGlsLmlzQXR0YWNoZWQgPSBlbGVtZW50ID0+IGRvY3VtZW50LmJvZHkuY29udGFpbnMoZWxlbWVudCk7XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJuIHtib29sZWFufVxuICovXG51dGlsLmhhc0FueUNvbXBvbmVudEFzUGFyZW50ID0gKGVsZW1lbnQpID0+IHtcbiAgd2hpbGUgKGVsZW1lbnQgJiYgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50ICE9PSBlbGVtZW50KSB7XG4gICAgZWxlbWVudCA9IGVsZW1lbnQucGFyZW50Tm9kZTtcbiAgICBpZiAoZWxlbWVudCAmJiBlbGVtZW50Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkubWF0Y2goLyhvbnMtbmF2aWdhdG9yfG9ucy10YWJiYXJ8b25zLW1vZGFsKS8pKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge09iamVjdH0gZWxlbWVudFxuICogQHJldHVybiB7QXJyYXl9XG4gKi9cbnV0aWwuZ2V0QWxsQ2hpbGROb2RlcyA9IChlbGVtZW50KSA9PiB7XG4gIHJldHVybiBbZWxlbWVudF0uY29uY2F0KFxuICAgIC4uLkFycmF5LmZyb20oZWxlbWVudC5jaGlsZHJlbikubWFwKGNoaWxkRWwgPT4ge1xuICAgICAgcmV0dXJuIHV0aWwuZ2V0QWxsQ2hpbGROb2RlcyhjaGlsZEVsKTtcbiAgICB9KVxuICApO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xudXRpbC5pc1BhZ2VDb250cm9sID0gZWxlbWVudCA9PiBlbGVtZW50Lm5vZGVOYW1lLm1hdGNoKC9eb25zLShuYXZpZ2F0b3J8c3BsaXR0ZXJ8dGFiYmFyfHBhZ2UpJC9pKTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBwYXJhbSB7U3RyaW5nfSBhY3Rpb24gdG8gcHJvcGFnYXRlXG4gKi9cbnV0aWwucHJvcGFnYXRlQWN0aW9uID0gKGVsZW1lbnQsIGFjdGlvbikgPT4ge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnQuY2hpbGROb2Rlcy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGNoaWxkID0gZWxlbWVudC5jaGlsZE5vZGVzW2ldO1xuICAgIGlmIChjaGlsZFthY3Rpb25dIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIGNoaWxkW2FjdGlvbl0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24oY2hpbGQsIGFjdGlvbik7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHJpbmcgLSBzdHJpbmcgdG8gYmUgY2FtZWxpemVkXG4gKiBAcmV0dXJuIHtTdHJpbmd9IENhbWVsaXplZCBzdHJpbmdcbiAqL1xudXRpbC5jYW1lbGl6ZSA9IHN0cmluZyA9PiBzdHJpbmcudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC8tKFthLXpdKS9nLCAobSwgbCkgPT4gbC50b1VwcGVyQ2FzZSgpKTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyaW5nIC0gc3RyaW5nIHRvIGJlIGh5cGhlbmF0ZWRcbiAqIEByZXR1cm4ge1N0cmluZ30gSHlwaGVuYXRlZCBzdHJpbmdcbiAqL1xudXRpbC5oeXBoZW5hdGUgPSBzdHJpbmcgPT4gc3RyaW5nLnJlcGxhY2UoLyhbYS16QS1aXSkoW0EtWl0pL2csICckMS0kMicpLnRvTG93ZXJDYXNlKCk7XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHNlbGVjdG9yIC0gdGFnIGFuZCBjbGFzcyBvbmx5XG4gKiBAcGFyYW0ge09iamVjdH0gc3R5bGVcbiAqIEBwYXJhbSB7RWxlbWVudH1cbiAqL1xudXRpbC5jcmVhdGUgPSAoc2VsZWN0b3IgPSAnJywgc3R5bGUgPSB7fSkgPT4ge1xuICBjb25zdCBjbGFzc0xpc3QgPSBzZWxlY3Rvci5zcGxpdCgnLicpO1xuICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChjbGFzc0xpc3Quc2hpZnQoKSB8fCAnZGl2Jyk7XG5cbiAgaWYgKGNsYXNzTGlzdC5sZW5ndGgpIHtcbiAgICBlbGVtZW50LmNsYXNzTmFtZSA9IGNsYXNzTGlzdC5qb2luKCcgJyk7XG4gIH1cblxuICBzdHlsZXIoZWxlbWVudCwgc3R5bGUpO1xuXG4gIHJldHVybiBlbGVtZW50O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gaHRtbFxuICogQHJldHVybiB7RWxlbWVudH1cbiAqL1xudXRpbC5jcmVhdGVFbGVtZW50ID0gKGh0bWwpID0+IHtcbiAgY29uc3Qgd3JhcHBlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gIGlmIChodG1sIGluc3RhbmNlb2YgRG9jdW1lbnRGcmFnbWVudCkge1xuICAgIHdyYXBwZXIuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuaW1wb3J0Tm9kZShodG1sLCB0cnVlKSk7XG4gIH0gZWxzZSB7XG4gICAgd3JhcHBlci5pbm5lckhUTUwgPSBodG1sLnRyaW0oKTtcbiAgfVxuXG4gIGlmICh3cmFwcGVyLmNoaWxkcmVuLmxlbmd0aCA+IDEpIHtcbiAgICB1dGlsLnRocm93KCdIVE1MIHRlbXBsYXRlIG11c3QgY29udGFpbiBhIHNpbmdsZSByb290IGVsZW1lbnQnKVxuICB9XG5cbiAgY29uc3QgZWxlbWVudCA9IHdyYXBwZXIuY2hpbGRyZW5bMF07XG4gIHdyYXBwZXIuY2hpbGRyZW5bMF0ucmVtb3ZlKCk7XG4gIHJldHVybiBlbGVtZW50O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge1N0cmluZ30gaHRtbFxuICogQHJldHVybiB7SFRNTEZyYWdtZW50fVxuICovXG51dGlsLmNyZWF0ZUZyYWdtZW50ID0gKGh0bWwpID0+IHtcbiAgY29uc3QgdGVtcGxhdGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0ZW1wbGF0ZScpO1xuICB0ZW1wbGF0ZS5pbm5lckhUTUwgPSBodG1sO1xuICByZXR1cm4gZG9jdW1lbnQuaW1wb3J0Tm9kZSh0ZW1wbGF0ZS5jb250ZW50LCB0cnVlKTtcbn07XG5cbi8qXG4gKiBAcGFyYW0ge09iamVjdH0gZHN0IERlc3RpbmF0aW9uIG9iamVjdC5cbiAqIEBwYXJhbSB7Li4uT2JqZWN0fSBzcmMgU291cmNlIG9iamVjdChzKS5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJlZmVyZW5jZSB0byBgZHN0YC5cbiAqL1xudXRpbC5leHRlbmQgPSAoZHN0LCAuLi5hcmdzKSA9PiB7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChhcmdzW2ldKSB7XG4gICAgICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoYXJnc1tpXSk7XG4gICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGtleXMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgY29uc3Qga2V5ID0ga2V5c1tqXTtcbiAgICAgICAgZHN0W2tleV0gPSBhcmdzW2ldW2tleV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGRzdDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtPYmplY3R9IGFycmF5TGlrZVxuICogQHJldHVybiB7QXJyYXl9XG4gKi9cbnV0aWwuYXJyYXlGcm9tID0gKGFycmF5TGlrZSkgPT4ge1xuICByZXR1cm4gQXJyYXkucHJvdG90eXBlLnNsaWNlLmFwcGx5KGFycmF5TGlrZSk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfSBqc29uU3RyaW5nXG4gKiBAcGFyYW0ge09iamVjdH0gW2ZhaWxTYWZlXVxuICogQHJldHVybiB7T2JqZWN0fVxuICovXG51dGlsLnBhcnNlSlNPTk9iamVjdFNhZmVseSA9IChqc29uU3RyaW5nLCBmYWlsU2FmZSA9IHt9KSA9PiB7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzdWx0ID0gSlNPTi5wYXJzZSgnJyArIGpzb25TdHJpbmcpO1xuICAgIGlmICh0eXBlb2YgcmVzdWx0ID09PSAnb2JqZWN0JyAmJiByZXN1bHQgIT09IG51bGwpIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhaWxTYWZlO1xuICB9XG4gIHJldHVybiBmYWlsU2FmZTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhdGggLSBwYXRoIHN1Y2ggYXMgJ215QXBwLmNvbnRyb2xsZXJzLmRhdGEubG9hZERhdGEnXG4gKiBAcmV0dXJuIHtBbnl9IC0gd2hhdGV2ZXIgaXMgbG9jYXRlZCBhdCB0aGF0IHBhdGhcbiAqL1xudXRpbC5maW5kRnJvbVBhdGggPSAocGF0aCkgPT4ge1xuICBwYXRoID0gcGF0aC5zcGxpdCgnLicpO1xuICB2YXIgZWwgPSB3aW5kb3csIGtleTtcbiAgd2hpbGUgKGtleSA9IHBhdGguc2hpZnQoKSkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbmQtYXNzaWduXG4gICAgZWwgPSBlbFtrZXldO1xuICB9XG4gIHJldHVybiBlbDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gY29udGFpbmVyIC0gUGFnZSBvciBwYWdlLWNvbnRhaW5lciB0aGF0IGltcGxlbWVudHMgJ3RvcFBhZ2UnXG4gKiBAcmV0dXJuIHtIVE1MRWxlbWVudHxudWxsfSAtIFZpc2libGUgcGFnZSBlbGVtZW50IG9yIG51bGwgaWYgbm90IGZvdW5kLlxuICovXG51dGlsLmdldFRvcFBhZ2UgPSBjb250YWluZXIgPT4gY29udGFpbmVyICYmIChjb250YWluZXIudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnb25zLXBhZ2UnID8gY29udGFpbmVyIDogY29udGFpbmVyLnRvcFBhZ2UpIHx8IG51bGw7XG5cbi8qKlxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gY29udGFpbmVyIC0gRWxlbWVudCB3aGVyZSB0aGUgc2VhcmNoIGJlZ2luc1xuICogQHJldHVybiB7SFRNTEVsZW1lbnR8bnVsbH0gLSBQYWdlIGVsZW1lbnQgdGhhdCBjb250YWlucyB0aGUgdmlzaWJsZSB0b29sYmFyIG9yIG51bGwuXG4gKi9cbnV0aWwuZmluZFRvb2xiYXJQYWdlID0gY29udGFpbmVyID0+IHtcbiAgY29uc3QgcGFnZSA9IHV0aWwuZ2V0VG9wUGFnZShjb250YWluZXIpO1xuXG4gIGlmIChwYWdlKSB7XG4gICAgaWYgKHBhZ2UuX2NhbkFuaW1hdGVUb29sYmFyKCkpIHtcbiAgICAgIHJldHVybiBwYWdlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFnZS5fY29udGVudEVsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IG5leHRQYWdlID0gdXRpbC5nZXRUb3BQYWdlKHBhZ2UuX2NvbnRlbnRFbGVtZW50LmNoaWxkcmVuW2ldKTtcbiAgICAgIGlmIChuZXh0UGFnZSAmJiAhL29ucy10YWJiYXIvaS50ZXN0KHBhZ2UuX2NvbnRlbnRFbGVtZW50LmNoaWxkcmVuW2ldLnRhZ05hbWUpKSB7XG4gICAgICAgIHJldHVybiB1dGlsLmZpbmRUb29sYmFyUGFnZShuZXh0UGFnZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gZWxlbWVudFxuICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtIHtPYmplY3R9IFtkZXRhaWxdXG4gKiBAcmV0dXJuIHtDdXN0b21FdmVudH1cbiAqL1xudXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50ID0gKHRhcmdldCwgZXZlbnROYW1lLCBkZXRhaWwgPSB7fSkgPT4ge1xuXG4gIGNvbnN0IGV2ZW50ID0gbmV3IEN1c3RvbUV2ZW50KGV2ZW50TmFtZSwge1xuICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgY2FuY2VsYWJsZTogdHJ1ZSxcbiAgICBkZXRhaWw6IGRldGFpbFxuICB9KTtcblxuICBPYmplY3Qua2V5cyhkZXRhaWwpLmZvckVhY2goa2V5ID0+IHtcbiAgICBldmVudFtrZXldID0gZGV0YWlsW2tleV07XG4gIH0pO1xuXG4gIHRhcmdldC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcblxuICByZXR1cm4gZXZlbnQ7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gdGFyZ2V0XG4gKiBAcGFyYW0ge1N0cmluZ30gbW9kaWZpZXJOYW1lXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG51dGlsLmhhc01vZGlmaWVyID0gKHRhcmdldCwgbW9kaWZpZXJOYW1lKSA9PiB7XG4gIGlmICghdGFyZ2V0Lmhhc0F0dHJpYnV0ZSgnbW9kaWZpZXInKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiBSZWdFeHAoYChefFxcXFxzKykke21vZGlmaWVyTmFtZX0oJHxcXFxccyspYCwgJ2knKS50ZXN0KHRhcmdldC5nZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJykpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IHRhcmdldFxuICogQHBhcmFtIHtTdHJpbmd9IG1vZGlmaWVyTmFtZVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMuYXV0b1N0eWxlIE1hcHMgdGhlIG1vZGlmaWVyTmFtZSB0byB0aGUgY29ycmVzcG9uZGluZyBzdHlsZWQgbW9kaWZpZXIuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucy5mb3JjZUF1dG9TdHlsZSBJZ25vcmVzIHBsYXRmb3JtIGxpbWl0YXRpb24uXG4gKiBAcmV0dXJuIHtCb29sZWFufSBXaGV0aGVyIGl0IHdhcyBhZGRlZCBvciBub3QuXG4gKi9cbnV0aWwuYWRkTW9kaWZpZXIgPSAodGFyZ2V0LCBtb2RpZmllck5hbWUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICBpZiAob3B0aW9ucy5hdXRvU3R5bGUpIHtcbiAgICBtb2RpZmllck5hbWUgPSBhdXRvU3R5bGUubWFwTW9kaWZpZXIobW9kaWZpZXJOYW1lLCB0YXJnZXQsIG9wdGlvbnMuZm9yY2VBdXRvU3R5bGUpO1xuICB9XG5cbiAgaWYgKHV0aWwuaGFzTW9kaWZpZXIodGFyZ2V0LCBtb2RpZmllck5hbWUpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdGFyZ2V0LnNldEF0dHJpYnV0ZSgnbW9kaWZpZXInLCAoKHRhcmdldC5nZXRBdHRyaWJ1dGUoJ21vZGlmaWVyJykgfHwgJycpICsgJyAnICsgbW9kaWZpZXJOYW1lKS50cmltKCkpO1xuICByZXR1cm4gdHJ1ZTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtFbGVtZW50fSB0YXJnZXRcbiAqIEBwYXJhbSB7U3RyaW5nfSBtb2RpZmllck5hbWVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLmF1dG9TdHlsZSBNYXBzIHRoZSBtb2RpZmllck5hbWUgdG8gdGhlIGNvcnJlc3BvbmRpbmcgc3R5bGVkIG1vZGlmaWVyLlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMuZm9yY2VBdXRvU3R5bGUgSWdub3JlcyBwbGF0Zm9ybSBsaW1pdGF0aW9uLlxuICogQHJldHVybiB7Qm9vbGVhbn0gV2hldGhlciBpdCB3YXMgZm91bmQgb3Igbm90LlxuICovXG51dGlsLnJlbW92ZU1vZGlmaWVyID0gKHRhcmdldCwgbW9kaWZpZXJOYW1lLCBvcHRpb25zID0ge30pID0+IHtcbiAgaWYgKG9wdGlvbnMuYXV0b1N0eWxlKSB7XG4gICAgbW9kaWZpZXJOYW1lID0gYXV0b1N0eWxlLm1hcE1vZGlmaWVyKG1vZGlmaWVyTmFtZSwgdGFyZ2V0LCBvcHRpb25zLmZvcmNlQXV0b1N0eWxlKTtcbiAgfVxuXG4gIGlmICghdGFyZ2V0LmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSB8fCAhdXRpbC5oYXNNb2RpZmllcih0YXJnZXQsIG1vZGlmaWVyTmFtZSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBuZXdNb2RpZmllcnMgPSB0YXJnZXQuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpLnNwbGl0KC9cXHMrLykuZmlsdGVyKG0gPT4gbSAmJiBtICE9PSBtb2RpZmllck5hbWUpO1xuICBuZXdNb2RpZmllcnMubGVuZ3RoID8gdGFyZ2V0LnNldEF0dHJpYnV0ZSgnbW9kaWZpZXInLCBuZXdNb2RpZmllcnMuam9pbignICcpKSA6IHRhcmdldC5yZW1vdmVBdHRyaWJ1dGUoJ21vZGlmaWVyJyk7XG4gIHJldHVybiB0cnVlO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IHRhcmdldFxuICogQHBhcmFtIHtTdHJpbmd9IG1vZGlmaWVyTmFtZVxuICogQHBhcmFtIHtCb29sZWFufSBvcHRpb25zLmZvcmNlIEZvcmNlcyBtb2RpZmllciB0byBiZSBhZGRlZCBvciByZW1vdmVkLlxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMuYXV0b1N0eWxlIE1hcHMgdGhlIG1vZGlmaWVyTmFtZSB0byB0aGUgY29ycmVzcG9uZGluZyBzdHlsZWQgbW9kaWZpZXIuXG4gKiBAcGFyYW0ge0Jvb2xlYW59IG9wdGlvbnMuZm9yY2VBdXRvU3R5bGUgSWdub3JlcyBwbGF0Zm9ybSBsaW1pdGF0aW9uLlxuICogQHJldHVybiB7Qm9vbGVhbn0gV2hldGhlciBpdCB3YXMgZm91bmQgb3Igbm90LlxuICovXG51dGlsLnRvZ2dsZU1vZGlmaWVyID0gKC4uLmFyZ3MpID0+IHtcbiAgY29uc3Qgb3B0aW9ucyA9IGFyZ3MubGVuZ3RoID4gMiA/IGFyZ3NbMl0gOiB7fTtcbiAgY29uc3QgZm9yY2UgPSB0eXBlb2Ygb3B0aW9ucyA9PT0gJ2Jvb2xlYW4nID8gb3B0aW9ucyA6IG9wdGlvbnMuZm9yY2U7XG5cbiAgY29uc3QgdG9nZ2xlID0gdHlwZW9mIGZvcmNlID09PSAnYm9vbGVhbicgPyBmb3JjZSA6ICF1dGlsLmhhc01vZGlmaWVyKC4uLmFyZ3MpO1xuICB0b2dnbGUgPyB1dGlsLmFkZE1vZGlmaWVyKC4uLmFyZ3MpIDogdXRpbC5yZW1vdmVNb2RpZmllciguLi5hcmdzKVxufTtcblxuLyoqXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsXG4gKiBAcGFyYW0ge1N0cmluZ30gZGVmYXVsdENsYXNzXG4gKiBAcGFyYW0ge09iamVjdH0gc2NoZW1lXG4gKi9cbnV0aWwucmVzdG9yZUNsYXNzID0gKGVsLCBkZWZhdWx0Q2xhc3MsIHNjaGVtZSkgPT4ge1xuICBkZWZhdWx0Q2xhc3Muc3BsaXQoL1xccysvKS5mb3JFYWNoKGMgPT4gYyAhPT0gJycgJiYgIWVsLmNsYXNzTGlzdC5jb250YWlucyhjKSAmJiBlbC5jbGFzc0xpc3QuYWRkKGMpKTtcbiAgZWwuaGFzQXR0cmlidXRlKCdtb2RpZmllcicpICYmIE1vZGlmaWVyVXRpbC5yZWZyZXNoKGVsLCBzY2hlbWUpO1xufVxuXG4vLyBUT0RPOiBGSVhcbnV0aWwudXBkYXRlUGFyZW50UG9zaXRpb24gPSAoZWwpID0+IHtcbiAgaWYgKCFlbC5fcGFyZW50VXBkYXRlZCAmJiBlbC5wYXJlbnRFbGVtZW50KSB7XG4gICAgaWYgKHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsLnBhcmVudEVsZW1lbnQpLmdldFByb3BlcnR5VmFsdWUoJ3Bvc2l0aW9uJykgPT09ICdzdGF0aWMnKSB7XG4gICAgICBlbC5wYXJlbnRFbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICB9XG4gICAgZWwuX3BhcmVudFVwZGF0ZWQgPSB0cnVlO1xuICB9XG59O1xuXG51dGlsLnRvZ2dsZUF0dHJpYnV0ZSA9IChlbGVtZW50LCBuYW1lLCB2YWx1ZSkgPT4ge1xuICBpZiAodmFsdWUpIHtcbiAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShuYW1lLCB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJyA/ICcnIDogdmFsdWUpO1xuICB9IGVsc2Uge1xuICAgIGVsZW1lbnQucmVtb3ZlQXR0cmlidXRlKG5hbWUpO1xuICB9XG59O1xuXG51dGlsLmJpbmRMaXN0ZW5lcnMgPSAoZWxlbWVudCwgbGlzdGVuZXJOYW1lcykgPT4ge1xuICBsaXN0ZW5lck5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgY29uc3QgYm91bmROYW1lID0gbmFtZS5yZXBsYWNlKC9eX1thLXpdLywgJ19ib3VuZCcgKyBuYW1lWzFdLnRvVXBwZXJDYXNlKCkpO1xuICAgIGVsZW1lbnRbYm91bmROYW1lXSA9IGVsZW1lbnRbYm91bmROYW1lXSB8fCBlbGVtZW50W25hbWVdLmJpbmQoZWxlbWVudCk7XG4gIH0pO1xufTtcblxudXRpbC5lYWNoID0gKG9iaiwgZikgPT4gT2JqZWN0LmtleXMob2JqKS5mb3JFYWNoKGtleSA9PiBmKGtleSwgb2JqW2tleV0pKTtcblxuXG4vKipcbiAqIEBwYXJhbSB7RWxlbWVudH0gdGFyZ2V0XG4gKiBAcGFyYW0ge2Jvb2xlYW59IGhhc1JpcHBsZVxuICogQHBhcmFtIHtPYmplY3R9IGF0dHJzXG4gKi9cbnV0aWwudXBkYXRlUmlwcGxlID0gKHRhcmdldCwgaGFzUmlwcGxlLCBhdHRycyA9IHt9KSA9PiB7XG4gIGlmIChoYXNSaXBwbGUgPT09IHVuZGVmaW5lZCkge1xuICAgIGhhc1JpcHBsZSA9IHRhcmdldC5oYXNBdHRyaWJ1dGUoJ3JpcHBsZScpO1xuICB9XG5cbiAgY29uc3QgcmlwcGxlRWxlbWVudCA9IHV0aWwuZmluZENoaWxkKHRhcmdldCwgJ29ucy1yaXBwbGUnKTtcblxuICBpZiAoaGFzUmlwcGxlKSB7XG4gICAgaWYgKCFyaXBwbGVFbGVtZW50KSB7XG4gICAgICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnb25zLXJpcHBsZScpO1xuICAgICAgT2JqZWN0LmtleXMoYXR0cnMpLmZvckVhY2goa2V5ID0+IGVsZW1lbnQuc2V0QXR0cmlidXRlKGtleSwgYXR0cnNba2V5XSkpO1xuICAgICAgdGFyZ2V0Lmluc2VydEJlZm9yZShlbGVtZW50LCB0YXJnZXQuZmlyc3RDaGlsZCk7XG4gICAgfVxuICB9IGVsc2UgaWYgKHJpcHBsZUVsZW1lbnQpIHtcbiAgICByaXBwbGVFbGVtZW50LnJlbW92ZSgpO1xuICB9XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7U3RyaW5nfVxuICogQHJldHVybiB7T2JqZWN0fVxuICovXG51dGlsLmFuaW1hdGlvbk9wdGlvbnNQYXJzZSA9IGFuaW1hdGlvbk9wdGlvbnNQYXJzZTtcblxuLyoqXG4gKiBAcGFyYW0geyp9IHZhbHVlXG4gKi9cbnV0aWwuaXNJbnRlZ2VyID0gKHZhbHVlKSA9PiB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmXG4gICAgaXNGaW5pdGUodmFsdWUpICYmXG4gICAgTWF0aC5mbG9vcih2YWx1ZSkgPT09IHZhbHVlO1xufTtcblxuLyoqXG4gKiBAcmV0dXJuIHtPYmplY3R9IERlZmVycmVkIHByb21pc2UuXG4gKi9cbnV0aWwuZGVmZXIgPSAoKSA9PiB7XG4gIGNvbnN0IGRlZmVycmVkID0ge307XG4gIGRlZmVycmVkLnByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgZGVmZXJyZWQucmVzb2x2ZSA9IHJlc29sdmU7XG4gICAgZGVmZXJyZWQucmVqZWN0ID0gcmVqZWN0O1xuICB9KTtcbiAgcmV0dXJuIGRlZmVycmVkO1xufTtcblxuLyoqXG4gKiBTaG93IHdhcm5pbmdzIHdoZW4gdGhleSBhcmUgZW5hYmxlZC5cbiAqXG4gKiBAcGFyYW0geyp9IGFyZ3VtZW50cyB0byBjb25zb2xlLndhcm5cbiAqL1xudXRpbC53YXJuID0gKC4uLmFyZ3MpID0+IHtcbiAgaWYgKCFpbnRlcm5hbC5jb25maWcud2FybmluZ3NEaXNhYmxlZCkge1xuICAgIGNvbnNvbGUud2FybihlcnJvclByZWZpeCwgLi4uYXJncyk7XG4gIH1cbn07XG5cbnV0aWwudGhyb3cgPSAobWVzc2FnZSkgPT4ge1xuICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXJyb3JQcmVmaXh9ICR7bWVzc2FnZX1gKTtcbn07XG5cbnV0aWwudGhyb3dBYnN0cmFjdCA9ICgpID0+IHV0aWwudGhyb3coJ0Nhbm5vdCBpbnN0YW50aWF0ZSBhYnN0cmFjdCBjbGFzcycpO1xudXRpbC50aHJvd01lbWJlciA9ICgpID0+IHV0aWwudGhyb3coJ0NsYXNzIG1lbWJlciBtdXN0IGJlIGltcGxlbWVudGVkJyk7XG51dGlsLnRocm93UGFnZUxvYWRlciA9ICgpID0+IHV0aWwudGhyb3coJ0ZpcnN0IHBhcmFtZXRlciBzaG91bGQgYmUgYW4gaW5zdGFuY2Ugb2YgUGFnZUxvYWRlcicpO1xudXRpbC50aHJvd0FuaW1hdG9yID0gKGVsKSA9PiB1dGlsLnRocm93KGBcIkFuaW1hdG9yXCIgcGFyYW0gbXVzdCBpbmhlcml0ICR7ZWx9QW5pbWF0b3JgKTtcblxuXG5jb25zdCBwcmV2ZW50ID0gZSA9PiBlLmNhbmNlbGFibGUgJiYgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4vKipcbiAqIFByZXZlbnQgc2Nyb2xsaW5nIHdoaWxlIGRyYWdpbmcgaG9yaXpvbnRhbGx5IG9uIGlPUy5cbiAqXG4gKiBAcGFyYW0ge2dkfSBHZXN0dXJlRGV0ZWN0b3IgaW5zdGFuY2VcbiAqL1xudXRpbC5pb3NQcmV2ZW50U2Nyb2xsID0gZ2QgPT4ge1xuICBpZiAodXRpbC5nbG9iYWxzLmFjdHVhbE1vYmlsZU9TID09PSAnaW9zJykge1xuICAgIGNvbnN0IGNsZWFuID0gKGUpID0+IHtcbiAgICAgIGdkLm9mZigndG91Y2htb3ZlJywgcHJldmVudCk7XG4gICAgICBnZC5vZmYoJ2RyYWdlbmQnLCBjbGVhbik7XG4gICAgfTtcblxuICAgIGdkLm9uKCd0b3VjaG1vdmUnLCBwcmV2ZW50KTtcbiAgICBnZC5vbignZHJhZ2VuZCcsIGNsZWFuKTtcbiAgfVxufTtcblxuLyoqXG4gKiBQcmV2ZW50cyBzY3JvbGwgaW4gdW5kZXJseWluZyBwYWdlcyBvbiBpT1MuIFNlZSAjMjIyMCAjMjI3NCAjMTk0OVxuICpcbiAqIEBwYXJhbSB7ZWx9IEhUTUxFbGVtZW50IHRoYXQgcHJldmVudHMgdGhlIGV2ZW50c1xuICogQHBhcmFtIHthZGR9IEJvb2xlYW4gQWRkIG9yIHJlbW92ZSBldmVudCBsaXN0ZW5lcnNcbiAqL1xudXRpbC5pb3NQYWdlU2Nyb2xsRml4ID0gKGFkZCkgPT4geyAvLyBGdWxsIGZpeCAtIE1heSBjYXVzZSBpc3N1ZXMgd2l0aCBVSVdlYlZpZXcncyBtb21lbnR1bSBzY3JvbGxcbiAgaWYgKHV0aWwuZ2xvYmFscy5hY3R1YWxNb2JpbGVPUyA9PT0gJ2lvcycpIHtcbiAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC50b2dnbGUoJ29ucy1pb3Mtc2Nyb2xsJywgYWRkKTsgLy8gQWxsb3dzIGN1c3RvbSBhbmQgbG9jYWxpemVkIGZpeGVzICgjMjI3NClcbiAgICBpZiAoIXV0aWwuZ2xvYmFscy5pc1VJV2ViVmlldyB8fCBpbnRlcm5hbC5jb25maWcuZm9yY2VVSVdlYlZpZXdTY3JvbGxGaXgpIHtcbiAgICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnRvZ2dsZSgnb25zLWlvcy1zY3JvbGwtZml4JywgYWRkKTtcbiAgICB9XG4gIH1cbn07XG51dGlsLmlvc01hc2tTY3JvbGxGaXggPSAoZWwsIGFkZCkgPT4geyAvLyBIYWxmIGZpeCAtIG9ubHkgcHJldmVudHMgc2Nyb2xsIG9uIG1hc2tzXG4gIGlmICh1dGlsLmdsb2JhbHMuaXNVSVdlYlZpZXcpIHtcbiAgICBjb25zdCBhY3Rpb24gPSAoYWRkID8gJ2FkZCcgOiAncmVtb3ZlJykgKyAnRXZlbnRMaXN0ZW5lcic7XG4gICAgZWxbYWN0aW9uXSgndG91Y2htb3ZlJywgcHJldmVudCwgZmFsc2UpO1xuICB9XG59O1xuXG4vKipcbiAqIERpc3RhbmNlIGFuZCBkZWx0YVRpbWUgZmlsdGVyIHNvbWUgd2VpcmQgZHJhZ3N0YXJ0IGV2ZW50cyB0aGF0IGFyZSBub3QgZmlyZWQgaW1tZWRpYXRlbHkuXG4gKlxuICogQHBhcmFtIHtldmVudH1cbiAqL1xudXRpbC5pc1ZhbGlkR2VzdHVyZSA9IGV2ZW50ID0+IGV2ZW50Lmdlc3R1cmUgIT09IHVuZGVmaW5lZCAmJiAoZXZlbnQuZ2VzdHVyZS5kaXN0YW5jZSA8PSAxNSB8fCBldmVudC5nZXN0dXJlLmRlbHRhVGltZSA8PSAxMDApO1xuXG51dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCA9ICguLi5lbGVtZW50TmFtZXMpID0+IHtcbiAgZWxlbWVudE5hbWVzLmZvckVhY2gobmFtZSA9PiB7XG4gICAgaWYgKCFvbnNFbGVtZW50c1tuYW1lXSkge1xuICAgICAgdXRpbC50aHJvdyhgT25zJHtuYW1lfSBpcyByZXF1aXJlZCBidXQgd2FzIG5vdCBpbXBvcnRlZCAoQ3VzdG9tIEVsZW1lbnRzKWApO1xuICAgIH1cbiAgfSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHV0aWw7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5cbi8qKlxuICogTWluaW1hbCBhbmltYXRpb24gbGlicmFyeSBmb3IgbWFuYWdpbmcgY3NzIHRyYW5zaXRpb24gb24gbW9iaWxlIGJyb3dzZXJzLlxuICovXG4ndXNlIHN0cmljdCc7XG5cbnZhciBUSU1FT1VUX1JBVElPID0gMS40O1xuXG52YXIgdXRpbCA9IHtcbn07XG5cbi8vIGNhcGl0YWxpemUgc3RyaW5nXG51dGlsLmNhcGl0YWxpemUgPSBmdW5jdGlvbihzdHIpIHtcbiAgcmV0dXJuIHN0ci5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIHN0ci5zbGljZSgxKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtPYmplY3R9IHBhcmFtc1xuICogQHBhcmFtIHtTdHJpbmd9IHBhcmFtcy5wcm9wZXJ0eVxuICogQHBhcmFtIHtGbG9hdH0gcGFyYW1zLmR1cmF0aW9uXG4gKiBAcGFyYW0ge1N0cmluZ30gcGFyYW1zLnRpbWluZ1xuICovXG51dGlsLmJ1aWxkVHJhbnNpdGlvblZhbHVlID0gZnVuY3Rpb24ocGFyYW1zKSB7XG4gIHBhcmFtcy5wcm9wZXJ0eSA9IHBhcmFtcy5wcm9wZXJ0eSB8fCAnYWxsJztcbiAgcGFyYW1zLmR1cmF0aW9uID0gcGFyYW1zLmR1cmF0aW9uIHx8IDAuNDtcbiAgcGFyYW1zLnRpbWluZyA9IHBhcmFtcy50aW1pbmcgfHwgJ2xpbmVhcic7XG5cbiAgdmFyIHByb3BzID0gcGFyYW1zLnByb3BlcnR5LnNwbGl0KC8gKy8pO1xuXG4gIHJldHVybiBwcm9wcy5tYXAoZnVuY3Rpb24ocHJvcCkge1xuICAgIHJldHVybiBwcm9wICsgJyAnICsgcGFyYW1zLmR1cmF0aW9uICsgJ3MgJyArIHBhcmFtcy50aW1pbmc7XG4gIH0pLmpvaW4oJywgJyk7XG59O1xuXG4vKipcbiAqIEFkZCBhbiBldmVudCBoYW5kbGVyIG9uIFwidHJhbnNpdGlvbmVuZFwiIGV2ZW50LlxuICovXG51dGlsLm9uY2VPblRyYW5zaXRpb25FbmQgPSBmdW5jdGlvbihlbGVtZW50LCBjYWxsYmFjaykge1xuICBpZiAoIWVsZW1lbnQpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7fTtcbiAgfVxuXG4gIHZhciBmbiA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgaWYgKGVsZW1lbnQgPT0gZXZlbnQudGFyZ2V0KSB7XG4gICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIHJlbW92ZUxpc3RlbmVycygpO1xuXG4gICAgICBjYWxsYmFjaygpO1xuICAgIH1cbiAgfTtcblxuICB2YXIgcmVtb3ZlTGlzdGVuZXJzID0gZnVuY3Rpb24oKSB7XG4gICAgdXRpbC5fdHJhbnNpdGlvbkVuZEV2ZW50cy5mb3JFYWNoKGZ1bmN0aW9uKGV2ZW50TmFtZSkge1xuICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZm4sIGZhbHNlKTtcbiAgICB9KTtcbiAgfTtcblxuICB1dGlsLl90cmFuc2l0aW9uRW5kRXZlbnRzLmZvckVhY2goZnVuY3Rpb24oZXZlbnROYW1lKSB7XG4gICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZm4sIGZhbHNlKTtcbiAgfSk7XG5cbiAgcmV0dXJuIHJlbW92ZUxpc3RlbmVycztcbn07XG5cbnV0aWwuX3RyYW5zaXRpb25FbmRFdmVudHMgPSAoZnVuY3Rpb24oKSB7XG5cbiAgaWYgKCdvbnRyYW5zaXRpb25lbmQnIGluIHdpbmRvdykge1xuICAgIHJldHVybiBbJ3RyYW5zaXRpb25lbmQnXTtcbiAgfVxuXG4gIGlmICgnb253ZWJraXR0cmFuc2l0aW9uZW5kJyBpbiB3aW5kb3cpIHtcbiAgICByZXR1cm4gWyd3ZWJraXRUcmFuc2l0aW9uRW5kJ107XG4gIH1cblxuICBpZiAodXRpbC52ZW5kb3JQcmVmaXggPT09ICd3ZWJraXQnIHx8IHV0aWwudmVuZG9yUHJlZml4ID09PSAnbycgfHwgdXRpbC52ZW5kb3JQcmVmaXggPT09ICdtb3onIHx8IHV0aWwudmVuZG9yUHJlZml4ID09PSAnbXMnKSB7XG4gICAgcmV0dXJuIFt1dGlsLnZlbmRvclByZWZpeCArICdUcmFuc2l0aW9uRW5kJywgJ3RyYW5zaXRpb25lbmQnXTtcbiAgfVxuXG4gIHJldHVybiBbXTtcbn0pKCk7XG5cbnV0aWwuX2Nzc1Byb3BlcnR5RGljdCA9IChmdW5jdGlvbigpIHtcbiAgdmFyIHN0eWxlcyA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCwgJycpO1xuICB2YXIgZGljdCA9IHt9O1xuICB2YXIgYSA9ICdBJy5jaGFyQ29kZUF0KDApO1xuICB2YXIgeiA9ICd6Jy5jaGFyQ29kZUF0KDApO1xuXG4gIHZhciB1cHBlciA9IGZ1bmN0aW9uKHMpIHtcbiAgICByZXR1cm4gcy5zdWJzdHIoMSkudG9VcHBlckNhc2UoKTtcbiAgfTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0eWxlcy5sZW5ndGg7IGkrKykge1xuXG4gICAgdmFyIGtleSA9IHN0eWxlc1tpXVxuICAgIC5yZXBsYWNlKC9eWy1dKy8sICcnKVxuICAgIC5yZXBsYWNlKC9bLV1bYS16XS9nLCB1cHBlcilcbiAgICAucmVwbGFjZSgvXm1vei8sICdNb3onKTtcblxuICAgIGlmIChhIDw9IGtleS5jaGFyQ29kZUF0KDApICYmIHogPj0ga2V5LmNoYXJDb2RlQXQoMCkpIHtcbiAgICAgIGlmIChrZXkgIT09ICdjc3NUZXh0JyAmJiBrZXkgIT09ICdwYXJlbnRUZXh0Jykge1xuICAgICAgICBkaWN0W2tleV0gPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkaWN0O1xufSkoKTtcblxudXRpbC5oYXNDc3NQcm9wZXJ0eSA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgcmV0dXJuIG5hbWUgaW4gdXRpbC5fY3NzUHJvcGVydHlEaWN0O1xufTtcblxuLyoqXG4gKiBWZW5kb3IgcHJlZml4IGZvciBjc3MgcHJvcGVydHkuXG4gKi9cbnV0aWwudmVuZG9yUHJlZml4ID0gKGZ1bmN0aW9uKCkge1xuICB2YXIgc3R5bGVzID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCAnJyksXG4gICAgcHJlID0gKEFycmF5LnByb3RvdHlwZS5zbGljZVxuICAgICAgLmNhbGwoc3R5bGVzKVxuICAgICAgLmpvaW4oJycpXG4gICAgICAubWF0Y2goLy0obW96fHdlYmtpdHxtcyktLykgfHwgKHN0eWxlcy5PTGluayA9PT0gJycgJiYgWycnLCAnbyddKVxuICAgIClbMV07XG4gICAgcmV0dXJuIHByZTtcbn0pKCk7XG5cbnV0aWwuZm9yY2VMYXlvdXRBdE9uY2UgPSBmdW5jdGlvbihlbGVtZW50cywgY2FsbGJhY2spIHtcbiAgdGhpcy5iYXRjaEltbWVkaWF0ZShmdW5jdGlvbigpIHtcbiAgICBlbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uKGVsZW1lbnQpIHtcbiAgICAgIC8vIGZvcmNlIGxheW91dFxuICAgICAgZWxlbWVudC5vZmZzZXRIZWlnaHQ7XG4gICAgfSk7XG4gICAgY2FsbGJhY2soKTtcbiAgfSk7XG59O1xuXG51dGlsLmJhdGNoSW1tZWRpYXRlID0gKGZ1bmN0aW9uKCkge1xuICB2YXIgY2FsbGJhY2tzID0gW107XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHNldEltbWVkaWF0ZShmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNvbmNyZWF0ZUNhbGxiYWNrcyA9IGNhbGxiYWNrcy5zbGljZSgwKTtcbiAgICAgICAgY2FsbGJhY2tzID0gW107XG4gICAgICAgIGNvbmNyZWF0ZUNhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjYWxsYmFja3MucHVzaChjYWxsYmFjayk7XG4gIH07XG59KSgpO1xuXG51dGlsLmJhdGNoQW5pbWF0aW9uRnJhbWUgPSAoZnVuY3Rpb24oKSB7XG4gIHZhciBjYWxsYmFja3MgPSBbXTtcblxuICB2YXIgcmFmID0gd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSB8fFxuICAgIHdpbmRvdy53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lIHx8XG4gICAgd2luZG93Lm9SZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICB3aW5kb3cubXNSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgIHNldFRpbWVvdXQoY2FsbGJhY2ssIDEwMDAgLyA2MCk7XG4gIH07XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKGNhbGxiYWNrcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJhZihmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGNvbmNyZWF0ZUNhbGxiYWNrcyA9IGNhbGxiYWNrcy5zbGljZSgwKTtcbiAgICAgICAgY2FsbGJhY2tzID0gW107XG4gICAgICAgIGNvbmNyZWF0ZUNhbGxiYWNrcy5mb3JFYWNoKGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjYWxsYmFja3MucHVzaChjYWxsYmFjayk7XG4gIH07XG59KSgpO1xuXG51dGlsLnRyYW5zaXRpb25Qcm9wZXJ0eU5hbWUgPSAoZnVuY3Rpb24oKSB7XG4gIGlmICh1dGlsLmhhc0Nzc1Byb3BlcnR5KCd0cmFuc2l0aW9uRHVyYXRpb24nKSkge1xuICAgIHJldHVybiAndHJhbnNpdGlvbic7XG4gIH1cblxuICBpZiAodXRpbC5oYXNDc3NQcm9wZXJ0eSh1dGlsLnZlbmRvclByZWZpeCArICdUcmFuc2l0aW9uRHVyYXRpb24nKSkge1xuICAgIHJldHVybiB1dGlsLnZlbmRvclByZWZpeCArICdUcmFuc2l0aW9uJztcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzdGF0ZScpO1xufSkoKTtcblxuXG4vKipcbiAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAqL1xudmFyIEFuaW1pdCA9IGZ1bmN0aW9uKGVsZW1lbnQsIGRlZmF1bHRzKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBBbmltaXQpKSB7XG4gICAgcmV0dXJuIG5ldyBBbmltaXQoZWxlbWVudCwgZGVmYXVsdHMpO1xuICB9XG5cbiAgaWYgKGVsZW1lbnQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkge1xuICAgIHRoaXMuZWxlbWVudHMgPSBbZWxlbWVudF07XG4gIH0gZWxzZSBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGVsZW1lbnQpID09PSAnW29iamVjdCBBcnJheV0nKSB7XG4gICAgdGhpcy5lbGVtZW50cyA9IGVsZW1lbnQ7XG5cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYW4gYXJyYXkgb3IgYW4gaW5zdGFuY2Ugb2YgSFRNTEVsZW1lbnQuJyk7XG4gIH1cblxuICB0aGlzLmRlZmF1bHRzID0gZGVmYXVsdHM7XG4gIHRoaXMudHJhbnNpdGlvblF1ZXVlID0gW107XG4gIHRoaXMubGFzdFN0eWxlQXR0cmlidXRlRGljdCA9IFtdO1xufTtcblxuQW5pbWl0LnByb3RvdHlwZSA9IHtcblxuICAvKipcbiAgICogQHByb3BlcnR5IHtBcnJheX1cbiAgICovXG4gIHRyYW5zaXRpb25RdWV1ZTogdW5kZWZpbmVkLFxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkge0FycmF5fVxuICAgKi9cbiAgZWxlbWVudHM6IHVuZGVmaW5lZCxcblxuICAvKipcbiAgICogQHByb3BlcnR5IHtPYmplY3R9XG4gICAqL1xuICBkZWZhdWx0czogdW5kZWZpbmVkLFxuXG4gIC8qKlxuICAgKiBTdGFydCBhbmltYXRpb24gc2VxdWVuY2Ugd2l0aCBwYXNzZWQgYW5pbWF0aW9ucy5cbiAgICpcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHBsYXk6IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhpcy50cmFuc2l0aW9uUXVldWUucHVzaChmdW5jdGlvbihkb25lKSB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMuc3RhcnRBbmltYXRpb24oKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuXG4gIC8qKlxuICAgKiBNb3N0IG9mIHRoZSBhbmltYXRpb25zIGZvbGxvdyB0aGlzIGRlZmF1bHQgcHJvY2Vzcy5cbiAgICpcbiAgICogQHBhcmFtIHtmcm9tfSBjc3Mgb3Igb3B0aW9ucyBvYmplY3QgY29udGFpbmluZyBjc3NcbiAgICogQHBhcmFtIHt0b30gY3NzIG9yIG9wdGlvbnMgb2JqZWN0IGNvbnRhaW5pbmcgY3NzXG4gICAqIEBwYXJhbSB7ZGVsYXl9IGRlbGF5IHRvIHdhaXRcbiAgICovXG4gIGRlZmF1bHQ6IGZ1bmN0aW9uKGZyb20sIHRvLCBkZWxheSkge1xuICAgIGZ1bmN0aW9uIHN0ZXAocGFyYW1zLCBkdXJhdGlvbiwgdGltaW5nKSB7XG4gICAgICBpZiAocGFyYW1zLmR1cmF0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZHVyYXRpb24gPSBwYXJhbXMuZHVyYXRpb247XG4gICAgICB9XG4gICAgICBpZiAocGFyYW1zLnRpbWluZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRpbWluZyA9IHBhcmFtcy50aW1pbmc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNzczogcGFyYW1zLmNzcyB8fCBwYXJhbXMsXG4gICAgICAgIGR1cmF0aW9uOiBkdXJhdGlvbixcbiAgICAgICAgdGltaW5nOiB0aW1pbmdcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc2F2ZVN0eWxlKClcbiAgICAgIC5xdWV1ZShzdGVwKGZyb20sIDAsIHRoaXMuZGVmYXVsdHMudGltaW5nKSlcbiAgICAgIC53YWl0KGRlbGF5ID09PSB1bmRlZmluZWQgPyB0aGlzLmRlZmF1bHRzLmRlbGF5IDogZGVsYXkpXG4gICAgICAucXVldWUoc3RlcCh0bywgdGhpcy5kZWZhdWx0cy5kdXJhdGlvbiwgdGhpcy5kZWZhdWx0cy50aW1pbmcpKVxuICAgICAgLnJlc3RvcmVTdHlsZSgpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBRdWV1ZSB0cmFuc2l0aW9uIGFuaW1hdGlvbnMgb3Igb3RoZXIgZnVuY3Rpb24uXG4gICAqXG4gICAqIGUuZy4gYW5pbWl0KGVsdCkucXVldWUoe2NvbG9yOiAncmVkJ30pXG4gICAqIGUuZy4gYW5pbWl0KGVsdCkucXVldWUoe2NvbG9yOiAncmVkJ30sIHtkdXJhdGlvbjogMC40fSlcbiAgICogZS5nLiBhbmltaXQoZWx0KS5xdWV1ZSh7Y3NzOiB7Y29sb3I6ICdyZWQnfSwgZHVyYXRpb246IDAuMn0pXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fEFuaW1pdC5UcmFuc2l0aW9ufEZ1bmN0aW9ufSB0cmFuc2l0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICovXG4gIHF1ZXVlOiBmdW5jdGlvbih0cmFuc2l0aW9uLCBvcHRpb25zKSB7XG4gICAgdmFyIHF1ZXVlID0gdGhpcy50cmFuc2l0aW9uUXVldWU7XG5cbiAgICBpZiAodHJhbnNpdGlvbiAmJiBvcHRpb25zKSB7XG4gICAgICBvcHRpb25zLmNzcyA9IHRyYW5zaXRpb247XG4gICAgICB0cmFuc2l0aW9uID0gbmV3IEFuaW1pdC5UcmFuc2l0aW9uKG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGlmICghKHRyYW5zaXRpb24gaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCB0cmFuc2l0aW9uIGluc3RhbmNlb2YgQW5pbWl0LlRyYW5zaXRpb24pKSB7XG4gICAgICBpZiAodHJhbnNpdGlvbi5jc3MpIHtcbiAgICAgICAgdHJhbnNpdGlvbiA9IG5ldyBBbmltaXQuVHJhbnNpdGlvbih0cmFuc2l0aW9uKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRyYW5zaXRpb24gPSBuZXcgQW5pbWl0LlRyYW5zaXRpb24oe1xuICAgICAgICAgIGNzczogdHJhbnNpdGlvblxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAodHJhbnNpdGlvbiBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICBxdWV1ZS5wdXNoKHRyYW5zaXRpb24pO1xuICAgIH0gZWxzZSBpZiAodHJhbnNpdGlvbiBpbnN0YW5jZW9mIEFuaW1pdC5UcmFuc2l0aW9uKSB7XG4gICAgICBxdWV1ZS5wdXNoKHRyYW5zaXRpb24uYnVpbGQoKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBhcmd1bWVudHMnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICAvKipcbiAgICogUXVldWUgdHJhbnNpdGlvbiBhbmltYXRpb25zLlxuICAgKlxuICAgKiBAcGFyYW0ge0Zsb2F0fSBzZWNvbmRzXG4gICAqL1xuICB3YWl0OiBmdW5jdGlvbihzZWNvbmRzKSB7XG4gICAgaWYgKHNlY29uZHMgPiAwKSB7XG4gICAgICB0aGlzLnRyYW5zaXRpb25RdWV1ZS5wdXNoKGZ1bmN0aW9uKGRvbmUpIHtcbiAgICAgICAgc2V0VGltZW91dChkb25lLCAxMDAwICogc2Vjb25kcyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICBzYXZlU3R5bGU6IGZ1bmN0aW9uKCkge1xuXG4gICAgdGhpcy50cmFuc2l0aW9uUXVldWUucHVzaChmdW5jdGlvbihkb25lKSB7XG4gICAgICB0aGlzLmVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCwgaW5kZXgpIHtcbiAgICAgICAgdmFyIGNzcyA9IHRoaXMubGFzdFN0eWxlQXR0cmlidXRlRGljdFtpbmRleF0gPSB7fTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsZW1lbnQuc3R5bGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBjc3NbZWxlbWVudC5zdHlsZVtpXV0gPSBlbGVtZW50LnN0eWxlW2VsZW1lbnQuc3R5bGVbaV1dO1xuICAgICAgICB9XG4gICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgZG9uZSgpO1xuICAgIH0uYmluZCh0aGlzKSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICAvKipcbiAgICogUmVzdG9yZSBlbGVtZW50J3Mgc3R5bGUuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogQHBhcmFtIHtGbG9hdH0gW29wdGlvbnMuZHVyYXRpb25dXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy50aW1pbmddXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy50cmFuc2l0aW9uXVxuICAgKi9cbiAgcmVzdG9yZVN0eWxlOiBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgaWYgKG9wdGlvbnMudHJhbnNpdGlvbiAmJiAhb3B0aW9ucy5kdXJhdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdcIm9wdGlvbnMuZHVyYXRpb25cIiBpcyByZXF1aXJlZCB3aGVuIFwib3B0aW9ucy50cmFuc2l0aW9uXCIgaXMgZW5hYmxlZC4nKTtcbiAgICB9XG5cbiAgICB2YXIgdHJhbnNpdGlvbk5hbWUgPSB1dGlsLnRyYW5zaXRpb25Qcm9wZXJ0eU5hbWU7XG5cbiAgICBpZiAob3B0aW9ucy50cmFuc2l0aW9uIHx8IChvcHRpb25zLmR1cmF0aW9uICYmIG9wdGlvbnMuZHVyYXRpb24gPiAwKSkge1xuICAgICAgdmFyIHRyYW5zaXRpb25WYWx1ZSA9IG9wdGlvbnMudHJhbnNpdGlvbiB8fCAoJ2FsbCAnICsgb3B0aW9ucy5kdXJhdGlvbiArICdzICcgKyAob3B0aW9ucy50aW1pbmcgfHwgJ2xpbmVhcicpKTtcblxuICAgICAgdGhpcy50cmFuc2l0aW9uUXVldWUucHVzaChmdW5jdGlvbihkb25lKSB7XG4gICAgICAgIHZhciBlbGVtZW50cyA9IHRoaXMuZWxlbWVudHM7XG4gICAgICAgIHZhciB0aW1lb3V0SWQ7XG5cbiAgICAgICAgdmFyIGNsZWFyVHJhbnNpdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICAgICAgZWxlbWVudC5zdHlsZVt0cmFuc2l0aW9uTmFtZV0gPSAnJztcbiAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBhZGQgXCJ0cmFuc2l0aW9uZW5kXCIgZXZlbnQgaGFuZGxlclxuICAgICAgICB2YXIgcmVtb3ZlTGlzdGVuZXJzID0gdXRpbC5vbmNlT25UcmFuc2l0aW9uRW5kKGVsZW1lbnRzWzBdLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgICAgICBjbGVhclRyYW5zaXRpb24oKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIGZvciBmYWlsIHNhZmUuXG4gICAgICAgIHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmVtb3ZlTGlzdGVuZXJzKCk7XG4gICAgICAgICAgY2xlYXJUcmFuc2l0aW9uKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9LCBvcHRpb25zLmR1cmF0aW9uICogMTAwMCAqIFRJTUVPVVRfUkFUSU8pO1xuXG4gICAgICAgIC8vIHRyYW5zaXRpb24gYW5kIHN0eWxlIHNldHRpbmdzXG4gICAgICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCwgaW5kZXgpIHtcblxuICAgICAgICAgIHZhciBjc3MgPSBzZWxmLmxhc3RTdHlsZUF0dHJpYnV0ZURpY3RbaW5kZXhdO1xuXG4gICAgICAgICAgaWYgKCFjc3MpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncmVzdG9yZVN0eWxlKCk6IFRoZSBzdHlsZSBpcyBub3Qgc2F2ZWQuIEludm9rZSBzYXZlU3R5bGUoKSBiZWZvcmUuJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc2VsZi5sYXN0U3R5bGVBdHRyaWJ1dGVEaWN0W2luZGV4XSA9IHVuZGVmaW5lZDtcblxuICAgICAgICAgIHZhciBuYW1lO1xuICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBlbGVtZW50LnN0eWxlLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBuYW1lID0gZWxlbWVudC5zdHlsZVtpXTtcbiAgICAgICAgICAgIGlmIChjc3NbbmFtZV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICBjc3NbbmFtZV0gPSAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBlbGVtZW50LnN0eWxlW3RyYW5zaXRpb25OYW1lXSA9IHRyYW5zaXRpb25WYWx1ZTtcblxuICAgICAgICAgIE9iamVjdC5rZXlzKGNzcykuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgIGlmIChrZXkgIT09IHRyYW5zaXRpb25OYW1lKSB7XG4gICAgICAgICAgICAgIGVsZW1lbnQuc3R5bGVba2V5XSA9IGNzc1trZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgZWxlbWVudC5zdHlsZVt0cmFuc2l0aW9uTmFtZV0gPSB0cmFuc2l0aW9uVmFsdWU7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudHJhbnNpdGlvblF1ZXVlLnB1c2goZnVuY3Rpb24oZG9uZSkge1xuICAgICAgICByZXNldCgpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcblxuICAgIGZ1bmN0aW9uIHJlc2V0KCkge1xuICAgICAgLy8gQ2xlYXIgdHJhbnNpdGlvbiBhbmltYXRpb24gc2V0dGluZ3MuXG4gICAgICBzZWxmLmVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCwgaW5kZXgpIHtcbiAgICAgICAgZWxlbWVudC5zdHlsZVt0cmFuc2l0aW9uTmFtZV0gPSAnbm9uZSc7XG5cbiAgICAgICAgdmFyIGNzcyA9IHNlbGYubGFzdFN0eWxlQXR0cmlidXRlRGljdFtpbmRleF07XG5cbiAgICAgICAgaWYgKCFjc3MpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Jlc3RvcmVTdHlsZSgpOiBUaGUgc3R5bGUgaXMgbm90IHNhdmVkLiBJbnZva2Ugc2F2ZVN0eWxlKCkgYmVmb3JlLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2VsZi5sYXN0U3R5bGVBdHRyaWJ1dGVEaWN0W2luZGV4XSA9IHVuZGVmaW5lZDtcblxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbmFtZSA9ICcnOyBpIDwgZWxlbWVudC5zdHlsZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIG5hbWUgPSBlbGVtZW50LnN0eWxlW2ldO1xuICAgICAgICAgIGlmICh0eXBlb2YgY3NzW2VsZW1lbnQuc3R5bGVbaV1dID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgY3NzW2VsZW1lbnQuc3R5bGVbaV1dID0gJyc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgT2JqZWN0LmtleXMoY3NzKS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgICAgICAgIGVsZW1lbnQuc3R5bGVba2V5XSA9IGNzc1trZXldO1xuICAgICAgICB9KTtcblxuICAgICAgfSk7XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBTdGFydCBhbmltYXRpb24gc2VxdWVuY2UuXG4gICAqL1xuICBzdGFydEFuaW1hdGlvbjogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fZGVxdWV1ZVRyYW5zaXRpb24oKTtcblxuICAgIHJldHVybiB0aGlzO1xuICB9LFxuXG4gIF9kZXF1ZXVlVHJhbnNpdGlvbjogZnVuY3Rpb24oKSB7XG4gICAgdmFyIHRyYW5zaXRpb24gPSB0aGlzLnRyYW5zaXRpb25RdWV1ZS5zaGlmdCgpO1xuICAgIGlmICh0aGlzLl9jdXJyZW50VHJhbnNpdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDdXJyZW50IHRyYW5zaXRpb24gZXhpc3RzLicpO1xuICAgIH1cbiAgICB0aGlzLl9jdXJyZW50VHJhbnNpdGlvbiA9IHRyYW5zaXRpb247XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBjYWxsZWQgPSBmYWxzZTtcblxuICAgIHZhciBkb25lID0gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoIWNhbGxlZCkge1xuICAgICAgICBjYWxsZWQgPSB0cnVlO1xuICAgICAgICBzZWxmLl9jdXJyZW50VHJhbnNpdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgc2VsZi5fZGVxdWV1ZVRyYW5zaXRpb24oKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzdGF0ZTogVGhpcyBjYWxsYmFjayBpcyBjYWxsZWQgdHdpY2UuJyk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGlmICh0cmFuc2l0aW9uKSB7XG4gICAgICB0cmFuc2l0aW9uLmNhbGwodGhpcywgZG9uZSk7XG4gICAgfVxuICB9XG5cbn07XG5cbi8qKlxuICogQHBhcmFtIHtBbmltaXR9IGFyZ3VtZW50c1xuICovXG5BbmltaXQucnVuQWxsID0gZnVuY3Rpb24oLyogYXJndW1lbnRzLi4uICovKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgYXJndW1lbnRzW2ldLnBsYXkoKTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAcGFyYW0ge0Zsb2F0fSBbb3B0aW9ucy5kdXJhdGlvbl1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wcm9wZXJ0eV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy50aW1pbmddXG4gKi9cbkFuaW1pdC5UcmFuc2l0aW9uID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB0aGlzLm9wdGlvbnMuZHVyYXRpb24gPSB0aGlzLm9wdGlvbnMuZHVyYXRpb24gfHwgMDtcbiAgdGhpcy5vcHRpb25zLnRpbWluZyA9IHRoaXMub3B0aW9ucy50aW1pbmcgfHwgJ2xpbmVhcic7XG4gIHRoaXMub3B0aW9ucy5jc3MgPSB0aGlzLm9wdGlvbnMuY3NzIHx8IHt9O1xuICB0aGlzLm9wdGlvbnMucHJvcGVydHkgPSB0aGlzLm9wdGlvbnMucHJvcGVydHkgfHwgJ2FsbCc7XG59O1xuXG5BbmltaXQuVHJhbnNpdGlvbi5wcm90b3R5cGUgPSB7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHJldHVybiB7RnVuY3Rpb259XG4gICAqL1xuICBidWlsZDogZnVuY3Rpb24oKSB7XG5cbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5vcHRpb25zLmNzcykubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ29wdGlvbnMuY3NzIGlzIHJlcXVpcmVkLicpO1xuICAgIH1cblxuICAgIHZhciBjc3MgPSBjcmVhdGVBY3R1YWxDc3NQcm9wcyh0aGlzLm9wdGlvbnMuY3NzKTtcblxuICAgIGlmICh0aGlzLm9wdGlvbnMuZHVyYXRpb24gPiAwKSB7XG4gICAgICB2YXIgdHJhbnNpdGlvblZhbHVlID0gdXRpbC5idWlsZFRyYW5zaXRpb25WYWx1ZSh0aGlzLm9wdGlvbnMpO1xuICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGVsZW1lbnRzID0gdGhpcy5lbGVtZW50cztcbiAgICAgICAgdmFyIHRpbWVvdXQgPSBzZWxmLm9wdGlvbnMuZHVyYXRpb24gKiAxMDAwICogVElNRU9VVF9SQVRJTztcbiAgICAgICAgdmFyIHRpbWVvdXRJZDtcblxuICAgICAgICB2YXIgcmVtb3ZlTGlzdGVuZXJzID0gdXRpbC5vbmNlT25UcmFuc2l0aW9uRW5kKGVsZW1lbnRzWzBdLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aW1lb3V0SWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHJlbW92ZUxpc3RlbmVycygpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIH0sIHRpbWVvdXQpO1xuXG4gICAgICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICAgIGVsZW1lbnQuc3R5bGVbdXRpbC50cmFuc2l0aW9uUHJvcGVydHlOYW1lXSA9IHRyYW5zaXRpb25WYWx1ZTtcblxuICAgICAgICAgIE9iamVjdC5rZXlzKGNzcykuZm9yRWFjaChmdW5jdGlvbihuYW1lKSB7XG4gICAgICAgICAgICBlbGVtZW50LnN0eWxlW25hbWVdID0gY3NzW25hbWVdO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgfTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmR1cmF0aW9uIDw9IDApIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgICAgICB2YXIgZWxlbWVudHMgPSB0aGlzLmVsZW1lbnRzO1xuXG4gICAgICAgIGVsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgICAgIGVsZW1lbnQuc3R5bGVbdXRpbC50cmFuc2l0aW9uUHJvcGVydHlOYW1lXSA9ICcnO1xuXG4gICAgICAgICAgT2JqZWN0LmtleXMoY3NzKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc3R5bGVbbmFtZV0gPSBjc3NbbmFtZV07XG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChlbGVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdXRpbC5mb3JjZUxheW91dEF0T25jZShlbGVtZW50cywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB1dGlsLmJhdGNoQW5pbWF0aW9uRnJhbWUoY2FsbGJhY2spO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHV0aWwuYmF0Y2hBbmltYXRpb25GcmFtZShjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlQWN0dWFsQ3NzUHJvcHMoY3NzKSB7XG4gICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgIE9iamVjdC5rZXlzKGNzcykuZm9yRWFjaChmdW5jdGlvbihuYW1lKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGNzc1tuYW1lXTtcblxuICAgICAgICBpZiAodXRpbC5oYXNDc3NQcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICAgIHJlc3VsdFtuYW1lXSA9IHZhbHVlO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwcmVmaXhlZCA9IHV0aWwudmVuZG9yUHJlZml4ICsgdXRpbC5jYXBpdGFsaXplKG5hbWUpO1xuICAgICAgICBpZiAodXRpbC5oYXNDc3NQcm9wZXJ0eShwcmVmaXhlZCkpIHtcbiAgICAgICAgICByZXN1bHRbcHJlZml4ZWRdID0gdmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVzdWx0W3ByZWZpeGVkXSA9IHZhbHVlO1xuICAgICAgICAgIHJlc3VsdFtuYW1lXSA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgfVxufTtcblxuZXhwb3J0IGRlZmF1bHQgQW5pbWl0O1xuXG4iLCIvKlxuICogR2VzdHVyZSBkZXRlY3RvciBsaWJyYXJ5IHRoYXQgZm9ya2VkIGZyb20gZ2l0aHViLmNvbS9FaWdodE1lZGlhL2hhbW1lci5qcy5cbiAqL1xuXG4ndXNlIHN0cmljdCc7XG5cbmltcG9ydCB1dGlsIGZyb20gJy4vdXRpbCc7XG5cbnZhciBFdmVudCwgVXRpbHMsIERldGVjdGlvbiwgUG9pbnRlckV2ZW50O1xuXG4vKipcbiAqIEBvYmplY3Qgb25zLkdlc3R1cmVEZXRlY3RvclxuICogQGNhdGVnb3J5IGdlc3R1cmVcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dVXRpbGl0eSBjbGFzcyBmb3IgZ2VzdHVyZSBkZXRlY3Rpb24uWy9lbl1cbiAqICAgW2phXeOCuOOCp+OCueODgeODo+OCkuaknOefpeOBmeOCi+OBn+OCgeOBruODpuODvOODhuOCo+ODquODhuOCo+OCr+ODqeOCueOBp+OBmeOAglsvamFdXG4gKi9cblxuLyoqXG4gKiBAbWV0aG9kIGNvbnN0cnVjdG9yXG4gKiBAc2lnbmF0dXJlIGNvbnN0cnVjdG9yKGVsZW1lbnRbLCBvcHRpb25zXSlcbiAqIEBkZXNjcmlwdGlvblxuICogIFtlbl1DcmVhdGUgYSBuZXcgR2VzdHVyZURldGVjdG9yIGluc3RhbmNlLlsvZW5dXG4gKiAgW2phXUdlc3R1cmVEZXRlY3RvcuOBruOCpOODs+OCueOCv+ODs+OCueOCkueUn+aIkOOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAqICAgW2VuXU5hbWUgb2YgdGhlIGV2ZW50LlsvZW5dXG4gKiAgIFtqYV3jgrjjgqfjgrnjg4Hjg6PjgpLmpJznn6XjgZnjgotET03opoHntKDjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogICBbZW5dT3B0aW9ucyBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcmV0dXJuIHtvbnMuR2VzdHVyZURldGVjdG9yLkluc3RhbmNlfVxuICovXG52YXIgR2VzdHVyZURldGVjdG9yID0gZnVuY3Rpb24gR2VzdHVyZURldGVjdG9yKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIG5ldyBHZXN0dXJlRGV0ZWN0b3IuSW5zdGFuY2UoZWxlbWVudCwgb3B0aW9ucyB8fCB7fSk7XG59O1xuXG5cbi8qKlxuICogZGVmYXVsdCBzZXR0aW5ncy5cbiAqIG1vcmUgc2V0dGluZ3MgYXJlIGRlZmluZWQgcGVyIGdlc3R1cmUgYXQgYC9nZXN0dXJlc2AuIEVhY2ggZ2VzdHVyZSBjYW4gYmUgZGlzYWJsZWQvZW5hYmxlZFxuICogYnkgc2V0dGluZyBpdCdzIG5hbWUgKGxpa2UgYHN3aXBlYCkgdG8gZmFsc2UuXG4gKiBZb3UgY2FuIHNldCB0aGUgZGVmYXVsdHMgZm9yIGFsbCBpbnN0YW5jZXMgYnkgY2hhbmdpbmcgdGhpcyBvYmplY3QgYmVmb3JlIGNyZWF0aW5nIGFuIGluc3RhbmNlLlxuICogQGV4YW1wbGVcbiAqIGBgYGBcbiAqICBHZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHMuZHJhZyA9IGZhbHNlO1xuICogIEdlc3R1cmVEZXRlY3Rvci5kZWZhdWx0cy5iZWhhdmlvci50b3VjaEFjdGlvbiA9ICdwYW4teSc7XG4gKiAgZGVsZXRlIEdlc3R1cmVEZXRlY3Rvci5kZWZhdWx0cy5iZWhhdmlvci51c2VyU2VsZWN0O1xuICogYGBgYFxuICogQHByb3BlcnR5IGRlZmF1bHRzXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5HZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHMgPSB7XG4gIGJlaGF2aW9yOiB7XG4gICAgLy8gdXNlclNlbGVjdDogJ25vbmUnLCAvLyBBbHNvIGRpc2FibGVzIHNlbGVjdGlvbiBpbiBgaW5wdXRgIGNoaWxkcmVuXG4gICAgdG91Y2hBY3Rpb246ICdwYW4teScsXG4gICAgdG91Y2hDYWxsb3V0OiAnbm9uZScsXG4gICAgY29udGVudFpvb21pbmc6ICdub25lJyxcbiAgICB1c2VyRHJhZzogJ25vbmUnLFxuICAgIHRhcEhpZ2hsaWdodENvbG9yOiAncmdiYSgwLDAsMCwwKSdcbiAgfVxufTtcblxuLyoqXG4gKiBHZXN0dXJlRGV0ZWN0b3IgZG9jdW1lbnQgd2hlcmUgdGhlIGJhc2UgZXZlbnRzIGFyZSBhZGRlZCBhdFxuICogQHByb3BlcnR5IERPQ1VNRU5UXG4gKiBAdHlwZSB7SFRNTEVsZW1lbnR9XG4gKiBAZGVmYXVsdCB3aW5kb3cuZG9jdW1lbnRcbiAqL1xuR2VzdHVyZURldGVjdG9yLkRPQ1VNRU5UID0gZG9jdW1lbnQ7XG5cbi8qKlxuICogZGV0ZWN0IHN1cHBvcnQgZm9yIHBvaW50ZXIgZXZlbnRzXG4gKiBAcHJvcGVydHkgSEFTX1BPSU5URVJFVkVOVFNcbiAqIEB0eXBlIHtCb29sZWFufVxuICovXG5HZXN0dXJlRGV0ZWN0b3IuSEFTX1BPSU5URVJFVkVOVFMgPSBuYXZpZ2F0b3IucG9pbnRlckVuYWJsZWQgfHwgbmF2aWdhdG9yLm1zUG9pbnRlckVuYWJsZWQ7XG5cbi8qKlxuICogZGV0ZWN0IHN1cHBvcnQgZm9yIHRvdWNoIGV2ZW50c1xuICogQHByb3BlcnR5IEhBU19UT1VDSEVWRU5UU1xuICogQHR5cGUge0Jvb2xlYW59XG4gKi9cbkdlc3R1cmVEZXRlY3Rvci5IQVNfVE9VQ0hFVkVOVFMgPSAoJ29udG91Y2hzdGFydCcgaW4gd2luZG93KTtcblxuLyoqXG4gKiBkZXRlY3QgbW9iaWxlIGJyb3dzZXJzXG4gKiBAcHJvcGVydHkgSVNfTU9CSUxFXG4gKiBAdHlwZSB7Qm9vbGVhbn1cbiAqL1xuR2VzdHVyZURldGVjdG9yLklTX01PQklMRSA9IC9tb2JpbGV8dGFibGV0fGlwKGFkfGhvbmV8b2QpfGFuZHJvaWR8c2lsay9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG5cbi8qKlxuICogZGV0ZWN0IGlmIHdlIHdhbnQgdG8gc3VwcG9ydCBtb3VzZWV2ZW50cyBhdCBhbGxcbiAqIEBwcm9wZXJ0eSBOT19NT1VTRUVWRU5UU1xuICogQHR5cGUge0Jvb2xlYW59XG4gKi9cbkdlc3R1cmVEZXRlY3Rvci5OT19NT1VTRUVWRU5UUyA9IChHZXN0dXJlRGV0ZWN0b3IuSEFTX1RPVUNIRVZFTlRTICYmIEdlc3R1cmVEZXRlY3Rvci5JU19NT0JJTEUpIHx8IEdlc3R1cmVEZXRlY3Rvci5IQVNfUE9JTlRFUkVWRU5UUztcblxuLyoqXG4gKiBpbnRlcnZhbCBpbiB3aGljaCBHZXN0dXJlRGV0ZWN0b3IgcmVjYWxjdWxhdGVzIGN1cnJlbnQgdmVsb2NpdHkvZGlyZWN0aW9uL2FuZ2xlIGluIG1zXG4gKiBAcHJvcGVydHkgQ0FMQ1VMQVRFX0lOVEVSVkFMXG4gKiBAdHlwZSB7TnVtYmVyfVxuICogQGRlZmF1bHQgMjVcbiAqL1xuR2VzdHVyZURldGVjdG9yLkNBTENVTEFURV9JTlRFUlZBTCA9IDI1O1xuXG4vKipcbiAqIGV2ZW50dHlwZXMgcGVyIHRvdWNoZXZlbnQgKHN0YXJ0LCBtb3ZlLCBlbmQpIGFyZSBmaWxsZWQgYnkgYEV2ZW50LmRldGVybWluZUV2ZW50VHlwZXNgIG9uIGBzZXR1cGBcbiAqIHRoZSBvYmplY3QgY29udGFpbnMgdGhlIERPTSBldmVudCBuYW1lcyBwZXIgdHlwZSAoYEVWRU5UX1NUQVJUYCwgYEVWRU5UX01PVkVgLCBgRVZFTlRfRU5EYClcbiAqIEBwcm9wZXJ0eSBFVkVOVF9UWVBFU1xuICogQHByaXZhdGVcbiAqIEB3cml0ZU9uY2VcbiAqIEB0eXBlIHtPYmplY3R9XG4gKi9cbnZhciBFVkVOVF9UWVBFUyA9IHt9O1xuXG4vKipcbiAqIGRpcmVjdGlvbiBzdHJpbmdzLCBmb3Igc2FmZSBjb21wYXJpc29uc1xuICogQHByb3BlcnR5IERJUkVDVElPTl9ET1dOfExFRlR8VVB8UklHSFRcbiAqIEBmaW5hbFxuICogQHR5cGUge1N0cmluZ31cbiAqIEBkZWZhdWx0ICdkb3duJyAnbGVmdCcgJ3VwJyAncmlnaHQnXG4gKi9cbnZhciBESVJFQ1RJT05fRE9XTiA9IEdlc3R1cmVEZXRlY3Rvci5ESVJFQ1RJT05fRE9XTiA9ICdkb3duJztcbnZhciBESVJFQ1RJT05fTEVGVCA9IEdlc3R1cmVEZXRlY3Rvci5ESVJFQ1RJT05fTEVGVCA9ICdsZWZ0JztcbnZhciBESVJFQ1RJT05fVVAgPSBHZXN0dXJlRGV0ZWN0b3IuRElSRUNUSU9OX1VQID0gJ3VwJztcbnZhciBESVJFQ1RJT05fUklHSFQgPSBHZXN0dXJlRGV0ZWN0b3IuRElSRUNUSU9OX1JJR0hUID0gJ3JpZ2h0JztcblxuLyoqXG4gKiBwb2ludGVydHlwZSBzdHJpbmdzLCBmb3Igc2FmZSBjb21wYXJpc29uc1xuICogQHByb3BlcnR5IFBPSU5URVJfTU9VU0V8VE9VQ0h8UEVOXG4gKiBAZmluYWxcbiAqIEB0eXBlIHtTdHJpbmd9XG4gKiBAZGVmYXVsdCAnbW91c2UnICd0b3VjaCcgJ3BlbidcbiAqL1xudmFyIFBPSU5URVJfTU9VU0UgPSBHZXN0dXJlRGV0ZWN0b3IuUE9JTlRFUl9NT1VTRSA9ICdtb3VzZSc7XG52YXIgUE9JTlRFUl9UT1VDSCA9IEdlc3R1cmVEZXRlY3Rvci5QT0lOVEVSX1RPVUNIID0gJ3RvdWNoJztcbnZhciBQT0lOVEVSX1BFTiA9IEdlc3R1cmVEZXRlY3Rvci5QT0lOVEVSX1BFTiA9ICdwZW4nO1xuXG4vKipcbiAqIGV2ZW50dHlwZXNcbiAqIEBwcm9wZXJ0eSBFVkVOVF9TVEFSVHxNT1ZFfEVORHxSRUxFQVNFfFRPVUNIXG4gKiBAZmluYWxcbiAqIEB0eXBlIHtTdHJpbmd9XG4gKiBAZGVmYXVsdCAnc3RhcnQnICdjaGFuZ2UnICdtb3ZlJyAnZW5kJyAncmVsZWFzZScgJ3RvdWNoJ1xuICovXG52YXIgRVZFTlRfU1RBUlQgPSBHZXN0dXJlRGV0ZWN0b3IuRVZFTlRfU1RBUlQgPSAnc3RhcnQnO1xudmFyIEVWRU5UX01PVkUgPSBHZXN0dXJlRGV0ZWN0b3IuRVZFTlRfTU9WRSA9ICdtb3ZlJztcbnZhciBFVkVOVF9FTkQgPSBHZXN0dXJlRGV0ZWN0b3IuRVZFTlRfRU5EID0gJ2VuZCc7XG52YXIgRVZFTlRfUkVMRUFTRSA9IEdlc3R1cmVEZXRlY3Rvci5FVkVOVF9SRUxFQVNFID0gJ3JlbGVhc2UnO1xudmFyIEVWRU5UX1RPVUNIID0gR2VzdHVyZURldGVjdG9yLkVWRU5UX1RPVUNIID0gJ3RvdWNoJztcblxuLyoqXG4gKiBpZiB0aGUgd2luZG93IGV2ZW50cyBhcmUgc2V0Li4uXG4gKiBAcHJvcGVydHkgUkVBRFlcbiAqIEB3cml0ZU9uY2VcbiAqIEB0eXBlIHtCb29sZWFufVxuICogQGRlZmF1bHQgZmFsc2VcbiAqL1xuR2VzdHVyZURldGVjdG9yLlJFQURZID0gZmFsc2U7XG5cbi8qKlxuICogcGx1Z2lucyBuYW1lc3BhY2VcbiAqIEBwcm9wZXJ0eSBwbHVnaW5zXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG5HZXN0dXJlRGV0ZWN0b3IucGx1Z2lucyA9IEdlc3R1cmVEZXRlY3Rvci5wbHVnaW5zIHx8IHt9O1xuXG4vKipcbiAqIGdlc3R1cmVzIG5hbWVzcGFjZVxuICogc2VlIGAvZ2VzdHVyZXNgIGZvciB0aGUgZGVmaW5pdGlvbnNcbiAqIEBwcm9wZXJ0eSBnZXN0dXJlc1xuICogQHR5cGUge09iamVjdH1cbiAqL1xuR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzID0gR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzIHx8IHt9O1xuXG4vKipcbiAqIHNldHVwIGV2ZW50cyB0byBkZXRlY3QgZ2VzdHVyZXMgb24gdGhlIGRvY3VtZW50XG4gKiB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuIGNyZWF0aW5nIGFuIG5ldyBpbnN0YW5jZVxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gc2V0dXAob3B0cykge1xuICBpZiAoR2VzdHVyZURldGVjdG9yLlJFQURZKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gZmluZCB3aGF0IGV2ZW50dHlwZXMgd2UgYWRkIGxpc3RlbmVycyB0b1xuICBFdmVudC5kZXRlcm1pbmVFdmVudFR5cGVzKCk7XG5cbiAgLy8gUmVnaXN0ZXIgYWxsIGdlc3R1cmVzIGluc2lkZSBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZXNcbiAgVXRpbHMuZWFjaChHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZXMsIGZ1bmN0aW9uKGdlc3R1cmUpIHtcbiAgICBEZXRlY3Rpb24ucmVnaXN0ZXIoZ2VzdHVyZSk7XG4gIH0pO1xuXG4gIC8vIEFkZCB0b3VjaCBldmVudHMgb24gdGhlIGRvY3VtZW50XG4gIEV2ZW50Lm9uVG91Y2goR2VzdHVyZURldGVjdG9yLkRPQ1VNRU5ULCBFVkVOVF9NT1ZFLCBEZXRlY3Rpb24uZGV0ZWN0LCBvcHRzKTtcbiAgRXZlbnQub25Ub3VjaChHZXN0dXJlRGV0ZWN0b3IuRE9DVU1FTlQsIEVWRU5UX0VORCwgRGV0ZWN0aW9uLmRldGVjdCwgb3B0cyk7XG5cbiAgLy8gR2VzdHVyZURldGVjdG9yIGlzIHJlYWR5Li4uIVxuICBHZXN0dXJlRGV0ZWN0b3IuUkVBRFkgPSB0cnVlO1xufVxuXG4vKipcbiAqIEBtb2R1bGUgR2VzdHVyZURldGVjdG9yXG4gKlxuICogQGNsYXNzIFV0aWxzXG4gKiBAc3RhdGljXG4gKi9cblV0aWxzID0gR2VzdHVyZURldGVjdG9yLnV0aWxzID0ge1xuICAvKipcbiAgICogZXh0ZW5kIG1ldGhvZCwgY291bGQgYWxzbyBiZSB1c2VkIGZvciBjbG9uaW5nIHdoZW4gYGRlc3RgIGlzIGFuIGVtcHR5IG9iamVjdC5cbiAgICogY2hhbmdlcyB0aGUgZGVzdCBvYmplY3RcbiAgICogQHBhcmFtIHtPYmplY3R9IGRlc3RcbiAgICogQHBhcmFtIHtPYmplY3R9IHNyY1xuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFttZXJnZT1mYWxzZV0gIGRvIGEgbWVyZ2VcbiAgICogQHJldHVybiB7T2JqZWN0fSBkZXN0XG4gICAqL1xuICBleHRlbmQ6IGZ1bmN0aW9uIGV4dGVuZChkZXN0LCBzcmMsIG1lcmdlKSB7XG4gICAgZm9yICh2YXIga2V5IGluIHNyYykge1xuICAgICAgaWYgKHNyYy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmIChkZXN0W2tleV0gPT09IHVuZGVmaW5lZCB8fCAhbWVyZ2UpKSB7XG4gICAgICAgIGRlc3Rba2V5XSA9IHNyY1trZXldO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVzdDtcbiAgfSxcblxuICAvKipcbiAgICogc2ltcGxlIGFkZEV2ZW50TGlzdGVuZXIgd3JhcHBlclxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICovXG4gIG9uOiBmdW5jdGlvbiBvbihlbGVtZW50LCB0eXBlLCBoYW5kbGVyLCBvcHQpIHtcbiAgICB1dGlsLmFkZEV2ZW50TGlzdGVuZXIoZWxlbWVudCwgdHlwZSwgaGFuZGxlciwgb3B0LCB0cnVlKTtcbiAgfSxcblxuICAvKipcbiAgICogc2ltcGxlIHJlbW92ZUV2ZW50TGlzdGVuZXIgd3JhcHBlclxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICovXG4gIG9mZjogZnVuY3Rpb24gb2ZmKGVsZW1lbnQsIHR5cGUsIGhhbmRsZXIsIG9wdCkge1xuICAgIHV0aWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihlbGVtZW50LCB0eXBlLCBoYW5kbGVyLCBvcHQsIHRydWUpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBmb3JFYWNoIG92ZXIgYXJyYXlzIGFuZCBvYmplY3RzXG4gICAqIEBwYXJhbSB7T2JqZWN0fEFycmF5fSBvYmpcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0b3JcbiAgICogQHBhcmFtIHthbnl9IGl0ZXJhdG9yLml0ZW1cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGl0ZXJhdG9yLmluZGV4XG4gICAqIEBwYXJhbSB7T2JqZWN0fEFycmF5fSBpdGVyYXRvci5vYmogdGhlIHNvdXJjZSBvYmplY3RcbiAgICogQHBhcmFtIHtPYmplY3R9IGNvbnRleHQgdmFsdWUgdG8gdXNlIGFzIGB0aGlzYCBpbiB0aGUgaXRlcmF0b3JcbiAgICovXG4gIGVhY2g6IGZ1bmN0aW9uIGVhY2gob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIHZhciBpLCBsZW47XG5cbiAgICAvLyBuYXRpdmUgZm9yRWFjaCBvbiBhcnJheXNcbiAgICBpZiAoJ2ZvckVhY2gnIGluIG9iaikge1xuICAgICAgb2JqLmZvckVhY2goaXRlcmF0b3IsIGNvbnRleHQpO1xuICAgICAgLy8gYXJyYXlzXG4gICAgfSBlbHNlIGlmIChvYmoubGVuZ3RoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGZvciAoaSA9IDAsIGxlbiA9IG9iai5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBpZiAoaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmpbaV0sIGksIG9iaikgPT09IGZhbHNlKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBvYmplY3RzXG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAoaSBpbiBvYmopIHtcbiAgICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShpKSAmJlxuICAgICAgICAgIGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqW2ldLCBpLCBvYmopID09PSBmYWxzZSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogZmluZCBpZiBhIHN0cmluZyBjb250YWlucyB0aGUgc3RyaW5nIHVzaW5nIGluZGV4T2ZcbiAgICogQHBhcmFtIHtTdHJpbmd9IHNyY1xuICAgKiBAcGFyYW0ge1N0cmluZ30gZmluZFxuICAgKiBAcmV0dXJuIHtCb29sZWFufSBmb3VuZFxuICAgKi9cbiAgaW5TdHI6IGZ1bmN0aW9uIGluU3RyKHNyYywgZmluZCkge1xuICAgIHJldHVybiBzcmMuaW5kZXhPZihmaW5kKSA+IC0xO1xuICB9LFxuXG4gIC8qKlxuICAgKiBmaW5kIGlmIGEgYXJyYXkgY29udGFpbnMgdGhlIG9iamVjdCB1c2luZyBpbmRleE9mIG9yIGEgc2ltcGxlIHBvbHlmaWxsXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzcmNcbiAgICogQHBhcmFtIHtTdHJpbmd9IGZpbmRcbiAgICogQHJldHVybiB7Qm9vbGVhbnxOdW1iZXJ9IGZhbHNlIHdoZW4gbm90IGZvdW5kLCBvciB0aGUgaW5kZXhcbiAgICovXG4gIGluQXJyYXk6IGZ1bmN0aW9uIGluQXJyYXkoc3JjLCBmaW5kLCBkZWVwKSB7XG4gICAgaWYgKGRlZXApIHtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBzcmMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHsgLy8gQXJyYXkuZmluZEluZGV4XG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhmaW5kKS5ldmVyeShmdW5jdGlvbihrZXkpIHsgcmV0dXJuIHNyY1tpXVtrZXldID09PSBmaW5kW2tleV07IH0pKSB7XG4gICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG5cbiAgICBpZiAoc3JjLmluZGV4T2YpIHtcbiAgICAgIHJldHVybiBzcmMuaW5kZXhPZihmaW5kKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IHNyYy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICBpZiAoc3JjW2ldID09PSBmaW5kKSB7XG4gICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIGNvbnZlcnQgYW4gYXJyYXktbGlrZSBvYmplY3QgKGBhcmd1bWVudHNgLCBgdG91Y2hsaXN0YCkgdG8gYW4gYXJyYXlcbiAgICogQHBhcmFtIHtPYmplY3R9IG9ialxuICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICovXG4gIHRvQXJyYXk6IGZ1bmN0aW9uIHRvQXJyYXkob2JqKSB7XG4gICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKG9iaiwgMCk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGZpbmQgaWYgYSBub2RlIGlzIGluIHRoZSBnaXZlbiBwYXJlbnRcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbm9kZVxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBwYXJlbnRcbiAgICogQHJldHVybiB7Qm9vbGVhbn0gZm91bmRcbiAgICovXG4gIGhhc1BhcmVudDogZnVuY3Rpb24gaGFzUGFyZW50KG5vZGUsIHBhcmVudCkge1xuICAgIHdoaWxlIChub2RlKSB7XG4gICAgICBpZiAobm9kZSA9PSBwYXJlbnQpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGdldCB0aGUgY2VudGVyIG9mIGFsbCB0aGUgdG91Y2hlc1xuICAgKiBAcGFyYW0ge0FycmF5fSB0b3VjaGVzXG4gICAqIEByZXR1cm4ge09iamVjdH0gY2VudGVyIGNvbnRhaW5zIGBwYWdlWGAsIGBwYWdlWWAsIGBjbGllbnRYYCBhbmQgYGNsaWVudFlgIHByb3BlcnRpZXNcbiAgICovXG4gIGdldENlbnRlcjogZnVuY3Rpb24gZ2V0Q2VudGVyKHRvdWNoZXMpIHtcbiAgICB2YXIgcGFnZVggPSBbXSxcbiAgICAgICAgcGFnZVkgPSBbXSxcbiAgICAgICAgY2xpZW50WCA9IFtdLFxuICAgICAgICBjbGllbnRZID0gW10sXG4gICAgICAgIG1pbiA9IE1hdGgubWluLFxuICAgICAgICBtYXggPSBNYXRoLm1heDtcblxuICAgIC8vIG5vIG5lZWQgdG8gbG9vcCB3aGVuIG9ubHkgb25lIHRvdWNoXG4gICAgaWYgKHRvdWNoZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBwYWdlWDogdG91Y2hlc1swXS5wYWdlWCxcbiAgICAgICAgcGFnZVk6IHRvdWNoZXNbMF0ucGFnZVksXG4gICAgICAgIGNsaWVudFg6IHRvdWNoZXNbMF0uY2xpZW50WCxcbiAgICAgICAgY2xpZW50WTogdG91Y2hlc1swXS5jbGllbnRZXG4gICAgICB9O1xuICAgIH1cblxuICAgIFV0aWxzLmVhY2godG91Y2hlcywgZnVuY3Rpb24odG91Y2gpIHtcbiAgICAgIHBhZ2VYLnB1c2godG91Y2gucGFnZVgpO1xuICAgICAgcGFnZVkucHVzaCh0b3VjaC5wYWdlWSk7XG4gICAgICBjbGllbnRYLnB1c2godG91Y2guY2xpZW50WCk7XG4gICAgICBjbGllbnRZLnB1c2godG91Y2guY2xpZW50WSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGFnZVg6IChtaW4uYXBwbHkoTWF0aCwgcGFnZVgpICsgbWF4LmFwcGx5KE1hdGgsIHBhZ2VYKSkgLyAyLFxuICAgICAgcGFnZVk6IChtaW4uYXBwbHkoTWF0aCwgcGFnZVkpICsgbWF4LmFwcGx5KE1hdGgsIHBhZ2VZKSkgLyAyLFxuICAgICAgY2xpZW50WDogKG1pbi5hcHBseShNYXRoLCBjbGllbnRYKSArIG1heC5hcHBseShNYXRoLCBjbGllbnRYKSkgLyAyLFxuICAgICAgY2xpZW50WTogKG1pbi5hcHBseShNYXRoLCBjbGllbnRZKSArIG1heC5hcHBseShNYXRoLCBjbGllbnRZKSkgLyAyXG4gICAgfTtcbiAgfSxcblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSB2ZWxvY2l0eSBiZXR3ZWVuIHR3byBwb2ludHMuIHVuaXQgaXMgaW4gcHggcGVyIG1zLlxuICAgKiBAcGFyYW0ge051bWJlcn0gZGVsdGFUaW1lXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVhcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGRlbHRhWVxuICAgKiBAcmV0dXJuIHtPYmplY3R9IHZlbG9jaXR5IGB4YCBhbmQgYHlgXG4gICAqL1xuICBnZXRWZWxvY2l0eTogZnVuY3Rpb24gZ2V0VmVsb2NpdHkoZGVsdGFUaW1lLCBkZWx0YVgsIGRlbHRhWSkge1xuICAgIHJldHVybiB7XG4gICAgICB4OiBNYXRoLmFicyhkZWx0YVggLyBkZWx0YVRpbWUpIHx8IDAsXG4gICAgICB5OiBNYXRoLmFicyhkZWx0YVkgLyBkZWx0YVRpbWUpIHx8IDBcbiAgICB9O1xuICB9LFxuXG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIGFuZ2xlIGJldHdlZW4gdHdvIGNvb3JkaW5hdGVzXG4gICAqIEBwYXJhbSB7VG91Y2h9IHRvdWNoMVxuICAgKiBAcGFyYW0ge1RvdWNofSB0b3VjaDJcbiAgICogQHJldHVybiB7TnVtYmVyfSBhbmdsZVxuICAgKi9cbiAgZ2V0QW5nbGU6IGZ1bmN0aW9uIGdldEFuZ2xlKHRvdWNoMSwgdG91Y2gyKSB7XG4gICAgdmFyIHggPSB0b3VjaDIuY2xpZW50WCAtIHRvdWNoMS5jbGllbnRYLFxuICAgICAgICB5ID0gdG91Y2gyLmNsaWVudFkgLSB0b3VjaDEuY2xpZW50WTtcblxuICAgIHJldHVybiBNYXRoLmF0YW4yKHksIHgpICogMTgwIC8gTWF0aC5QSTtcbiAgfSxcblxuICAvKipcbiAgICogZG8gYSBzbWFsbCBjb21wYXJpc29uIHRvIGdldCB0aGUgZGlyZWN0aW9uIGJldHdlZW4gdHdvIHRvdWNoZXMuXG4gICAqIEBwYXJhbSB7VG91Y2h9IHRvdWNoMVxuICAgKiBAcGFyYW0ge1RvdWNofSB0b3VjaDJcbiAgICogQHJldHVybiB7U3RyaW5nfSBkaXJlY3Rpb24gbWF0Y2hlcyBgRElSRUNUSU9OX0xFRlR8UklHSFR8VVB8RE9XTmBcbiAgICovXG4gIGdldERpcmVjdGlvbjogZnVuY3Rpb24gZ2V0RGlyZWN0aW9uKHRvdWNoMSwgdG91Y2gyKSB7XG4gICAgdmFyIHggPSBNYXRoLmFicyh0b3VjaDEuY2xpZW50WCAtIHRvdWNoMi5jbGllbnRYKSxcbiAgICAgICAgeSA9IE1hdGguYWJzKHRvdWNoMS5jbGllbnRZIC0gdG91Y2gyLmNsaWVudFkpO1xuXG4gICAgaWYgKHggPj0geSkge1xuICAgICAgcmV0dXJuIHRvdWNoMS5jbGllbnRYIC0gdG91Y2gyLmNsaWVudFggPiAwID8gRElSRUNUSU9OX0xFRlQgOiBESVJFQ1RJT05fUklHSFQ7XG4gICAgfVxuICAgIHJldHVybiB0b3VjaDEuY2xpZW50WSAtIHRvdWNoMi5jbGllbnRZID4gMCA/IERJUkVDVElPTl9VUCA6IERJUkVDVElPTl9ET1dOO1xuICB9LFxuXG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIGRpc3RhbmNlIGJldHdlZW4gdHdvIHRvdWNoZXNcbiAgICogQHBhcmFtIHtUb3VjaH10b3VjaDFcbiAgICogQHBhcmFtIHtUb3VjaH0gdG91Y2gyXG4gICAqIEByZXR1cm4ge051bWJlcn0gZGlzdGFuY2VcbiAgICovXG4gIGdldERpc3RhbmNlOiBmdW5jdGlvbiBnZXREaXN0YW5jZSh0b3VjaDEsIHRvdWNoMikge1xuICAgIHZhciB4ID0gdG91Y2gyLmNsaWVudFggLSB0b3VjaDEuY2xpZW50WCxcbiAgICAgICAgeSA9IHRvdWNoMi5jbGllbnRZIC0gdG91Y2gxLmNsaWVudFk7XG5cbiAgICByZXR1cm4gTWF0aC5zcXJ0KCh4ICogeCkgKyAoeSAqIHkpKTtcbiAgfSxcblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSBzY2FsZSBmYWN0b3IgYmV0d2VlbiB0d28gdG91Y2hMaXN0c1xuICAgKiBubyBzY2FsZSBpcyAxLCBhbmQgZ29lcyBkb3duIHRvIDAgd2hlbiBwaW5jaGVkIHRvZ2V0aGVyLCBhbmQgYmlnZ2VyIHdoZW4gcGluY2hlZCBvdXRcbiAgICogQHBhcmFtIHtBcnJheX0gc3RhcnQgYXJyYXkgb2YgdG91Y2hlc1xuICAgKiBAcGFyYW0ge0FycmF5fSBlbmQgYXJyYXkgb2YgdG91Y2hlc1xuICAgKiBAcmV0dXJuIHtOdW1iZXJ9IHNjYWxlXG4gICAqL1xuICBnZXRTY2FsZTogZnVuY3Rpb24gZ2V0U2NhbGUoc3RhcnQsIGVuZCkge1xuICAgIC8vIG5lZWQgdHdvIGZpbmdlcnMuLi5cbiAgICBpZiAoc3RhcnQubGVuZ3RoID49IDIgJiYgZW5kLmxlbmd0aCA+PSAyKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXREaXN0YW5jZShlbmRbMF0sIGVuZFsxXSkgLyB0aGlzLmdldERpc3RhbmNlKHN0YXJ0WzBdLCBzdGFydFsxXSk7XG4gICAgfVxuICAgIHJldHVybiAxO1xuICB9LFxuXG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIHJvdGF0aW9uIGRlZ3JlZXMgYmV0d2VlbiB0d28gdG91Y2hMaXN0c1xuICAgKiBAcGFyYW0ge0FycmF5fSBzdGFydCBhcnJheSBvZiB0b3VjaGVzXG4gICAqIEBwYXJhbSB7QXJyYXl9IGVuZCBhcnJheSBvZiB0b3VjaGVzXG4gICAqIEByZXR1cm4ge051bWJlcn0gcm90YXRpb25cbiAgICovXG4gIGdldFJvdGF0aW9uOiBmdW5jdGlvbiBnZXRSb3RhdGlvbihzdGFydCwgZW5kKSB7XG4gICAgLy8gbmVlZCB0d28gZmluZ2Vyc1xuICAgIGlmIChzdGFydC5sZW5ndGggPj0gMiAmJiBlbmQubGVuZ3RoID49IDIpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldEFuZ2xlKGVuZFsxXSwgZW5kWzBdKSAtIHRoaXMuZ2V0QW5nbGUoc3RhcnRbMV0sIHN0YXJ0WzBdKTtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGZpbmQgb3V0IGlmIHRoZSBkaXJlY3Rpb24gaXMgdmVydGljYWwgICAqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBkaXJlY3Rpb24gbWF0Y2hlcyBgRElSRUNUSU9OX1VQfERPV05gXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59IGlzX3ZlcnRpY2FsXG4gICAqL1xuICBpc1ZlcnRpY2FsOiBmdW5jdGlvbiBpc1ZlcnRpY2FsKGRpcmVjdGlvbikge1xuICAgIHJldHVybiBkaXJlY3Rpb24gPT0gRElSRUNUSU9OX1VQIHx8IGRpcmVjdGlvbiA9PSBESVJFQ1RJT05fRE9XTjtcbiAgfSxcblxuICAvKipcbiAgICogc2V0IGNzcyBwcm9wZXJ0aWVzIHdpdGggdGhlaXIgcHJlZml4ZXNcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdmFsdWVcbiAgICogQHBhcmFtIHtCb29sZWFufSBbdG9nZ2xlPXRydWVdXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBzZXRQcmVmaXhlZENzczogZnVuY3Rpb24gc2V0UHJlZml4ZWRDc3MoZWxlbWVudCwgcHJvcCwgdmFsdWUsIHRvZ2dsZSkge1xuICAgIHZhciBwcmVmaXhlcyA9IFsnJywgJ1dlYmtpdCcsICdNb3onLCAnTycsICdtcyddO1xuICAgIHByb3AgPSBVdGlscy50b0NhbWVsQ2FzZShwcm9wKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJlZml4ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBwID0gcHJvcDtcbiAgICAgIC8vIHByZWZpeGVzXG4gICAgICBpZiAocHJlZml4ZXNbaV0pIHtcbiAgICAgICAgcCA9IHByZWZpeGVzW2ldICsgcC5zbGljZSgwLCAxKS50b1VwcGVyQ2FzZSgpICsgcC5zbGljZSgxKTtcbiAgICAgIH1cblxuICAgICAgLy8gdGVzdCB0aGUgc3R5bGVcbiAgICAgIGlmIChwIGluIGVsZW1lbnQuc3R5bGUpIHtcbiAgICAgICAgZWxlbWVudC5zdHlsZVtwXSA9ICh0b2dnbGUgPT09IG51bGwgfHwgdG9nZ2xlKSAmJiB2YWx1ZSB8fCAnJztcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiB0b2dnbGUgYnJvd3NlciBkZWZhdWx0IGJlaGF2aW9yIGJ5IHNldHRpbmcgY3NzIHByb3BlcnRpZXMuXG4gICAqIGB1c2VyU2VsZWN0PSdub25lJ2AgYWxzbyBzZXRzIGBlbGVtZW50Lm9uc2VsZWN0c3RhcnRgIHRvIGZhbHNlXG4gICAqIGB1c2VyRHJhZz0nbm9uZSdgIGFsc28gc2V0cyBgZWxlbWVudC5vbmRyYWdzdGFydGAgdG8gZmFsc2VcbiAgICpcbiAgICogQHBhcmFtIHtIdG1sRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJvcHNcbiAgICogQHBhcmFtIHtCb29sZWFufSBbdG9nZ2xlPXRydWVdXG4gICAqL1xuICB0b2dnbGVCZWhhdmlvcjogZnVuY3Rpb24gdG9nZ2xlQmVoYXZpb3IoZWxlbWVudCwgcHJvcHMsIHRvZ2dsZSkge1xuICAgIGlmICghcHJvcHMgfHwgIWVsZW1lbnQgfHwgIWVsZW1lbnQuc3R5bGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBzZXQgdGhlIGNzcyBwcm9wZXJ0aWVzXG4gICAgVXRpbHMuZWFjaChwcm9wcywgZnVuY3Rpb24odmFsdWUsIHByb3ApIHtcbiAgICAgIFV0aWxzLnNldFByZWZpeGVkQ3NzKGVsZW1lbnQsIHByb3AsIHZhbHVlLCB0b2dnbGUpO1xuICAgIH0pO1xuXG4gICAgdmFyIGZhbHNlRm4gPSB0b2dnbGUgJiYgZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcblxuICAgIC8vIGFsc28gdGhlIGRpc2FibGUgb25zZWxlY3RzdGFydFxuICAgIGlmIChwcm9wcy51c2VyU2VsZWN0ID09ICdub25lJykge1xuICAgICAgZWxlbWVudC5vbnNlbGVjdHN0YXJ0ID0gZmFsc2VGbjtcbiAgICB9XG4gICAgLy8gYW5kIGRpc2FibGUgb25kcmFnc3RhcnRcbiAgICBpZiAocHJvcHMudXNlckRyYWcgPT0gJ25vbmUnKSB7XG4gICAgICBlbGVtZW50Lm9uZHJhZ3N0YXJ0ID0gZmFsc2VGbjtcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIGNvbnZlcnQgYSBzdHJpbmcgd2l0aCB1bmRlcnNjb3JlcyB0byBjYW1lbENhc2VcbiAgICogc28gcHJldmVudF9kZWZhdWx0IGJlY29tZXMgcHJldmVudERlZmF1bHRcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0clxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IGNhbWVsQ2FzZVN0clxuICAgKi9cbiAgdG9DYW1lbENhc2U6IGZ1bmN0aW9uIHRvQ2FtZWxDYXNlKHN0cikge1xuICAgIHJldHVybiBzdHIucmVwbGFjZSgvW18tXShbYS16XSkvZywgZnVuY3Rpb24ocykge1xuICAgICAgcmV0dXJuIHNbMV0udG9VcHBlckNhc2UoKTtcbiAgICB9KTtcbiAgfVxufTtcblxuXG4vKipcbiAqIEBtb2R1bGUgR2VzdHVyZURldGVjdG9yXG4gKi9cbi8qKlxuICogQGNsYXNzIEV2ZW50XG4gKiBAc3RhdGljXG4gKi9cbkV2ZW50ID0gR2VzdHVyZURldGVjdG9yLmV2ZW50ID0ge1xuICAvKipcbiAgICogd2hlbiB0b3VjaCBldmVudHMgaGF2ZSBiZWVuIGZpcmVkLCB0aGlzIGlzIHRydWVcbiAgICogdGhpcyBpcyB1c2VkIHRvIHN0b3AgbW91c2UgZXZlbnRzXG4gICAqIEBwcm9wZXJ0eSBwcmV2ZW50X21vdXNlZXZlbnRzXG4gICAqIEBwcml2YXRlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKi9cbiAgcHJldmVudE1vdXNlRXZlbnRzOiBmYWxzZSxcblxuICAvKipcbiAgICogaWYgRVZFTlRfU1RBUlQgaGFzIGJlZW4gZmlyZWRcbiAgICogQHByb3BlcnR5IHN0YXJ0ZWRcbiAgICogQHByaXZhdGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqL1xuICBzdGFydGVkOiBmYWxzZSxcblxuICAvKipcbiAgICogd2hlbiB0aGUgbW91c2UgaXMgaG9sZCBkb3duLCB0aGlzIGlzIHRydWVcbiAgICogQHByb3BlcnR5IHNob3VsZF9kZXRlY3RcbiAgICogQHByaXZhdGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqL1xuICBzaG91bGREZXRlY3Q6IGZhbHNlLFxuXG4gIC8qKlxuICAgKiBzaW1wbGUgZXZlbnQgYmluZGVyIHdpdGggYSBob29rIGFuZCBzdXBwb3J0IGZvciBtdWx0aXBsZSB0eXBlc1xuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtob29rXVxuICAgKiBAcGFyYW0ge09iamVjdH0gaG9vay50eXBlXG4gICAqL1xuICBvbjogZnVuY3Rpb24gb24oZWxlbWVudCwgdHlwZSwgaGFuZGxlciwgb3B0LCBob29rKSB7XG4gICAgdmFyIHR5cGVzID0gdHlwZS5zcGxpdCgnICcpO1xuICAgIFV0aWxzLmVhY2godHlwZXMsIGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgIFV0aWxzLm9uKGVsZW1lbnQsIHR5cGUsIGhhbmRsZXIsIG9wdCk7XG4gICAgICBob29rICYmIGhvb2sodHlwZSk7XG4gICAgfSk7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHNpbXBsZSBldmVudCB1bmJpbmRlciB3aXRoIGEgaG9vayBhbmQgc3VwcG9ydCBmb3IgbXVsdGlwbGUgdHlwZXNcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdHlwZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0XVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaG9va11cbiAgICogQHBhcmFtIHtPYmplY3R9IGhvb2sudHlwZVxuICAgKi9cbiAgb2ZmOiBmdW5jdGlvbiBvZmYoZWxlbWVudCwgdHlwZSwgaGFuZGxlciwgb3B0LCBob29rKSB7XG4gICAgdmFyIHR5cGVzID0gdHlwZS5zcGxpdCgnICcpO1xuICAgIFV0aWxzLmVhY2godHlwZXMsIGZ1bmN0aW9uKHR5cGUpIHtcbiAgICAgIFV0aWxzLm9mZihlbGVtZW50LCB0eXBlLCBoYW5kbGVyLCBvcHQpO1xuICAgICAgaG9vayAmJiBob29rKHR5cGUpO1xuICAgIH0pO1xuICB9LFxuXG4gIC8qKlxuICAgKiB0aGUgY29yZSB0b3VjaCBldmVudCBoYW5kbGVyLlxuICAgKiB0aGlzIGZpbmRzIG91dCBpZiB3ZSBzaG91bGQgdG8gZGV0ZWN0IGdlc3R1cmVzXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50VHlwZSBtYXRjaGVzIGBFVkVOVF9TVEFSVHxNT1ZFfEVORGBcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaGFuZGxlclxuICAgKiBAcmV0dXJuIG9uVG91Y2hIYW5kbGVyIHtGdW5jdGlvbn0gdGhlIGNvcmUgZXZlbnQgaGFuZGxlclxuICAgKi9cbiAgb25Ub3VjaDogZnVuY3Rpb24gb25Ub3VjaChlbGVtZW50LCBldmVudFR5cGUsIGhhbmRsZXIsIG9wdCkge1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIHZhciBvblRvdWNoSGFuZGxlciA9IGZ1bmN0aW9uIG9uVG91Y2hIYW5kbGVyKGV2KSB7XG4gICAgICB2YXIgc3JjVHlwZSA9IGV2LnR5cGUudG9Mb3dlckNhc2UoKSxcbiAgICAgICAgICBpc1BvaW50ZXIgPSBHZXN0dXJlRGV0ZWN0b3IuSEFTX1BPSU5URVJFVkVOVFMsXG4gICAgICAgICAgaXNNb3VzZSA9IFV0aWxzLmluU3RyKHNyY1R5cGUsICdtb3VzZScpLFxuICAgICAgICAgIHRyaWdnZXJUeXBlO1xuXG4gICAgICAvLyBpZiB3ZSBhcmUgaW4gYSBtb3VzZWV2ZW50LCBidXQgdGhlcmUgaGFzIGJlZW4gYSB0b3VjaGV2ZW50IHRyaWdnZXJlZCBpbiB0aGlzIHNlc3Npb25cbiAgICAgIC8vIHdlIHdhbnQgdG8gZG8gbm90aGluZy4gc2ltcGx5IGJyZWFrIG91dCBvZiB0aGUgZXZlbnQuXG4gICAgICBpZiAoaXNNb3VzZSAmJiBzZWxmLnByZXZlbnRNb3VzZUV2ZW50cykge1xuICAgICAgICByZXR1cm47XG5cbiAgICAgICAgLy8gbW91c2VidXR0b24gbXVzdCBiZSBkb3duXG4gICAgICB9IGVsc2UgaWYgKGlzTW91c2UgJiYgZXZlbnRUeXBlID09IEVWRU5UX1NUQVJUICYmIGV2LmJ1dHRvbiA9PT0gMCkge1xuICAgICAgICBzZWxmLnByZXZlbnRNb3VzZUV2ZW50cyA9IGZhbHNlO1xuICAgICAgICBzZWxmLnNob3VsZERldGVjdCA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYgKGlzUG9pbnRlciAmJiBldmVudFR5cGUgPT0gRVZFTlRfU1RBUlQpIHtcbiAgICAgICAgc2VsZi5zaG91bGREZXRlY3QgPSAoZXYuYnV0dG9ucyA9PT0gMSB8fCBQb2ludGVyRXZlbnQubWF0Y2hUeXBlKFBPSU5URVJfVE9VQ0gsIGV2KSk7XG4gICAgICAgIC8vIGp1c3QgYSB2YWxpZCBzdGFydCBldmVudCwgYnV0IG5vIG1vdXNlXG4gICAgICB9IGVsc2UgaWYgKCFpc01vdXNlICYmIGV2ZW50VHlwZSA9PSBFVkVOVF9TVEFSVCkge1xuICAgICAgICBzZWxmLnByZXZlbnRNb3VzZUV2ZW50cyA9IHRydWU7XG4gICAgICAgIHNlbGYuc2hvdWxkRGV0ZWN0ID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gdXBkYXRlIHRoZSBwb2ludGVyIGV2ZW50IGJlZm9yZSBlbnRlcmluZyB0aGUgZGV0ZWN0aW9uXG4gICAgICBpZiAoaXNQb2ludGVyICYmIGV2ZW50VHlwZSAhPSBFVkVOVF9FTkQpIHtcbiAgICAgICAgUG9pbnRlckV2ZW50LnVwZGF0ZVBvaW50ZXIoZXZlbnRUeXBlLCBldik7XG4gICAgICB9XG5cbiAgICAgIC8vIHdlIGFyZSBpbiBhIHRvdWNoL2Rvd24gc3RhdGUsIHNvIGFsbG93ZWQgZGV0ZWN0aW9uIG9mIGdlc3R1cmVzXG4gICAgICBpZiAoc2VsZi5zaG91bGREZXRlY3QpIHtcbiAgICAgICAgdHJpZ2dlclR5cGUgPSBzZWxmLmRvRGV0ZWN0LmNhbGwoc2VsZiwgZXYsIGV2ZW50VHlwZSwgZWxlbWVudCwgaGFuZGxlcik7XG4gICAgICB9XG5cbiAgICAgIC8vIC4uLmFuZCB3ZSBhcmUgZG9uZSB3aXRoIHRoZSBkZXRlY3Rpb25cbiAgICAgIC8vIHNvIHJlc2V0IGV2ZXJ5dGhpbmcgdG8gc3RhcnQgZWFjaCBkZXRlY3Rpb24gdG90YWxseSBmcmVzaFxuICAgICAgaWYgKHRyaWdnZXJUeXBlID09IEVWRU5UX0VORCkge1xuICAgICAgICBzZWxmLnByZXZlbnRNb3VzZUV2ZW50cyA9IGZhbHNlO1xuICAgICAgICBzZWxmLnNob3VsZERldGVjdCA9IGZhbHNlO1xuICAgICAgICBQb2ludGVyRXZlbnQucmVzZXQoKTtcbiAgICAgICAgLy8gdXBkYXRlIHRoZSBwb2ludGVyZXZlbnQgb2JqZWN0IGFmdGVyIHRoZSBkZXRlY3Rpb25cbiAgICAgIH1cblxuICAgICAgaWYgKGlzUG9pbnRlciAmJiBldmVudFR5cGUgPT0gRVZFTlRfRU5EKSB7XG4gICAgICAgIFBvaW50ZXJFdmVudC51cGRhdGVQb2ludGVyKGV2ZW50VHlwZSwgZXYpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLm9uKGVsZW1lbnQsIEVWRU5UX1RZUEVTW2V2ZW50VHlwZV0sIG9uVG91Y2hIYW5kbGVyLCBvcHQpO1xuICAgIHJldHVybiBvblRvdWNoSGFuZGxlcjtcbiAgfSxcblxuICAvKipcbiAgICogdGhlIGNvcmUgZGV0ZWN0aW9uIG1ldGhvZFxuICAgKiB0aGlzIGZpbmRzIG91dCB3aGF0IEdlc3R1cmVEZXRlY3Rvci10b3VjaC1ldmVudHMgdG8gdHJpZ2dlclxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50VHlwZSBtYXRjaGVzIGBFVkVOVF9TVEFSVHxNT1ZFfEVORGBcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyXG4gICAqIEByZXR1cm4ge1N0cmluZ30gdHJpZ2dlclR5cGUgbWF0Y2hlcyBgRVZFTlRfU1RBUlR8TU9WRXxFTkRgXG4gICAqL1xuICBkb0RldGVjdDogZnVuY3Rpb24gZG9EZXRlY3QoZXYsIGV2ZW50VHlwZSwgZWxlbWVudCwgaGFuZGxlcikge1xuICAgIHZhciB0b3VjaExpc3QgPSB0aGlzLmdldFRvdWNoTGlzdChldiwgZXZlbnRUeXBlKTtcbiAgICB2YXIgdG91Y2hMaXN0TGVuZ3RoID0gdG91Y2hMaXN0Lmxlbmd0aDtcbiAgICB2YXIgdHJpZ2dlclR5cGUgPSBldmVudFR5cGU7XG4gICAgdmFyIHRyaWdnZXJDaGFuZ2UgPSB0b3VjaExpc3QudHJpZ2dlcjsgLy8gdXNlZCBieSBmYWtlTXVsdGl0b3VjaCBwbHVnaW5cbiAgICB2YXIgY2hhbmdlZExlbmd0aCA9IHRvdWNoTGlzdExlbmd0aDtcblxuICAgIC8vIGF0IGVhY2ggdG91Y2hzdGFydC1saWtlIGV2ZW50IHdlIHdhbnQgYWxzbyB3YW50IHRvIHRyaWdnZXIgYSBUT1VDSCBldmVudC4uLlxuICAgIGlmIChldmVudFR5cGUgPT0gRVZFTlRfU1RBUlQpIHtcbiAgICAgIHRyaWdnZXJDaGFuZ2UgPSBFVkVOVF9UT1VDSDtcbiAgICAgIC8vIC4uLnRoZSBzYW1lIGZvciBhIHRvdWNoZW5kLWxpa2UgZXZlbnRcbiAgICB9IGVsc2UgaWYgKGV2ZW50VHlwZSA9PSBFVkVOVF9FTkQpIHtcbiAgICAgIHRyaWdnZXJDaGFuZ2UgPSBFVkVOVF9SRUxFQVNFO1xuXG4gICAgICAvLyBrZWVwIHRyYWNrIG9mIGhvdyBtYW55IHRvdWNoZXMgaGF2ZSBiZWVuIHJlbW92ZWRcbiAgICAgIGNoYW5nZWRMZW5ndGggPSB0b3VjaExpc3QubGVuZ3RoIC0gKChldi5jaGFuZ2VkVG91Y2hlcykgPyBldi5jaGFuZ2VkVG91Y2hlcy5sZW5ndGggOiAxKTtcbiAgICB9XG5cbiAgICAvLyBhZnRlciB0aGVyZSBhcmUgc3RpbGwgdG91Y2hlcyBvbiB0aGUgc2NyZWVuLFxuICAgIC8vIHdlIGp1c3Qgd2FudCB0byB0cmlnZ2VyIGEgTU9WRSBldmVudC4gc28gY2hhbmdlIHRoZSBTVEFSVCBvciBFTkQgdG8gYSBNT1ZFXG4gICAgLy8gYnV0IG9ubHkgYWZ0ZXIgZGV0ZWN0aW9uIGhhcyBiZWVuIHN0YXJ0ZWQsIHRoZSBmaXJzdCB0aW1lIHdlIGFjdHVhbGx5IHdhbnQgYSBTVEFSVFxuICAgIGlmIChjaGFuZ2VkTGVuZ3RoID4gMCAmJiB0aGlzLnN0YXJ0ZWQpIHtcbiAgICAgIHRyaWdnZXJUeXBlID0gRVZFTlRfTU9WRTtcbiAgICB9XG5cbiAgICAvLyBkZXRlY3Rpb24gaGFzIGJlZW4gc3RhcnRlZCwgd2Uga2VlcCB0cmFjayBvZiB0aGlzLCBzZWUgYWJvdmVcbiAgICB0aGlzLnN0YXJ0ZWQgPSB0cnVlO1xuXG4gICAgLy8gZ2VuZXJhdGUgc29tZSBldmVudCBkYXRhLCBzb21lIGJhc2ljIGluZm9ybWF0aW9uXG4gICAgdmFyIGV2RGF0YSA9IHRoaXMuY29sbGVjdEV2ZW50RGF0YShlbGVtZW50LCB0cmlnZ2VyVHlwZSwgdG91Y2hMaXN0LCBldik7XG5cbiAgICAvLyB0cmlnZ2VyIHRoZSB0cmlnZ2VyVHlwZSBldmVudCBiZWZvcmUgdGhlIGNoYW5nZSAoVE9VQ0gsIFJFTEVBU0UpIGV2ZW50c1xuICAgIC8vIGJ1dCB0aGUgRU5EIGV2ZW50IHNob3VsZCBiZSBhdCBsYXN0XG4gICAgaWYgKGV2ZW50VHlwZSAhPSBFVkVOVF9FTkQpIHtcbiAgICAgIGhhbmRsZXIuY2FsbChEZXRlY3Rpb24sIGV2RGF0YSk7XG4gICAgfVxuXG4gICAgLy8gdHJpZ2dlciBhIGNoYW5nZSAoVE9VQ0gsIFJFTEVBU0UpIGV2ZW50LCB0aGlzIG1lYW5zIHRoZSBsZW5ndGggb2YgdGhlIHRvdWNoZXMgY2hhbmdlZFxuICAgIGlmICh0cmlnZ2VyQ2hhbmdlKSB7XG4gICAgICBldkRhdGEuY2hhbmdlZExlbmd0aCA9IGNoYW5nZWRMZW5ndGg7XG4gICAgICBldkRhdGEuZXZlbnRUeXBlID0gdHJpZ2dlckNoYW5nZTtcblxuICAgICAgaGFuZGxlci5jYWxsKERldGVjdGlvbiwgZXZEYXRhKTtcblxuICAgICAgZXZEYXRhLmV2ZW50VHlwZSA9IHRyaWdnZXJUeXBlO1xuICAgICAgZGVsZXRlIGV2RGF0YS5jaGFuZ2VkTGVuZ3RoO1xuICAgIH1cblxuICAgIC8vIHRyaWdnZXIgdGhlIEVORCBldmVudFxuICAgIGlmICh0cmlnZ2VyVHlwZSA9PSBFVkVOVF9FTkQpIHtcbiAgICAgIGhhbmRsZXIuY2FsbChEZXRlY3Rpb24sIGV2RGF0YSk7XG5cbiAgICAgIC8vIC4uLmFuZCB3ZSBhcmUgZG9uZSB3aXRoIHRoZSBkZXRlY3Rpb25cbiAgICAgIC8vIHNvIHJlc2V0IGV2ZXJ5dGhpbmcgdG8gc3RhcnQgZWFjaCBkZXRlY3Rpb24gdG90YWxseSBmcmVzaFxuICAgICAgdGhpcy5zdGFydGVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRyaWdnZXJUeXBlO1xuICB9LFxuXG4gIC8qKlxuICAgKiB3ZSBoYXZlIGRpZmZlcmVudCBldmVudHMgZm9yIGVhY2ggZGV2aWNlL2Jyb3dzZXJcbiAgICogZGV0ZXJtaW5lIHdoYXQgd2UgbmVlZCBhbmQgc2V0IHRoZW0gaW4gdGhlIEVWRU5UX1RZUEVTIGNvbnN0YW50XG4gICAqIHRoZSBgb25Ub3VjaGAgbWV0aG9kIGlzIGJpbmQgdG8gdGhlc2UgcHJvcGVydGllcy5cbiAgICogQHJldHVybiB7T2JqZWN0fSBldmVudHNcbiAgICovXG4gIGRldGVybWluZUV2ZW50VHlwZXM6IGZ1bmN0aW9uIGRldGVybWluZUV2ZW50VHlwZXMoKSB7XG4gICAgdmFyIHR5cGVzO1xuICAgIGlmIChHZXN0dXJlRGV0ZWN0b3IuSEFTX1BPSU5URVJFVkVOVFMpIHtcbiAgICAgIGlmICh3aW5kb3cuUG9pbnRlckV2ZW50KSB7XG4gICAgICAgIHR5cGVzID0gW1xuICAgICAgICAgICdwb2ludGVyZG93bicsXG4gICAgICAgICAgJ3BvaW50ZXJtb3ZlJyxcbiAgICAgICAgICAncG9pbnRlcnVwIHBvaW50ZXJjYW5jZWwgbG9zdHBvaW50ZXJjYXB0dXJlJ1xuICAgICAgICBdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHlwZXMgPSBbXG4gICAgICAgICAgJ01TUG9pbnRlckRvd24nLFxuICAgICAgICAgICdNU1BvaW50ZXJNb3ZlJyxcbiAgICAgICAgICAnTVNQb2ludGVyVXAgTVNQb2ludGVyQ2FuY2VsIE1TTG9zdFBvaW50ZXJDYXB0dXJlJ1xuICAgICAgICBdO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoR2VzdHVyZURldGVjdG9yLk5PX01PVVNFRVZFTlRTKSB7XG4gICAgICB0eXBlcyA9IFtcbiAgICAgICAgJ3RvdWNoc3RhcnQnLFxuICAgICAgICAndG91Y2htb3ZlJyxcbiAgICAgICAgJ3RvdWNoZW5kIHRvdWNoY2FuY2VsJ1xuICAgICAgXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdHlwZXMgPSBbXG4gICAgICAgICd0b3VjaHN0YXJ0IG1vdXNlZG93bicsXG4gICAgICAgICd0b3VjaG1vdmUgbW91c2Vtb3ZlJyxcbiAgICAgICAgJ3RvdWNoZW5kIHRvdWNoY2FuY2VsIG1vdXNldXAnXG4gICAgICBdO1xuICAgIH1cblxuICAgIEVWRU5UX1RZUEVTW0VWRU5UX1NUQVJUXSA9IHR5cGVzWzBdO1xuICAgIEVWRU5UX1RZUEVTW0VWRU5UX01PVkVdID0gdHlwZXNbMV07XG4gICAgRVZFTlRfVFlQRVNbRVZFTlRfRU5EXSA9IHR5cGVzWzJdO1xuICAgIHJldHVybiBFVkVOVF9UWVBFUztcbiAgfSxcblxuICAvKipcbiAgICogY3JlYXRlIHRvdWNoTGlzdCBkZXBlbmRpbmcgb24gdGhlIGV2ZW50XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRUeXBlXG4gICAqIEByZXR1cm4ge0FycmF5fSB0b3VjaGVzXG4gICAqL1xuICBnZXRUb3VjaExpc3Q6IGZ1bmN0aW9uIGdldFRvdWNoTGlzdChldiwgZXZlbnRUeXBlKSB7XG4gICAgLy8gZ2V0IHRoZSBmYWtlIHBvaW50ZXJFdmVudCB0b3VjaGxpc3RcbiAgICBpZiAoR2VzdHVyZURldGVjdG9yLkhBU19QT0lOVEVSRVZFTlRTKSB7XG4gICAgICByZXR1cm4gUG9pbnRlckV2ZW50LmdldFRvdWNoTGlzdCgpO1xuICAgIH1cblxuICAgIC8vIGdldCB0aGUgdG91Y2hsaXN0XG4gICAgaWYgKGV2LnRvdWNoZXMpIHtcbiAgICAgIGlmIChldmVudFR5cGUgPT0gRVZFTlRfTU9WRSkge1xuICAgICAgICByZXR1cm4gZXYudG91Y2hlcztcbiAgICAgIH1cblxuICAgICAgdmFyIGlkZW50aWZpZXJzID0gW107XG4gICAgICB2YXIgY29uY2F0ID0gW10uY29uY2F0KFV0aWxzLnRvQXJyYXkoZXYudG91Y2hlcyksIFV0aWxzLnRvQXJyYXkoZXYuY2hhbmdlZFRvdWNoZXMpKTtcbiAgICAgIHZhciB0b3VjaExpc3QgPSBbXTtcblxuICAgICAgVXRpbHMuZWFjaChjb25jYXQsIGZ1bmN0aW9uKHRvdWNoKSB7XG4gICAgICAgIGlmIChVdGlscy5pbkFycmF5KGlkZW50aWZpZXJzLCB0b3VjaC5pZGVudGlmaWVyKSA9PT0gLTEpIHtcbiAgICAgICAgICB0b3VjaExpc3QucHVzaCh0b3VjaCk7XG4gICAgICAgIH1cbiAgICAgICAgaWRlbnRpZmllcnMucHVzaCh0b3VjaC5pZGVudGlmaWVyKTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gdG91Y2hMaXN0O1xuICAgIH1cblxuICAgIC8vIG1ha2UgZmFrZSB0b3VjaExpc3QgZnJvbSBtb3VzZSBwb3NpdGlvblxuICAgIGV2LmlkZW50aWZpZXIgPSAxO1xuICAgIHJldHVybiBbZXZdO1xuICB9LFxuXG4gIC8qKlxuICAgKiBjb2xsZWN0IGJhc2ljIGV2ZW50IGRhdGFcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRUeXBlIG1hdGNoZXMgYEVWRU5UX1NUQVJUfE1PVkV8RU5EYFxuICAgKiBAcGFyYW0ge0FycmF5fSB0b3VjaGVzXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKiBAcmV0dXJuIHtPYmplY3R9IGV2XG4gICAqL1xuICBjb2xsZWN0RXZlbnREYXRhOiBmdW5jdGlvbiBjb2xsZWN0RXZlbnREYXRhKGVsZW1lbnQsIGV2ZW50VHlwZSwgdG91Y2hlcywgZXYpIHtcbiAgICAvLyBmaW5kIG91dCBwb2ludGVyVHlwZVxuICAgIHZhciBwb2ludGVyVHlwZSA9IFBPSU5URVJfVE9VQ0g7XG4gICAgaWYgKFV0aWxzLmluU3RyKGV2LnR5cGUsICdtb3VzZScpIHx8IFBvaW50ZXJFdmVudC5tYXRjaFR5cGUoUE9JTlRFUl9NT1VTRSwgZXYpKSB7XG4gICAgICBwb2ludGVyVHlwZSA9IFBPSU5URVJfTU9VU0U7XG4gICAgfSBlbHNlIGlmIChQb2ludGVyRXZlbnQubWF0Y2hUeXBlKFBPSU5URVJfUEVOLCBldikpIHtcbiAgICAgIHBvaW50ZXJUeXBlID0gUE9JTlRFUl9QRU47XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNlbnRlcjogVXRpbHMuZ2V0Q2VudGVyKHRvdWNoZXMpLFxuICAgICAgdGltZVN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgdGFyZ2V0OiBldi50YXJnZXQsXG4gICAgICB0b3VjaGVzOiB0b3VjaGVzLFxuICAgICAgZXZlbnRUeXBlOiBldmVudFR5cGUsXG4gICAgICBwb2ludGVyVHlwZTogcG9pbnRlclR5cGUsXG4gICAgICBzcmNFdmVudDogZXYsXG5cbiAgICAgIC8qKlxuICAgICAgICogcHJldmVudCB0aGUgYnJvd3NlciBkZWZhdWx0IGFjdGlvbnNcbiAgICAgICAqIG1vc3RseSB1c2VkIHRvIGRpc2FibGUgc2Nyb2xsaW5nIG9mIHRoZSBicm93c2VyXG4gICAgICAgKi9cbiAgICAgIHByZXZlbnREZWZhdWx0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHNyY0V2ZW50ID0gdGhpcy5zcmNFdmVudDtcbiAgICAgICAgc3JjRXZlbnQucHJldmVudE1hbmlwdWxhdGlvbiAmJiBzcmNFdmVudC5wcmV2ZW50TWFuaXB1bGF0aW9uKCk7XG4gICAgICAgIHNyY0V2ZW50LnByZXZlbnREZWZhdWx0ICYmIHNyY0V2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9LFxuXG4gICAgICAvKipcbiAgICAgICAqIHN0b3AgYnViYmxpbmcgdGhlIGV2ZW50IHVwIHRvIGl0cyBwYXJlbnRzXG4gICAgICAgKi9cbiAgICAgIHN0b3BQcm9wYWdhdGlvbjogZnVuY3Rpb24oKSB7XG4gICAgICAgIHRoaXMuc3JjRXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICB9LFxuXG4gICAgICAvKipcbiAgICAgICAqIGltbWVkaWF0ZWx5IHN0b3AgZ2VzdHVyZSBkZXRlY3Rpb25cbiAgICAgICAqIG1pZ2h0IGJlIHVzZWZ1bCBhZnRlciBhIHN3aXBlIHdhcyBkZXRlY3RlZFxuICAgICAgICogQHJldHVybiB7Kn1cbiAgICAgICAqL1xuICAgICAgc3RvcERldGVjdDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiBEZXRlY3Rpb24uc3RvcERldGVjdCgpO1xuICAgICAgfVxuICAgIH07XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAbW9kdWxlIEdlc3R1cmVEZXRlY3RvclxuICpcbiAqIEBjbGFzcyBQb2ludGVyRXZlbnRcbiAqIEBzdGF0aWNcbiAqL1xuUG9pbnRlckV2ZW50ID0gR2VzdHVyZURldGVjdG9yLlBvaW50ZXJFdmVudCA9IHtcbiAgLyoqXG4gICAqIGhvbGRzIGFsbCBwb2ludGVycywgYnkgYGlkZW50aWZpZXJgXG4gICAqIEBwcm9wZXJ0eSBwb2ludGVyc1xuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgcG9pbnRlcnM6IHt9LFxuXG4gIC8qKlxuICAgKiBnZXQgdGhlIHBvaW50ZXJzIGFzIGFuIGFycmF5XG4gICAqIEByZXR1cm4ge0FycmF5fSB0b3VjaGxpc3RcbiAgICovXG4gIGdldFRvdWNoTGlzdDogZnVuY3Rpb24gZ2V0VG91Y2hMaXN0KCkge1xuICAgIHZhciB0b3VjaGxpc3QgPSBbXTtcbiAgICAvLyB3ZSBjYW4gdXNlIGZvckVhY2ggc2luY2UgcG9pbnRlckV2ZW50cyBvbmx5IGlzIGluIElFMTBcbiAgICBVdGlscy5lYWNoKHRoaXMucG9pbnRlcnMsIGZ1bmN0aW9uKHBvaW50ZXIpIHtcbiAgICAgIHRvdWNobGlzdC5wdXNoKHBvaW50ZXIpO1xuICAgIH0pO1xuICAgIHJldHVybiB0b3VjaGxpc3Q7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHVwZGF0ZSB0aGUgcG9zaXRpb24gb2YgYSBwb2ludGVyXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudFR5cGUgbWF0Y2hlcyBgRVZFTlRfU1RBUlR8TU9WRXxFTkRgXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwb2ludGVyRXZlbnRcbiAgICovXG4gIHVwZGF0ZVBvaW50ZXI6IGZ1bmN0aW9uIHVwZGF0ZVBvaW50ZXIoZXZlbnRUeXBlLCBwb2ludGVyRXZlbnQpIHtcbiAgICBpZiAoZXZlbnRUeXBlID09IEVWRU5UX0VORCB8fCAoZXZlbnRUeXBlICE9IEVWRU5UX0VORCAmJiBwb2ludGVyRXZlbnQuYnV0dG9ucyAhPT0gMSkpIHtcbiAgICAgIGRlbGV0ZSB0aGlzLnBvaW50ZXJzW3BvaW50ZXJFdmVudC5wb2ludGVySWRdO1xuICAgIH0gZWxzZSB7XG4gICAgICBwb2ludGVyRXZlbnQuaWRlbnRpZmllciA9IHBvaW50ZXJFdmVudC5wb2ludGVySWQ7XG4gICAgICB0aGlzLnBvaW50ZXJzW3BvaW50ZXJFdmVudC5wb2ludGVySWRdID0gcG9pbnRlckV2ZW50O1xuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogY2hlY2sgaWYgZXYgbWF0Y2hlcyBwb2ludGVydHlwZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gcG9pbnRlclR5cGUgbWF0Y2hlcyBgUE9JTlRFUl9NT1VTRXxUT1VDSHxQRU5gXG4gICAqIEBwYXJhbSB7UG9pbnRlckV2ZW50fSBldlxuICAgKi9cbiAgbWF0Y2hUeXBlOiBmdW5jdGlvbiBtYXRjaFR5cGUocG9pbnRlclR5cGUsIGV2KSB7XG4gICAgaWYgKCFldi5wb2ludGVyVHlwZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHZhciBwdCA9IGV2LnBvaW50ZXJUeXBlLFxuICAgICAgICB0eXBlcyA9IHt9O1xuXG4gICAgdHlwZXNbUE9JTlRFUl9NT1VTRV0gPSAocHQgPT09IChldi5NU1BPSU5URVJfVFlQRV9NT1VTRSB8fCBQT0lOVEVSX01PVVNFKSk7XG4gICAgdHlwZXNbUE9JTlRFUl9UT1VDSF0gPSAocHQgPT09IChldi5NU1BPSU5URVJfVFlQRV9UT1VDSCB8fCBQT0lOVEVSX1RPVUNIKSk7XG4gICAgdHlwZXNbUE9JTlRFUl9QRU5dID0gKHB0ID09PSAoZXYuTVNQT0lOVEVSX1RZUEVfUEVOIHx8IFBPSU5URVJfUEVOKSk7XG4gICAgcmV0dXJuIHR5cGVzW3BvaW50ZXJUeXBlXTtcbiAgfSxcblxuICAvKipcbiAgICogcmVzZXQgdGhlIHN0b3JlZCBwb2ludGVyc1xuICAgKi9cbiAgcmVzZXQ6IGZ1bmN0aW9uIHJlc2V0TGlzdCgpIHtcbiAgICB0aGlzLnBvaW50ZXJzID0ge307XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAbW9kdWxlIEdlc3R1cmVEZXRlY3RvclxuICpcbiAqIEBjbGFzcyBEZXRlY3Rpb25cbiAqIEBzdGF0aWNcbiAqL1xuRGV0ZWN0aW9uID0gR2VzdHVyZURldGVjdG9yLmRldGVjdGlvbiA9IHtcbiAgLy8gY29udGFpbnMgYWxsIHJlZ2lzdGVyZWQgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzIGluIHRoZSBjb3JyZWN0IG9yZGVyXG4gIGdlc3R1cmVzOiBbXSxcblxuICAvLyBkYXRhIG9mIHRoZSBjdXJyZW50IEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlIGRldGVjdGlvbiBzZXNzaW9uXG4gIGN1cnJlbnQ6IG51bGwsXG5cbiAgLy8gdGhlIHByZXZpb3VzIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlIHNlc3Npb24gZGF0YVxuICAvLyBpcyBhIGZ1bGwgY2xvbmUgb2YgdGhlIHByZXZpb3VzIGdlc3R1cmUuY3VycmVudCBvYmplY3RcbiAgcHJldmlvdXM6IG51bGwsXG5cbiAgLy8gd2hlbiB0aGlzIGJlY29tZXMgdHJ1ZSwgbm8gZ2VzdHVyZXMgYXJlIGZpcmVkXG4gIHN0b3BwZWQ6IGZhbHNlLFxuXG4gIC8qKlxuICAgKiBzdGFydCBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZSBkZXRlY3Rpb25cbiAgICogQHBhcmFtIHtHZXN0dXJlRGV0ZWN0b3IuSW5zdGFuY2V9IGluc3RcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50RGF0YVxuICAgKi9cbiAgc3RhcnREZXRlY3Q6IGZ1bmN0aW9uIHN0YXJ0RGV0ZWN0KGluc3QsIGV2ZW50RGF0YSkge1xuICAgIC8vIGFscmVhZHkgYnVzeSB3aXRoIGEgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgZGV0ZWN0aW9uIG9uIGFuIGVsZW1lbnRcbiAgICBpZiAodGhpcy5jdXJyZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdG9wcGVkID0gZmFsc2U7XG5cbiAgICAvLyBob2xkcyBjdXJyZW50IHNlc3Npb25cbiAgICB0aGlzLmN1cnJlbnQgPSB7XG4gICAgICBpbnN0OiBpbnN0LCAvLyByZWZlcmVuY2UgdG8gR2VzdHVyZURldGVjdG9ySW5zdGFuY2Ugd2UncmUgd29ya2luZyBmb3JcbiAgICAgIHN0YXJ0RXZlbnQ6IFV0aWxzLmV4dGVuZCh7fSwgZXZlbnREYXRhKSwgLy8gc3RhcnQgZXZlbnREYXRhIGZvciBkaXN0YW5jZXMsIHRpbWluZyBldGNcbiAgICAgIGxhc3RFdmVudDogZmFsc2UsIC8vIGxhc3QgZXZlbnREYXRhXG4gICAgICBsYXN0Q2FsY0V2ZW50OiBmYWxzZSwgLy8gbGFzdCBldmVudERhdGEgZm9yIGNhbGN1bGF0aW9ucy5cbiAgICAgIGZ1dHVyZUNhbGNFdmVudDogZmFsc2UsIC8vIGxhc3QgZXZlbnREYXRhIGZvciBjYWxjdWxhdGlvbnMuXG4gICAgICBsYXN0Q2FsY0RhdGE6IHt9LCAvLyBsYXN0IGxhc3RDYWxjRGF0YVxuICAgICAgbmFtZTogJycgLy8gY3VycmVudCBnZXN0dXJlIHdlJ3JlIGluL2RldGVjdGVkLCBjYW4gYmUgJ3RhcCcsICdob2xkJyBldGNcbiAgICB9O1xuXG4gICAgdGhpcy5kZXRlY3QoZXZlbnREYXRhKTtcbiAgfSxcblxuICAvKipcbiAgICogR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgZGV0ZWN0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudERhdGFcbiAgICogQHJldHVybiB7YW55fVxuICAgKi9cbiAgZGV0ZWN0OiBmdW5jdGlvbiBkZXRlY3QoZXZlbnREYXRhKSB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnQgfHwgdGhpcy5zdG9wcGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gZXh0ZW5kIGV2ZW50IGRhdGEgd2l0aCBjYWxjdWxhdGlvbnMgYWJvdXQgc2NhbGUsIGRpc3RhbmNlIGV0Y1xuICAgIGV2ZW50RGF0YSA9IHRoaXMuZXh0ZW5kRXZlbnREYXRhKGV2ZW50RGF0YSk7XG5cbiAgICAvLyBHZXN0dXJlRGV0ZWN0b3IgaW5zdGFuY2UgYW5kIGluc3RhbmNlIG9wdGlvbnNcbiAgICB2YXIgaW5zdCA9IHRoaXMuY3VycmVudC5pbnN0LFxuICAgICAgICBpbnN0T3B0aW9ucyA9IGluc3Qub3B0aW9ucztcblxuICAgIC8vIGNhbGwgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgaGFuZGxlcnNcbiAgICBVdGlscy5lYWNoKHRoaXMuZ2VzdHVyZXMsIGZ1bmN0aW9uIHRyaWdnZXJHZXN0dXJlKGdlc3R1cmUpIHtcbiAgICAgIC8vIG9ubHkgd2hlbiB0aGUgaW5zdGFuY2Ugb3B0aW9ucyBoYXZlIGVuYWJsZWQgdGhpcyBnZXN0dXJlXG4gICAgICBpZiAoIXRoaXMuc3RvcHBlZCAmJiBpbnN0LmVuYWJsZWQgJiYgaW5zdE9wdGlvbnNbZ2VzdHVyZS5uYW1lXSkge1xuICAgICAgICBnZXN0dXJlLmhhbmRsZXIuY2FsbChnZXN0dXJlLCBldmVudERhdGEsIGluc3QpO1xuICAgICAgfVxuICAgIH0sIHRoaXMpO1xuXG4gICAgLy8gc3RvcmUgYXMgcHJldmlvdXMgZXZlbnQgZXZlbnRcbiAgICBpZiAodGhpcy5jdXJyZW50KSB7XG4gICAgICB0aGlzLmN1cnJlbnQubGFzdEV2ZW50ID0gZXZlbnREYXRhO1xuICAgIH1cblxuICAgIGlmIChldmVudERhdGEuZXZlbnRUeXBlID09IEVWRU5UX0VORCkge1xuICAgICAgdGhpcy5zdG9wRGV0ZWN0KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV2ZW50RGF0YTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBjb25zaXN0ZW50LXJldHVyblxuICB9LFxuXG4gIC8qKlxuICAgKiBjbGVhciB0aGUgR2VzdHVyZURldGVjdG9yLmdlc3R1cmUgdmFyc1xuICAgKiB0aGlzIGlzIGNhbGxlZCBvbiBlbmREZXRlY3QsIGJ1dCBjYW4gYWxzbyBiZSB1c2VkIHdoZW4gYSBmaW5hbCBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZSBoYXMgYmVlbiBkZXRlY3RlZFxuICAgKiB0byBzdG9wIG90aGVyIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcyBmcm9tIGJlaW5nIGZpcmVkXG4gICAqL1xuICBzdG9wRGV0ZWN0OiBmdW5jdGlvbiBzdG9wRGV0ZWN0KCkge1xuICAgIC8vIGNsb25lIGN1cnJlbnQgZGF0YSB0byB0aGUgc3RvcmUgYXMgdGhlIHByZXZpb3VzIGdlc3R1cmVcbiAgICAvLyB1c2VkIGZvciB0aGUgZG91YmxlIHRhcCBnZXN0dXJlLCBzaW5jZSB0aGlzIGlzIGFuIG90aGVyIGdlc3R1cmUgZGV0ZWN0IHNlc3Npb25cbiAgICB0aGlzLnByZXZpb3VzID0gVXRpbHMuZXh0ZW5kKHt9LCB0aGlzLmN1cnJlbnQpO1xuXG4gICAgLy8gcmVzZXQgdGhlIGN1cnJlbnRcbiAgICB0aGlzLmN1cnJlbnQgPSBudWxsO1xuICAgIHRoaXMuc3RvcHBlZCA9IHRydWU7XG4gIH0sXG5cbiAgLyoqXG4gICAqIGNhbGN1bGF0ZSB2ZWxvY2l0eSwgYW5nbGUgYW5kIGRpcmVjdGlvblxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICogQHBhcmFtIHtPYmplY3R9IGNlbnRlclxuICAgKiBAcGFyYW0ge051bWJlcn0gZGVsdGFUaW1lXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVhcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGRlbHRhWVxuICAgKi9cbiAgZ2V0Q2FsY3VsYXRlZERhdGE6IGZ1bmN0aW9uIGdldENhbGN1bGF0ZWREYXRhKGV2LCBjZW50ZXIsIGRlbHRhVGltZSwgZGVsdGFYLCBkZWx0YVkpIHtcbiAgICB2YXIgY3VyID0gdGhpcy5jdXJyZW50LFxuICAgICAgICByZWNhbGMgPSBmYWxzZSxcbiAgICAgICAgY2FsY0V2ID0gY3VyLmxhc3RDYWxjRXZlbnQsXG4gICAgICAgIGNhbGNEYXRhID0gY3VyLmxhc3RDYWxjRGF0YTtcblxuICAgIGlmIChjYWxjRXYgJiYgZXYudGltZVN0YW1wIC0gY2FsY0V2LnRpbWVTdGFtcCA+IEdlc3R1cmVEZXRlY3Rvci5DQUxDVUxBVEVfSU5URVJWQUwpIHtcbiAgICAgIGNlbnRlciA9IGNhbGNFdi5jZW50ZXI7XG4gICAgICBkZWx0YVRpbWUgPSBldi50aW1lU3RhbXAgLSBjYWxjRXYudGltZVN0YW1wO1xuICAgICAgZGVsdGFYID0gZXYuY2VudGVyLmNsaWVudFggLSBjYWxjRXYuY2VudGVyLmNsaWVudFg7XG4gICAgICBkZWx0YVkgPSBldi5jZW50ZXIuY2xpZW50WSAtIGNhbGNFdi5jZW50ZXIuY2xpZW50WTtcbiAgICAgIHJlY2FsYyA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9UT1VDSCB8fCBldi5ldmVudFR5cGUgPT0gRVZFTlRfUkVMRUFTRSkge1xuICAgICAgY3VyLmZ1dHVyZUNhbGNFdmVudCA9IGV2O1xuICAgIH1cblxuICAgIGlmICghY3VyLmxhc3RDYWxjRXZlbnQgfHwgcmVjYWxjKSB7XG4gICAgICBjYWxjRGF0YS52ZWxvY2l0eSA9IFV0aWxzLmdldFZlbG9jaXR5KGRlbHRhVGltZSwgZGVsdGFYLCBkZWx0YVkpO1xuICAgICAgY2FsY0RhdGEuYW5nbGUgPSBVdGlscy5nZXRBbmdsZShjZW50ZXIsIGV2LmNlbnRlcik7XG4gICAgICBjYWxjRGF0YS5kaXJlY3Rpb24gPSBVdGlscy5nZXREaXJlY3Rpb24oY2VudGVyLCBldi5jZW50ZXIpO1xuXG4gICAgICBjdXIubGFzdENhbGNFdmVudCA9IGN1ci5mdXR1cmVDYWxjRXZlbnQgfHwgZXY7XG4gICAgICBjdXIuZnV0dXJlQ2FsY0V2ZW50ID0gZXY7XG4gICAgfVxuXG4gICAgZXYudmVsb2NpdHlYID0gY2FsY0RhdGEudmVsb2NpdHkueDtcbiAgICBldi52ZWxvY2l0eVkgPSBjYWxjRGF0YS52ZWxvY2l0eS55O1xuICAgIGV2LmludGVyaW1BbmdsZSA9IGNhbGNEYXRhLmFuZ2xlO1xuICAgIGV2LmludGVyaW1EaXJlY3Rpb24gPSBjYWxjRGF0YS5kaXJlY3Rpb247XG4gIH0sXG5cbiAgLyoqXG4gICAqIGV4dGVuZCBldmVudERhdGEgZm9yIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlc1xuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICogQHJldHVybiB7T2JqZWN0fSBldlxuICAgKi9cbiAgZXh0ZW5kRXZlbnREYXRhOiBmdW5jdGlvbiBleHRlbmRFdmVudERhdGEoZXYpIHtcbiAgICB2YXIgY3VyID0gdGhpcy5jdXJyZW50LFxuICAgICAgICBzdGFydEV2ID0gY3VyLnN0YXJ0RXZlbnQsXG4gICAgICAgIGxhc3RFdiA9IGN1ci5sYXN0RXZlbnQgfHwgc3RhcnRFdjtcblxuICAgIC8vIHVwZGF0ZSB0aGUgc3RhcnQgdG91Y2hsaXN0IHRvIGNhbGN1bGF0ZSB0aGUgc2NhbGUvcm90YXRpb25cbiAgICBpZiAoZXYuZXZlbnRUeXBlID09IEVWRU5UX1RPVUNIIHx8IGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9SRUxFQVNFKSB7XG4gICAgICBzdGFydEV2LnRvdWNoZXMgPSBbXTtcbiAgICAgIFV0aWxzLmVhY2goZXYudG91Y2hlcywgZnVuY3Rpb24odG91Y2gpIHtcbiAgICAgICAgc3RhcnRFdi50b3VjaGVzLnB1c2goe1xuICAgICAgICAgIGNsaWVudFg6IHRvdWNoLmNsaWVudFgsXG4gICAgICAgICAgY2xpZW50WTogdG91Y2guY2xpZW50WVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHZhciBkZWx0YVRpbWUgPSBldi50aW1lU3RhbXAgLSBzdGFydEV2LnRpbWVTdGFtcCxcbiAgICAgICAgZGVsdGFYID0gZXYuY2VudGVyLmNsaWVudFggLSBzdGFydEV2LmNlbnRlci5jbGllbnRYLFxuICAgICAgICBkZWx0YVkgPSBldi5jZW50ZXIuY2xpZW50WSAtIHN0YXJ0RXYuY2VudGVyLmNsaWVudFk7XG5cbiAgICB0aGlzLmdldENhbGN1bGF0ZWREYXRhKGV2LCBsYXN0RXYuY2VudGVyLCBkZWx0YVRpbWUsIGRlbHRhWCwgZGVsdGFZKTtcblxuICAgIFV0aWxzLmV4dGVuZChldiwge1xuICAgICAgc3RhcnRFdmVudDogc3RhcnRFdixcblxuICAgICAgZGVsdGFUaW1lOiBkZWx0YVRpbWUsXG4gICAgICBkZWx0YVg6IGRlbHRhWCxcbiAgICAgIGRlbHRhWTogZGVsdGFZLFxuXG4gICAgICBkaXN0YW5jZTogVXRpbHMuZ2V0RGlzdGFuY2Uoc3RhcnRFdi5jZW50ZXIsIGV2LmNlbnRlciksXG4gICAgICBhbmdsZTogVXRpbHMuZ2V0QW5nbGUoc3RhcnRFdi5jZW50ZXIsIGV2LmNlbnRlciksXG4gICAgICBkaXJlY3Rpb246IFV0aWxzLmdldERpcmVjdGlvbihzdGFydEV2LmNlbnRlciwgZXYuY2VudGVyKSxcbiAgICAgIHNjYWxlOiBVdGlscy5nZXRTY2FsZShzdGFydEV2LnRvdWNoZXMsIGV2LnRvdWNoZXMpLFxuICAgICAgcm90YXRpb246IFV0aWxzLmdldFJvdGF0aW9uKHN0YXJ0RXYudG91Y2hlcywgZXYudG91Y2hlcylcbiAgICB9KTtcblxuICAgIHJldHVybiBldjtcbiAgfSxcblxuICAvKipcbiAgICogcmVnaXN0ZXIgbmV3IGdlc3R1cmVcbiAgICogQHBhcmFtIHtPYmplY3R9IGdlc3R1cmUgb2JqZWN0LCBzZWUgYGdlc3R1cmVzL2AgZm9yIGRvY3VtZW50YXRpb25cbiAgICogQHJldHVybiB7QXJyYXl9IGdlc3R1cmVzXG4gICAqL1xuICByZWdpc3RlcjogZnVuY3Rpb24gcmVnaXN0ZXIoZ2VzdHVyZSkge1xuICAgIC8vIGFkZCBhbiBlbmFibGUgZ2VzdHVyZSBvcHRpb25zIGlmIHRoZXJlIGlzIG5vIGdpdmVuXG4gICAgdmFyIG9wdGlvbnMgPSBnZXN0dXJlLmRlZmF1bHRzIHx8IHt9O1xuICAgIGlmIChvcHRpb25zW2dlc3R1cmUubmFtZV0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgb3B0aW9uc1tnZXN0dXJlLm5hbWVdID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvLyBleHRlbmQgR2VzdHVyZURldGVjdG9yIGRlZmF1bHQgb3B0aW9ucyB3aXRoIHRoZSBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZSBvcHRpb25zXG4gICAgVXRpbHMuZXh0ZW5kKEdlc3R1cmVEZXRlY3Rvci5kZWZhdWx0cywgb3B0aW9ucywgdHJ1ZSk7XG5cbiAgICAvLyBzZXQgaXRzIGluZGV4XG4gICAgZ2VzdHVyZS5pbmRleCA9IGdlc3R1cmUuaW5kZXggfHwgMTAwMDtcblxuICAgIC8vIGFkZCBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZSB0byB0aGUgbGlzdFxuICAgIHRoaXMuZ2VzdHVyZXMucHVzaChnZXN0dXJlKTtcblxuICAgIC8vIHNvcnQgdGhlIGxpc3QgYnkgaW5kZXhcbiAgICB0aGlzLmdlc3R1cmVzLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgICAgaWYgKGEuaW5kZXggPCBiLmluZGV4KSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIGlmIChhLmluZGV4ID4gYi5pbmRleCkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAwO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuZ2VzdHVyZXM7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAbW9kdWxlIEdlc3R1cmVEZXRlY3RvclxuICovXG5cbi8qKlxuICogY3JlYXRlIG5ldyBHZXN0dXJlRGV0ZWN0b3IgaW5zdGFuY2VcbiAqIGFsbCBtZXRob2RzIHNob3VsZCByZXR1cm4gdGhlIGluc3RhbmNlIGl0c2VsZiwgc28gaXQgaXMgY2hhaW5hYmxlLlxuICpcbiAqIEBjbGFzcyBJbnN0YW5jZVxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIG9wdGlvbnMgYXJlIG1lcmdlZCB3aXRoIGBHZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHNgXG4gKiBAcmV0dXJuIHtHZXN0dXJlRGV0ZWN0b3IuSW5zdGFuY2V9XG4gKi9cbkdlc3R1cmVEZXRlY3Rvci5JbnN0YW5jZSA9IGZ1bmN0aW9uKGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgbGlzdGVuZXJPcHRpb25zID0gKG9wdGlvbnMgJiYgb3B0aW9ucy5wYXNzaXZlKSA/IHsgcGFzc2l2ZTogdHJ1ZSB9IDogdW5kZWZpbmVkO1xuXG4gIC8vIHNldHVwIEdlc3R1cmVEZXRlY3RvckpTIHdpbmRvdyBldmVudHMgYW5kIHJlZ2lzdGVyIGFsbCBnZXN0dXJlc1xuICAvLyB0aGlzIGFsc28gc2V0cyB1cCB0aGUgZGVmYXVsdCBvcHRpb25zXG4gIHNldHVwKGxpc3RlbmVyT3B0aW9ucyk7XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBlbGVtZW50XG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBlbmFibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuICB0aGlzLmVuYWJsZWQgPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBvcHRpb25zLCBtZXJnZWQgd2l0aCB0aGUgZGVmYXVsdHNcbiAgICogb3B0aW9ucyB3aXRoIGFuIF8gYXJlIGNvbnZlcnRlZCB0byBjYW1lbENhc2VcbiAgICogQHByb3BlcnR5IG9wdGlvbnNcbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIFV0aWxzLmVhY2gob3B0aW9ucywgZnVuY3Rpb24odmFsdWUsIG5hbWUpIHtcbiAgICBkZWxldGUgb3B0aW9uc1tuYW1lXTtcbiAgICBvcHRpb25zW1V0aWxzLnRvQ2FtZWxDYXNlKG5hbWUpXSA9IHZhbHVlO1xuICB9KTtcblxuICB0aGlzLm9wdGlvbnMgPSBVdGlscy5leHRlbmQoVXRpbHMuZXh0ZW5kKHt9LCBHZXN0dXJlRGV0ZWN0b3IuZGVmYXVsdHMpLCBvcHRpb25zIHx8IHt9KTtcbiAgdGhpcy5vcHRpb25zLmxpc3RlbmVyT3B0aW9ucyA9IGxpc3RlbmVyT3B0aW9ucztcblxuICAvLyBhZGQgc29tZSBjc3MgdG8gdGhlIGVsZW1lbnQgdG8gcHJldmVudCB0aGUgYnJvd3NlciBmcm9tIGRvaW5nIGl0cyBuYXRpdmUgYmVoYXZpb3JcbiAgaWYgKHRoaXMub3B0aW9ucy5iZWhhdmlvcikge1xuICAgIFV0aWxzLnRvZ2dsZUJlaGF2aW9yKHRoaXMuZWxlbWVudCwgdGhpcy5vcHRpb25zLmJlaGF2aW9yLCB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBldmVudCBzdGFydCBoYW5kbGVyIG9uIHRoZSBlbGVtZW50IHRvIHN0YXJ0IHRoZSBkZXRlY3Rpb25cbiAgICogQHByb3BlcnR5IGV2ZW50U3RhcnRIYW5kbGVyXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICB0aGlzLmV2ZW50U3RhcnRIYW5kbGVyID0gRXZlbnQub25Ub3VjaChlbGVtZW50LCBFVkVOVF9TVEFSVCwgZnVuY3Rpb24oZXYpIHtcbiAgICBpZiAoc2VsZi5lbmFibGVkICYmIGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9TVEFSVCkge1xuICAgICAgRGV0ZWN0aW9uLnN0YXJ0RGV0ZWN0KHNlbGYsIGV2KTtcbiAgICB9IGVsc2UgaWYgKGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9UT1VDSCkge1xuICAgICAgRGV0ZWN0aW9uLmRldGVjdChldik7XG4gICAgfVxuICB9LCBsaXN0ZW5lck9wdGlvbnMpO1xuXG4gIC8qKlxuICAgKiBrZWVwIGEgbGlzdCBvZiB1c2VyIGV2ZW50IGhhbmRsZXJzIHdoaWNoIG5lZWRzIHRvIGJlIHJlbW92ZWQgd2hlbiBjYWxsaW5nICdkaXNwb3NlJ1xuICAgKiBAcHJvcGVydHkgZXZlbnRIYW5kbGVyc1xuICAgKiBAdHlwZSB7QXJyYXl9XG4gICAqL1xuICB0aGlzLmV2ZW50SGFuZGxlcnMgPSBbXTtcbn07XG5cbkdlc3R1cmVEZXRlY3Rvci5JbnN0YW5jZS5wcm90b3R5cGUgPSB7XG4gIC8qKlxuICAgKiBAbWV0aG9kIG9uXG4gICAqIEBzaWduYXR1cmUgb24oZ2VzdHVyZXMsIGhhbmRsZXIpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUFkZHMgYW4gZXZlbnQgaGFuZGxlciBmb3IgYSBnZXN0dXJlLiBBdmFpbGFibGUgZ2VzdHVyZXMgYXJlOiBkcmFnLCBkcmFnbGVmdCwgZHJhZ3JpZ2h0LCBkcmFndXAsIGRyYWdkb3duLCBob2xkLCByZWxlYXNlLCBzd2lwZSwgc3dpcGVsZWZ0LCBzd2lwZXJpZ2h0LCBzd2lwZXVwLCBzd2lwZWRvd24sIHRhcCwgZG91YmxldGFwLCB0b3VjaCwgdHJhbnNmb3JtLCBwaW5jaCwgcGluY2hpbiwgcGluY2hvdXQgYW5kIHJvdGF0ZS4gWy9lbl1cbiAgICogIFtqYV3jgrjjgqfjgrnjg4Hjg6Pjgavlr77jgZnjgovjgqTjg5njg7Pjg4jjg4/jg7Pjg4njg6njgpLov73liqDjgZfjgb7jgZnjgILmjIflrprjgafjgY3jgovjgrjjgqfjgrnjg4Hjg6PlkI3jga/jgIFkcmFnIGRyYWdsZWZ0IGRyYWdyaWdodCBkcmFndXAgZHJhZ2Rvd24gaG9sZCByZWxlYXNlIHN3aXBlIHN3aXBlbGVmdCBzd2lwZXJpZ2h0IHN3aXBldXAgc3dpcGVkb3duIHRhcCBkb3VibGV0YXAgdG91Y2ggdHJhbnNmb3JtIHBpbmNoIHBpbmNoaW4gcGluY2hvdXQgcm90YXRlIOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBnZXN0dXJlc1xuICAgKiAgIFtlbl1BIHNwYWNlIHNlcGFyYXRlZCBsaXN0IG9mIGdlc3R1cmVzLlsvZW5dXG4gICAqICAgW2phXeaknOefpeOBmeOCi+OCuOOCp+OCueODgeODo+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAguOCueODmuODvOOCueOBp+ikh+aVsOaMh+WumuOBmeOCi+OBk+OBqOOBjOOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGhhbmRsZXJcbiAgICogICBbZW5dQW4gZXZlbnQgaGFuZGxpbmcgZnVuY3Rpb24uWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44OP44Oz44OJ44Op44Go44Gq44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIG9uOiBmdW5jdGlvbiBvbkV2ZW50KGdlc3R1cmVzLCBoYW5kbGVyLCBvcHQpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBFdmVudC5vbihzZWxmLmVsZW1lbnQsIGdlc3R1cmVzLCBoYW5kbGVyLCB1dGlsLmV4dGVuZCh7fSwgc2VsZi5vcHRpb25zLmxpc3RlbmVyT3B0aW9ucywgb3B0KSwgZnVuY3Rpb24odHlwZSkge1xuICAgICAgc2VsZi5ldmVudEhhbmRsZXJzLnB1c2goeyBnZXN0dXJlOiB0eXBlLCBoYW5kbGVyOiBoYW5kbGVyIH0pO1xuICAgIH0pO1xuICAgIHJldHVybiBzZWxmO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIG9mZlxuICAgKiBAc2lnbmF0dXJlIG9mZihnZXN0dXJlcywgaGFuZGxlcilcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dUmVtb3ZlIGFuIGV2ZW50IGxpc3RlbmVyLlsvZW5dXG4gICAqICBbamFd44Kk44OZ44Oz44OI44Oq44K544OK44O844KS5YmK6Zmk44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IGdlc3R1cmVzXG4gICAqICAgW2VuXUEgc3BhY2Ugc2VwYXJhdGVkIGxpc3Qgb2YgZ2VzdHVyZXMuWy9lbl1cbiAgICogICBbamFd44K444Kn44K544OB44Oj5ZCN44KS5oyH5a6a44GX44G+44GZ44CC44K544Oa44O844K544Gn6KSH5pWw5oyH5a6a44GZ44KL44GT44Go44GM44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gaGFuZGxlclxuICAgKiAgIFtlbl1BbiBldmVudCBoYW5kbGluZyBmdW5jdGlvbi5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjg4/jg7Pjg4njg6njgajjgarjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgb2ZmOiBmdW5jdGlvbiBvZmZFdmVudChnZXN0dXJlcywgaGFuZGxlciwgb3B0KSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgRXZlbnQub2ZmKHNlbGYuZWxlbWVudCwgZ2VzdHVyZXMsIGhhbmRsZXIsIHV0aWwuZXh0ZW5kKHt9LCBzZWxmLm9wdGlvbnMubGlzdGVuZXJPcHRpb25zLCBvcHQpLCBmdW5jdGlvbih0eXBlKSB7XG4gICAgICB2YXIgaW5kZXggPSBVdGlscy5pbkFycmF5KHNlbGYuZXZlbnRIYW5kbGVycywgeyBnZXN0dXJlOiB0eXBlLCBoYW5kbGVyOiBoYW5kbGVyIH0sIHRydWUpO1xuICAgICAgaWYgKGluZGV4ID49IDApIHtcbiAgICAgICAgc2VsZi5ldmVudEhhbmRsZXJzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH0sXG5cbiAgLyoqXG4gICAqIHRyaWdnZXIgZ2VzdHVyZSBldmVudFxuICAgKiBAbWV0aG9kIHRyaWdnZXJcbiAgICogQHNpZ25hdHVyZSB0cmlnZ2VyKGdlc3R1cmUsIGV2ZW50RGF0YSlcbiAgICogQHBhcmFtIHtTdHJpbmd9IGdlc3R1cmVcbiAgICogQHBhcmFtIHtPYmplY3R9IFtldmVudERhdGFdXG4gICAqL1xuICB0cmlnZ2VyOiBmdW5jdGlvbiB0cmlnZ2VyRXZlbnQoZ2VzdHVyZSwgZXZlbnREYXRhKSB7XG4gICAgLy8gb3B0aW9uYWxcbiAgICBpZiAoIWV2ZW50RGF0YSkge1xuICAgICAgZXZlbnREYXRhID0ge307XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIERPTSBldmVudFxuICAgIHZhciBldmVudCA9IEdlc3R1cmVEZXRlY3Rvci5ET0NVTUVOVC5jcmVhdGVFdmVudCgnRXZlbnQnKTtcbiAgICBldmVudC5pbml0RXZlbnQoZ2VzdHVyZSwgdHJ1ZSwgdHJ1ZSk7XG4gICAgZXZlbnQuZ2VzdHVyZSA9IGV2ZW50RGF0YTtcblxuICAgIC8vIHRyaWdnZXIgb24gdGhlIHRhcmdldCBpZiBpdCBpcyBpbiB0aGUgaW5zdGFuY2UgZWxlbWVudCxcbiAgICAvLyB0aGlzIGlzIGZvciBldmVudCBkZWxlZ2F0aW9uIHRyaWNrc1xuICAgIHZhciBlbGVtZW50ID0gdGhpcy5lbGVtZW50O1xuICAgIGlmIChVdGlscy5oYXNQYXJlbnQoZXZlbnREYXRhLnRhcmdldCwgZWxlbWVudCkpIHtcbiAgICAgIGVsZW1lbnQgPSBldmVudERhdGEudGFyZ2V0O1xuICAgIH1cblxuICAgIGVsZW1lbnQuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEBtZXRob2QgZW5hYmxlXG4gICAqIEBzaWduYXR1cmUgZW5hYmxlKHN0YXRlKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1FbmFibGUgb3IgZGlzYWJsZSBnZXN0dXJlIGRldGVjdGlvbi5bL2VuXVxuICAgKiAgW2phXeOCuOOCp+OCueODgeODo+aknOefpeOCkuacieWKueWMli/nhKHlirnljJbjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IHN0YXRlXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgaXQgc2hvdWxkIGJlIGVuYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeacieWKueOBq+OBmeOCi+OBi+OBqeOBhuOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBlbmFibGU6IGZ1bmN0aW9uIGVuYWJsZShzdGF0ZSkge1xuICAgIHRoaXMuZW5hYmxlZCA9IHN0YXRlO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGRpc3Bvc2VcbiAgICogQHNpZ25hdHVyZSBkaXNwb3NlKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dUmVtb3ZlIGFuZCBkZXN0cm95IGFsbCBldmVudCBoYW5kbGVycyBmb3IgdGhpcyBpbnN0YW5jZS5bL2VuXVxuICAgKiAgW2phXeOBk+OBruOCpOODs+OCueOCv+ODs+OCueOBp+OBruOCuOOCp+OCueODgeODo+OBruaknOefpeOChOOAgeOCpOODmeODs+ODiOODj+ODs+ODieODqeOCkuWFqOOBpuino+mZpOOBl+OBpuW7g+ajhOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBkaXNwb3NlOiBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgIHZhciBpLCBlaDtcblxuICAgIC8vIHVuZG8gYWxsIGNoYW5nZXMgbWFkZSBieSBzdG9wX2Jyb3dzZXJfYmVoYXZpb3JcbiAgICBVdGlscy50b2dnbGVCZWhhdmlvcih0aGlzLmVsZW1lbnQsIHRoaXMub3B0aW9ucy5iZWhhdmlvciwgZmFsc2UpO1xuXG4gICAgLy8gdW5iaW5kIGFsbCBjdXN0b20gZXZlbnQgaGFuZGxlcnNcbiAgICBmb3IgKGkgPSAtMTsgKGVoID0gdGhpcy5ldmVudEhhbmRsZXJzWysraV0pOykgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWNvbmQtYXNzaWduXG4gICAgICBVdGlscy5vZmYodGhpcy5lbGVtZW50LCBlaC5nZXN0dXJlLCBlaC5oYW5kbGVyKTtcbiAgICB9XG5cbiAgICB0aGlzLmV2ZW50SGFuZGxlcnMgPSBbXTtcblxuICAgIC8vIHVuYmluZCB0aGUgc3RhcnQgZXZlbnQgbGlzdGVuZXJcbiAgICBFdmVudC5vZmYodGhpcy5lbGVtZW50LCBFVkVOVF9UWVBFU1tFVkVOVF9TVEFSVF0sIHRoaXMuZXZlbnRTdGFydEhhbmRsZXIpO1xuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn07XG5cblxuLyoqXG4gKiBAbW9kdWxlIGdlc3R1cmVzXG4gKi9cbi8qKlxuICogTW92ZSB3aXRoIHggZmluZ2VycyAoZGVmYXVsdCAxKSBhcm91bmQgb24gdGhlIHBhZ2UuXG4gKiBQcmV2ZW50aW5nIHRoZSBkZWZhdWx0IGJyb3dzZXIgYmVoYXZpb3IgaXMgYSBnb29kIHdheSB0byBpbXByb3ZlIGZlZWwgYW5kIHdvcmtpbmcuXG4gKiBgYGBgXG4gKiAgR2VzdHVyZURldGVjdG9ydGltZS5vbihcImRyYWdcIiwgZnVuY3Rpb24oZXYpIHtcbiAqICAgIGNvbnNvbGUubG9nKGV2KTtcbiAqICAgIGV2Lmdlc3R1cmUucHJldmVudERlZmF1bHQoKTtcbiAqICB9KTtcbiAqIGBgYGBcbiAqXG4gKiBAY2xhc3MgRHJhZ1xuICogQHN0YXRpY1xuICovXG4vKipcbiAqIEBldmVudCBkcmFnXG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ3N0YXJ0XG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ2VuZFxuICogQHBhcmFtIHtPYmplY3R9IGV2XG4gKi9cbi8qKlxuICogQGV2ZW50IGRyYXBsZWZ0XG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ3JpZ2h0XG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ3VwXG4gKiBAcGFyYW0ge09iamVjdH0gZXZcbiAqL1xuLyoqXG4gKiBAZXZlbnQgZHJhZ2Rvd25cbiAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICovXG5cbi8qKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAqL1xuKGZ1bmN0aW9uKG5hbWUpIHtcbiAgdmFyIHRyaWdnZXJlZCA9IGZhbHNlO1xuXG4gIGZ1bmN0aW9uIGRyYWdHZXN0dXJlKGV2LCBpbnN0KSB7XG4gICAgdmFyIGN1ciA9IERldGVjdGlvbi5jdXJyZW50O1xuXG4gICAgLy8gbWF4IHRvdWNoZXNcbiAgICBpZiAoaW5zdC5vcHRpb25zLmRyYWdNYXhUb3VjaGVzID4gMCAmJlxuICAgICAgZXYudG91Y2hlcy5sZW5ndGggPiBpbnN0Lm9wdGlvbnMuZHJhZ01heFRvdWNoZXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKGV2LmV2ZW50VHlwZSkge1xuICAgIGNhc2UgRVZFTlRfU1RBUlQ6XG4gICAgICB0cmlnZ2VyZWQgPSBmYWxzZTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBFVkVOVF9NT1ZFOlxuICAgICAgLy8gd2hlbiB0aGUgZGlzdGFuY2Ugd2UgbW92ZWQgaXMgdG9vIHNtYWxsIHdlIHNraXAgdGhpcyBnZXN0dXJlXG4gICAgICAvLyBvciB3ZSBjYW4gYmUgYWxyZWFkeSBpbiBkcmFnZ2luZ1xuICAgICAgaWYgKGV2LmRpc3RhbmNlIDwgaW5zdC5vcHRpb25zLmRyYWdNaW5EaXN0YW5jZSAmJlxuICAgICAgICBjdXIubmFtZSAhPSBuYW1lKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIHN0YXJ0Q2VudGVyID0gY3VyLnN0YXJ0RXZlbnQuY2VudGVyO1xuXG4gICAgICAvLyB3ZSBhcmUgZHJhZ2dpbmchXG4gICAgICBpZiAoY3VyLm5hbWUgIT0gbmFtZSkge1xuICAgICAgICBjdXIubmFtZSA9IG5hbWU7XG4gICAgICAgIGlmIChpbnN0Lm9wdGlvbnMuZHJhZ0Rpc3RhbmNlQ29ycmVjdGlvbiAmJiBldi5kaXN0YW5jZSA+IDApIHtcbiAgICAgICAgICAvLyBXaGVuIGEgZHJhZyBpcyB0cmlnZ2VyZWQsIHNldCB0aGUgZXZlbnQgY2VudGVyIHRvIGRyYWdNaW5EaXN0YW5jZSBwaXhlbHMgZnJvbSB0aGUgb3JpZ2luYWwgZXZlbnQgY2VudGVyLlxuICAgICAgICAgIC8vIFdpdGhvdXQgdGhpcyBjb3JyZWN0aW9uLCB0aGUgZHJhZ2dlZCBkaXN0YW5jZSB3b3VsZCBqdW1wc3RhcnQgYXQgZHJhZ01pbkRpc3RhbmNlIHBpeGVscyBpbnN0ZWFkIG9mIGF0IDAuXG4gICAgICAgICAgLy8gSXQgbWlnaHQgYmUgdXNlZnVsIHRvIHNhdmUgdGhlIG9yaWdpbmFsIHN0YXJ0IHBvaW50IHNvbWV3aGVyZVxuICAgICAgICAgIHZhciBmYWN0b3IgPSBNYXRoLmFicyhpbnN0Lm9wdGlvbnMuZHJhZ01pbkRpc3RhbmNlIC8gZXYuZGlzdGFuY2UpO1xuICAgICAgICAgIHN0YXJ0Q2VudGVyLnBhZ2VYICs9IGV2LmRlbHRhWCAqIGZhY3RvcjtcbiAgICAgICAgICBzdGFydENlbnRlci5wYWdlWSArPSBldi5kZWx0YVkgKiBmYWN0b3I7XG4gICAgICAgICAgc3RhcnRDZW50ZXIuY2xpZW50WCArPSBldi5kZWx0YVggKiBmYWN0b3I7XG4gICAgICAgICAgc3RhcnRDZW50ZXIuY2xpZW50WSArPSBldi5kZWx0YVkgKiBmYWN0b3I7XG5cbiAgICAgICAgICAvLyByZWNhbGN1bGF0ZSBldmVudCBkYXRhIHVzaW5nIG5ldyBzdGFydCBwb2ludFxuICAgICAgICAgIGV2ID0gRGV0ZWN0aW9uLmV4dGVuZEV2ZW50RGF0YShldik7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gbG9jayBkcmFnIHRvIGF4aXM/XG4gICAgICBpZiAoY3VyLmxhc3RFdmVudC5kcmFnTG9ja1RvQXhpcyB8fFxuICAgICAgICAoIGluc3Qub3B0aW9ucy5kcmFnTG9ja1RvQXhpcyAmJlxuICAgICAgICAgIGluc3Qub3B0aW9ucy5kcmFnTG9ja01pbkRpc3RhbmNlIDw9IGV2LmRpc3RhbmNlXG4gICAgICAgICkpIHtcbiAgICAgICAgICBldi5kcmFnTG9ja1RvQXhpcyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBrZWVwIGRpcmVjdGlvbiBvbiB0aGUgYXhpcyB0aGF0IHRoZSBkcmFnIGdlc3R1cmUgc3RhcnRlZCBvblxuICAgICAgICB2YXIgbGFzdERpcmVjdGlvbiA9IGN1ci5sYXN0RXZlbnQuZGlyZWN0aW9uO1xuICAgICAgICBpZiAoZXYuZHJhZ0xvY2tUb0F4aXMgJiYgbGFzdERpcmVjdGlvbiAhPT0gZXYuZGlyZWN0aW9uKSB7XG4gICAgICAgICAgaWYgKFV0aWxzLmlzVmVydGljYWwobGFzdERpcmVjdGlvbikpIHtcbiAgICAgICAgICAgIGV2LmRpcmVjdGlvbiA9IChldi5kZWx0YVkgPCAwKSA/IERJUkVDVElPTl9VUCA6IERJUkVDVElPTl9ET1dOO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBldi5kaXJlY3Rpb24gPSAoZXYuZGVsdGFYIDwgMCkgPyBESVJFQ1RJT05fTEVGVCA6IERJUkVDVElPTl9SSUdIVDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmaXJzdCB0aW1lLCB0cmlnZ2VyIGRyYWdzdGFydCBldmVudFxuICAgICAgICBpZiAoIXRyaWdnZXJlZCkge1xuICAgICAgICAgIGluc3QudHJpZ2dlcihuYW1lICsgJ3N0YXJ0JywgZXYpO1xuICAgICAgICAgIHRyaWdnZXJlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0cmlnZ2VyIGV2ZW50c1xuICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSwgZXYpO1xuICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSArIGV2LmRpcmVjdGlvbiwgZXYpO1xuXG4gICAgICAgIHZhciBpc1ZlcnRpY2FsID0gVXRpbHMuaXNWZXJ0aWNhbChldi5kaXJlY3Rpb24pO1xuXG4gICAgICAgIC8vIGJsb2NrIHRoZSBicm93c2VyIGV2ZW50c1xuICAgICAgICBpZiAoKGluc3Qub3B0aW9ucy5kcmFnQmxvY2tWZXJ0aWNhbCAmJiBpc1ZlcnRpY2FsKSB8fFxuICAgICAgICAgIChpbnN0Lm9wdGlvbnMuZHJhZ0Jsb2NrSG9yaXpvbnRhbCAmJiAhaXNWZXJ0aWNhbCkpIHtcbiAgICAgICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX1JFTEVBU0U6XG4gICAgICAgIGlmICh0cmlnZ2VyZWQgJiYgZXYuY2hhbmdlZExlbmd0aCA8PSBpbnN0Lm9wdGlvbnMuZHJhZ01heFRvdWNoZXMpIHtcbiAgICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSArICdlbmQnLCBldik7XG4gICAgICAgICAgdHJpZ2dlcmVkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRVZFTlRfRU5EOlxuICAgICAgICB0cmlnZ2VyZWQgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLkRyYWcgPSB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgaW5kZXg6IDUwLFxuICAgICAgaGFuZGxlcjogZHJhZ0dlc3R1cmUsXG4gICAgICBkZWZhdWx0czoge1xuICAgICAgICAvKipcbiAgICAgICAgICogbWluaW1hbCBtb3ZlbWVudCB0aGF0IGhhdmUgdG8gYmUgbWFkZSBiZWZvcmUgdGhlIGRyYWcgZXZlbnQgZ2V0cyB0cmlnZ2VyZWRcbiAgICAgICAgICogQHByb3BlcnR5IGRyYWdNaW5EaXN0YW5jZVxuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCAxMFxuICAgICAgICAgKi9cbiAgICAgICAgZHJhZ01pbkRpc3RhbmNlOiAxMCxcblxuICAgICAgICAvKipcbiAgICAgICAgICogU2V0IGRyYWdEaXN0YW5jZUNvcnJlY3Rpb24gdG8gdHJ1ZSB0byBtYWtlIHRoZSBzdGFydGluZyBwb2ludCBvZiB0aGUgZHJhZ1xuICAgICAgICAgKiBiZSBjYWxjdWxhdGVkIGZyb20gd2hlcmUgdGhlIGRyYWcgd2FzIHRyaWdnZXJlZCwgbm90IGZyb20gd2hlcmUgdGhlIHRvdWNoIHN0YXJ0ZWQuXG4gICAgICAgICAqIFVzZWZ1bCB0byBhdm9pZCBhIGplcmstc3RhcnRpbmcgZHJhZywgd2hpY2ggY2FuIG1ha2UgZmluZS1hZGp1c3RtZW50c1xuICAgICAgICAgKiB0aHJvdWdoIGRyYWdnaW5nIGRpZmZpY3VsdCwgYW5kIGJlIHZpc3VhbGx5IHVuYXBwZWFsaW5nLlxuICAgICAgICAgKiBAcHJvcGVydHkgZHJhZ0Rpc3RhbmNlQ29ycmVjdGlvblxuICAgICAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgICAgICogQGRlZmF1bHQgdHJ1ZVxuICAgICAgICAgKi9cbiAgICAgICAgZHJhZ0Rpc3RhbmNlQ29ycmVjdGlvbjogdHJ1ZSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogc2V0IDAgZm9yIHVubGltaXRlZCwgYnV0IHRoaXMgY2FuIGNvbmZsaWN0IHdpdGggdHJhbnNmb3JtXG4gICAgICAgICAqIEBwcm9wZXJ0eSBkcmFnTWF4VG91Y2hlc1xuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCAxXG4gICAgICAgICAqL1xuICAgICAgICBkcmFnTWF4VG91Y2hlczogMSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogcHJldmVudCBkZWZhdWx0IGJyb3dzZXIgYmVoYXZpb3Igd2hlbiBkcmFnZ2luZyBvY2N1cnNcbiAgICAgICAgICogYmUgY2FyZWZ1bCB3aXRoIGl0LCBpdCBtYWtlcyB0aGUgZWxlbWVudCBhIGJsb2NraW5nIGVsZW1lbnRcbiAgICAgICAgICogd2hlbiB5b3UgYXJlIHVzaW5nIHRoZSBkcmFnIGdlc3R1cmUsIGl0IGlzIGEgZ29vZCBwcmFjdGljZSB0byBzZXQgdGhpcyB0cnVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSBkcmFnQmxvY2tIb3Jpem9udGFsXG4gICAgICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAgICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgICAgICAgKi9cbiAgICAgICAgZHJhZ0Jsb2NrSG9yaXpvbnRhbDogZmFsc2UsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIHNhbWUgYXMgYGRyYWdCbG9ja0hvcml6b250YWxgLCBidXQgZm9yIHZlcnRpY2FsIG1vdmVtZW50XG4gICAgICAgICAqIEBwcm9wZXJ0eSBkcmFnQmxvY2tWZXJ0aWNhbFxuICAgICAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgICAgICovXG4gICAgICAgIGRyYWdCbG9ja1ZlcnRpY2FsOiBmYWxzZSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogZHJhZ0xvY2tUb0F4aXMga2VlcHMgdGhlIGRyYWcgZ2VzdHVyZSBvbiB0aGUgYXhpcyB0aGF0IGl0IHN0YXJ0ZWQgb24sXG4gICAgICAgICAqIEl0IGRpc2FsbG93cyB2ZXJ0aWNhbCBkaXJlY3Rpb25zIGlmIHRoZSBpbml0aWFsIGRpcmVjdGlvbiB3YXMgaG9yaXpvbnRhbCwgYW5kIHZpY2UgdmVyc2EuXG4gICAgICAgICAqIEBwcm9wZXJ0eSBkcmFnTG9ja1RvQXhpc1xuICAgICAgICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICAgICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgICAgICovXG4gICAgICAgIGRyYWdMb2NrVG9BeGlzOiBmYWxzZSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogZHJhZyBsb2NrIG9ubHkga2lja3MgaW4gd2hlbiBkaXN0YW5jZSA+IGRyYWdMb2NrTWluRGlzdGFuY2VcbiAgICAgICAgICogVGhpcyB3YXksIGxvY2tpbmcgb2NjdXJzIG9ubHkgd2hlbiB0aGUgZGlzdGFuY2UgaGFzIGJlY29tZSBsYXJnZSBlbm91Z2ggdG8gcmVsaWFibHkgZGV0ZXJtaW5lIHRoZSBkaXJlY3Rpb25cbiAgICAgICAgICogQHByb3BlcnR5IGRyYWdMb2NrTWluRGlzdGFuY2VcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMjVcbiAgICAgICAgICovXG4gICAgICAgIGRyYWdMb2NrTWluRGlzdGFuY2U6IDI1XG4gICAgICB9XG4gICAgfTtcbiAgfSkoJ2RyYWcnKTtcblxuICAvKipcbiAgICogQG1vZHVsZSBnZXN0dXJlc1xuICAgKi9cbiAgLyoqXG4gICAqIHRyaWdnZXIgYSBzaW1wbGUgZ2VzdHVyZSBldmVudCwgc28geW91IGNhbiBkbyBhbnl0aGluZyBpbiB5b3VyIGhhbmRsZXIuXG4gICAqIG9ubHkgdXNhYmxlIGlmIHlvdSBrbm93IHdoYXQgeW91ciBkb2luZy4uLlxuICAgKlxuICAgKiBAY2xhc3MgR2VzdHVyZVxuICAgKiBAc3RhdGljXG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IGdlc3R1cmVcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICBHZXN0dXJlRGV0ZWN0b3IuZ2VzdHVyZXMuR2VzdHVyZSA9IHtcbiAgICBuYW1lOiAnZ2VzdHVyZScsXG4gICAgaW5kZXg6IDEzMzcsXG4gICAgaGFuZGxlcjogZnVuY3Rpb24gcmVsZWFzZUdlc3R1cmUoZXYsIGluc3QpIHtcbiAgICAgIGluc3QudHJpZ2dlcih0aGlzLm5hbWUsIGV2KTtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEBtb2R1bGUgZ2VzdHVyZXNcbiAgICovXG4gIC8qKlxuICAgKiBUb3VjaCBzdGF5cyBhdCB0aGUgc2FtZSBwbGFjZSBmb3IgeCB0aW1lXG4gICAqXG4gICAqIEBjbGFzcyBIb2xkXG4gICAqIEBzdGF0aWNcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgaG9sZFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqL1xuICAoZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciB0aW1lcjtcblxuICAgIGZ1bmN0aW9uIGhvbGRHZXN0dXJlKGV2LCBpbnN0KSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IGluc3Qub3B0aW9ucyxcbiAgICAgICAgICBjdXJyZW50ID0gRGV0ZWN0aW9uLmN1cnJlbnQ7XG5cbiAgICAgIHN3aXRjaCAoZXYuZXZlbnRUeXBlKSB7XG4gICAgICBjYXNlIEVWRU5UX1NUQVJUOlxuICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuXG4gICAgICAgIC8vIHNldCB0aGUgZ2VzdHVyZSBzbyB3ZSBjYW4gY2hlY2sgaW4gdGhlIHRpbWVvdXQgaWYgaXQgc3RpbGwgaXNcbiAgICAgICAgY3VycmVudC5uYW1lID0gbmFtZTtcblxuICAgICAgICAvLyBzZXQgdGltZXIgYW5kIGlmIGFmdGVyIHRoZSB0aW1lb3V0IGl0IHN0aWxsIGlzIGhvbGQsXG4gICAgICAgIC8vIHdlIHRyaWdnZXIgdGhlIGhvbGQgZXZlbnRcbiAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgIGlmIChjdXJyZW50ICYmIGN1cnJlbnQubmFtZSA9PSBuYW1lKSB7XG4gICAgICAgICAgICBpbnN0LnRyaWdnZXIobmFtZSwgZXYpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgb3B0aW9ucy5ob2xkVGltZW91dCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX01PVkU6XG4gICAgICAgIGlmIChldi5kaXN0YW5jZSA+IG9wdGlvbnMuaG9sZFRocmVzaG9sZCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRVZFTlRfUkVMRUFTRTpcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLkhvbGQgPSB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgaW5kZXg6IDEwLFxuICAgICAgZGVmYXVsdHM6IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwcm9wZXJ0eSBob2xkVGltZW91dFxuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCA1MDBcbiAgICAgICAgICovXG4gICAgICAgIGhvbGRUaW1lb3V0OiA1MDAsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIG1vdmVtZW50IGFsbG93ZWQgd2hpbGUgaG9sZGluZ1xuICAgICAgICAgKiBAcHJvcGVydHkgaG9sZFRocmVzaG9sZFxuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCAyXG4gICAgICAgICAqL1xuICAgICAgICBob2xkVGhyZXNob2xkOiAyXG4gICAgICB9LFxuICAgICAgaGFuZGxlcjogaG9sZEdlc3R1cmVcbiAgICB9O1xuICB9KSgnaG9sZCcpO1xuXG4gIC8qKlxuICAgKiBAbW9kdWxlIGdlc3R1cmVzXG4gICAqL1xuICAvKipcbiAgICogd2hlbiBhIHRvdWNoIGlzIGJlaW5nIHJlbGVhc2VkIGZyb20gdGhlIHBhZ2VcbiAgICpcbiAgICogQGNsYXNzIFJlbGVhc2VcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCByZWxlYXNlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLlJlbGVhc2UgPSB7XG4gICAgbmFtZTogJ3JlbGVhc2UnLFxuICAgIGluZGV4OiBJbmZpbml0eSxcbiAgICBoYW5kbGVyOiBmdW5jdGlvbiByZWxlYXNlR2VzdHVyZShldiwgaW5zdCkge1xuICAgICAgaWYgKGV2LmV2ZW50VHlwZSA9PSBFVkVOVF9SRUxFQVNFKSB7XG4gICAgICAgIGluc3QudHJpZ2dlcih0aGlzLm5hbWUsIGV2KTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEBtb2R1bGUgZ2VzdHVyZXNcbiAgICovXG4gIC8qKlxuICAgKiB0cmlnZ2VycyBzd2lwZSBldmVudHMgd2hlbiB0aGUgZW5kIHZlbG9jaXR5IGlzIGFib3ZlIHRoZSB0aHJlc2hvbGRcbiAgICogZm9yIGJlc3QgdXNhZ2UsIHNldCBgcHJldmVudERlZmF1bHRgIChvbiB0aGUgZHJhZyBnZXN0dXJlKSB0byBgdHJ1ZWBcbiAgICogYGBgYFxuICAgKiAgR2VzdHVyZURldGVjdG9ydGltZS5vbihcImRyYWdsZWZ0IHN3aXBlbGVmdFwiLCBmdW5jdGlvbihldikge1xuICAgKiAgICBjb25zb2xlLmxvZyhldik7XG4gICAqICAgIGV2Lmdlc3R1cmUucHJldmVudERlZmF1bHQoKTtcbiAgICogIH0pO1xuICAgKiBgYGBgXG4gICAqXG4gICAqIEBjbGFzcyBTd2lwZVxuICAgKiBAc3RhdGljXG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCBzd2lwZWxlZnRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBlcmlnaHRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBldXBcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHN3aXBlZG93blxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcy5Td2lwZSA9IHtcbiAgICBuYW1lOiAnc3dpcGUnLFxuICAgIGluZGV4OiA0MCxcbiAgICBkZWZhdWx0czoge1xuICAgICAgLyoqXG4gICAgICAgKiBAcHJvcGVydHkgc3dpcGVNaW5Ub3VjaGVzXG4gICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICogQGRlZmF1bHQgMVxuICAgICAgICovXG4gICAgICBzd2lwZU1pblRvdWNoZXM6IDEsXG5cbiAgICAgIC8qKlxuICAgICAgICogQHByb3BlcnR5IHN3aXBlTWF4VG91Y2hlc1xuICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAqIEBkZWZhdWx0IDFcbiAgICAgICAqL1xuICAgICAgc3dpcGVNYXhUb3VjaGVzOiAxLFxuXG4gICAgICAvKipcbiAgICAgICAqIGhvcml6b250YWwgc3dpcGUgdmVsb2NpdHlcbiAgICAgICAqIEBwcm9wZXJ0eSBzd2lwZVZlbG9jaXR5WFxuICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAqIEBkZWZhdWx0IDAuNlxuICAgICAgICovXG4gICAgICBzd2lwZVZlbG9jaXR5WDogMC42LFxuXG4gICAgICAvKipcbiAgICAgICAqIHZlcnRpY2FsIHN3aXBlIHZlbG9jaXR5XG4gICAgICAgKiBAcHJvcGVydHkgc3dpcGVWZWxvY2l0eVlcbiAgICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICAgKiBAZGVmYXVsdCAwLjZcbiAgICAgICAqL1xuICAgICAgc3dpcGVWZWxvY2l0eVk6IDAuNlxuICAgIH0sXG5cbiAgICBoYW5kbGVyOiBmdW5jdGlvbiBzd2lwZUdlc3R1cmUoZXYsIGluc3QpIHtcbiAgICAgIGlmIChldi5ldmVudFR5cGUgPT0gRVZFTlRfUkVMRUFTRSkge1xuICAgICAgICB2YXIgdG91Y2hlcyA9IGV2LnRvdWNoZXMubGVuZ3RoLFxuICAgICAgICAgICAgb3B0aW9ucyA9IGluc3Qub3B0aW9ucztcblxuICAgICAgICAvLyBtYXggdG91Y2hlc1xuICAgICAgICBpZiAodG91Y2hlcyA8IG9wdGlvbnMuc3dpcGVNaW5Ub3VjaGVzIHx8XG4gICAgICAgICAgdG91Y2hlcyA+IG9wdGlvbnMuc3dpcGVNYXhUb3VjaGVzKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gd2hlbiB0aGUgZGlzdGFuY2Ugd2UgbW92ZWQgaXMgdG9vIHNtYWxsIHdlIHNraXAgdGhpcyBnZXN0dXJlXG4gICAgICAgIC8vIG9yIHdlIGNhbiBiZSBhbHJlYWR5IGluIGRyYWdnaW5nXG4gICAgICAgIGlmIChldi52ZWxvY2l0eVggPiBvcHRpb25zLnN3aXBlVmVsb2NpdHlYIHx8XG4gICAgICAgICAgZXYudmVsb2NpdHlZID4gb3B0aW9ucy5zd2lwZVZlbG9jaXR5WSkge1xuICAgICAgICAgIC8vIHRyaWdnZXIgc3dpcGUgZXZlbnRzXG4gICAgICAgICAgaW5zdC50cmlnZ2VyKHRoaXMubmFtZSwgZXYpO1xuICAgICAgICAgIGluc3QudHJpZ2dlcih0aGlzLm5hbWUgKyBldi5kaXJlY3Rpb24sIGV2KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQG1vZHVsZSBnZXN0dXJlc1xuICAgKi9cbiAgLyoqXG4gICAqIFNpbmdsZSB0YXAgYW5kIGEgZG91YmxlIHRhcCBvbiBhIHBsYWNlXG4gICAqXG4gICAqIEBjbGFzcyBUYXBcbiAgICogQHN0YXRpY1xuICAgKi9cbiAgLyoqXG4gICAqIEBldmVudCB0YXBcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IGRvdWJsZXRhcFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqL1xuICAoZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBoYXNNb3ZlZCA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gdGFwR2VzdHVyZShldiwgaW5zdCkge1xuICAgICAgdmFyIG9wdGlvbnMgPSBpbnN0Lm9wdGlvbnMsXG4gICAgICAgICAgY3VycmVudCA9IERldGVjdGlvbi5jdXJyZW50LFxuICAgICAgICAgIHByZXYgPSBEZXRlY3Rpb24ucHJldmlvdXMsXG4gICAgICAgICAgc2luY2VQcmV2LFxuICAgICAgICAgIGRpZERvdWJsZVRhcDtcblxuICAgICAgc3dpdGNoIChldi5ldmVudFR5cGUpIHtcbiAgICAgIGNhc2UgRVZFTlRfU1RBUlQ6XG4gICAgICAgIGhhc01vdmVkID0gZmFsc2U7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX01PVkU6XG4gICAgICAgIGhhc01vdmVkID0gaGFzTW92ZWQgfHwgKGV2LmRpc3RhbmNlID4gb3B0aW9ucy50YXBNYXhEaXN0YW5jZSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIEVWRU5UX0VORDpcbiAgICAgICAgaWYgKCFVdGlscy5pblN0cihldi5zcmNFdmVudC50eXBlLCAnY2FuY2VsJykgJiYgZXYuZGVsdGFUaW1lIDwgb3B0aW9ucy50YXBNYXhUaW1lICYmICFoYXNNb3ZlZCkge1xuICAgICAgICAgIC8vIHByZXZpb3VzIGdlc3R1cmUsIGZvciB0aGUgZG91YmxlIHRhcCBzaW5jZSB0aGVzZSBhcmUgdHdvIGRpZmZlcmVudCBnZXN0dXJlIGRldGVjdGlvbnNcbiAgICAgICAgICBzaW5jZVByZXYgPSBwcmV2ICYmIHByZXYubGFzdEV2ZW50ICYmIGV2LnRpbWVTdGFtcCAtIHByZXYubGFzdEV2ZW50LnRpbWVTdGFtcDtcbiAgICAgICAgICBkaWREb3VibGVUYXAgPSBmYWxzZTtcblxuICAgICAgICAgIC8vIGNoZWNrIGlmIGRvdWJsZSB0YXBcbiAgICAgICAgICBpZiAocHJldiAmJiBwcmV2Lm5hbWUgPT0gbmFtZSAmJlxuICAgICAgICAgICAgKHNpbmNlUHJldiAmJiBzaW5jZVByZXYgPCBvcHRpb25zLmRvdWJsZVRhcEludGVydmFsKSAmJlxuICAgICAgICAgICAgZXYuZGlzdGFuY2UgPCBvcHRpb25zLmRvdWJsZVRhcERpc3RhbmNlKSB7XG4gICAgICAgICAgICBpbnN0LnRyaWdnZXIoJ2RvdWJsZXRhcCcsIGV2KTtcbiAgICAgICAgICAgIGRpZERvdWJsZVRhcCA9IHRydWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gZG8gYSBzaW5nbGUgdGFwXG4gICAgICAgICAgaWYgKCFkaWREb3VibGVUYXAgfHwgb3B0aW9ucy50YXBBbHdheXMpIHtcbiAgICAgICAgICAgIGN1cnJlbnQubmFtZSA9IG5hbWU7XG4gICAgICAgICAgICBpbnN0LnRyaWdnZXIoY3VycmVudC5uYW1lLCBldik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcy5UYXAgPSB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgaW5kZXg6IDEwMCxcbiAgICAgIGhhbmRsZXI6IHRhcEdlc3R1cmUsXG4gICAgICBkZWZhdWx0czoge1xuICAgICAgICAvKipcbiAgICAgICAgICogbWF4IHRpbWUgb2YgYSB0YXAsIHRoaXMgaXMgZm9yIHRoZSBzbG93IHRhcHBlcnNcbiAgICAgICAgICogQHByb3BlcnR5IHRhcE1heFRpbWVcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMjUwXG4gICAgICAgICAqL1xuICAgICAgICB0YXBNYXhUaW1lOiAyNTAsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIG1heCBkaXN0YW5jZSBvZiBtb3ZlbWVudCBvZiBhIHRhcCwgdGhpcyBpcyBmb3IgdGhlIHNsb3cgdGFwcGVyc1xuICAgICAgICAgKiBAcHJvcGVydHkgdGFwTWF4RGlzdGFuY2VcbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMTBcbiAgICAgICAgICovXG4gICAgICAgIHRhcE1heERpc3RhbmNlOiAxMCxcblxuICAgICAgICAvKipcbiAgICAgICAgICogYWx3YXlzIHRyaWdnZXIgdGhlIGB0YXBgIGV2ZW50LCBldmVuIHdoaWxlIGRvdWJsZS10YXBwaW5nXG4gICAgICAgICAqIEBwcm9wZXJ0eSB0YXBBbHdheXNcbiAgICAgICAgICogQHR5cGUge0Jvb2xlYW59XG4gICAgICAgICAqIEBkZWZhdWx0IHRydWVcbiAgICAgICAgICovXG4gICAgICAgIHRhcEFsd2F5czogdHJ1ZSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogbWF4IGRpc3RhbmNlIGJldHdlZW4gdHdvIHRhcHNcbiAgICAgICAgICogQHByb3BlcnR5IGRvdWJsZVRhcERpc3RhbmNlXG4gICAgICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICAgICAqIEBkZWZhdWx0IDIwXG4gICAgICAgICAqL1xuICAgICAgICBkb3VibGVUYXBEaXN0YW5jZTogMjAsXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIG1heCB0aW1lIGJldHdlZW4gdHdvIHRhcHNcbiAgICAgICAgICogQHByb3BlcnR5IGRvdWJsZVRhcEludGVydmFsXG4gICAgICAgICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAgICAgICAqIEBkZWZhdWx0IDMwMFxuICAgICAgICAgKi9cbiAgICAgICAgZG91YmxlVGFwSW50ZXJ2YWw6IDMwMFxuICAgICAgfVxuICAgIH07XG4gIH0pKCd0YXAnKTtcblxuICAvKipcbiAgICogQG1vZHVsZSBnZXN0dXJlc1xuICAgKi9cbiAgLyoqXG4gICAqIHdoZW4gYSB0b3VjaCBpcyBiZWluZyB0b3VjaGVkIGF0IHRoZSBwYWdlXG4gICAqXG4gICAqIEBjbGFzcyBUb3VjaFxuICAgKiBAc3RhdGljXG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHRvdWNoXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldlxuICAgKi9cbiAgR2VzdHVyZURldGVjdG9yLmdlc3R1cmVzLlRvdWNoID0ge1xuICAgIG5hbWU6ICd0b3VjaCcsXG4gICAgaW5kZXg6IC1JbmZpbml0eSxcbiAgICBkZWZhdWx0czoge1xuICAgICAgLyoqXG4gICAgICAgKiBjYWxsIHByZXZlbnREZWZhdWx0IGF0IHRvdWNoc3RhcnQsIGFuZCBtYWtlcyB0aGUgZWxlbWVudCBibG9ja2luZyBieSBkaXNhYmxpbmcgdGhlIHNjcm9sbGluZyBvZiB0aGUgcGFnZSxcbiAgICAgICAqIGJ1dCBpdCBpbXByb3ZlcyBnZXN0dXJlcyBsaWtlIHRyYW5zZm9ybWluZyBhbmQgZHJhZ2dpbmcuXG4gICAgICAgKiBiZSBjYXJlZnVsIHdpdGggdXNpbmcgdGhpcywgaXQgY2FuIGJlIHZlcnkgYW5ub3lpbmcgZm9yIHVzZXJzIHRvIGJlIHN0dWNrIG9uIHRoZSBwYWdlXG4gICAgICAgKiBAcHJvcGVydHkgcHJldmVudERlZmF1bHRcbiAgICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgICAqL1xuICAgICAgcHJldmVudERlZmF1bHQ6IGZhbHNlLFxuXG4gICAgICAvKipcbiAgICAgICAqIGRpc2FibGUgbW91c2UgZXZlbnRzLCBzbyBvbmx5IHRvdWNoIChvciBwZW4hKSBpbnB1dCB0cmlnZ2VycyBldmVudHNcbiAgICAgICAqIEBwcm9wZXJ0eSBwcmV2ZW50TW91c2VcbiAgICAgICAqIEB0eXBlIHtCb29sZWFufVxuICAgICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgICAqL1xuICAgICAgcHJldmVudE1vdXNlOiBmYWxzZVxuICAgIH0sXG4gICAgaGFuZGxlcjogZnVuY3Rpb24gdG91Y2hHZXN0dXJlKGV2LCBpbnN0KSB7XG4gICAgICBpZiAoaW5zdC5vcHRpb25zLnByZXZlbnRNb3VzZSAmJiBldi5wb2ludGVyVHlwZSA9PSBQT0lOVEVSX01PVVNFKSB7XG4gICAgICAgIGV2LnN0b3BEZXRlY3QoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoaW5zdC5vcHRpb25zLnByZXZlbnREZWZhdWx0KSB7XG4gICAgICAgIGV2LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChldi5ldmVudFR5cGUgPT0gRVZFTlRfVE9VQ0gpIHtcbiAgICAgICAgaW5zdC50cmlnZ2VyKCd0b3VjaCcsIGV2KTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEBtb2R1bGUgZ2VzdHVyZXNcbiAgICovXG4gIC8qKlxuICAgKiBVc2VyIHdhbnQgdG8gc2NhbGUgb3Igcm90YXRlIHdpdGggMiBmaW5nZXJzXG4gICAqIFByZXZlbnRpbmcgdGhlIGRlZmF1bHQgYnJvd3NlciBiZWhhdmlvciBpcyBhIGdvb2Qgd2F5IHRvIGltcHJvdmUgZmVlbCBhbmQgd29ya2luZy4gVGhpcyBjYW4gYmUgZG9uZSB3aXRoIHRoZVxuICAgKiBgcHJldmVudERlZmF1bHRgIG9wdGlvbi5cbiAgICpcbiAgICogQGNsYXNzIFRyYW5zZm9ybVxuICAgKiBAc3RhdGljXG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHRyYW5zZm9ybVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgdHJhbnNmb3Jtc3RhcnRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHRyYW5zZm9ybWVuZFxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgcGluY2hpblxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG4gIC8qKlxuICAgKiBAZXZlbnQgcGluY2hvdXRcbiAgICogQHBhcmFtIHtPYmplY3R9IGV2XG4gICAqL1xuICAvKipcbiAgICogQGV2ZW50IHJvdGF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZcbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqL1xuICAoZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciB0cmlnZ2VyZWQgPSBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIHRyYW5zZm9ybUdlc3R1cmUoZXYsIGluc3QpIHtcbiAgICAgIHN3aXRjaCAoZXYuZXZlbnRUeXBlKSB7XG4gICAgICBjYXNlIEVWRU5UX1NUQVJUOlxuICAgICAgICB0cmlnZ2VyZWQgPSBmYWxzZTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgRVZFTlRfTU9WRTpcbiAgICAgICAgLy8gYXQgbGVhc3QgbXVsdGl0b3VjaFxuICAgICAgICBpZiAoZXYudG91Y2hlcy5sZW5ndGggPCAyKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNjYWxlVGhyZXNob2xkID0gTWF0aC5hYnMoMSAtIGV2LnNjYWxlKTtcbiAgICAgICAgdmFyIHJvdGF0aW9uVGhyZXNob2xkID0gTWF0aC5hYnMoZXYucm90YXRpb24pO1xuXG4gICAgICAgIC8vIHdoZW4gdGhlIGRpc3RhbmNlIHdlIG1vdmVkIGlzIHRvbyBzbWFsbCB3ZSBza2lwIHRoaXMgZ2VzdHVyZVxuICAgICAgICAvLyBvciB3ZSBjYW4gYmUgYWxyZWFkeSBpbiBkcmFnZ2luZ1xuICAgICAgICBpZiAoc2NhbGVUaHJlc2hvbGQgPCBpbnN0Lm9wdGlvbnMudHJhbnNmb3JtTWluU2NhbGUgJiZcbiAgICAgICAgICByb3RhdGlvblRocmVzaG9sZCA8IGluc3Qub3B0aW9ucy50cmFuc2Zvcm1NaW5Sb3RhdGlvbikge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHdlIGFyZSB0cmFuc2Zvcm1pbmchXG4gICAgICAgIERldGVjdGlvbi5jdXJyZW50Lm5hbWUgPSBuYW1lO1xuXG4gICAgICAgIC8vIGZpcnN0IHRpbWUsIHRyaWdnZXIgZHJhZ3N0YXJ0IGV2ZW50XG4gICAgICAgIGlmICghdHJpZ2dlcmVkKSB7XG4gICAgICAgICAgaW5zdC50cmlnZ2VyKG5hbWUgKyAnc3RhcnQnLCBldik7XG4gICAgICAgICAgdHJpZ2dlcmVkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGluc3QudHJpZ2dlcihuYW1lLCBldik7IC8vIGJhc2ljIHRyYW5zZm9ybSBldmVudFxuXG4gICAgICAgIC8vIHRyaWdnZXIgcm90YXRlIGV2ZW50XG4gICAgICAgIGlmIChyb3RhdGlvblRocmVzaG9sZCA+IGluc3Qub3B0aW9ucy50cmFuc2Zvcm1NaW5Sb3RhdGlvbikge1xuICAgICAgICAgIGluc3QudHJpZ2dlcigncm90YXRlJywgZXYpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdHJpZ2dlciBwaW5jaCBldmVudFxuICAgICAgICBpZiAoc2NhbGVUaHJlc2hvbGQgPiBpbnN0Lm9wdGlvbnMudHJhbnNmb3JtTWluU2NhbGUpIHtcbiAgICAgICAgICBpbnN0LnRyaWdnZXIoJ3BpbmNoJywgZXYpO1xuICAgICAgICAgIGluc3QudHJpZ2dlcigncGluY2gnICsgKGV2LnNjYWxlIDwgMSA/ICdpbicgOiAnb3V0JyksIGV2KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBFVkVOVF9SRUxFQVNFOlxuICAgICAgICBpZiAodHJpZ2dlcmVkICYmIGV2LmNoYW5nZWRMZW5ndGggPCAyKSB7XG4gICAgICAgICAgaW5zdC50cmlnZ2VyKG5hbWUgKyAnZW5kJywgZXYpO1xuICAgICAgICAgIHRyaWdnZXJlZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIEdlc3R1cmVEZXRlY3Rvci5nZXN0dXJlcy5UcmFuc2Zvcm0gPSB7XG4gICAgICBuYW1lOiBuYW1lLFxuICAgICAgaW5kZXg6IDQ1LFxuICAgICAgZGVmYXVsdHM6IHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIG1pbmltYWwgc2NhbGUgZmFjdG9yLCBubyBzY2FsZSBpcyAxLCB6b29taW4gaXMgdG8gMCBhbmQgem9vbW91dCB1bnRpbCBoaWdoZXIgdGhlbiAxXG4gICAgICAgICAqIEBwcm9wZXJ0eSB0cmFuc2Zvcm1NaW5TY2FsZVxuICAgICAgICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgICAgICAgKiBAZGVmYXVsdCAwLjAxXG4gICAgICAgICAqL1xuICAgICAgICB0cmFuc2Zvcm1NaW5TY2FsZTogMC4wMSxcblxuICAgICAgICAvKipcbiAgICAgICAgICogcm90YXRpb24gaW4gZGVncmVlc1xuICAgICAgICAgKiBAcHJvcGVydHkgdHJhbnNmb3JtTWluUm90YXRpb25cbiAgICAgICAgICogQHR5cGUge051bWJlcn1cbiAgICAgICAgICogQGRlZmF1bHQgMVxuICAgICAgICAgKi9cbiAgICAgICAgdHJhbnNmb3JtTWluUm90YXRpb246IDFcbiAgICAgIH0sXG5cbiAgICAgIGhhbmRsZXI6IHRyYW5zZm9ybUdlc3R1cmVcbiAgICB9O1xuICB9KSgndHJhbnNmb3JtJyk7XG5cbmV4cG9ydCBkZWZhdWx0IEdlc3R1cmVEZXRlY3RvcjtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmxldCByZWFkeU1hcCwgcXVldWVNYXA7XG5cbmZ1bmN0aW9uIGlzQ29udGVudFJlYWR5KGVsZW1lbnQpIHtcbiAgaWYgKGVsZW1lbnQuY2hpbGROb2Rlcy5sZW5ndGggPiAwKSB7XG4gICAgc2V0Q29udGVudFJlYWR5KGVsZW1lbnQpO1xuICB9XG4gIHJldHVybiByZWFkeU1hcC5oYXMoZWxlbWVudCk7XG59XG5cbmZ1bmN0aW9uIHNldENvbnRlbnRSZWFkeShlbGVtZW50KSB7XG4gIHJlYWR5TWFwLnNldChlbGVtZW50LCB0cnVlKTtcbn1cblxuZnVuY3Rpb24gYWRkQ2FsbGJhY2soZWxlbWVudCwgZm4pIHtcbiAgaWYgKCFxdWV1ZU1hcC5oYXMoZWxlbWVudCkpIHtcbiAgICBxdWV1ZU1hcC5zZXQoZWxlbWVudCwgW10pO1xuICB9XG4gIHF1ZXVlTWFwLmdldChlbGVtZW50KS5wdXNoKGZuKTtcbn1cblxuZnVuY3Rpb24gY29uc3VtZVF1ZXVlKGVsZW1lbnQpIHtcbiAgY29uc3QgY2FsbGJhY2tzID0gcXVldWVNYXAuZ2V0KGVsZW1lbnQsIFtdKSB8fCBbXTtcbiAgcXVldWVNYXAuZGVsZXRlKGVsZW1lbnQpO1xuICBjYWxsYmFja3MuZm9yRWFjaChjYWxsYmFjayA9PiBjYWxsYmFjaygpKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gY29udGVudFJlYWR5KGVsZW1lbnQsIGZuID0gKCkgPT4ge30pIHtcbiAgaWYgKHJlYWR5TWFwID09PSB1bmRlZmluZWQpIHtcbiAgICByZWFkeU1hcCA9IG5ldyBXZWFrTWFwKCk7XG4gICAgcXVldWVNYXAgPSBuZXcgV2Vha01hcCgpO1xuICB9XG5cbiAgYWRkQ2FsbGJhY2soZWxlbWVudCwgZm4pO1xuXG4gIGlmIChpc0NvbnRlbnRSZWFkeShlbGVtZW50KSkge1xuICAgIGNvbnN1bWVRdWV1ZShlbGVtZW50KTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBvYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKGNoYW5nZXMgPT4ge1xuICAgIHNldENvbnRlbnRSZWFkeShlbGVtZW50KTtcbiAgICBjb25zdW1lUXVldWUoZWxlbWVudCk7XG4gIH0pO1xuICBvYnNlcnZlci5vYnNlcnZlKGVsZW1lbnQsIHtjaGlsZExpc3Q6IHRydWUsIGNoYXJhY3RlckRhdGE6IHRydWV9KTtcblxuICAvLyBmYWlsYmFjayBmb3IgZWxlbWVudHMgaGFzIGVtcHR5IGNvbnRlbnQuXG4gIHNldEltbWVkaWF0ZSgoKSA9PiB7XG4gICAgc2V0Q29udGVudFJlYWR5KGVsZW1lbnQpO1xuICAgIGNvbnN1bWVRdWV1ZShlbGVtZW50KTtcbiAgfSk7XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5jbGFzcyBUb2FzdFF1ZXVlIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5xdWV1ZSA9IFtdO1xuICB9XG5cbiAgYWRkKGZuLCBwcm9taXNlKSB7XG4gICAgdGhpcy5xdWV1ZS5wdXNoKGZuKTtcblxuICAgIGlmICh0aGlzLnF1ZXVlLmxlbmd0aCA9PT0gMSkge1xuICAgICAgc2V0SW1tZWRpYXRlKHRoaXMucXVldWVbMF0pO1xuICAgIH1cblxuICAgIHByb21pc2UudGhlbigoKSA9PiB7XG4gICAgICB0aGlzLnF1ZXVlLnNoaWZ0KCk7XG5cbiAgICAgIGlmICh0aGlzLnF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgc2V0VGltZW91dCh0aGlzLnF1ZXVlWzBdLCAxMDAwLzMwKTsgLy8gQXBwbHkgc29tZSB2aXN1YWwgZGVsYXlcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBuZXcgVG9hc3RRdWV1ZSgpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi9jb250ZW50LXJlYWR5JztcbmltcG9ydCBUb2FzdFF1ZXVlIGZyb20gJy4vaW50ZXJuYWwvdG9hc3QtcXVldWUnO1xuXG5jb25zdCBfc2V0QXR0cmlidXRlcyA9IChlbGVtZW50LCBvcHRpb25zKSA9PiB7XG4gIFsnaWQnLCAnY2xhc3MnLCAnYW5pbWF0aW9uJ11cbiAgICAuZm9yRWFjaChhID0+IG9wdGlvbnMuaGFzT3duUHJvcGVydHkoYSkgJiYgZWxlbWVudC5zZXRBdHRyaWJ1dGUoYSwgb3B0aW9uc1thXSkpO1xuXG4gIGlmIChvcHRpb25zLm1vZGlmaWVyKSB7XG4gICAgdXRpbC5hZGRNb2RpZmllcihlbGVtZW50LCBvcHRpb25zLm1vZGlmaWVyKTtcbiAgfVxufTtcblxuY29uc3QgX25vcm1hbGl6ZUFyZ3VtZW50cyA9IChtZXNzYWdlLCBvcHRpb25zID0ge30sIGRlZmF1bHRzID0ge30pID0+IHtcbiAgb3B0aW9ucyA9IHsgLi4ub3B0aW9ucyB9O1xuICB0eXBlb2YgbWVzc2FnZSA9PT0gJ3N0cmluZycgPyAob3B0aW9ucy5tZXNzYWdlID0gbWVzc2FnZSkgOiAob3B0aW9ucyA9IG1lc3NhZ2UpO1xuICBpZiAoIW9wdGlvbnMgfHwgIW9wdGlvbnMubWVzc2FnZSAmJiAhb3B0aW9ucy5tZXNzYWdlSFRNTCkge1xuICAgIHV0aWwudGhyb3coJ05vdGlmaWNhdGlvbnMgbXVzdCBjb250YWluIGEgbWVzc2FnZScpO1xuICB9XG5cbiAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2J1dHRvbkxhYmVscycpIHx8IG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ2J1dHRvbkxhYmVsJykpIHtcbiAgICBvcHRpb25zLmJ1dHRvbkxhYmVscyA9IG9wdGlvbnMuYnV0dG9uTGFiZWxzIHx8IG9wdGlvbnMuYnV0dG9uTGFiZWw7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KG9wdGlvbnMuYnV0dG9uTGFiZWxzKSkge1xuICAgICAgb3B0aW9ucy5idXR0b25MYWJlbHMgPSBbb3B0aW9ucy5idXR0b25MYWJlbHMgfHwgJyddXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHV0aWwuZXh0ZW5kKHtcbiAgICAgIGNvbXBpbGU6IHBhcmFtID0+IHBhcmFtLFxuICAgICAgY2FsbGJhY2s6IHBhcmFtID0+IHBhcmFtLFxuICAgICAgYW5pbWF0aW9uOiAnZGVmYXVsdCcsXG4gICAgICBjYW5jZWxhYmxlOiBmYWxzZSxcbiAgICAgIHByaW1hcnlCdXR0b25JbmRleDogKG9wdGlvbnMuYnV0dG9uTGFiZWxzIHx8IGRlZmF1bHRzLmJ1dHRvbkxhYmVscyB8fCBbXSkubGVuZ3RoIC0gMVxuICAgIH0sIGRlZmF1bHRzLCBvcHRpb25zKTtcbn07XG5cbi8qKlxuICogQG9iamVjdCBvbnMubm90aWZpY2F0aW9uXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvbm90aWZpY2F0aW9uXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIFV0aWxpdHkgbWV0aG9kcyB0byBjcmVhdGUgZGlmZmVyZW50IGtpbmRzIG9mIG5vdGlmaWNhdGlvbnMuIFRoZXJlIGFyZSB0aHJlZSBtZXRob2RzIGF2YWlsYWJsZTpcbiAqXG4gKiAgICAgKiBgb25zLm5vdGlmaWNhdGlvbi5hbGVydCgpYFxuICogICAgICogYG9ucy5ub3RpZmljYXRpb24uY29uZmlybSgpYFxuICogICAgICogYG9ucy5ub3RpZmljYXRpb24ucHJvbXB0KClgXG4gKiAgICAgKiBgb25zLm5vdGlmaWNhdGlvbi50b2FzdCgpYFxuICpcbiAqICAgICBJdCB3aWxsIGF1dG9tYXRpY2FsbHkgZGlzcGxheSBhIE1hdGVyaWFsIERlc2lnbiBkaWFsb2cgb24gQW5kcm9pZCBkZXZpY2VzLlxuICogICBbL2VuXVxuICogICBbamFd44GE44GP44Gk44GL44Gu56iu6aGe44Gu44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44KS5L2c5oiQ44GZ44KL44Gf44KB44Gu44Om44O844OG44Kj44Oq44OG44Kj44Oh44K944OD44OJ44KS5Y+O44KB44Gf44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAqIEBleGFtcGxlXG4gKiBvbnMubm90aWZpY2F0aW9uLmFsZXJ0KCdIZWxsbywgd29ybGQhJyk7XG4gKlxuICogb25zLm5vdGlmaWNhdGlvbi5jb25maXJtKCdBcmUgeW91IHJlYWR5PycpXG4gKiAgIC50aGVuKFxuICogICAgIGZ1bmN0aW9uKGFuc3dlcikge1xuICogICAgICAgaWYgKGFuc3dlciA9PT0gMSkge1xuICogICAgICAgICBvbnMubm90aWZpY2F0aW9uLmFsZXJ0KCdMZXRcXCdzIGdvIScpO1xuICogICAgICAgfVxuICogICAgIH1cbiAqICAgKTtcbiAqXG4gKiBvbnMubm90aWZpY2F0aW9uLnByb21wdCgnSG93IG9sZCBhcmUgPycpXG4gKiAgIC50aGVuKFxuICogICAgIGZ1bmN0aW9uKGFnZSkge1xuICogICAgICAgb25zLm5vdGlmaWNhdGlvbi5hbGVydCgnWW91IGFyZSAnICsgYWdlICsgJyB5ZWFycyBvbGQuJyk7XG4gKiAgICAgfVxuICogICApO1xuICovXG5jb25zdCBub3RpZmljYXRpb24gPSB7fTtcblxubm90aWZpY2F0aW9uLl9jcmVhdGVBbGVydERpYWxvZyA9ICguLi5wYXJhbXMpID0+IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICBjb25zdCBvcHRpb25zID0gX25vcm1hbGl6ZUFyZ3VtZW50cyguLi5wYXJhbXMpO1xuICB1dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCgnQWxlcnREaWFsb2cnLCAnQWxlcnREaWFsb2dCdXR0b24nKTtcblxuICAvLyBQcm9tcHQgaW5wdXQgc3RyaW5nXG4gIGxldCBpbnB1dFN0cmluZyA9ICcnO1xuICBpZiAob3B0aW9ucy5pc1Byb21wdCkge1xuICAgIGlucHV0U3RyaW5nID0gYFxuICAgICAgPGlucHV0XG4gICAgICAgIGNsYXNzPVwidGV4dC1pbnB1dCB0ZXh0LWlucHV0LS11bmRlcmJhclwiXG4gICAgICAgIHR5cGU9XCIke29wdGlvbnMuaW5wdXRUeXBlIHx8ICd0ZXh0J31cIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIiR7b3B0aW9ucy5wbGFjZWhvbGRlciB8fCAnJ31cIlxuICAgICAgICB2YWx1ZT1cIiR7b3B0aW9ucy5kZWZhdWx0VmFsdWUgfHwgJyd9XCJcbiAgICAgICAgc3R5bGU9XCJ3aWR0aDogMTAwJTsgbWFyZ2luLXRvcDogMTBweDtcIlxuICAgICAgLz5cbiAgICBgO1xuICB9XG5cbiAgLy8gQnV0dG9ucyBzdHJpbmdcbiAgbGV0IGJ1dHRvbnMgPSAnJztcbiAgb3B0aW9ucy5idXR0b25MYWJlbHMuZm9yRWFjaCgobGFiZWwsIGluZGV4KSA9PiB7XG4gICAgYnV0dG9ucyArPSBgXG4gICAgICA8b25zLWFsZXJ0LWRpYWxvZy1idXR0b25cbiAgICAgICAgY2xhc3M9XCJcbiAgICAgICAgICAke2luZGV4ID09PSBvcHRpb25zLnByaW1hcnlCdXR0b25JbmRleCA/ICcgYWxlcnQtZGlhbG9nLWJ1dHRvbi0tcHJpbWFsJyA6ICcnfVxuICAgICAgICAgICR7b3B0aW9ucy5idXR0b25MYWJlbHMubGVuZ3RoIDw9IDIgPyAnIGFsZXJ0LWRpYWxvZy1idXR0b24tLXJvd2Zvb3RlcicgOiAnJ31cbiAgICAgICAgXCJcbiAgICAgICAgc3R5bGU9XCJwb3NpdGlvbjogcmVsYXRpdmU7XCI+XG4gICAgICAgICR7bGFiZWx9XG4gICAgICA8L29ucy1hbGVydC1kaWFsb2ctYnV0dG9uPlxuICAgIGA7XG4gIH0pO1xuXG4gIC8vIERpYWxvZyBFbGVtZW50XG4gIGxldCBlbCA9IHt9O1xuICBjb25zdCBfZGVzdHJveURpYWxvZyA9ICgpID0+IHtcbiAgICBpZiAoZWwuZGlhbG9nLm9uRGlhbG9nQ2FuY2VsKSB7XG4gICAgICBlbC5kaWFsb2cucmVtb3ZlRXZlbnRMaXN0ZW5lcignZGlhbG9nLWNhbmNlbCcsIGVsLmRpYWxvZy5vbkRpYWxvZ0NhbmNlbCk7XG4gICAgfVxuXG4gICAgT2JqZWN0LmtleXMoZWwpLmZvckVhY2goa2V5ID0+IGRlbGV0ZSBlbFtrZXldKTtcbiAgICBlbCA9IG51bGw7XG5cbiAgICBpZiAob3B0aW9ucy5kZXN0cm95IGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIG9wdGlvbnMuZGVzdHJveSgpO1xuICAgIH1cbiAgfTtcblxuICBlbC5kaWFsb2cgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdvbnMtYWxlcnQtZGlhbG9nJyk7XG4gIGVsLmRpYWxvZy5pbm5lckhUTUwgPSBgXG4gICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy1tYXNrXCJcbiAgICAgIHN0eWxlPVwiXG4gICAgICAgICR7b3B0aW9ucy5tYXNrQ29sb3IgPyAnYmFja2dyb3VuZC1jb2xvcjogJyArIG9wdGlvbnMubWFza0NvbG9yIDogJyd9XG4gICAgICBcIj48L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLWNvbnRhaW5lclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLXRpdGxlXCI+XG4gICAgICAgICAgJHtvcHRpb25zLnRpdGxlIHx8ICcnfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy1jb250ZW50XCI+XG4gICAgICAgICAgJHtvcHRpb25zLm1lc3NhZ2UgfHwgb3B0aW9ucy5tZXNzYWdlSFRNTH1cbiAgICAgICAgICAke2lucHV0U3RyaW5nfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cIlxuICAgICAgICAgIGFsZXJ0LWRpYWxvZy1mb290ZXJcbiAgICAgICAgICAke29wdGlvbnMuYnV0dG9uTGFiZWxzLmxlbmd0aCA8PSAyID8gJyBhbGVydC1kaWFsb2ctZm9vdGVyLS1yb3dmb290ZXInIDogJyd9XG4gICAgICAgIFwiPlxuICAgICAgICAgICR7YnV0dG9uc31cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYDtcbiAgY29udGVudFJlYWR5KGVsLmRpYWxvZyk7XG5cbiAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgX3NldEF0dHJpYnV0ZXMoZWwuZGlhbG9nLCBvcHRpb25zKTtcblxuICAvLyBQcm9tcHQgZXZlbnRzXG4gIGlmIChvcHRpb25zLmlzUHJvbXB0ICYmIG9wdGlvbnMuc3VibWl0T25FbnRlcikge1xuICAgIGVsLmlucHV0ID0gZWwuZGlhbG9nLnF1ZXJ5U2VsZWN0b3IoJy50ZXh0LWlucHV0Jyk7XG4gICAgZWwuaW5wdXQub25rZXlwcmVzcyA9IGV2ZW50ID0+IHtcbiAgICAgIGlmIChldmVudC5rZXlDb2RlID09PSAxMykge1xuICAgICAgICBlbC5kaWFsb2cuaGlkZSgpXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHJlc29sdmVWYWx1ZSA9IGVsLmlucHV0LnZhbHVlO1xuICAgICAgICAgICAgICBfZGVzdHJveURpYWxvZygpO1xuICAgICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHJlc29sdmVWYWx1ZSk7XG4gICAgICAgICAgICAgIHJlc29sdmUocmVzb2x2ZVZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLy8gQnV0dG9uIGV2ZW50c1xuICBlbC5mb290ZXIgPSBlbC5kaWFsb2cucXVlcnlTZWxlY3RvcignLmFsZXJ0LWRpYWxvZy1mb290ZXInKTtcbiAgdXRpbC5hcnJheUZyb20oZWwuZGlhbG9nLnF1ZXJ5U2VsZWN0b3JBbGwoJy5hbGVydC1kaWFsb2ctYnV0dG9uJykpLmZvckVhY2goKGJ1dHRvbkVsZW1lbnQsIGluZGV4KSA9PiB7XG4gICAgYnV0dG9uRWxlbWVudC5vbmNsaWNrID0gKCkgPT4ge1xuICAgICAgICBlbC5kaWFsb2cuaGlkZSgpXG4gICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgaWYgKGVsKSB7XG4gICAgICAgICAgICAgIGxldCByZXNvbHZlVmFsdWUgPSBpbmRleDtcbiAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuaXNQcm9tcHQpIHtcbiAgICAgICAgICAgICAgICByZXNvbHZlVmFsdWUgPSBpbmRleCA9PT0gb3B0aW9ucy5wcmltYXJ5QnV0dG9uSW5kZXggPyBlbC5pbnB1dC52YWx1ZSA6IG51bGw7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWwuZGlhbG9nLnJlbW92ZSgpO1xuICAgICAgICAgICAgICBfZGVzdHJveURpYWxvZygpO1xuICAgICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHJlc29sdmVWYWx1ZSk7XG4gICAgICAgICAgICAgIHJlc29sdmUocmVzb2x2ZVZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgZWwuZm9vdGVyLmFwcGVuZENoaWxkKGJ1dHRvbkVsZW1lbnQpO1xuICB9KTtcblxuICAvLyBDYW5jZWwgZXZlbnRzXG4gIGlmIChvcHRpb25zLmNhbmNlbGFibGUpIHtcbiAgICBlbC5kaWFsb2cuY2FuY2VsYWJsZSA9IHRydWU7XG4gICAgZWwuZGlhbG9nLm9uRGlhbG9nQ2FuY2VsID0gKCkgPT4ge1xuICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHtcbiAgICAgICAgZWwuZGlhbG9nLnJlbW92ZSgpO1xuICAgICAgICBfZGVzdHJveURpYWxvZygpO1xuICAgICAgfSk7XG4gICAgICBjb25zdCByZXNvbHZlVmFsdWUgPSBvcHRpb25zLmlzUHJvbXB0ID8gbnVsbCA6IC0xO1xuICAgICAgb3B0aW9ucy5jYWxsYmFjayhyZXNvbHZlVmFsdWUpO1xuICAgICAgcmVzb2x2ZShyZXNvbHZlVmFsdWUpO1xuICAgIH07XG4gICAgZWwuZGlhbG9nLmFkZEV2ZW50TGlzdGVuZXIoJ2RpYWxvZy1jYW5jZWwnLCBlbC5kaWFsb2cub25EaWFsb2dDYW5jZWwsIGZhbHNlKTtcbiAgfVxuXG4gIC8vIFNob3cgZGlhbG9nXG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZWwuZGlhbG9nKTtcbiAgb3B0aW9ucy5jb21waWxlKGVsLmRpYWxvZyk7XG4gIHNldEltbWVkaWF0ZSgoKSA9PiB7XG4gICAgZWwuZGlhbG9nLnNob3coKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICBpZiAoZWwuaW5wdXQgJiYgb3B0aW9ucy5pc1Byb21wdCAmJiBvcHRpb25zLmF1dG9mb2N1cykge1xuICAgICAgICAgIGNvbnN0IHN0ckxlbmd0aCA9IGVsLmlucHV0LnZhbHVlLmxlbmd0aDtcbiAgICAgICAgICBlbC5pbnB1dC5mb2N1cygpO1xuICAgICAgICAgIGVsLmlucHV0LnNldFNlbGVjdGlvblJhbmdlKHN0ckxlbmd0aCwgc3RyTGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH0pO1xufSk7XG5cbi8qKlxuICogQG1ldGhvZCBhbGVydFxuICogQHNpZ25hdHVyZSBhbGVydChtZXNzYWdlIFssIG9wdGlvbnNdIHwgb3B0aW9ucylcbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKiAgIFtlbl1XaWxsIHJlc29sdmUgdG8gdGhlIGluZGV4IG9mIHRoZSBidXR0b24gdGhhdCB3YXMgcHJlc3NlZCBvciBgLTFgIHdoZW4gY2FuY2VsZWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICogICBbZW5dTm90aWZpY2F0aW9uIG1lc3NhZ2UuIFRoaXMgYXJndW1lbnQgaXMgb3B0aW9uYWwgYnV0IGlmIGl0J3Mgbm90IGRlZmluZWQgZWl0aGVyIGBvcHRpb25zLm1lc3NhZ2VgIG9yIGBvcHRpb25zLm1lc3NhZ2VIVE1MYCBtdXN0IGJlIGRlZmluZWQgaW5zdGVhZC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLm1lc3NhZ2VdXG4gKiAgIFtlbl1Ob3RpZmljYXRpb24gbWVzc2FnZS5bL2VuXVxuICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44Gr6KGo56S644GZ44KL5paH5a2X5YiX44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tZXNzYWdlSFRNTF1cbiAqICAgW2VuXU5vdGlmaWNhdGlvbiBtZXNzYWdlIGluIEhUTUwuWy9lbl1cbiAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBq+ihqOekuuOBmeOCi0hUTUzjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmcgfCBBcnJheX0gW29wdGlvbnMuYnV0dG9uTGFiZWxzXVxuICogICBbZW5dTGFiZWxzIGZvciB0aGUgYnV0dG9ucy4gRGVmYXVsdCBpcyBgXCJPS1wiYC5bL2VuXVxuICogICBbamFd56K66KqN44Oc44K/44Oz44Gu44Op44OZ44Or44KS5oyH5a6a44GX44G+44GZ44CCXCJPS1wi44GM44OH44OV44Kp44Or44OI44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5wcmltYXJ5QnV0dG9uSW5kZXhdXG4gKiAgIFtlbl1JbmRleCBvZiBwcmltYXJ5IGJ1dHRvbi4gRGVmYXVsdCBpcyB0aGUgbGFzdCBvbmUuWy9lbl1cbiAqICAgW2phXeODl+ODqeOCpOODnuODquODnOOCv+ODs+OBruOCpOODs+ODh+ODg+OCr+OCueOCkuaMh+WumuOBl+OBvuOBmeOAguODh+ODleOCqeODq+ODiOOBryAwIOOBp+OBmeOAglsvamFdXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmNhbmNlbGFibGVdXG4gKiAgIFtlbl1XaGV0aGVyIHRoZSBkaWFsb2cgaXMgY2FuY2VsYWJsZSBvciBub3QuIERlZmF1bHQgaXMgYGZhbHNlYC4gSWYgdGhlIGRpYWxvZyBpcyBjYW5jZWxhYmxlIGl0IGNhbiBiZSBjbG9zZWQgYnkgY2xpY2tpbmcgdGhlIGJhY2tncm91bmQgb3IgcHJlc3NpbmcgdGhlIEFuZHJvaWQgYmFjayBidXR0b24uWy9lbl1cbiAqICAgW2phXeODgOOCpOOCouODreOCsOOBjOOCreODo+ODs+OCu+ODq+WPr+iDveOBi+OBqeOBhuOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgbm9uZWAgYW5kIGBmYWRlYC4gRGVmYXVsdCBpcyBgZmFkZWAuWy9lbl1cbiAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOCkuihqOekuuOBmeOCi+mam+OBruOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwiLCBcImZhZGVcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuaWRdXG4gKiAgIFtlbl1UaGUgYDxvbnMtYWxlcnQtZGlhbG9nPmAgZWxlbWVudCdzIElELlsvZW5dXG4gKiAgIFtqYV1vbnMtYWxlcnQtZGlhbG9n6KaB57Sg44GuSUTjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmNsYXNzXVxuICogICBbZW5dVGhlIGA8b25zLWFsZXJ0LWRpYWxvZz5gIGVsZW1lbnQncyBjbGFzcy5bL2VuXVxuICogICBbamFdb25zLWFsZXJ0LWRpYWxvZ+imgee0oOOBrmNsYXNz44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy50aXRsZV1cbiAqICAgW2VuXURpYWxvZyB0aXRsZS4gRGVmYXVsdCBpcyBgXCJBbGVydFwiYC5bL2VuXVxuICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44Gu5LiK6YOo44Gr6KGo56S644GZ44KL44K/44Kk44OI44Or44KS5oyH5a6a44GX44G+44GZ44CCXCJBbGVydFwi44GM44OH44OV44Kp44Or44OI44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tb2RpZmllcl1cbiAqICAgW2VuXU1vZGlmaWVyIGZvciB0aGUgZGlhbG9nLlsvZW5dXG4gKiAgIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga5tb2RpZmllcuWxnuaAp+OBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMubWFza0NvbG9yXVxuICogICBbZW5dQ29sb3Igb2YgdGhlIGJhY2tncm91bmQgbWFzay4gRGVmYXVsdCBpcyBcInJnYmEoMCwgMCwgMCwgMC4yKVwiIChcInJnYmEoMCwgMCwgMCwgMC4zKVwiIGZvciBNYXRlcmlhbCkuWy9lbl1cbiAqICAgW2phXeiDjOaZr+OBruODnuOCueOCr+OBruiJsuOCkuaMh+WumuOBl+OBvuOBmeOAglwicmdiYSgwLCAwLCAwLCAwLjIpXCLjgYzjg4fjg5Xjgqnjg6vjg4jlgKTjgafjgZnjgIJbL2phXVxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gKiAgIFtlbl1GdW5jdGlvbiB0aGF0IGV4ZWN1dGVzIGFmdGVyIGRpYWxvZyBoYXMgYmVlbiBjbG9zZWQuWy9lbl1cbiAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBjOmWieOBmOOCieOCjOOBn+aZguOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIERpc3BsYXkgYW4gYWxlcnQgZGlhbG9nIHRvIHNob3cgdGhlIHVzZXIgYSBtZXNzYWdlLlxuICpcbiAqICAgICBUaGUgY29udGVudCBvZiB0aGUgbWVzc2FnZSBjYW4gYmUgZWl0aGVyIHNpbXBsZSB0ZXh0IG9yIEhUTUwuXG4gKlxuICogICAgIEl0IGNhbiBiZSBjYWxsZWQgaW4gdGhlIGZvbGxvd2luZyB3YXlzOlxuICpcbiAqICAgICBgYGBcbiAqICAgICBvbnMubm90aWZpY2F0aW9uLmFsZXJ0KG1lc3NhZ2UsIG9wdGlvbnMpO1xuICogICAgIG9ucy5ub3RpZmljYXRpb24uYWxlcnQob3B0aW9ucyk7XG4gKiAgICAgYGBgXG4gKlxuICogICAgIE11c3Qgc3BlY2lmeSBlaXRoZXIgYG1lc3NhZ2VgIG9yIGBtZXNzYWdlSFRNTGAuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1cbiAqICAgICDjg6bjg7zjgrbjg7zjgbjjg6Hjg4Pjgrvjg7zjgrjjgpLopovjgZvjgovjgZ/jgoHjga7jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjgpLooajnpLrjgZfjgb7jgZnjgIJcbiAqICAgICDooajnpLrjgZnjgovjg6Hjg4Pjgrvjg7zjgrjjga/jgIHjg4bjgq3jgrnjg4jjgYvjgoLjgZfjgY/jga9IVE1M44KS5oyH5a6a44Gn44GN44G+44GZ44CCXG4gKiAgICAg44GT44Gu44Oh44K944OD44OJ44Gu5byV5pWw44Gr44Gv44CBb3B0aW9ucy5tZXNzYWdl44KC44GX44GP44Gvb3B0aW9ucy5tZXNzYWdlSFRNTOOBruOBqeOBoeOCieOBi+OCkuW/heOBmuaMh+WumuOBmeOCi+W/heimgeOBjOOBguOCiuOBvuOBmeOAglxuICogICBbL2phXVxuICovXG5ub3RpZmljYXRpb24uYWxlcnQgPSAobWVzc2FnZSwgb3B0aW9ucykgPT5cbiAgbm90aWZpY2F0aW9uLl9jcmVhdGVBbGVydERpYWxvZyhtZXNzYWdlLCBvcHRpb25zLCB7XG4gICAgYnV0dG9uTGFiZWxzOiBbJ09LJ10sXG4gICAgdGl0bGU6ICdBbGVydCdcbiAgfSk7XG5cbi8qKlxuICogQG1ldGhvZCBjb25maXJtXG4gKiBAc2lnbmF0dXJlIGNvbmZpcm0obWVzc2FnZSBbLCBvcHRpb25zXSB8IG9wdGlvbnMpXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dV2lsbCByZXNvbHZlIHRvIHRoZSBpbmRleCBvZiB0aGUgYnV0dG9uIHRoYXQgd2FzIHByZXNzZWQgb3IgYC0xYCB3aGVuIGNhbmNlbGVkLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAqICAgW2VuXU5vdGlmaWNhdGlvbiBtZXNzYWdlLiBUaGlzIGFyZ3VtZW50IGlzIG9wdGlvbmFsIGJ1dCBpZiBpdCdzIG5vdCBkZWZpbmVkIGVpdGhlciBgb3B0aW9ucy5tZXNzYWdlYCBvciBgb3B0aW9ucy5tZXNzYWdlSFRNTGAgbXVzdCBiZSBkZWZpbmVkIGluc3RlYWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogQHBhcmFtIHtBcnJheX0gW29wdGlvbnMuYnV0dG9uTGFiZWxzXVxuICogICBbZW5dTGFiZWxzIGZvciB0aGUgYnV0dG9ucy4gRGVmYXVsdCBpcyBgW1wiQ2FuY2VsXCIsIFwiT0tcIl1gLlsvZW5dXG4gKiAgIFtqYV3jg5zjgr/jg7Pjga7jg6njg5njg6vjga7phY3liJfjgpLmjIflrprjgZfjgb7jgZnjgIJbXCJDYW5jZWxcIiwgXCJPS1wiXeOBjOODh+ODleOCqeODq+ODiOOBp+OBmeOAglsvamFdXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMucHJpbWFyeUJ1dHRvbkluZGV4XVxuICogICBbZW5dSW5kZXggb2YgcHJpbWFyeSBidXR0b24uIERlZmF1bHQgaXMgdGhlIGxhc3Qgb25lLlsvZW5dXG4gKiAgIFtqYV3jg5fjg6njgqTjg57jg6rjg5zjgr/jg7Pjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgpLmjIflrprjgZfjgb7jgZnjgILjg4fjg5Xjgqnjg6vjg4jjga8gMSDjgafjgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBEaXNwbGF5IGEgZGlhbG9nIHRvIGFzayB0aGUgdXNlciBmb3IgY29uZmlybWF0aW9uLiBFeHRlbmRzIGBhbGVydCgpYCBwYXJhbWV0ZXJzLlxuICogICAgIFRoZSBkZWZhdWx0IGJ1dHRvbiBsYWJlbHMgYXJlIGBcIkNhbmNlbFwiYCBhbmQgYFwiT0tcImAgYnV0IHRoZXkgY2FuIGJlIGN1c3RvbWl6ZWQuXG4gKlxuICogICAgIEl0IGNhbiBiZSBjYWxsZWQgaW4gdGhlIGZvbGxvd2luZyB3YXlzOlxuICpcbiAqICAgICBgYGBcbiAqICAgICBvbnMubm90aWZpY2F0aW9uLmNvbmZpcm0obWVzc2FnZSwgb3B0aW9ucyk7XG4gKiAgICAgb25zLm5vdGlmaWNhdGlvbi5jb25maXJtKG9wdGlvbnMpO1xuICogICAgIGBgYFxuICpcbiAqICAgICBNdXN0IHNwZWNpZnkgZWl0aGVyIGBtZXNzYWdlYCBvciBgbWVzc2FnZUhUTUxgLlxuICogICBbL2VuXVxuICogICBbamFdXG4gKiAgICAg44Om44O844K244Gr56K66KqN44KS5L+D44GZ44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GX44G+44GZ44CCXG4gKiAgICAg44OH44Kq44Or44Go44Gu44Oc44K/44Oz44Op44OZ44Or44Gv44CBXCJDYW5jZWxcIuOBqFwiT0tcIuOBp+OBmeOBjOOAgeOBk+OCjOOBr+OBk+OBruODoeOCveODg+ODieOBruW8leaVsOOBp+OCq+OCueOCv+ODnuOCpOOCuuOBp+OBjeOBvuOBmeOAglxuICogICAgIOOBk+OBruODoeOCveODg+ODieOBruW8leaVsOOBq+OBr+OAgW9wdGlvbnMubWVzc2FnZeOCguOBl+OBj+OBr29wdGlvbnMubWVzc2FnZUhUTUzjga7jganjgaHjgonjgYvjgpLlv4XjgZrmjIflrprjgZnjgovlv4XopoHjgYzjgYLjgorjgb7jgZnjgIJcbiAqICAgWy9qYV1cbiAqL1xubm90aWZpY2F0aW9uLmNvbmZpcm0gPSAobWVzc2FnZSwgb3B0aW9ucykgPT5cbiAgbm90aWZpY2F0aW9uLl9jcmVhdGVBbGVydERpYWxvZyhtZXNzYWdlLCBvcHRpb25zLCB7XG4gICAgYnV0dG9uTGFiZWxzOiBbJ0NhbmNlbCcsICdPSyddLFxuICAgIHRpdGxlOiAnQ29uZmlybSdcbiAgfSk7XG5cbi8qKlxuICogQG1ldGhvZCBwcm9tcHRcbiAqIEBzaWduYXR1cmUgcHJvbXB0KG1lc3NhZ2UgWywgb3B0aW9uc10gfCBvcHRpb25zKVxuICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAqICAgW2VuXU5vdGlmaWNhdGlvbiBtZXNzYWdlLiBUaGlzIGFyZ3VtZW50IGlzIG9wdGlvbmFsIGJ1dCBpZiBpdCdzIG5vdCBkZWZpbmVkIGVpdGhlciBgb3B0aW9ucy5tZXNzYWdlYCBvciBgb3B0aW9ucy5tZXNzYWdlSFRNTGAgbXVzdCBiZSBkZWZpbmVkIGluc3RlYWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dV2lsbCByZXNvbHZlIHRvIHRoZSBpbnB1dCB2YWx1ZSB3aGVuIHRoZSBkaWFsb2cgaXMgY2xvc2VkIG9yIGBudWxsYCB3aGVuIGNhbmNlbGVkLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZyB8IEFycmF5fSBbb3B0aW9ucy5idXR0b25MYWJlbHNdXG4gKiAgIFtlbl1MYWJlbHMgZm9yIHRoZSBidXR0b25zLiBEZWZhdWx0IGlzIGBcIk9LXCJgLlsvZW5dXG4gKiAgIFtqYV3norroqo3jg5zjgr/jg7Pjga7jg6njg5njg6vjgpLmjIflrprjgZfjgb7jgZnjgIJcIk9LXCLjgYzjg4fjg5Xjgqnjg6vjg4jjgafjgZnjgIJbL2phXVxuICogQHBhcmFtIHtOdW1iZXJ9IFtvcHRpb25zLnByaW1hcnlCdXR0b25JbmRleF1cbiAqICAgW2VuXUluZGV4IG9mIHByaW1hcnkgYnV0dG9uLiBEZWZhdWx0IGlzIHRoZSBsYXN0IG9uZS5bL2VuXVxuICogICBbamFd44OX44Op44Kk44Oe44Oq44Oc44K/44Oz44Gu44Kk44Oz44OH44OD44Kv44K544KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44GvIDAg44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wbGFjZWhvbGRlcl1cbiAqICAgW2VuXVBsYWNlaG9sZGVyIGZvciB0aGUgdGV4dCBpbnB1dC5bL2VuXVxuICogICBbamFd44OG44Kt44K544OI5qyE44Gu44OX44Os44O844K544Ob44Or44OA44Gr6KGo56S644GZ44KL44OG44Kt44K544OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5kZWZhdWx0VmFsdWVdXG4gKiAgIFtlbl1EZWZhdWx0IHZhbHVlIGZvciB0aGUgdGV4dCBpbnB1dC5bL2VuXVxuICogICBbamFd44OG44Kt44K544OI5qyE44Gu44OH44OV44Kp44Or44OI44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5pbnB1dFR5cGVdXG4gKiAgIFtlbl1UeXBlIG9mIHRoZSBpbnB1dCBlbGVtZW50IChgcGFzc3dvcmRgLCBgZGF0ZWAuLi4pLiBEZWZhdWx0IGlzIGB0ZXh0YC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuYXV0b2ZvY3VzXVxuICogICBbZW5dQXV0b2ZvY3VzIHRoZSBpbnB1dCBlbGVtZW50LiBEZWZhdWx0IGlzIGB0cnVlYC4gSW4gQ29yZG92YSwgYEtleWJvYXJkRGlzcGxheVJlcXVpcmVzVXNlckFjdGlvbmAgaW4gYGNvbmZpZy54bWxgIG11c3QgYmUgYGZhbHNlYCB0byBhY3RpdmF0ZSB0aGlzIGZlYXR1cmUuWy9lbl1cbiAqICAgW2phXWlucHV06KaB57Sg44Gr6Ieq5YuV55qE44Gr44OV44Kp44O844Kr44K544GZ44KL44GL44Gp44GG44GL44KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44GvdHJ1ZeOBp+OBmeOAgkNvcmRvdmHnkrDlooPjgafjga/jgIHjgZPjga7mqZ/og73jgpLmnInlirnjgavjgZnjgovjgZ/jgoHjgavjga8gYGNvbmZpZy54bWxgIOOBpyBgS2V5Ym9hcmREaXNwbGF5UmVxdWlyZXNVc2VyQWN0aW9uYCDjgpIgYGZhbHNlYCDjgavoqK3lrprjgZnjgovlv4XopoHjgYzjgYLjgorjgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5zdWJtaXRPbkVudGVyXVxuICogICBbZW5dU3VibWl0IGF1dG9tYXRpY2FsbHkgd2hlbiBlbnRlciBpcyBwcmVzc2VkLiBEZWZhdWx0IGlzIGB0cnVlYC5bL2VuXVxuICogICBbamFdRW50ZXLjgYzmirzjgZXjgozjgZ/pmpvjgavjgZ3jga5mb3Jt44KSc3VibWl044GZ44KL44GL44Gp44GG44GL44KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44GvdHJ1ZeOBp+OBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIERpc3BsYXkgYSBkaWFsb2cgd2l0aCBhIHByb21wdCB0byBhc2sgdGhlIHVzZXIgYSBxdWVzdGlvbi4gRXh0ZW5kcyBgYWxlcnQoKWAgcGFyYW1ldGVycy5cbiAqXG4gKiAgICAgSXQgY2FuIGJlIGNhbGxlZCBpbiB0aGUgZm9sbG93aW5nIHdheXM6XG4gKlxuICogICAgIGBgYFxuICogICAgIG9ucy5ub3RpZmljYXRpb24ucHJvbXB0KG1lc3NhZ2UsIG9wdGlvbnMpO1xuICogICAgIG9ucy5ub3RpZmljYXRpb24ucHJvbXB0KG9wdGlvbnMpO1xuICogICAgIGBgYFxuICpcbiAqICAgICBNdXN0IHNwZWNpZnkgZWl0aGVyIGBtZXNzYWdlYCBvciBgbWVzc2FnZUhUTUxgLlxuICogICBbL2VuXVxuICogICBbamFdXG4gKiAgICAg44Om44O844K244O844Gr5YWl5Yqb44KS5L+D44GZ44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GX44G+44GZ44CCXG4gKiAgICAg44GT44Gu44Oh44K944OD44OJ44Gu5byV5pWw44Gr44Gv44CBb3B0aW9ucy5tZXNzYWdl44KC44GX44GP44Gvb3B0aW9ucy5tZXNzYWdlSFRNTOOBruOBqeOBoeOCieOBi+OCkuW/heOBmuaMh+WumuOBmeOCi+W/heimgeOBjOOBguOCiuOBvuOBmeOAglxuICogICBbL2phXVxuICovXG5ub3RpZmljYXRpb24ucHJvbXB0ID0gKG1lc3NhZ2UsIG9wdGlvbnMpID0+XG4gIG5vdGlmaWNhdGlvbi5fY3JlYXRlQWxlcnREaWFsb2cobWVzc2FnZSwgb3B0aW9ucywge1xuICAgIGJ1dHRvbkxhYmVsczogWydPSyddLFxuICAgIHRpdGxlOiAnQWxlcnQnLFxuICAgIGlzUHJvbXB0OiB0cnVlLFxuICAgIGF1dG9mb2N1czogdHJ1ZSxcbiAgICBzdWJtaXRPbkVudGVyOiB0cnVlXG4gIH0pO1xuXG4vKipcbiAqIEBtZXRob2QgdG9hc3RcbiAqIEBzaWduYXR1cmUgdG9hc3QobWVzc2FnZSBbLCBvcHRpb25zXSB8IG9wdGlvbnMpXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dV2lsbCByZXNvbHZlIHdoZW4gdGhlIHRvYXN0IGlzIGhpZGRlbi5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gKiAgIFtlbl1Ub2FzdCBtZXNzYWdlLiBUaGlzIGFyZ3VtZW50IGlzIG9wdGlvbmFsIGJ1dCBpZiBpdCdzIG5vdCBkZWZpbmVkIHRoZW4gYG9wdGlvbnMubWVzc2FnZWAgbXVzdCBiZSBkZWZpbmVkIGluc3RlYWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tZXNzYWdlXVxuICogICBbZW5dTm90aWZpY2F0aW9uIG1lc3NhZ2UuWy9lbl1cbiAqICAgW2phXeODiOODvOOCueODiOOBq+ihqOekuuOBmeOCi+aWh+Wtl+WIl+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYnV0dG9uTGFiZWxdXG4gKiAgIFtlbl1MYWJlbCBmb3IgdGhlIGJ1dHRvbi5bL2VuXVxuICogICBbamFd56K66KqN44Oc44K/44Oz44Gu44Op44OZ44Or44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBub25lYCwgYGZhZGVgLCBgYXNjZW5kYCwgYGxpZnRgIGFuZCBgZmFsbGAuIERlZmF1bHQgaXMgYGFzY2VuZGAgZm9yIEFuZHJvaWQgYW5kIGBsaWZ0YCBmb3IgaU9TLlsvZW5dXG4gKiAgIFtqYV3jg4jjg7zjgrnjg4jjgpLooajnpLrjgZnjgovpmpvjga7jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIiwgXCJmYWRlXCIsIFwiYXNjZW5kXCIsIFwibGlmdFwiLCBcImZhbGxcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMudGltZW91dF1cbiAqICAgW2VuXU51bWJlciBvZiBtaWxpc2Vjb25kcyB3aGVyZSB0aGUgdG9hc3QgaXMgdmlzaWJsZSBiZWZvcmUgaGlkaW5nIGF1dG9tYXRpY2FsbHkuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmZvcmNlXVxuICogICBbZW5dSWYgYHRydWVgLCB0aGUgdG9hc3Qgc2tpcHMgdGhlIG5vdGlmaWNhdGlvbiBxdWV1ZSBhbmQgaXMgc2hvd24gaW1tZWRpYXRlbHkuIERlZmF1bHRzIHRvIGBmYWxzZWAuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuaWRdXG4gKiAgIFtlbl1UaGUgYDxvbnMtdG9hc3Q+YCBlbGVtZW50J3MgSUQuWy9lbl1cbiAqICAgW2phXW9ucy10b2FzdOimgee0oOOBrklE44CCWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5jbGFzc11cbiAqICAgW2VuXVRoZSBgPG9ucy10b2FzdD5gIGVsZW1lbnQncyBjbGFzcy5bL2VuXVxuICogICBbamFdb25zLXRvYXN06KaB57Sg44GuY2xhc3PjgIJbL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLm1vZGlmaWVyXVxuICogICBbZW5dTW9kaWZpZXIgZm9yIHRoZSBlbGVtZW50LlsvZW5dXG4gKiAgIFtqYV3jg4jjg7zjgrnjg4jjga5tb2RpZmllcuWxnuaAp+OBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAqICAgW2VuXUZ1bmN0aW9uIHRoYXQgZXhlY3V0ZXMgYWZ0ZXIgdG9hc3QgaGFzIGJlZW4gaGlkZGVuLlsvZW5dXG4gKiAgIFtqYV3jg4jjg7zjgrnjg4jjgYzplonjgZjjgonjgozjgZ/mmYLjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBEaXNwbGF5IGEgc2ltcGxlIG5vdGlmaWNhdGlvbiB0b2FzdCB3aXRoIGFuIG9wdGlvbmFsIGJ1dHRvbiB0aGF0IGNhbiBiZSB1c2VkIGZvciBzaW1wbGUgYWN0aW9ucy5cbiAqXG4gKiAgICAgSXQgY2FuIGJlIGNhbGxlZCBpbiB0aGUgZm9sbG93aW5nIHdheXM6XG4gKlxuICogICAgIGBgYFxuICogICAgIG9ucy5ub3RpZmljYXRpb24udG9hc3QobWVzc2FnZSwgb3B0aW9ucyk7XG4gKiAgICAgb25zLm5vdGlmaWNhdGlvbi50b2FzdChvcHRpb25zKTtcbiAqICAgICBgYGBcbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKi9cbm5vdGlmaWNhdGlvbi50b2FzdCA9IChtZXNzYWdlLCBvcHRpb25zKSA9PiB7XG4gIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICB1dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCgnVG9hc3QnKTsgLy8gVGhyb3dzIGVycm9yLCBtdXN0IGJlIGluc2lkZSBwcm9taXNlXG5cbiAgICBvcHRpb25zID0gX25vcm1hbGl6ZUFyZ3VtZW50cyhtZXNzYWdlLCBvcHRpb25zLCB7XG4gICAgICB0aW1lb3V0OiAwLFxuICAgICAgZm9yY2U6IGZhbHNlXG4gICAgfSk7XG5cbiAgICBsZXQgdG9hc3QgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoYFxuICAgICAgPG9ucy10b2FzdD5cbiAgICAgICAgJHtvcHRpb25zLm1lc3NhZ2V9XG4gICAgICAgICR7b3B0aW9ucy5idXR0b25MYWJlbHMgPyBgPGJ1dHRvbj4ke29wdGlvbnMuYnV0dG9uTGFiZWxzWzBdfTwvYnV0dG9uPmAgOiAnJ31cbiAgICAgIDwvb25zLXRvYXN0PlxuICAgIGApO1xuXG4gICAgX3NldEF0dHJpYnV0ZXModG9hc3QsIG9wdGlvbnMpO1xuXG4gICAgY29uc3QgZmluaXNoID0gdmFsdWUgPT4ge1xuICAgICAgaWYgKHRvYXN0KSB7XG4gICAgICAgIHRvYXN0XG4gICAgICAgIC5oaWRlKClcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIGlmICh0b2FzdCkge1xuICAgICAgICAgICAgdG9hc3QucmVtb3ZlKCk7XG4gICAgICAgICAgICB0b2FzdCA9IG51bGw7XG4gICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHZhbHVlKTtcbiAgICAgICAgICAgIHJlc29sdmUodmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIGlmIChvcHRpb25zLmJ1dHRvbkxhYmVscykge1xuICAgICAgdXRpbC5maW5kQ2hpbGQodG9hc3QuX3RvYXN0LCAnYnV0dG9uJykub25jbGljayA9ICgpID0+IGZpbmlzaCgwKTtcbiAgICB9XG5cbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHRvYXN0KTtcbiAgICBvcHRpb25zLmNvbXBpbGUodG9hc3QpO1xuXG4gICAgY29uc3Qgc2hvdyA9ICgpID0+IHtcbiAgICAgIHRvYXN0LnBhcmVudEVsZW1lbnQgJiYgdG9hc3Quc2hvdyhvcHRpb25zKS50aGVuKCgpID0+IHtcbiAgICAgICAgaWYgKG9wdGlvbnMudGltZW91dCkge1xuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gZmluaXNoKC0xKSwgb3B0aW9ucy50aW1lb3V0KVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgc2V0SW1tZWRpYXRlKCgpID0+IG9wdGlvbnMuZm9yY2UgPyBzaG93KCkgOiBUb2FzdFF1ZXVlLmFkZChzaG93LCBwcm9taXNlKSlcbiAgfSk7XG5cbiAgcmV0dXJuIHByb21pc2U7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBub3RpZmljYXRpb247XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuL3V0aWwnO1xuXG4vLyBWYWxpZGF0ZSBwYXJhbWV0ZXJzXG5jb25zdCBjaGVja09wdGlvbnMgPSBvcHRpb25zID0+IHtcbiAgY29uc3QgZXJyID0gKHByb3AsIHR5cGUgPSAnRnVuY3Rpb24nKSA9PiB1dGlsLnRocm93KGBcIm9wdGlvbnMuJHtwcm9wfVwiIG11c3QgYmUgYW4gaW5zdGFuY2Ugb2YgJHt0eXBlfWApO1xuICBjb25zdCBoYXNPd25Qcm9wZXJ0eSA9IHByb3AgPT4gT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwob3B0aW9ucywgcHJvcCk7XG4gIGNvbnN0IGluc3RhbmNlT2YgPSAocHJvcCwgdHlwZSA9IEZ1bmN0aW9uKSA9PiBvcHRpb25zW3Byb3BdIGluc3RhbmNlb2YgdHlwZTtcblxuICBjb25zdCBiID0gJ2J1dHRvbnMnLCBjYiA9ICdjYWxsYmFjaycsIGMgPSAnY29tcGlsZScsIGQgPSAnZGVzdHJveSc7XG4gICghaGFzT3duUHJvcGVydHkoYikgfHwgIWluc3RhbmNlT2YoYiwgQXJyYXkpKSAmJiBlcnIoYiwgJ0FycmF5Jyk7XG4gIChoYXNPd25Qcm9wZXJ0eShjYikgJiYgIWluc3RhbmNlT2YoY2IpKSAmJiBlcnIoY2IpO1xuICAoaGFzT3duUHJvcGVydHkoYykgJiYgIWluc3RhbmNlT2YoYykpICYmIGVycihjKTtcbiAgKGhhc093blByb3BlcnR5KGQpICYmICFpbnN0YW5jZU9mKGQpKSAmJiBlcnIoZCk7XG59O1xuXG4vLyBBY3Rpb24gU2hlZXRcbmV4cG9ydCBkZWZhdWx0IChvcHRpb25zID0ge30pID0+IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICB1dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCgnQWN0aW9uU2hlZXQnKTtcbiAgY2hlY2tPcHRpb25zKG9wdGlvbnMpO1xuXG4gIC8vIE1haW4gY29tcG9uZW50XG4gIGxldCBhY3Rpb25TaGVldCA9IHV0aWwuY3JlYXRlRWxlbWVudChgXG4gICAgPG9ucy1hY3Rpb24tc2hlZXRcbiAgICAgICR7b3B0aW9ucy50aXRsZSA/IGB0aXRsZT1cIiR7b3B0aW9ucy50aXRsZX1cImAgOiAnJ31cbiAgICAgICR7b3B0aW9ucy5jYW5jZWxhYmxlID8gJ2NhbmNlbGFibGUnIDogJyd9XG4gICAgICAke29wdGlvbnMubW9kaWZpZXIgPyBgbW9kaWZpZXI9XCIke29wdGlvbnMubW9kaWZpZXJ9XCJgIDogJyd9XG4gICAgICAke29wdGlvbnMubWFza0NvbG9yID8gYG1hc2stY29sb3I9XCIke29wdGlvbnMubWFza0NvbG9yfVwiYCA6ICcnfVxuICAgICAgJHtvcHRpb25zLmlkID8gYGlkPVwiJHtvcHRpb25zLmlkfVwiYCA6ICcnfVxuICAgICAgJHtvcHRpb25zLmNsYXNzID8gYGNsYXNzPVwiJHtvcHRpb25zLmNsYXNzfVwiYCA6ICcnfVxuICAgID5cbiAgICAgIDxkaXYgY2xhc3M9XCJhY3Rpb24tc2hlZXRcIj48L2Rpdj5cbiAgICA8L29ucy1hY3Rpb24tc2hlZXQ+XG4gIGApO1xuXG4gIC8vIFJlc29sdmUgYWN0aW9uIGFuZCBjbGVhbiB1cFxuICBjb25zdCBmaW5pc2ggPSAoZXZlbnQsIGluZGV4ID0gLTEpID0+IHtcbiAgICBpZiAoYWN0aW9uU2hlZXQpIHtcbiAgICAgIG9wdGlvbnMuZGVzdHJveSAmJiBvcHRpb25zLmRlc3Ryb3koYWN0aW9uU2hlZXQpO1xuXG4gICAgICBhY3Rpb25TaGVldC5yZW1vdmVFdmVudExpc3RlbmVyKCdkaWFsb2ctY2FuY2VsJywgZmluaXNoLCBmYWxzZSk7XG4gICAgICBhY3Rpb25TaGVldC5yZW1vdmUoKTtcbiAgICAgIGFjdGlvblNoZWV0ID0gbnVsbDtcblxuICAgICAgb3B0aW9ucy5jYWxsYmFjayAmJiBvcHRpb25zLmNhbGxiYWNrKGluZGV4KTtcbiAgICAgIHJlc29sdmUoaW5kZXgpO1xuICAgIH1cbiAgfTtcblxuICAvLyBMaW5rIGNhbmNlbCBoYW5kbGVyXG4gIGFjdGlvblNoZWV0LmFkZEV2ZW50TGlzdGVuZXIoJ2RpYWxvZy1jYW5jZWwnLCBmaW5pc2gsIGZhbHNlKTtcblxuICAvLyBDcmVhdGUgYnV0dG9ucyBhbmQgbGluayBhY3Rpb24gaGFuZGxlclxuICBjb25zdCBidXR0b25zID0gZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpO1xuICBvcHRpb25zLmJ1dHRvbnMuZm9yRWFjaCgoaXRlbSwgaW5kZXgpID0+IHtcbiAgICBjb25zdCBidXR0b25PcHRpb25zID0gKHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJykgPyB7IGxhYmVsOiBpdGVtIH0gOiB7IC4uLml0ZW0gfTtcbiAgICBpZiAob3B0aW9ucy5kZXN0cnVjdGl2ZSA9PT0gaW5kZXgpIHtcbiAgICAgIGJ1dHRvbk9wdGlvbnMubW9kaWZpZXIgPSAoYnV0dG9uT3B0aW9ucy5tb2RpZmllciB8fCAnJykgKyAnIGRlc3RydWN0aXZlJztcbiAgICB9XG5cbiAgICBjb25zdCBidXR0b24gPSB1dGlsLmNyZWF0ZUVsZW1lbnQoYFxuICAgICAgPG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uXG4gICAgICAgICR7YnV0dG9uT3B0aW9ucy5pY29uID8gYGljb249XCIke2J1dHRvbk9wdGlvbnMuaWNvbn1cImAgOiAnJ31cbiAgICAgICAgJHtidXR0b25PcHRpb25zLm1vZGlmaWVyID8gYG1vZGlmaWVyPVwiJHtidXR0b25PcHRpb25zLm1vZGlmaWVyfVwiYCA6ICcnfVxuICAgICAgPlxuICAgICAgICAke2J1dHRvbk9wdGlvbnMubGFiZWx9XG4gICAgICA8L29ucy1hY3Rpb24tc2hlZXQtYnV0dG9uPlxuICAgIGApO1xuXG4gICAgYnV0dG9uLm9uY2xpY2sgPSBldmVudCA9PiBhY3Rpb25TaGVldC5oaWRlKCkudGhlbigoKSA9PiBmaW5pc2goZXZlbnQsIGluZGV4KSk7XG4gICAgYnV0dG9ucy5hcHBlbmRDaGlsZChidXR0b24pO1xuICB9KTtcblxuICAvLyBGaW5pc2ggY29tcG9uZW50IGFuZCBhdHRhY2hcbiAgdXRpbC5maW5kQ2hpbGQoYWN0aW9uU2hlZXQsICcuYWN0aW9uLXNoZWV0JykuYXBwZW5kQ2hpbGQoYnV0dG9ucyk7XG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoYWN0aW9uU2hlZXQpO1xuICBvcHRpb25zLmNvbXBpbGUgJiYgb3B0aW9ucy5jb21waWxlKGVsLmRpYWxvZyk7XG5cbiAgLy8gU2hvd1xuICBzZXRJbW1lZGlhdGUoKCkgPT4gYWN0aW9uU2hlZXQuc2hvdyh7XG4gICAgYW5pbWF0aW9uOiBvcHRpb25zLmFuaW1hdGlvbixcbiAgICBhbmltYXRpb25PcHRpb25zOiBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNcbiAgfSkpO1xufSk7XG4iLCIvKipcbiAqIE1pY3JvRXZlbnQgLSB0byBtYWtlIGFueSBqcyBvYmplY3QgYW4gZXZlbnQgZW1pdHRlciAoc2VydmVyIG9yIGJyb3dzZXIpXG4gKlxuICogLSBwdXJlIGphdmFzY3JpcHQgLSBzZXJ2ZXIgY29tcGF0aWJsZSwgYnJvd3NlciBjb21wYXRpYmxlXG4gKiAtIGRvbnQgcmVseSBvbiB0aGUgYnJvd3NlciBkb21zXG4gKiAtIHN1cGVyIHNpbXBsZSAtIHlvdSBnZXQgaXQgaW1tZWRpYXRlbHksIG5vIG15c3RlcnksIG5vIG1hZ2ljIGludm9sdmVkXG4gKlxuICogLSBjcmVhdGUgYSBNaWNyb0V2ZW50RGVidWcgd2l0aCBnb29kaWVzIHRvIGRlYnVnXG4gKiAgIC0gbWFrZSBpdCBzYWZlciB0byB1c2VcbiovXG5cbi8qKiBOT1RFOiBUaGlzIGxpYnJhcnkgaXMgY3VzdG9taXplZCBmb3IgT25zZW4gVUkuICovXG5cbmNvbnN0IE1pY3JvRXZlbnQgID0gZnVuY3Rpb24oKXt9O1xuTWljcm9FdmVudC5wcm90b3R5cGUgID0ge1xuICBvbjogZnVuY3Rpb24oZXZlbnQsIGZjdCl7XG4gICAgdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICAgIHRoaXMuX2V2ZW50c1tldmVudF0gPSB0aGlzLl9ldmVudHNbZXZlbnRdIHx8IFtdO1xuICAgIHRoaXMuX2V2ZW50c1tldmVudF0ucHVzaChmY3QpO1xuICB9LFxuICBvbmNlOiBmdW5jdGlvbihldmVudCwgZmN0KXtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIHdyYXBwZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIHNlbGYub2ZmKGV2ZW50LCB3cmFwcGVyKTtcbiAgICAgIHJldHVybiBmY3QuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICB9O1xuICAgIHRoaXMub24oZXZlbnQsIHdyYXBwZXIpO1xuICB9LFxuICBvZmY6IGZ1bmN0aW9uKGV2ZW50LCBmY3Qpe1xuICAgIHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgICBpZiAoZXZlbnQgaW4gdGhpcy5fZXZlbnRzID09PSBmYWxzZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX2V2ZW50c1tldmVudF0gPSB0aGlzLl9ldmVudHNbZXZlbnRdXG4gICAgICAuZmlsdGVyKGZ1bmN0aW9uKF9mY3QpIHtcbiAgICAgICAgaWYgKGZjdCkge1xuICAgICAgICAgICByZXR1cm4gZmN0ICE9PSBfZmN0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH0sXG4gIGVtaXQ6IGZ1bmN0aW9uKGV2ZW50IC8qICwgYXJncy4uLiAqLyl7XG4gICAgdGhpcy5fZXZlbnRzID0gdGhpcy5fZXZlbnRzIHx8IHt9O1xuICAgIGlmIChldmVudCBpbiB0aGlzLl9ldmVudHMgPT09IGZhbHNlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5fZXZlbnRzW2V2ZW50XS5sZW5ndGg7IGkrKyl7XG4gICAgICB0aGlzLl9ldmVudHNbZXZlbnRdW2ldLmFwcGx5KHRoaXMsIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBtaXhpbiB3aWxsIGRlbGVnYXRlIGFsbCBNaWNyb0V2ZW50LmpzIGZ1bmN0aW9uIGluIHRoZSBkZXN0aW5hdGlvbiBvYmplY3RcbiAqXG4gKiAtIHJlcXVpcmUoJ01pY3JvRXZlbnQnKS5taXhpbihGb29iYXIpIHdpbGwgbWFrZSBGb29iYXIgYWJsZSB0byB1c2UgTWljcm9FdmVudFxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSB0aGUgb2JqZWN0IHdoaWNoIHdpbGwgc3VwcG9ydCBNaWNyb0V2ZW50XG4qL1xuTWljcm9FdmVudC5taXhpbiAgPSBmdW5jdGlvbihkZXN0T2JqZWN0KXtcbiAgdmFyIHByb3BzID0gWydvbicsICdvbmNlJywgJ29mZicsICdlbWl0J107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpICsrKXtcbiAgICBpZiAodHlwZW9mIGRlc3RPYmplY3QgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGRlc3RPYmplY3QucHJvdG90eXBlW3Byb3BzW2ldXSAgPSBNaWNyb0V2ZW50LnByb3RvdHlwZVtwcm9wc1tpXV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlc3RPYmplY3RbcHJvcHNbaV1dID0gTWljcm9FdmVudC5wcm90b3R5cGVbcHJvcHNbaV1dO1xuICAgIH1cbiAgfVxufVxuXG53aW5kb3cuTWljcm9FdmVudCA9IE1pY3JvRXZlbnQ7XG5leHBvcnQgZGVmYXVsdCBNaWNyb0V2ZW50O1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE1pY3JvRXZlbnQgZnJvbSAnLi9taWNyb2V2ZW50JztcblxuY29uc3QgY3JlYXRlID0gKCkgPT4ge1xuXG4gIC8qKlxuICAgKiBAb2JqZWN0IG9ucy5vcmllbnRhdGlvblxuICAgKiBAY2F0ZWdvcnkgdXRpbFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVXRpbGl0eSBtZXRob2RzIGZvciBvcmllbnRhdGlvbiBkZXRlY3Rpb24uWy9lbl1cbiAgICogICBbamFd55S76Z2i44Gu44Kq44Oq44Ko44Oz44OG44O844K344On44Oz5qSc55+l44Gu44Gf44KB44Gu44Om44O844OG44Kj44Oq44OG44Kj44Oh44K944OD44OJ44KS5Y+O44KB44Gm44GE44KL44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICovXG4gIGNvbnN0IG9iaiA9IHtcbiAgICAvKipcbiAgICAgKiBAZXZlbnQgY2hhbmdlXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogICBbZW5dRmlyZWQgd2hlbiB0aGUgZGV2aWNlIG9yaWVudGF0aW9uIGNoYW5nZXMuWy9lbl1cbiAgICAgKiAgIFtqYV3jg4fjg5DjgqTjgrnjga7jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYzlpInljJbjgZfjgZ/pmpvjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAgICogQHBhcmFtIHtCb29sZWFufSBldmVudC5pc1BvcnRyYWl0XG4gICAgICogICBbZW5dV2lsbCBiZSB0cnVlIGlmIHRoZSBjdXJyZW50IG9yaWVudGF0aW9uIGlzIHBvcnRyYWl0IG1vZGUuWy9lbl1cbiAgICAgKiAgIFtqYV3nj77lnKjjga7jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYxwb3J0cmFpdOOBruWgtOWQiOOBq3RydWXjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqL1xuXG4gICAgLyoqXG4gICAgICogQG1ldGhvZCBvblxuICAgICAqIEBzaWduYXR1cmUgb24oZXZlbnROYW1lLCBsaXN0ZW5lcilcbiAgICAgKiBAZGVzY3JpcHRpb25cbiAgICAgKiAgIFtlbl1BZGQgYW4gZXZlbnQgbGlzdGVuZXIuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjg6rjgrnjg4rjg7zjgpLov73liqDjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudE5hbWVcbiAgICAgKiAgIFtlbl1OYW1lIG9mIHRoZSBldmVudC5bL2VuXVxuICAgICAqICAgW2phXeOCpOODmeODs+ODiOWQjeOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAgICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXJcbiAgICAgKiAgIFtlbl1GdW5jdGlvbiB0byBleGVjdXRlIHdoZW4gdGhlIGV2ZW50IGlzIHRyaWdnZXJlZC5bL2VuXVxuICAgICAqICAgW2phXeOBk+OBruOCpOODmeODs+ODiOOBjOeZuueBq+OBleOCjOOBn+mam+OBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAgICovXG5cbiAgICAvKipcbiAgICAgKiBAbWV0aG9kIG9uY2VcbiAgICAgKiBAc2lnbmF0dXJlIG9uY2UoZXZlbnROYW1lLCBsaXN0ZW5lcilcbiAgICAgKiBAZGVzY3JpcHRpb25cbiAgICAgKiAgW2VuXUFkZCBhbiBldmVudCBsaXN0ZW5lciB0aGF0J3Mgb25seSB0cmlnZ2VyZWQgb25jZS5bL2VuXVxuICAgICAqICBbamFd5LiA5bqm44Gg44GR5ZG844Gz5Ye644GV44KM44KL44Kk44OZ44Oz44OI44Oq44K544OK44O844KS6L+95Yqg44GX44G+44GZ44CCWy9qYV1cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lXG4gICAgICogICBbZW5dTmFtZSBvZiB0aGUgZXZlbnQuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyXG4gICAgICogICBbZW5dRnVuY3Rpb24gdG8gZXhlY3V0ZSB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgYznmbrngavjgZfjgZ/pmpvjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqL1xuXG4gICAgLyoqXG4gICAgICogQG1ldGhvZCBvZmZcbiAgICAgKiBAc2lnbmF0dXJlIG9mZihldmVudE5hbWUsIFtsaXN0ZW5lcl0pXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogIFtlbl1SZW1vdmUgYW4gZXZlbnQgbGlzdGVuZXIuIElmIHRoZSBsaXN0ZW5lciBpcyBub3Qgc3BlY2lmaWVkIGFsbCBsaXN0ZW5lcnMgZm9yIHRoZSBldmVudCB0eXBlIHdpbGwgYmUgcmVtb3ZlZC5bL2VuXVxuICAgICAqICBbamFd44Kk44OZ44Oz44OI44Oq44K544OK44O844KS5YmK6Zmk44GX44G+44GZ44CC44KC44GX44Kk44OZ44Oz44OI44Oq44K544OK44O844KS5oyH5a6a44GX44Gq44GL44Gj44Gf5aC05ZCI44Gr44Gv44CB44Gd44Gu44Kk44OZ44Oz44OI44Gr57SQ44Gl44GP5YWo44Gm44Gu44Kk44OZ44Oz44OI44Oq44K544OK44O844GM5YmK6Zmk44GV44KM44G+44GZ44CCWy9qYV1cbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnROYW1lXG4gICAgICogICBbZW5dTmFtZSBvZiB0aGUgZXZlbnQuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGxpc3RlbmVyXG4gICAgICogICBbZW5dRnVuY3Rpb24gdG8gZXhlY3V0ZSB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuWy9lbl1cbiAgICAgKiAgIFtqYV3liYrpmaTjgZnjgovjgqTjg5njg7Pjg4jjg6rjgrnjg4rjg7zjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqL1xuXG4gICAgLy8gYWN0dWFsIGltcGxlbWVudGF0aW9uIHRvIGRldGVjdCBpZiB3aGV0aGVyIGN1cnJlbnQgc2NyZWVuIGlzIHBvcnRyYWl0IG9yIG5vdFxuICAgIF9pc1BvcnRyYWl0OiBmYWxzZSxcblxuICAgIC8qKlxuICAgICAqIEBtZXRob2QgaXNQb3J0cmFpdFxuICAgICAqIEBzaWduYXR1cmUgaXNQb3J0cmFpdCgpXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiAgIFtlbl1XaWxsIGJlIHRydWUgaWYgdGhlIGN1cnJlbnQgb3JpZW50YXRpb24gaXMgcG9ydHJhaXQgbW9kZS5bL2VuXVxuICAgICAqICAgW2phXeOCquODquOCqOODs+ODhuODvOOCt+ODp+ODs+OBjHBvcnRyYWl044Oi44O844OJ44Gu5aC05ZCI44GrdHJ1ZeOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAgICogQGRlc2NyaXB0aW9uXG4gICAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBjdXJyZW50IHNjcmVlbiBvcmllbnRhdGlvbiBpcyBwb3J0cmFpdCBvciBub3QuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYxwb3J0cmFpdOODouODvOODieOBi+OBqeOBhuOBi+OCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAgICovXG4gICAgaXNQb3J0cmFpdDogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5faXNQb3J0cmFpdCgpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBAbWV0aG9kIGlzTGFuZHNjYXBlXG4gICAgICogQHNpZ25hdHVyZSBpc0xhbmRzY2FwZSgpXG4gICAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICAgKiAgIFtlbl1XaWxsIGJlIHRydWUgaWYgdGhlIGN1cnJlbnQgb3JpZW50YXRpb24gaXMgbGFuZHNjYXBlIG1vZGUuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYxsYW5kc2NhcGXjg6Ljg7zjg4njga7loLTlkIjjgat0cnVl44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICAgKiBAZGVzY3JpcHRpb25cbiAgICAgKiAgIFtlbl1SZXR1cm5zIHdoZXRoZXIgdGhlIGN1cnJlbnQgc2NyZWVuIG9yaWVudGF0aW9uIGlzIGxhbmRzY2FwZSBvciBub3QuWy9lbl1cbiAgICAgKiAgIFtqYV3jgqrjg6rjgqjjg7Pjg4bjg7zjgrfjg6fjg7PjgYxsYW5kc2NhcGXjg6Ljg7zjg4njgYvjganjgYbjgYvjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgICAqL1xuICAgIGlzTGFuZHNjYXBlOiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiAhdGhpcy5pc1BvcnRyYWl0KCk7XG4gICAgfSxcblxuICAgIF9pbml0OiBmdW5jdGlvbigpIHtcbiAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCB0aGlzLl9vbkRPTUNvbnRlbnRMb2FkZWQuYmluZCh0aGlzKSwgZmFsc2UpO1xuXG4gICAgICBpZiAoJ29yaWVudGF0aW9uJyBpbiB3aW5kb3cpIHtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ29yaWVudGF0aW9uY2hhbmdlJywgdGhpcy5fb25PcmllbnRhdGlvbkNoYW5nZS5iaW5kKHRoaXMpLCBmYWxzZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fb25SZXNpemUuYmluZCh0aGlzKSwgZmFsc2UpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9pc1BvcnRyYWl0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuaW5uZXJIZWlnaHQgPiB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICAgIH07XG5cbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBfb25ET01Db250ZW50TG9hZGVkOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuX2luc3RhbGxJc1BvcnRyYWl0SW1wbGVtZW50YXRpb24oKTtcbiAgICAgIHRoaXMuZW1pdCgnY2hhbmdlJywge2lzUG9ydHJhaXQ6IHRoaXMuaXNQb3J0cmFpdCgpfSk7XG4gICAgfSxcblxuICAgIF9pbnN0YWxsSXNQb3J0cmFpdEltcGxlbWVudGF0aW9uOiBmdW5jdGlvbigpIHtcbiAgICAgIGNvbnN0IGlzUG9ydHJhaXQgPSB3aW5kb3cuaW5uZXJXaWR0aCA8IHdpbmRvdy5pbm5lckhlaWdodDtcblxuICAgICAgaWYgKCEoJ29yaWVudGF0aW9uJyBpbiB3aW5kb3cpKSB7XG4gICAgICAgIHRoaXMuX2lzUG9ydHJhaXQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICByZXR1cm4gd2luZG93LmlubmVySGVpZ2h0ID4gd2luZG93LmlubmVyV2lkdGg7XG4gICAgICAgIH07XG4gICAgICB9IGVsc2UgaWYgKHdpbmRvdy5vcmllbnRhdGlvbiAlIDE4MCA9PT0gMCkge1xuICAgICAgICB0aGlzLl9pc1BvcnRyYWl0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIE1hdGguYWJzKHdpbmRvdy5vcmllbnRhdGlvbiAlIDE4MCkgPT09IDAgPyBpc1BvcnRyYWl0IDogIWlzUG9ydHJhaXQ7XG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9pc1BvcnRyYWl0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIE1hdGguYWJzKHdpbmRvdy5vcmllbnRhdGlvbiAlIDE4MCkgPT09IDkwID8gaXNQb3J0cmFpdCA6ICFpc1BvcnRyYWl0O1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBfb25PcmllbnRhdGlvbkNoYW5nZTogZnVuY3Rpb24oKSB7XG4gICAgICBjb25zdCBpc1BvcnRyYWl0ID0gdGhpcy5faXNQb3J0cmFpdCgpO1xuXG4gICAgICAvLyBXYWl0IGZvciB0aGUgZGltZW5zaW9ucyB0byBjaGFuZ2UgYmVjYXVzZVxuICAgICAgLy8gb2YgQW5kcm9pZCBpbmNvbnNpc3RlbmN5LlxuICAgICAgbGV0IG5JdGVyID0gMDtcbiAgICAgIGNvbnN0IGludGVydmFsID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICBuSXRlcisrO1xuXG4gICAgICAgIGNvbnN0IHcgPSB3aW5kb3cuaW5uZXJXaWR0aDtcbiAgICAgICAgY29uc3QgaCA9IHdpbmRvdy5pbm5lckhlaWdodDtcblxuICAgICAgICBpZiAoKGlzUG9ydHJhaXQgJiYgdyA8PSBoKSB8fFxuICAgICAgICAgICAoIWlzUG9ydHJhaXQgJiYgdyA+PSBoKSkge1xuICAgICAgICAgIHRoaXMuZW1pdCgnY2hhbmdlJywge2lzUG9ydHJhaXQ6IGlzUG9ydHJhaXR9KTtcbiAgICAgICAgICBjbGVhckludGVydmFsKGludGVydmFsKTtcbiAgICAgICAgfSBlbHNlIGlmIChuSXRlciA9PT0gNTApIHtcbiAgICAgICAgICB0aGlzLmVtaXQoJ2NoYW5nZScsIHtpc1BvcnRyYWl0OiBpc1BvcnRyYWl0fSk7XG4gICAgICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgIH0sIDIwKTtcbiAgICB9LFxuXG4gICAgLy8gUnVuIG9uIG5vdCBtb2JpbGUgYnJvd3Nlci5cbiAgICBfb25SZXNpemU6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5lbWl0KCdjaGFuZ2UnLCB7aXNQb3J0cmFpdDogdGhpcy5pc1BvcnRyYWl0KCl9KTtcbiAgICB9XG4gIH07XG5cbiAgTWljcm9FdmVudC5taXhpbihvYmopO1xuXG4gIHJldHVybiBvYmo7XG59O1xuXG5leHBvcnQgZGVmYXVsdCBjcmVhdGUoKS5faW5pdCgpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcblxuLyoqXG4gKiBAb2JqZWN0IG9ucy5tb2RpZmllclxuICogQGNhdGVnb3J5IHZpc3VhbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBVdGlsaXR5IG1ldGhvZHMgdG8gY2hhbmdlIG1vZGlmaWVyIGF0dHJpYnV0ZXMgb2YgT25zZW4gVUkgZWxlbWVudHMuLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiBvbnMubW9kaWZpZXIuYWRkKG15T25zSW5wdXRFbGVtZW50LCAndW5kZXJiYXInKTtcbiAqIG9ucy5tb2RpZmllci50b2dnbGUobXlPbnNUb2FzdEVsZW1lbnQsICdjdXN0b20tbW9kaWZpZXInKTtcbiAqXG4gKi9cbmV4cG9ydCBkZWZhdWx0IHtcbiAgLyoqXG4gICAqIEBtZXRob2QgYWRkXG4gICAqIEBzaWduYXR1cmUgYWRkKGVsZW1lbnQsIG1vZGlmaWVyIFssIG1vZGlmaWVyXSlcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUFkZCB0aGUgc3BlY2lmaWVkIG1vZGlmaWVycyB0byB0aGUgZWxlbWVudCBpZiB0aGV5IGFyZSBub3QgYWxyZWFkeSBpbmNsdWRlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqICAgW2VuXVRhcmdldCBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtb2RpZmllclxuICAgKiAgIFtlbl1OYW1lIG9mIHRoZSBtb2RpZmllci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgYWRkOiAoZWxlbWVudCwgLi4ubW9kaWZpZXJzKSA9PiBtb2RpZmllcnMuZm9yRWFjaChtb2RpZmllciA9PiB1dGlsLmFkZE1vZGlmaWVyKGVsZW1lbnQsIG1vZGlmaWVyKSksXG4gIC8qKlxuICAgKiBAbWV0aG9kIHJlbW92ZVxuICAgKiBAc2lnbmF0dXJlIHJlbW92ZShlbGVtZW50LCBtb2RpZmllciBbLCBtb2RpZmllcl0pXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZW1vdmUgdGhlIHNwZWNpZmllZCBtb2RpZmllcnMgZnJvbSB0aGUgZWxlbWVudCBpZiB0aGV5IGFyZSBpbmNsdWRlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqICAgW2VuXVRhcmdldCBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtb2RpZmllclxuICAgKiAgIFtlbl1OYW1lIG9mIHRoZSBtb2RpZmllci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgcmVtb3ZlOiAoZWxlbWVudCwgLi4ubW9kaWZpZXJzKSA9PiBtb2RpZmllcnMuZm9yRWFjaChtb2RpZmllciA9PiB1dGlsLnJlbW92ZU1vZGlmaWVyKGVsZW1lbnQsIG1vZGlmaWVyKSksXG4gIC8qKlxuICAgKiBAbWV0aG9kIGNvbnRhaW5zXG4gICAqIEBzaWduYXR1cmUgY29udGFpbnMoZWxlbWVudCwgbW9kaWZpZXIpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DaGVjayB3aGV0aGVyIHRoZSBzcGVjaWZpZWQgbW9kaWZpZXIgaXMgaW5jbHVkZWQgaW4gdGhlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICAgKiAgIFtlbl1UYXJnZXQgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbW9kaWZpZXJcbiAgICogICBbZW5dTmFtZSBvZiB0aGUgbW9kaWZpZXIuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICogICBbZW5dYHRydWVgIHdoZW4gdGhlIHNwZWNpZmllZCBtb2RpZmllciBpcyBmb3VuZCBpbiB0aGUgZWxlbWVudCdzIGBtb2RpZmllcmAgYXR0cmlidXRlLiBgZmFsc2VgIG90aGVyd2lzZS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgY29udGFpbnM6IHV0aWwuaGFzTW9kaWZpZXIsXG4gIC8qKlxuICAgKiBAbWV0aG9kIHRvZ2dsZVxuICAgKiBAc2lnbmF0dXJlIHRvZ2dsZShlbGVtZW50LCBtb2RpZmllciBbLCBmb3JjZV0pXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Ub2dnbGUgdGhlIHNwZWNpZmllZCBtb2RpZmllci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBlbGVtZW50XG4gICAqICAgW2VuXVRhcmdldCBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtb2RpZmllclxuICAgKiAgIFtlbl1OYW1lIG9mIHRoZSBtb2RpZmllci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gZm9yY2VcbiAgICogICBbZW5dSWYgaXQgZXZhbHVhdGVzIHRvIHRydWUsIGFkZCBzcGVjaWZpZWQgbW9kaWZpZXIgdmFsdWUsIGFuZCBpZiBpdCBldmFsdWF0ZXMgdG8gZmFsc2UsIHJlbW92ZSBpdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgdG9nZ2xlOiB1dGlsLnRvZ2dsZU1vZGlmaWVyXG59O1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcbmltcG9ydCBNaWNyb0V2ZW50IGZyb20gJy4vbWljcm9ldmVudCc7XG5cbmNvbnN0IHNvZnR3YXJlS2V5Ym9hcmQgPSBuZXcgTWljcm9FdmVudCgpO1xuc29mdHdhcmVLZXlib2FyZC5fdmlzaWJsZSA9IGZhbHNlO1xuXG5jb25zdCBvblNob3cgPSAoKSA9PiB7XG4gIHNvZnR3YXJlS2V5Ym9hcmQuX3Zpc2libGUgPSB0cnVlO1xuICBzb2Z0d2FyZUtleWJvYXJkLmVtaXQoJ3Nob3cnKTtcbn07XG5cbmNvbnN0IG9uSGlkZSA9ICgpID0+IHtcbiAgc29mdHdhcmVLZXlib2FyZC5fdmlzaWJsZSA9IGZhbHNlO1xuICBzb2Z0d2FyZUtleWJvYXJkLmVtaXQoJ2hpZGUnKTtcbn07XG5cbmNvbnN0IGJpbmRFdmVudHMgPSAoKSA9PiB7XG4gIGlmICh0eXBlb2YgS2V5Ym9hcmQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL21hcnRpbm1vc2UvY29yZG92YS1rZXlib2FyZC9ibG9iLzk1ZjNkYTNhMzhkOGY4ZTFmYTQxZmJmNDAxNDUzNTJjMTM1MzVhMDAvUkVBRE1FLm1kXG4gICAgS2V5Ym9hcmQub25zaG93ID0gb25TaG93O1xuICAgIEtleWJvYXJkLm9uaGlkZSA9IG9uSGlkZTtcbiAgICBzb2Z0d2FyZUtleWJvYXJkLmVtaXQoJ2luaXQnLCB7dmlzaWJsZTogS2V5Ym9hcmQuaXNWaXNpYmxlfSk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgY29yZG92YS5wbHVnaW5zICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgY29yZG92YS5wbHVnaW5zLktleWJvYXJkICE9PSAndW5kZWZpbmVkJykge1xuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9kcmlmdHljby9pb25pYy1wbHVnaW5zLWtleWJvYXJkL2Jsb2IvY2EyN2VjZi9SRUFETUUubWRcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbmF0aXZlLmtleWJvYXJkc2hvdycsIG9uU2hvdyk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ25hdGl2ZS5rZXlib2FyZGhpZGUnLCBvbkhpZGUpO1xuICAgIHNvZnR3YXJlS2V5Ym9hcmQuZW1pdCgnaW5pdCcsIHt2aXNpYmxlOiBjb3Jkb3ZhLnBsdWdpbnMuS2V5Ym9hcmQuaXNWaXNpYmxlfSk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbmNvbnN0IG5vUGx1Z2luRXJyb3IgPSAoKSA9PiB7XG4gIHV0aWwud2Fybignb25zLWtleWJvYXJkOiBDb3Jkb3ZhIEtleWJvYXJkIHBsdWdpbiBpcyBub3QgcHJlc2VudC4nKTtcbn07XG5cbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RldmljZXJlYWR5JywgKCkgPT4ge1xuICBpZiAoIWJpbmRFdmVudHMoKSkge1xuICAgIGlmIChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdbb25zLWtleWJvYXJkLWFjdGl2ZV0nKSB8fFxuICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW29ucy1rZXlib2FyZC1pbmFjdGl2ZV0nKSkge1xuICAgICAgbm9QbHVnaW5FcnJvcigpO1xuICAgIH1cblxuICAgIHNvZnR3YXJlS2V5Ym9hcmQub24gPSBub1BsdWdpbkVycm9yO1xuICB9XG59KTtcblxuZXhwb3J0IGRlZmF1bHQgc29mdHdhcmVLZXlib2FyZDtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmNvbnN0IGdlbmVyYXRlSWQgPSAoZnVuY3Rpb24oKSB7XG4gIGxldCBpID0gMDtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBpKys7XG4gIH07XG59KSgpO1xuXG4vKipcbiAqIERvb3IgbG9ja2luZyBzeXN0ZW0uXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMubG9nXVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBEb29yTG9jayB7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fbG9ja0xpc3QgPSBbXTtcbiAgICB0aGlzLl93YWl0TGlzdCA9IFtdO1xuICAgIHRoaXMuX2xvZyA9IG9wdGlvbnMubG9nIHx8IGZ1bmN0aW9uKCkge307XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBsb2NrLlxuICAgKlxuICAgKiBAcmV0dXJuIHtGdW5jdGlvbn0gQ2FsbGJhY2sgZm9yIHVubG9ja2luZy5cbiAgICovXG4gIGxvY2soKSB7XG4gICAgY29uc3QgdW5sb2NrID0gKCkgPT4ge1xuICAgICAgdGhpcy5fdW5sb2NrKHVubG9jayk7XG4gICAgfTtcbiAgICB1bmxvY2suaWQgPSBnZW5lcmF0ZUlkKCk7XG4gICAgdGhpcy5fbG9ja0xpc3QucHVzaCh1bmxvY2spO1xuICAgIHRoaXMuX2xvZygnbG9jazogJyArICh1bmxvY2suaWQpKTtcblxuICAgIHJldHVybiB1bmxvY2s7XG4gIH1cblxuICBfdW5sb2NrKGZuKSB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLl9sb2NrTGlzdC5pbmRleE9mKGZuKTtcbiAgICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoaXMgZnVuY3Rpb24gaXMgbm90IHJlZ2lzdGVyZWQgaW4gdGhlIGxvY2sgbGlzdC4nKTtcbiAgICB9XG5cbiAgICB0aGlzLl9sb2NrTGlzdC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIHRoaXMuX2xvZygndW5sb2NrOiAnICsgZm4uaWQpO1xuXG4gICAgdGhpcy5fdHJ5VG9GcmVlV2FpdExpc3QoKTtcbiAgfVxuXG4gIF90cnlUb0ZyZWVXYWl0TGlzdCgpIHtcbiAgICB3aGlsZSAoIXRoaXMuaXNMb2NrZWQoKSAmJiB0aGlzLl93YWl0TGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLl93YWl0TGlzdC5zaGlmdCgpKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZm9yIHdhaXRpbmcgdW5sb2NrZWQgZG9vci5cbiAgICpcbiAgICogQHBhcmFtcyB7RnVuY3Rpb259IGNhbGxiYWNrIENhbGxiYWNrIG9uIHVubG9ja2luZyB0aGUgZG9vciBjb21wbGV0ZWx5LlxuICAgKi9cbiAgd2FpdFVubG9jayhjYWxsYmFjaykge1xuICAgIGlmICghKGNhbGxiYWNrIGluc3RhbmNlb2YgRnVuY3Rpb24pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBjYWxsYmFjayBwYXJhbSBtdXN0IGJlIGEgZnVuY3Rpb24uJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaXNMb2NrZWQoKSkge1xuICAgICAgdGhpcy5fd2FpdExpc3QucHVzaChjYWxsYmFjayk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNhbGxiYWNrKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0xvY2tlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fbG9ja0xpc3QubGVuZ3RoID4gMDtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cbmltcG9ydCB1dGlsIGZyb20gJy4vdXRpbCc7XG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi9pbnRlcm5hbCc7XG5cbi8vIERlZmF1bHQgaW1wbGVtZW50YXRpb24gZm9yIGdsb2JhbCBQYWdlTG9hZGVyLlxuZnVuY3Rpb24gbG9hZFBhZ2Uoe3BhZ2UsIHBhcmVudCwgcGFyYW1zID0ge319LCBkb25lKSB7XG4gIGludGVybmFsLmdldFBhZ2VIVE1MQXN5bmMocGFnZSkudGhlbihodG1sID0+IHtcbiAgICBjb25zdCBwYWdlRWxlbWVudCA9IHV0aWwuY3JlYXRlRWxlbWVudChodG1sKTtcbiAgICBwYXJlbnQuYXBwZW5kQ2hpbGQocGFnZUVsZW1lbnQpO1xuXG4gICAgZG9uZShwYWdlRWxlbWVudCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiB1bmxvYWRQYWdlKGVsZW1lbnQpIHtcbiAgaWYgKGVsZW1lbnQuX2Rlc3Ryb3kgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIGVsZW1lbnQuX2Rlc3Ryb3koKTtcbiAgfSBlbHNlIHtcbiAgICBlbGVtZW50LnJlbW92ZSgpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBQYWdlTG9hZGVyIHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtmbl0gUmV0dXJucyBhbiBvYmplY3QgdGhhdCBoYXMgXCJlbGVtZW50XCIgcHJvcGVydHkgYW5kIFwidW5sb2FkXCIgZnVuY3Rpb24uXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihsb2FkZXIsIHVubG9hZGVyKSB7XG4gICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyIGluc3RhbmNlb2YgRnVuY3Rpb24gPyBsb2FkZXIgOiBsb2FkUGFnZTtcbiAgICB0aGlzLl91bmxvYWRlciA9IHVubG9hZGVyIGluc3RhbmNlb2YgRnVuY3Rpb24gPyB1bmxvYWRlciA6IHVubG9hZFBhZ2U7XG4gIH1cblxuICAvKipcbiAgICogU2V0IGludGVybmFsIGxvYWRlciBpbXBsZW1lbnRhdGlvbi5cbiAgICovXG4gIHNldCBpbnRlcm5hbExvYWRlcihmbikge1xuICAgIGlmICghKGZuIGluc3RhbmNlb2YgRnVuY3Rpb24pKSB7XG4gICAgICB0aHJvdyBFcnJvcignRmlyc3QgcGFyYW1ldGVyIG11c3QgYmUgYW4gaW5zdGFuY2Ugb2YgRnVuY3Rpb24nKTtcbiAgICB9XG4gICAgdGhpcy5fbG9hZGVyID0gZm47XG4gIH1cblxuICBnZXQgaW50ZXJuYWxMb2FkZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2xvYWRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge2FueX0gb3B0aW9ucy5wYWdlXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gb3B0aW9ucy5wYXJlbnQgQSBsb2NhdGlvbiB0byBsb2FkIHBhZ2UuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5wYXJhbXNdIEV4dHJhIHBhcmFtZXRlcnMgZm9yIG9ucy1wYWdlLlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lIFRha2UgYW4gb2JqZWN0IHRoYXQgaGFzIFwiZWxlbWVudFwiIHByb3BlcnR5IGFuZCBcInVubG9hZFwiIGZ1bmN0aW9uLlxuICAgKi9cbiAgbG9hZCh7cGFnZSwgcGFyZW50LCBwYXJhbXMgPSB7fX0sIGRvbmUpIHtcbiAgICB0aGlzLl9sb2FkZXIoe3BhZ2UsIHBhcmVudCwgcGFyYW1zfSwgcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgaWYgKCEocGFnZUVsZW1lbnQgaW5zdGFuY2VvZiBFbGVtZW50KSkge1xuICAgICAgICB0aHJvdyBFcnJvcigncGFnZUVsZW1lbnQgbXVzdCBiZSBhbiBpbnN0YW5jZSBvZiBFbGVtZW50LicpO1xuICAgICAgfVxuXG4gICAgICBkb25lKHBhZ2VFbGVtZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIHVubG9hZChwYWdlRWxlbWVudCkge1xuICAgIGlmICghKHBhZ2VFbGVtZW50IGluc3RhbmNlb2YgRWxlbWVudCkpIHtcbiAgICAgIHRocm93IEVycm9yKCdwYWdlRWxlbWVudCBtdXN0IGJlIGFuIGluc3RhbmNlIG9mIEVsZW1lbnQuJyk7XG4gICAgfVxuXG4gICAgdGhpcy5fdW5sb2FkZXIocGFnZUVsZW1lbnQpO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBkZWZhdWx0UGFnZUxvYWRlciA9IG5ldyBQYWdlTG9hZGVyKCk7XG5cbmV4cG9ydCBjb25zdCBpbnN0YW50UGFnZUxvYWRlciA9IG5ldyBQYWdlTG9hZGVyKFxuICBmdW5jdGlvbih7cGFnZSwgcGFyZW50LCBwYXJhbXMgPSB7fX0sIGRvbmUpIHtcbiAgICBjb25zdCBlbGVtZW50ID0gdXRpbC5jcmVhdGVFbGVtZW50KHBhZ2UudHJpbSgpKTtcbiAgICBwYXJlbnQuYXBwZW5kQ2hpbGQoZWxlbWVudCk7XG5cbiAgICBkb25lKGVsZW1lbnQpO1xuICB9LFxuICB1bmxvYWRQYWdlXG4pO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi91dGlsJztcbmltcG9ydCBlbGVtZW50cyBmcm9tICcuL2VsZW1lbnRzJ1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuL2FuaW1pdCdcbmltcG9ydCBHZXN0dXJlRGV0ZWN0b3IgZnJvbSAnLi9nZXN0dXJlLWRldGVjdG9yJztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuL3BsYXRmb3JtJztcbmltcG9ydCBub3RpZmljYXRpb24gZnJvbSAnLi9ub3RpZmljYXRpb24nO1xuaW1wb3J0IGFjdGlvblNoZWV0IGZyb20gJy4vYWN0aW9uLXNoZWV0JztcbmltcG9ydCBpbnRlcm5hbCBmcm9tICcuL2ludGVybmFsJztcbmltcG9ydCBvcmllbnRhdGlvbiBmcm9tICcuL29yaWVudGF0aW9uJztcbmltcG9ydCBtb2RpZmllciBmcm9tICcuL21vZGlmaWVyJztcbmltcG9ydCBzb2Z0d2FyZUtleWJvYXJkIGZyb20gJy4vc29mdHdhcmUta2V5Ym9hcmQnO1xuaW1wb3J0IHBhZ2VBdHRyaWJ1dGVFeHByZXNzaW9uIGZyb20gJy4vcGFnZS1hdHRyaWJ1dGUtZXhwcmVzc2lvbic7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4vYXV0b3N0eWxlJztcbmltcG9ydCBEb29yTG9jayBmcm9tICcuL2Rvb3Jsb2NrJztcbmltcG9ydCB7IGRlZmF1bHRQYWdlTG9hZGVyLCBQYWdlTG9hZGVyIH0gZnJvbSAnLi9wYWdlLWxvYWRlcic7XG5cbi8qKlxuICogQG9iamVjdCBvbnNcbiAqIEBjYXRlZ29yeSB1dGlsXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2phXU9uc2VuIFVJ44Gn5Yip55So44Gn44GN44KL44Kw44Ot44O844OQ44Or44Gq44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAqICAgW2VuXUEgZ2xvYmFsIG9iamVjdCB0aGF0J3MgdXNlZCBpbiBPbnNlbiBVSS4gWy9lbl1cbiAqL1xuY29uc3Qgb25zID0ge1xuICBhbmltaXQsXG4gIGRlZmF1bHRQYWdlTG9hZGVyLFxuICBlbGVtZW50cyxcbiAgR2VzdHVyZURldGVjdG9yLFxuICBtb2RpZmllcixcbiAgbm90aWZpY2F0aW9uLFxuICBvcmllbnRhdGlvbixcbiAgcGFnZUF0dHJpYnV0ZUV4cHJlc3Npb24sXG4gIFBhZ2VMb2FkZXIsXG4gIHBsYXRmb3JtLFxuICBzb2Z0d2FyZUtleWJvYXJkLFxuICBfYXV0b1N0eWxlOiBhdXRvU3R5bGUsXG4gIF9pbnRlcm5hbDogaW50ZXJuYWwsXG4gIF9yZWFkeUxvY2s6IG5ldyBEb29yTG9jaygpLFxuICBfdXRpbDogdXRpbCxcbn07XG5cbm9ucy5wbGF0Zm9ybS5zZWxlY3QoKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gubWF0Y2goL3BsYXRmb3JtPShbXFx3LV0rKS8pIHx8IFtdKVsxXSk7XG5cbndhaXREZXZpY2VSZWFkeSgpO1xuXG5jb25zdCByZWFkeUVycm9yID0gYWZ0ZXIgPT4gdXRpbC50aHJvdyhgVGhpcyBtZXRob2QgbXVzdCBiZSBjYWxsZWQgJHthZnRlciA/ICdhZnRlcicgOiAnYmVmb3JlJ30gb25zLmlzUmVhZHkoKSBpcyB0cnVlYCk7XG5cbi8qKlxuICogQG1ldGhvZCBpc1JlYWR5XG4gKiBAc2lnbmF0dXJlIGlzUmVhZHkoKVxuICogQHJldHVybiB7Qm9vbGVhbn1cbiAqICAgW2VuXVdpbGwgYmUgdHJ1ZSBpZiBPbnNlbiBVSSBpcyBpbml0aWFsaXplZC5bL2VuXVxuICogICBbamFd5Yid5pyf5YyW44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dUmV0dXJucyB0cnVlIGlmIE9uc2VuIFVJIGlzIGluaXRpYWxpemVkLlsvZW5dXG4gKiAgIFtqYV1PbnNlbiBVSeOBjOOBmeOBp+OBq+WIneacn+WMluOBleOCjOOBpuOBhOOCi+OBi+OBqeOBhuOBi+OCkui/lOOBmeODoeOCveODg+ODieOBp+OBmeOAglsvamFdXG4gKi9cbm9ucy5pc1JlYWR5ID0gKCkgPT4ge1xuICByZXR1cm4gIW9ucy5fcmVhZHlMb2NrLmlzTG9ja2VkKCk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgaXNXZWJWaWV3XG4gKiBAc2lnbmF0dXJlIGlzV2ViVmlldygpXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogICBbZW5dV2lsbCBiZSB0cnVlIGlmIHRoZSBhcHAgaXMgcnVubmluZyBpbiBDb3Jkb3ZhLlsvZW5dXG4gKiAgIFtqYV1Db3Jkb3Zh44Gn5a6f6KGM44GV44KM44Gm44GE44KL5aC05ZCI44GrdHJ1ZeOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVJldHVybnMgdHJ1ZSBpZiBydW5uaW5nIGluc2lkZSBDb3Jkb3ZhLlsvZW5dXG4gKiAgIFtqYV1Db3Jkb3Zh44Gn5a6f6KGM44GV44KM44Gm44GE44KL44GL44Gp44GG44GL44KS6L+U44GZ44Oh44K944OD44OJ44Gn44GZ44CCWy9qYV1cbiAqL1xub25zLmlzV2ViVmlldyA9IG9ucy5wbGF0Zm9ybS5pc1dlYlZpZXc7XG5cbi8qKlxuICogQG1ldGhvZCByZWFkeVxuICogQHNpZ25hdHVyZSByZWFkeShjYWxsYmFjaylcbiAqIEBkZXNjcmlwdGlvblxuICogICBbamFd44Ki44OX44Oq44Gu5Yid5pyf5YyW44Gr5Yip55So44GZ44KL44Oh44K944OD44OJ44Gn44GZ44CC5rih44GV44KM44Gf6Zai5pWw44Gv44CBT25zZW4gVUnjga7liJ3mnJ/ljJbjgYzntYLkuobjgZfjgabjgYTjgovmmYLngrnjgaflv4XjgZrlkbzjgbDjgozjgb7jgZnjgIJbL2phXVxuICogICBbZW5dTWV0aG9kIHVzZWQgdG8gd2FpdCBmb3IgYXBwIGluaXRpYWxpemF0aW9uLiBXYWl0cyBmb3IgYERPTUNvbnRlbnRMb2FkZWRgIGFuZCBgZGV2aWNlcmVhZHlgLCB3aGVuIG5lY2Vzc2FyeSwgYmVmb3JlIGV4ZWN1dGluZyB0aGUgY2FsbGJhY2suWy9lbl1cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gKiAgIFtlbl1GdW5jdGlvbiB0aGF0IGV4ZWN1dGVzIGFmdGVyIE9uc2VuIFVJIGhhcyBiZWVuIGluaXRpYWxpemVkLlsvZW5dXG4gKiAgIFtqYV1PbnNlbiBVSeOBjOWIneacn+WMluOBjOWujOS6huOBl+OBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5yZWFkeSA9IGNhbGxiYWNrID0+IHtcbiAgaWYgKG9ucy5pc1JlYWR5KCkpIHtcbiAgICBjYWxsYmFjaygpO1xuICB9IGVsc2Uge1xuICAgIG9ucy5fcmVhZHlMb2NrLndhaXRVbmxvY2soY2FsbGJhY2spO1xuICB9XG59O1xuXG4vKipcbiAqIEBtZXRob2Qgc2V0RGVmYXVsdERldmljZUJhY2tCdXR0b25MaXN0ZW5lclxuICogQHNpZ25hdHVyZSBzZXREZWZhdWx0RGV2aWNlQmFja0J1dHRvbkxpc3RlbmVyKGxpc3RlbmVyKVxuICogQHBhcmFtIHtGdW5jdGlvbn0gbGlzdGVuZXJcbiAqICAgW2VuXUZ1bmN0aW9uIHRoYXQgZXhlY3V0ZXMgd2hlbiBkZXZpY2UgYmFjayBidXR0b24gaXMgcHJlc3NlZC4gTXVzdCBiZSBjYWxsZWQgb24gYG9ucy5yZWFkeWAuWy9lbl1cbiAqICAgW2phXeODh+ODkOOCpOOCueOBruODkOODg+OCr+ODnOOCv+ODs+OBjOaKvOOBleOCjOOBn+aZguOBq+Wun+ihjOOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVNldCBkZWZhdWx0IGhhbmRsZXIgZm9yIGRldmljZSBiYWNrIGJ1dHRvbi5bL2VuXVxuICogICBbamFd44OH44OQ44Kk44K544Gu44OQ44OD44Kv44Oc44K/44Oz44Gu44Gf44KB44Gu44OH44OV44Kp44Or44OI44Gu44OP44Oz44OJ44Op44KS6Kit5a6a44GX44G+44GZ44CCWy9qYV1cbiAqL1xub25zLnNldERlZmF1bHREZXZpY2VCYWNrQnV0dG9uTGlzdGVuZXIgPSBmdW5jdGlvbihsaXN0ZW5lcikge1xuICBpZiAoIW9ucy5pc1JlYWR5KCkpIHtcbiAgICByZWFkeUVycm9yKHRydWUpO1xuICB9XG4gIG9ucy5fZGVmYXVsdERldmljZUJhY2tCdXR0b25IYW5kbGVyLnNldExpc3RlbmVyKGxpc3RlbmVyKTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBkaXNhYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXJcbiAqIEBzaWduYXR1cmUgZGlzYWJsZURldmljZUJhY2tCdXR0b25IYW5kbGVyKClcbiAqIEBkZXNjcmlwdGlvblxuICogW2VuXURpc2FibGUgZGV2aWNlIGJhY2sgYnV0dG9uIGV2ZW50IGhhbmRsZXIuIE11c3QgYmUgY2FsbGVkIG9uIGBvbnMucmVhZHlgLlsvZW5dXG4gKiBbamFd44OH44OQ44Kk44K544Gu44OQ44OD44Kv44Oc44K/44Oz44Gu44Kk44OZ44Oz44OI44KS5Y+X44GR5LuY44GR44Gq44GE44KI44GG44Gr44GX44G+44GZ44CCWy9qYV1cbiAqL1xub25zLmRpc2FibGVEZXZpY2VCYWNrQnV0dG9uSGFuZGxlciA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIW9ucy5pc1JlYWR5KCkpIHtcbiAgICByZWFkeUVycm9yKHRydWUpO1xuICB9XG4gIGludGVybmFsLmRiYkRpc3BhdGNoZXIuZGlzYWJsZSgpO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIGVuYWJsZURldmljZUJhY2tCdXR0b25IYW5kbGVyXG4gKiBAc2lnbmF0dXJlIGVuYWJsZURldmljZUJhY2tCdXR0b25IYW5kbGVyKClcbiAqIEBkZXNjcmlwdGlvblxuICogW2VuXUVuYWJsZSBkZXZpY2UgYmFjayBidXR0b24gZXZlbnQgaGFuZGxlci4gTXVzdCBiZSBjYWxsZWQgb24gYG9ucy5yZWFkeWAuWy9lbl1cbiAqIFtqYV3jg4fjg5DjgqTjgrnjga7jg5Djg4Pjgq/jg5zjgr/jg7Pjga7jgqTjg5njg7Pjg4jjgpLlj5fjgZHku5jjgZHjgovjgojjgYbjgavjgZfjgb7jgZnjgIJbL2phXVxuICovXG5vbnMuZW5hYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXIgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCFvbnMuaXNSZWFkeSgpKSB7XG4gICAgcmVhZHlFcnJvcih0cnVlKTtcbiAgfVxuICBpbnRlcm5hbC5kYmJEaXNwYXRjaGVyLmVuYWJsZSgpO1xufTtcblxub25zLmZpcmVEZXZpY2VCYWNrQnV0dG9uRXZlbnQgPSBmdW5jdGlvbigpIHtcbiAgaW50ZXJuYWwuZGJiRGlzcGF0Y2hlci5maXJlRGV2aWNlQmFja0J1dHRvbkV2ZW50KCk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgZW5hYmxlQXV0b1N0YXR1c0JhckZpbGxcbiAqIEBzaWduYXR1cmUgZW5hYmxlQXV0b1N0YXR1c0JhckZpbGwoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1FbmFibGUgc3RhdHVzIGJhciBmaWxsIGZlYXR1cmUgb24gaU9TNyBhbmQgYWJvdmUgKGV4Y2VwdCBmb3IgaVBob25lIFgpLiBNdXN0IGJlIGNhbGxlZCBiZWZvcmUgYG9ucy5yZWFkeWAuWy9lbl1cbiAqICAgW2phXWlPUzfku6XkuIrvvIhpUGhvbmUgWOOBr+mZpOOBj++8ieOBp+OAgeOCueODhuODvOOCv+OCueODkOODvOmDqOWIhuOBrumrmOOBleOCkuiHquWLleeahOOBq+Wfi+OCgeOCi+WHpueQhuOCkuacieWKueOBq+OBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5lbmFibGVBdXRvU3RhdHVzQmFyRmlsbCA9ICgpID0+IHtcbiAgaWYgKG9ucy5pc1JlYWR5KCkpIHtcbiAgICByZWFkeUVycm9yKGZhbHNlKTtcbiAgfVxuICBpbnRlcm5hbC5jb25maWcuYXV0b1N0YXR1c0JhckZpbGwgPSB0cnVlO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIGRpc2FibGVBdXRvU3RhdHVzQmFyRmlsbFxuICogQHNpZ25hdHVyZSBkaXNhYmxlQXV0b1N0YXR1c0JhckZpbGwoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1EaXNhYmxlIHN0YXR1cyBiYXIgZmlsbCBmZWF0dXJlIG9uIGlPUzcgYW5kIGFib3ZlIChleGNlcHQgZm9yIGlQaG9uZSBYKS4gTXVzdCBiZSBjYWxsZWQgYmVmb3JlIGBvbnMucmVhZHlgLlsvZW5dXG4gKiAgIFtqYV1pT1M35Lul5LiK77yIaVBob25lIFjjga/pmaTjgY/vvInjgafjgIHjgrnjg4bjg7zjgr/jgrnjg5Djg7zpg6jliIbjga7pq5jjgZXjgpLoh6rli5XnmoTjgavln4vjgoHjgovlh6bnkIbjgpLnhKHlirnjgavjgZfjgb7jgZnjgIJbL2phXVxuICovXG5vbnMuZGlzYWJsZUF1dG9TdGF0dXNCYXJGaWxsID0gKCkgPT4ge1xuICBpZiAob25zLmlzUmVhZHkoKSkge1xuICAgIHJlYWR5RXJyb3IoZmFsc2UpO1xuICB9XG4gIGludGVybmFsLmNvbmZpZy5hdXRvU3RhdHVzQmFyRmlsbCA9IGZhbHNlO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIG1vY2tTdGF0dXNCYXJcbiAqIEBzaWduYXR1cmUgbW9ja1N0YXR1c0JhcigpXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUNyZWF0ZXMgYSBzdGF0aWMgZWxlbWVudCBzaW1pbGFyIHRvIGlPUyBzdGF0dXMgYmFyLiBPbmx5IHVzZWZ1bCBmb3IgYnJvd3NlciB0ZXN0aW5nLiBNdXN0IGJlIGNhbGxlZCBiZWZvcmUgYG9ucy5yZWFkeWAuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKi9cbm9ucy5tb2NrU3RhdHVzQmFyID0gKCkgPT4ge1xuICBpZiAob25zLmlzUmVhZHkoKSkge1xuICAgIHJlYWR5RXJyb3IoZmFsc2UpO1xuICB9XG5cbiAgY29uc3QgbW9jayA9ICgpID0+IHtcbiAgICBpZiAoIWRvY3VtZW50LmJvZHkuY2hpbGRyZW5bMF0gfHwgIWRvY3VtZW50LmJvZHkuY2hpbGRyZW5bMF0uY2xhc3NMaXN0LmNvbnRhaW5zKCdvbnMtc3RhdHVzLWJhci1tb2NrJykpIHtcbiAgICAgIGNvbnN0IGFuZHJvaWQgPSBwbGF0Zm9ybS5pc0FuZHJvaWQoKSwgaSA9IGkgPT4gYDxpIGNsYXNzPVwiJHtpLnNwbGl0KCctJylbMF19ICR7aX1cIj48L2k+YDtcbiAgICAgIGNvbnN0IGxlZnQgPSBhbmRyb2lkID8gYCR7aSgnem1kaS10d2l0dGVyJyl9ICR7aSgnem1kaS1nb29nbGUtcGxheScpfWAgOiBgTm8gU0lNICR7aSgnZmEtd2lmaScpfWAsXG4gICAgICAgIGNlbnRlciA9IGFuZHJvaWQgPyAnJyA6ICcxMjoyOCBQTScsXG4gICAgICAgIHJpZ2h0ID0gYW5kcm9pZCA/IGAke2koJ3ptZGktbmV0d29yaycpfSAke2koJ3ptZGktd2lmaScpfSAke2koJ3ptZGktYmF0dGVyeScpfSAxMjoyOCBQTWAgOiBgODAlICR7aSgnZmEtYmF0dGVyeS10aHJlZS1xdWFydGVycycpfWA7XG5cbiAgICAgIGRvY3VtZW50LmJvZHkuaW5zZXJ0QmVmb3JlKHV0aWwuY3JlYXRlRWxlbWVudChcbiAgICAgICAgYDxkaXYgY2xhc3M9XCJvbnMtc3RhdHVzLWJhci1tb2NrICR7YW5kcm9pZCA/ICdhbmRyb2lkJyA6ICdpb3MnfVwiPmAgK1xuICAgICAgICAgIGA8ZGl2PiR7bGVmdH08L2Rpdj48ZGl2PiR7Y2VudGVyfTwvZGl2PjxkaXY+JHtyaWdodH08L2Rpdj5gICtcbiAgICAgICAgYDwvZGl2PmBcbiAgICAgICksIGRvY3VtZW50LmJvZHkuZmlyc3RDaGlsZCk7XG4gICAgfVxuICB9O1xuXG4gIGRvY3VtZW50LmJvZHlcbiAgICA/IG1vY2soKVxuICAgIDogaW50ZXJuYWwud2FpdERPTUNvbnRlbnRMb2FkZWQobW9jayk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgZGlzYWJsZUFuaW1hdGlvbnNcbiAqIEBzaWduYXR1cmUgZGlzYWJsZUFuaW1hdGlvbnMoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1EaXNhYmxlIGFsbCBhbmltYXRpb25zLiBDb3VsZCBiZSBoYW5keSBmb3IgdGVzdGluZyBhbmQgb2xkZXIgZGV2aWNlcy5bL2VuXVxuICogICBbamFd44Ki44OL44Oh44O844K344On44Oz44KS5YWo44Gm54Sh5Yq544Gr44GX44G+44GZ44CC44OG44K544OI44Gu6Zqb44Gr5L6/5Yip44Gn44GZ44CCWy9qYV1cbiAqL1xub25zLmRpc2FibGVBbmltYXRpb25zID0gKCkgPT4ge1xuICBpbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkID0gdHJ1ZTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBlbmFibGVBbmltYXRpb25zXG4gKiBAc2lnbmF0dXJlIGVuYWJsZUFuaW1hdGlvbnMoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1FbmFibGUgYW5pbWF0aW9ucyAoZGVmYXVsdCkuWy9lbl1cbiAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+OCkuacieWKueOBq+OBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5lbmFibGVBbmltYXRpb25zID0gKCkgPT4ge1xuICBpbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkID0gZmFsc2U7XG59O1xuXG5vbnMuX2Rpc2FibGVXYXJuaW5ncyA9ICgpID0+IHtcbiAgaW50ZXJuYWwuY29uZmlnLndhcm5pbmdzRGlzYWJsZWQgPSB0cnVlO1xufTtcblxub25zLl9lbmFibGVXYXJuaW5ncyA9ICgpID0+IHtcbiAgaW50ZXJuYWwuY29uZmlnLndhcm5pbmdzRGlzYWJsZWQgPSBmYWxzZTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBkaXNhYmxlQXV0b1N0eWxpbmdcbiAqIEBzaWduYXR1cmUgZGlzYWJsZUF1dG9TdHlsaW5nKClcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dRGlzYWJsZSBhdXRvbWF0aWMgc3R5bGluZy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqL1xub25zLmRpc2FibGVBdXRvU3R5bGluZyA9IGF1dG9TdHlsZS5kaXNhYmxlO1xuXG4vKipcbiAqIEBtZXRob2QgZW5hYmxlQXV0b1N0eWxpbmdcbiAqIEBzaWduYXR1cmUgZW5hYmxlQXV0b1N0eWxpbmcoKVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1FbmFibGUgYXV0b21hdGljIHN0eWxpbmcgYmFzZWQgb24gT1MgKGRlZmF1bHQpLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5vbnMuZW5hYmxlQXV0b1N0eWxpbmcgPSBhdXRvU3R5bGUuZW5hYmxlO1xuXG4vKipcbiAqIEBtZXRob2QgZGlzYWJsZUljb25BdXRvUHJlZml4XG4gKiBAc2lnbmF0dXJlIGRpc2FibGVJY29uQXV0b1ByZWZpeCgpXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXURpc2FibGUgYWRkaW5nIGBmYS1gIHByZWZpeCBhdXRvbWF0aWNhbGx5IHRvIGBvbnMtaWNvbmAgY2xhc3Nlcy4gVXNlZnVsIHdoZW4gaW5jbHVkaW5nIGN1c3RvbSBpY29uIHBhY2tzLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5vbnMuZGlzYWJsZUljb25BdXRvUHJlZml4ID0gKCkgPT4ge1xuICB1dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCgnSWNvbicpO1xuICBlbGVtZW50cy5JY29uLnNldEF1dG9QcmVmaXgoZmFsc2UpO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIGZvcmNlVUlXZWJWaWV3U2Nyb2xsRml4XG4gKiBAc2lnbmF0dXJlIGZvcmNlVUlXZWJWaWV3U2Nyb2xsRml4KClcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gZm9yY2UgRW5hYmxlIG9yIGRpc2FibGUgdGhlIGZpeC5cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dQXBwbGllcyBhIGZpeCBmb3IgaU9TIFVJV2ViVmlldyB3aGljaCBwcmV2ZW50cyBzY3JvbGwgZXZlbnRzIGp1bXBpbmcgdG8gcGFnZXMgdW5kZXIgdGhlIHRvcCBsYXllci4gVGhpcyBtYXkgdmlzdWFsbHkgYWZmZWN0IG5vcm1hbCBzY3JvbGxpbmcgb2YgVUlXZWJWaWV3IGlmIHlvdSBvcGVuIGEgZGlhbG9nL21lbnUgYmVmb3JlIHRoZSBzY3JvbGwgbW9tZW50dW0gZmluaXNoZWQuIERpc2FibGVkIGJ5IGRlZmF1bHQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKi9cbm9ucy5mb3JjZVVJV2ViVmlld1Njcm9sbEZpeCA9IChmb3JjZSA9IHRydWUpID0+IHtcbiAgaW50ZXJuYWwuY29uZmlnLmZvcmNlVUlXZWJWaWV3U2Nyb2xsRml4ID0gZm9yY2U7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgZm9yY2VQbGF0Zm9ybVN0eWxpbmdcbiAqIEBzaWduYXR1cmUgZm9yY2VQbGF0Zm9ybVN0eWxpbmcocGxhdGZvcm0pXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVJlZnJlc2ggc3R5bGluZyBmb3IgdGhlIGdpdmVuIHBsYXRmb3JtLiBPbmx5IHVzZWZ1bCBmb3IgZGVtb3MuIFVzZSBgb25zLnBsYXRmb3JtLnNlbGVjdCguLi4pYCBpbnN0ZWFkIGZvciBkZXZlbG9wbWVudCBhbmQgcHJvZHVjdGlvbi5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7c3RyaW5nfSBwbGF0Zm9ybSBOZXcgcGxhdGZvcm0gdG8gc3R5bGUgdGhlIGVsZW1lbnRzLlxuICovXG5vbnMuZm9yY2VQbGF0Zm9ybVN0eWxpbmcgPSBuZXdQbGF0Zm9ybSA9PiB7XG4gIG9ucy5lbmFibGVBdXRvU3R5bGluZygpO1xuICBvbnMucGxhdGZvcm0uc2VsZWN0KG5ld1BsYXRmb3JtIHx8ICdpb3MnKTtcblxuICBvbnMuX3V0aWwuYXJyYXlGcm9tKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJyonKSlcbiAgICAuZm9yRWFjaChmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICBpZiAoZWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdvbnMtaWYnKSB7XG4gICAgICAgIGVsZW1lbnQuX3BsYXRmb3JtVXBkYXRlKCk7XG4gICAgICB9IGVsc2UgaWYgKGVsZW1lbnQudGFnTmFtZS5tYXRjaCgvXm9ucy0vaSkpIHtcbiAgICAgICAgYXV0b1N0eWxlLnByZXBhcmUoZWxlbWVudCwgdHJ1ZSk7XG4gICAgICAgIGlmIChlbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29ucy10YWJiYXInKSB7XG4gICAgICAgICAgZWxlbWVudC5fdXBkYXRlUG9zaXRpb24oKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xufTtcblxuLyoqXG4gKiBAbWV0aG9kIHByZWxvYWRcbiAqIEBzaWduYXR1cmUgcHJlbG9hZCh0ZW1wbGF0ZVBhdGhzKVxuICogQHBhcmFtIHtTdHJpbmd8QXJyYXl9IHRlbXBsYXRlUGF0aHNcbiAqICAgW2VuXVNldCBvZiBIVE1MIGZpbGUgcGF0aHMgY29udGFpbmluZyAnb25zLXBhZ2UnIGVsZW1lbnRzLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHJldHVybiB7UHJvbWlzZX1cbiAqICAgW2VuXVByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCB0aGUgdGVtcGxhdGVzIGFyZSBjYWNoZWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVNlcGFyYXRlZCBmaWxlcyBuZWVkIHRvIGJlIHJlcXVlc3RlZCBvbiBkZW1hbmQgYW5kIHRoaXMgY2FuIHNsaWdodGx5IGRlbGF5IHB1c2hpbmcgbmV3IHBhZ2VzLiBUaGlzIG1ldGhvZCByZXF1ZXN0cyBhbmQgY2FjaGVzIHRlbXBsYXRlcyBmb3IgbGF0ZXIgdXNlLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5vbnMucHJlbG9hZCA9IGZ1bmN0aW9uKHRlbXBsYXRlcyA9IFtdKSB7XG4gIHJldHVybiBQcm9taXNlLmFsbCgodGVtcGxhdGVzIGluc3RhbmNlb2YgQXJyYXkgPyB0ZW1wbGF0ZXMgOiBbdGVtcGxhdGVzXSkubWFwKHRlbXBsYXRlID0+IHtcbiAgICBpZiAodHlwZW9mIHRlbXBsYXRlICE9PSAnc3RyaW5nJykge1xuICAgICAgdXRpbC50aHJvdygnRXhwZWN0ZWQgc3RyaW5nIGFyZ3VtZW50cyBidXQgZ290ICcgKyB0eXBlb2YgdGVtcGxhdGUpO1xuICAgIH1cbiAgICByZXR1cm4gaW50ZXJuYWwuZ2V0VGVtcGxhdGVIVE1MQXN5bmModGVtcGxhdGUpO1xuICB9KSk7XG59O1xuXG4vKipcbiAqIEBtZXRob2QgY3JlYXRlRWxlbWVudFxuICogQHNpZ25hdHVyZSBjcmVhdGVFbGVtZW50KHRlbXBsYXRlLCBvcHRpb25zKVxuICogQHBhcmFtIHtTdHJpbmd9IHRlbXBsYXRlXG4gKiAgIFtlbl1FaXRoZXIgYW4gSFRNTCBmaWxlIHBhdGgsIGEgYDx0ZW1wbGF0ZT5gIGlkIG9yIGFuIEhUTUwgc3RyaW5nIHN1Y2ggYXMgYCc8ZGl2IGlkPVwiZm9vXCI+aG9nZTwvZGl2PidgLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAqIEBwYXJhbSB7Qm9vbGVhbnxIVE1MRWxlbWVudH0gW29wdGlvbnMuYXBwZW5kXVxuICogICBbZW5dV2hldGhlciBvciBub3QgdGhlIGVsZW1lbnQgc2hvdWxkIGJlIGF1dG9tYXRpY2FsbHkgYXBwZW5kZWQgdG8gdGhlIERPTS4gIERlZmF1bHRzIHRvIGBmYWxzZWAuIElmIGB0cnVlYCB2YWx1ZSBpcyBnaXZlbiwgYGRvY3VtZW50LmJvZHlgIHdpbGwgYmUgdXNlZCBhcyB0aGUgdGFyZ2V0LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gW29wdGlvbnMuaW5zZXJ0QmVmb3JlXVxuICogICBbZW5dUmVmZXJlbmNlIG5vZGUgdGhhdCBiZWNvbWVzIHRoZSBuZXh0IHNpYmxpbmcgb2YgdGhlIG5ldyBub2RlIChgb3B0aW9ucy5hcHBlbmRgIGVsZW1lbnQpLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHJldHVybiB7SFRNTEVsZW1lbnR8UHJvbWlzZX1cbiAqICAgW2VuXUlmIHRoZSBwcm92aWRlZCB0ZW1wbGF0ZSB3YXMgYW4gaW5saW5lIEhUTUwgc3RyaW5nLCBpdCByZXR1cm5zIHRoZSBuZXcgZWxlbWVudC4gT3RoZXJ3aXNlLCBpdCByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBuZXcgZWxlbWVudC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dQ3JlYXRlIGEgbmV3IGVsZW1lbnQgZnJvbSBhIHRlbXBsYXRlLiBCb3RoIGlubGluZSBIVE1MIGFuZCBleHRlcm5hbCBmaWxlcyBhcmUgc3VwcG9ydGVkIGFsdGhvdWdoIHRoZSByZXR1cm4gdmFsdWUgZGlmZmVycy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqL1xub25zLmNyZWF0ZUVsZW1lbnQgPSAodGVtcGxhdGUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICB0ZW1wbGF0ZSA9IHRlbXBsYXRlLnRyaW0oKTtcblxuICBjb25zdCBjcmVhdGUgPSBodG1sID0+IHtcbiAgICBjb25zdCBlbGVtZW50ID0gb25zLl91dGlsLmNyZWF0ZUVsZW1lbnQoaHRtbCk7XG4gICAgZWxlbWVudC5yZW1vdmUoKTtcblxuICAgIGlmIChvcHRpb25zLmFwcGVuZCkge1xuICAgICAgY29uc3QgdGFyZ2V0ID0gb3B0aW9ucy5hcHBlbmQgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCA/IG9wdGlvbnMuYXBwZW5kIDogZG9jdW1lbnQuYm9keTtcbiAgICAgIHRhcmdldC5pbnNlcnRCZWZvcmUoZWxlbWVudCwgb3B0aW9ucy5pbnNlcnRCZWZvcmUgfHwgbnVsbCk7XG4gICAgICBvcHRpb25zLmxpbmsgaW5zdGFuY2VvZiBGdW5jdGlvbiAmJiBvcHRpb25zLmxpbmsoZWxlbWVudCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH07XG5cbiAgcmV0dXJuIHRlbXBsYXRlLmNoYXJBdCgwKSA9PT0gJzwnID8gY3JlYXRlKHRlbXBsYXRlKSA6IGludGVybmFsLmdldFBhZ2VIVE1MQXN5bmModGVtcGxhdGUpLnRoZW4oY3JlYXRlKTtcbn07XG5cbi8qKlxuICogQG1ldGhvZCBjcmVhdGVQb3BvdmVyXG4gKiBAc2lnbmF0dXJlIGNyZWF0ZVBvcG92ZXIocGFnZSwgW29wdGlvbnNdKVxuICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAqICAgW2VuXVBhZ2UgbmFtZS4gQ2FuIGJlIGVpdGhlciBhbiBIVE1MIGZpbGUgb3IgYSA8dGVtcGxhdGU+IGNvbnRhaW5pbmcgYSA8b25zLWRpYWxvZz4gY29tcG9uZW50LlsvZW5dXG4gKiAgIFtqYV1wYWdl44GuVVJM44GL44CB44KC44GX44GP44GvYDx0ZW1wbGF0ZT5g44Gn5a6j6KiA44GX44Gf44OG44Oz44OX44Os44O844OI44GuaWTlsZ7mgKfjga7lgKTjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5wYXJlbnRTY29wZV1cbiAqICAgW2VuXVBhcmVudCBzY29wZSBvZiB0aGUgZGlhbG9nLiBVc2VkIHRvIGJpbmQgbW9kZWxzIGFuZCBhY2Nlc3Mgc2NvcGUgbWV0aG9kcyBmcm9tIHRoZSBkaWFsb2cuWy9lbl1cbiAqICAgW2phXeODgOOCpOOCouODreOCsOWGheOBp+WIqeeUqOOBmeOCi+imquOCueOCs+ODvOODl+OCkuaMh+WumuOBl+OBvuOBmeOAguODgOOCpOOCouODreOCsOOBi+OCieODouODh+ODq+OChOOCueOCs+ODvOODl+OBruODoeOCveODg+ODieOBq+OCouOCr+OCu+OCueOBmeOCi+OBruOBq+S9v+OBhOOBvuOBmeOAguOBk+OBruODkeODqeODoeODvOOCv+OBr0FuZ3VsYXJKU+ODkOOCpOODs+ODh+OCo+ODs+OCsOOBp+OBruOBv+WIqeeUqOOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dUHJvbWlzZSBvYmplY3QgdGhhdCByZXNvbHZlcyB0byB0aGUgcG9wb3ZlciBjb21wb25lbnQgb2JqZWN0LlsvZW5dXG4gKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgpLop6PmsbrjgZnjgotQcm9taXNl44Kq44OW44K444Kn44Kv44OI44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dQ3JlYXRlIGEgcG9wb3ZlciBpbnN0YW5jZSBmcm9tIGEgdGVtcGxhdGUuWy9lbl1cbiAqICAgW2phXeODhuODs+ODl+ODrOODvOODiOOBi+OCieODneODg+ODl+OCquODvOODkOODvOOBruOCpOODs+OCueOCv+ODs+OCueOCkueUn+aIkOOBl+OBvuOBmeOAglsvamFdXG4gKi9cbi8qKlxuICogQG1ldGhvZCBjcmVhdGVEaWFsb2dcbiAqIEBzaWduYXR1cmUgY3JlYXRlRGlhbG9nKHBhZ2UsIFtvcHRpb25zXSlcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYWdlXG4gKiAgIFtlbl1QYWdlIG5hbWUuIENhbiBiZSBlaXRoZXIgYW4gSFRNTCBmaWxlIG9yIGFuIGA8dGVtcGxhdGU+YCBjb250YWluaW5nIGEgPG9ucy1kaWFsb2c+IGNvbXBvbmVudC5bL2VuXVxuICogICBbamFdcGFnZeOBrlVSTOOBi+OAgeOCguOBl+OBj+OBr2A8dGVtcGxhdGU+YOOBp+Wuo+iogOOBl+OBn+ODhuODs+ODl+ODrOODvOODiOOBrmlk5bGe5oCn44Gu5YCk44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gKiBAcmV0dXJuIHtQcm9taXNlfVxuICogICBbZW5dUHJvbWlzZSBvYmplY3QgdGhhdCByZXNvbHZlcyB0byB0aGUgZGlhbG9nIGNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAqICAgW2phXeODgOOCpOOCouODreOCsOOBruOCs+ODs+ODneODvOODjeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOCkuino+axuuOBmeOCi1Byb21pc2Xjgqrjg5bjgrjjgqfjgq/jg4jjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1DcmVhdGUgYSBkaWFsb2cgaW5zdGFuY2UgZnJvbSBhIHRlbXBsYXRlLlsvZW5dXG4gKiAgIFtqYV3jg4bjg7Pjg5fjg6zjg7zjg4jjgYvjgonjg4DjgqTjgqLjg63jgrDjga7jgqTjg7Pjgrnjgr/jg7PjgrnjgpLnlJ/miJDjgZfjgb7jgZnjgIJbL2phXVxuICovXG4vKipcbiAqIEBtZXRob2QgY3JlYXRlQWxlcnREaWFsb2dcbiAqIEBzaWduYXR1cmUgY3JlYXRlQWxlcnREaWFsb2cocGFnZSwgW29wdGlvbnNdKVxuICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAqICAgW2VuXVBhZ2UgbmFtZS4gQ2FuIGJlIGVpdGhlciBhbiBIVE1MIGZpbGUgb3IgYW4gYDx0ZW1wbGF0ZT5gIGNvbnRhaW5pbmcgYSA8b25zLWFsZXJ0LWRpYWxvZz4gY29tcG9uZW50LlsvZW5dXG4gKiAgIFtqYV1wYWdl44GuVVJM44GL44CB44KC44GX44GP44GvYDx0ZW1wbGF0ZT5g44Gn5a6j6KiA44GX44Gf44OG44Oz44OX44Os44O844OI44GuaWTlsZ7mgKfjga7lgKTjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKiAgIFtlbl1Qcm9taXNlIG9iamVjdCB0aGF0IHJlc29sdmVzIHRvIHRoZSBhbGVydCBkaWFsb2cgY29tcG9uZW50IG9iamVjdC5bL2VuXVxuICogICBbamFd44OA44Kk44Ki44Ot44Kw44Gu44Kz44Oz44Od44O844ON44Oz44OI44Kq44OW44K444Kn44Kv44OI44KS6Kej5rG644GZ44KLUHJvbWlzZeOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUNyZWF0ZSBhIGFsZXJ0IGRpYWxvZyBpbnN0YW5jZSBmcm9tIGEgdGVtcGxhdGUuWy9lbl1cbiAqICAgW2phXeODhuODs+ODl+ODrOODvOODiOOBi+OCieOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBruOCpOODs+OCueOCv+ODs+OCueOCkueUn+aIkOOBl+OBvuOBmeOAglsvamFdXG4gKi9cbm9ucy5jcmVhdGVQb3BvdmVyID0gb25zLmNyZWF0ZURpYWxvZyA9IG9ucy5jcmVhdGVBbGVydERpYWxvZyA9ICh0ZW1wbGF0ZSwgb3B0aW9ucyA9IHt9KSA9PiBvbnMuY3JlYXRlRWxlbWVudCh0ZW1wbGF0ZSwgeyBhcHBlbmQ6IHRydWUsIC4uLm9wdGlvbnMgfSk7XG5cbi8qKlxuICogQG1ldGhvZCBvcGVuQWN0aW9uU2hlZXRcbiAqIEBzaWduYXR1cmUgb3BlbkFjdGlvblNoZWV0KG9wdGlvbnMpXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVNob3dzIGFuIGluc3RhbnQgQWN0aW9uIFNoZWV0IGFuZCBsZXRzIHRoZSB1c2VyIGNob29zZSBhbiBhY3Rpb24uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICogQHBhcmFtIHtBcnJheX0gW29wdGlvbnMuYnV0dG9uc11cbiAqICAgW2VuXVJlcHJlc2VudCBlYWNoIGJ1dHRvbiBvZiB0aGUgYWN0aW9uIHNoZWV0IGZvbGxvd2luZyB0aGUgc3BlY2lmaWVkIG9yZGVyLiBFdmVyeSBpdGVtIGNhbiBiZSBlaXRoZXIgYSBzdHJpbmcgbGFiZWwgb3IgYW4gb2JqZWN0IGNvbnRhaW5pbmcgYGxhYmVsYCwgYGljb25gIGFuZCBgbW9kaWZpZXJgIHByb3BlcnRpZXMuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMudGl0bGVdXG4gKiAgIFtlbl1PcHRpb25hbCB0aXRsZSBmb3IgdGhlIGFjdGlvbiBzaGVldC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5kZXN0cnVjdGl2ZV1cbiAqICAgW2VuXU9wdGlvbmFsIGluZGV4IG9mIHRoZSBcImRlc3RydWN0aXZlXCIgYnV0dG9uIChvbmx5IGZvciBpT1MpLiBJdCBjYW4gYmUgc3BlY2lmaWVkIGluIHRoZSBidXR0b24gYXJyYXkgYXMgd2VsbC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW29wdGlvbnMuY2FuY2VsYWJsZV1cbiAqICAgW2VuXVdoZXRoZXIgdGhlIGFjdGlvbiBzaGVldCBjYW4gYmUgY2FuY2VsZWQgYnkgdGFwcGluZyBvbiB0aGUgYmFja2dyb3VuZCBtYXNrIG9yIG5vdC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tb2RpZmllcl1cbiAqICAgW2VuXU1vZGlmaWVyIGF0dHJpYnV0ZSBvZiB0aGUgYWN0aW9uIHNoZWV0LiBFLmcuIGAnZGVzdHJ1Y3RpdmUnYC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5tYXNrQ29sb3JdXG4gKiAgIFtlbl1PcHRpb25hbGx5IGNoYW5nZSB0aGUgYmFja2dyb3VuZCBtYXNrIGNvbG9yLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmlkXVxuICogICBbZW5dVGhlIGVsZW1lbnQncyBpZCBhdHRyaWJ1dGUuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuY2xhc3NdXG4gKiAgIFtlbl1UaGUgZWxlbWVudCdzIGNsYXNzIGF0dHJpYnV0ZS5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEByZXR1cm4ge1Byb21pc2V9XG4gKiAgIFtlbl1XaWxsIHJlc29sdmUgd2hlbiB0aGUgYWN0aW9uIHNoZWV0IGlzIGNsb3NlZC4gVGhlIHJlc29sdmUgdmFsdWUgaXMgZWl0aGVyIHRoZSBpbmRleCBvZiB0aGUgdGFwcGVkIGJ1dHRvbiBvciAtMSB3aGVuIGNhbmNlbGVkLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5vbnMub3BlbkFjdGlvblNoZWV0ID0gYWN0aW9uU2hlZXQ7XG5cbi8qKlxuICogQG1ldGhvZCByZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyXG4gKiBAc2lnbmF0dXJlIHJlc29sdmVMb2FkaW5nUGxhY2Vob2xkZXIocGFnZSlcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYWdlXG4gKiAgIFtlbl1QYWdlIG5hbWUuIENhbiBiZSBlaXRoZXIgYW4gSFRNTCBmaWxlIG9yIGEgYDx0ZW1wbGF0ZT5gIGlkLlsvZW5dXG4gKiAgIFtqYV1wYWdl44GuVVJM44GL44CB44KC44GX44GP44GvYDx0ZW1wbGF0ZT5g44Gn5a6j6KiA44GX44Gf44OG44Oz44OX44Os44O844OI44GuaWTlsZ7mgKfjga7lgKTjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1JZiBubyBwYWdlIGlzIGRlZmluZWQgZm9yIHRoZSBgb25zLWxvYWRpbmctcGxhY2Vob2xkZXJgIGF0dHJpYnV0ZSBpdCB3aWxsIHdhaXQgZm9yIHRoaXMgbWV0aG9kIGJlaW5nIGNhbGxlZCBiZWZvcmUgbG9hZGluZyB0aGUgcGFnZS5bL2VuXVxuICogICBbamFdb25zLWxvYWRpbmctcGxhY2Vob2xkZXLjga7lsZ7mgKflgKTjgajjgZfjgabjg5rjg7zjgrjjgYzmjIflrprjgZXjgozjgabjgYTjgarjgYTloLTlkIjjga/jgIHjg5rjg7zjgrjjg63jg7zjg4nliY3jgavlkbzjgbDjgozjgotvbnMucmVzb2x2ZUxvYWRpbmdQbGFjZWhvbGRlcuWHpueQhuOBjOihjOOCj+OCjOOCi+OBvuOBp+ihqOekuuOBleOCjOOBvuOBm+OCk+OAglsvamFdXG4gKi9cbm9ucy5yZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyID0gKHBhZ2UsIGxpbmspID0+IHtcbiAgY29uc3QgZWxlbWVudHMgPSBvbnMuX3V0aWwuYXJyYXlGcm9tKHdpbmRvdy5kb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbb25zLWxvYWRpbmctcGxhY2Vob2xkZXJdJykpO1xuICBpZiAoZWxlbWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgdXRpbC50aHJvdygnTm8gb25zLWxvYWRpbmctcGxhY2Vob2xkZXIgZXhpc3RzJyk7XG4gIH1cblxuICBlbGVtZW50c1xuICAgIC5maWx0ZXIoZWxlbWVudCA9PiAhZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3BhZ2UnKSlcbiAgICAuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKCdvbnMtbG9hZGluZy1wbGFjZWhvbGRlcicsIHBhZ2UpO1xuICAgICAgb25zLl9yZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyKGVsZW1lbnQsIHBhZ2UsIGxpbmspO1xuICAgIH0pO1xufTtcblxuXG5vbnMuX3NldHVwTG9hZGluZ1BsYWNlSG9sZGVycyA9IGZ1bmN0aW9uKCkge1xuICBvbnMucmVhZHkoKCkgPT4ge1xuICAgIGNvbnN0IGVsZW1lbnRzID0gb25zLl91dGlsLmFycmF5RnJvbSh3aW5kb3cuZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnW29ucy1sb2FkaW5nLXBsYWNlaG9sZGVyXScpKTtcblxuICAgIGVsZW1lbnRzLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICBjb25zdCBwYWdlID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ29ucy1sb2FkaW5nLXBsYWNlaG9sZGVyJyk7XG4gICAgICBpZiAodHlwZW9mIHBhZ2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG9ucy5fcmVzb2x2ZUxvYWRpbmdQbGFjZWhvbGRlcihlbGVtZW50LCBwYWdlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSk7XG59O1xuXG5vbnMuX3Jlc29sdmVMb2FkaW5nUGxhY2Vob2xkZXIgPSBmdW5jdGlvbihwYXJlbnQsIHBhZ2UsIGxpbmsgPSAoKGVsLCBkb25lKSA9PiBkb25lKCkpKSB7XG4gIHBhZ2UgJiYgb25zLmNyZWF0ZUVsZW1lbnQocGFnZSlcbiAgICAudGhlbihlbGVtZW50ID0+IHtcbiAgICAgIGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICAgIHBhcmVudC5hcHBlbmRDaGlsZChlbGVtZW50KTtcbiAgICAgIGxpbmsoZWxlbWVudCwgKCkgPT4ge1xuICAgICAgICB3aGlsZSAocGFyZW50LmZpcnN0Q2hpbGQgJiYgcGFyZW50LmZpcnN0Q2hpbGQgIT09IGVsZW1lbnQpIHtcbiAgICAgICAgICBwYXJlbnQucmVtb3ZlQ2hpbGQocGFyZW50LmZpcnN0Q2hpbGQpO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICcnO1xuICAgICAgfSk7XG4gICAgfSlcbiAgICAuY2F0Y2goZXJyb3IgPT4gUHJvbWlzZS5yZWplY3QoJ1VuYWJsZWQgdG8gcmVzb2x2ZSBwbGFjZWhvbGRlcjogJyArIGVycm9yKSk7XG59O1xuXG5mdW5jdGlvbiB3YWl0RGV2aWNlUmVhZHkoKSB7XG4gIGNvbnN0IHVubG9ja0RldmljZVJlYWR5ID0gb25zLl9yZWFkeUxvY2subG9jaygpO1xuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHtcbiAgICBpZiAob25zLmlzV2ViVmlldygpKSB7XG4gICAgICB3aW5kb3cuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZGV2aWNlcmVhZHknLCB1bmxvY2tEZXZpY2VSZWFkeSwgZmFsc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICB1bmxvY2tEZXZpY2VSZWFkeSgpO1xuICAgIH1cbiAgfSwgZmFsc2UpO1xufVxuXG4vKipcbiAqIEBtZXRob2QgZ2V0U2NyaXB0UGFnZVxuICogQHNpZ25hdHVyZSBnZXRTY3JpcHRQYWdlKClcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dQWNjZXNzIHRoZSBsYXN0IGNyZWF0ZWQgcGFnZSBmcm9tIHRoZSBjdXJyZW50IGBzY3JpcHRgIHNjb3BlLiBPbmx5IHdvcmtzIGluc2lkZSBgPHNjcmlwdD48L3NjcmlwdD5gIHRhZ3MgdGhhdCBhcmUgZGlyZWN0IGNoaWxkcmVuIG9mIGBvbnMtcGFnZWAgZWxlbWVudC4gVXNlIHRoaXMgdG8gYWRkIGxpZmVjeWNsZSBob29rcyB0byBhIHBhZ2UuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAqICAgW2VuXVJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcgcGFnZSBlbGVtZW50LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5jb25zdCBnZXRDUyA9ICdjdXJyZW50U2NyaXB0JyBpbiBkb2N1bWVudCA/ICgpID0+IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgOiAoKSA9PiBkb2N1bWVudC5zY3JpcHRzW2RvY3VtZW50LnNjcmlwdHMubGVuZ3RoIC0gMV07XG5vbnMuZ2V0U2NyaXB0UGFnZSA9ICgpID0+IGdldENTKCkgJiYgL29ucy1wYWdlL2kudGVzdChnZXRDUygpLnBhcmVudEVsZW1lbnQudGFnTmFtZSkgJiYgZ2V0Q1MoKS5wYXJlbnRFbGVtZW50IHx8IG51bGw7XG5cbmV4cG9ydCBkZWZhdWx0IG9ucztcbiIsIjsoZnVuY3Rpb24gKCkge1xuXHQndXNlIHN0cmljdCc7XG5cblx0LyoqXG5cdCAqIEBwcmVzZXJ2ZSBGYXN0Q2xpY2s6IHBvbHlmaWxsIHRvIHJlbW92ZSBjbGljayBkZWxheXMgb24gYnJvd3NlcnMgd2l0aCB0b3VjaCBVSXMuXG5cdCAqXG5cdCAqIEBjb2RpbmdzdGFuZGFyZCBmdGxhYnMtanN2MlxuXHQgKiBAY29weXJpZ2h0IFRoZSBGaW5hbmNpYWwgVGltZXMgTGltaXRlZCBbQWxsIFJpZ2h0cyBSZXNlcnZlZF1cblx0ICogQGxpY2Vuc2UgTUlUIExpY2Vuc2UgKHNlZSBMSUNFTlNFLnR4dClcblx0ICovXG5cblx0Lypqc2xpbnQgYnJvd3Nlcjp0cnVlLCBub2RlOnRydWUqL1xuXHQvKmdsb2JhbCBkZWZpbmUsIEV2ZW50LCBOb2RlKi9cblxuXG5cdC8qKlxuXHQgKiBJbnN0YW50aWF0ZSBmYXN0LWNsaWNraW5nIGxpc3RlbmVycyBvbiB0aGUgc3BlY2lmaWVkIGxheWVyLlxuXHQgKlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICogQHBhcmFtIHtFbGVtZW50fSBsYXllciBUaGUgbGF5ZXIgdG8gbGlzdGVuIG9uXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV0gVGhlIG9wdGlvbnMgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHRzXG5cdCAqL1xuXHRmdW5jdGlvbiBGYXN0Q2xpY2sobGF5ZXIsIG9wdGlvbnMpIHtcblx0XHR2YXIgb2xkT25DbGljaztcblxuXHRcdG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG5cdFx0LyoqXG5cdFx0ICogV2hldGhlciBhIGNsaWNrIGlzIGN1cnJlbnRseSBiZWluZyB0cmFja2VkLlxuXHRcdCAqXG5cdFx0ICogQHR5cGUgYm9vbGVhblxuXHRcdCAqL1xuXHRcdHRoaXMudHJhY2tpbmdDbGljayA9IGZhbHNlO1xuXG5cblx0XHQvKipcblx0XHQgKiBUaW1lc3RhbXAgZm9yIHdoZW4gY2xpY2sgdHJhY2tpbmcgc3RhcnRlZC5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIG51bWJlclxuXHRcdCAqL1xuXHRcdHRoaXMudHJhY2tpbmdDbGlja1N0YXJ0ID0gMDtcblxuXG5cdFx0LyoqXG5cdFx0ICogVGhlIGVsZW1lbnQgYmVpbmcgdHJhY2tlZCBmb3IgYSBjbGljay5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIEV2ZW50VGFyZ2V0XG5cdFx0ICovXG5cdFx0dGhpcy50YXJnZXRFbGVtZW50ID0gbnVsbDtcblxuXG5cdFx0LyoqXG5cdFx0ICogWC1jb29yZGluYXRlIG9mIHRvdWNoIHN0YXJ0IGV2ZW50LlxuXHRcdCAqXG5cdFx0ICogQHR5cGUgbnVtYmVyXG5cdFx0ICovXG5cdFx0dGhpcy50b3VjaFN0YXJ0WCA9IDA7XG5cblxuXHRcdC8qKlxuXHRcdCAqIFktY29vcmRpbmF0ZSBvZiB0b3VjaCBzdGFydCBldmVudC5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIG51bWJlclxuXHRcdCAqL1xuXHRcdHRoaXMudG91Y2hTdGFydFkgPSAwO1xuXG5cblx0XHQvKipcblx0XHQgKiBJRCBvZiB0aGUgbGFzdCB0b3VjaCwgcmV0cmlldmVkIGZyb20gVG91Y2guaWRlbnRpZmllci5cblx0XHQgKlxuXHRcdCAqIEB0eXBlIG51bWJlclxuXHRcdCAqL1xuXHRcdHRoaXMubGFzdFRvdWNoSWRlbnRpZmllciA9IDA7XG5cblxuXHRcdC8qKlxuXHRcdCAqIFRvdWNobW92ZSBib3VuZGFyeSwgYmV5b25kIHdoaWNoIGEgY2xpY2sgd2lsbCBiZSBjYW5jZWxsZWQuXG5cdFx0ICpcblx0XHQgKiBAdHlwZSBudW1iZXJcblx0XHQgKi9cblx0XHR0aGlzLnRvdWNoQm91bmRhcnkgPSBvcHRpb25zLnRvdWNoQm91bmRhcnkgfHwgMTA7XG5cblxuXHRcdC8qKlxuXHRcdCAqIFRoZSBGYXN0Q2xpY2sgbGF5ZXIuXG5cdFx0ICpcblx0XHQgKiBAdHlwZSBFbGVtZW50XG5cdFx0ICovXG5cdFx0dGhpcy5sYXllciA9IGxheWVyO1xuXG5cdFx0LyoqXG5cdFx0ICogVGhlIG1pbmltdW0gdGltZSBiZXR3ZWVuIHRhcCh0b3VjaHN0YXJ0IGFuZCB0b3VjaGVuZCkgZXZlbnRzXG5cdFx0ICpcblx0XHQgKiBAdHlwZSBudW1iZXJcblx0XHQgKi9cblx0XHR0aGlzLnRhcERlbGF5ID0gb3B0aW9ucy50YXBEZWxheSB8fCAyMDA7XG5cblx0XHQvKipcblx0XHQgKiBUaGUgbWF4aW11bSB0aW1lIGZvciBhIHRhcFxuXHRcdCAqXG5cdFx0ICogQHR5cGUgbnVtYmVyXG5cdFx0ICovXG5cdFx0dGhpcy50YXBUaW1lb3V0ID0gb3B0aW9ucy50YXBUaW1lb3V0IHx8IDcwMDtcblxuXHRcdGlmIChGYXN0Q2xpY2subm90TmVlZGVkKGxheWVyKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIFNvbWUgb2xkIHZlcnNpb25zIG9mIEFuZHJvaWQgZG9uJ3QgaGF2ZSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZFxuXHRcdGZ1bmN0aW9uIGJpbmQobWV0aG9kLCBjb250ZXh0KSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oKSB7IHJldHVybiBtZXRob2QuYXBwbHkoY29udGV4dCwgYXJndW1lbnRzKTsgfTtcblx0XHR9XG5cblxuXHRcdHZhciBtZXRob2RzID0gWydvbk1vdXNlJywgJ29uQ2xpY2snLCAnb25Ub3VjaFN0YXJ0JywgJ29uVG91Y2hNb3ZlJywgJ29uVG91Y2hFbmQnLCAnb25Ub3VjaENhbmNlbCddO1xuXHRcdHZhciBjb250ZXh0ID0gdGhpcztcblx0XHRmb3IgKHZhciBpID0gMCwgbCA9IG1ldGhvZHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG5cdFx0XHRjb250ZXh0W21ldGhvZHNbaV1dID0gYmluZChjb250ZXh0W21ldGhvZHNbaV1dLCBjb250ZXh0KTtcblx0XHR9XG5cblx0XHQvLyBTZXQgdXAgZXZlbnQgaGFuZGxlcnMgYXMgcmVxdWlyZWRcblx0XHRpZiAoZGV2aWNlSXNBbmRyb2lkKSB7XG5cdFx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCB0aGlzLm9uTW91c2UsIHRydWUpO1xuXHRcdFx0bGF5ZXIuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgdGhpcy5vbk1vdXNlLCB0cnVlKTtcblx0XHRcdGxheWVyLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLm9uTW91c2UsIHRydWUpO1xuXHRcdH1cblxuXHRcdGxheWVyLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5vbkNsaWNrLCB0cnVlKTtcblx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgdGhpcy5vblRvdWNoU3RhcnQsIGZhbHNlKTtcblx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCB0aGlzLm9uVG91Y2hNb3ZlLCBmYWxzZSk7XG5cdFx0bGF5ZXIuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLm9uVG91Y2hFbmQsIGZhbHNlKTtcblx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCd0b3VjaGNhbmNlbCcsIHRoaXMub25Ub3VjaENhbmNlbCwgZmFsc2UpO1xuXG5cdFx0Ly8gSGFjayBpcyByZXF1aXJlZCBmb3IgYnJvd3NlcnMgdGhhdCBkb24ndCBzdXBwb3J0IEV2ZW50I3N0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbiAoZS5nLiBBbmRyb2lkIDIpXG5cdFx0Ly8gd2hpY2ggaXMgaG93IEZhc3RDbGljayBub3JtYWxseSBzdG9wcyBjbGljayBldmVudHMgYnViYmxpbmcgdG8gY2FsbGJhY2tzIHJlZ2lzdGVyZWQgb24gdGhlIEZhc3RDbGlja1xuXHRcdC8vIGxheWVyIHdoZW4gdGhleSBhcmUgY2FuY2VsbGVkLlxuXHRcdGlmICghRXZlbnQucHJvdG90eXBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbikge1xuXHRcdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGNhbGxiYWNrLCBjYXB0dXJlKSB7XG5cdFx0XHRcdHZhciBybXYgPSBOb2RlLnByb3RvdHlwZS5yZW1vdmVFdmVudExpc3RlbmVyO1xuXHRcdFx0XHRpZiAodHlwZSA9PT0gJ2NsaWNrJykge1xuXHRcdFx0XHRcdHJtdi5jYWxsKGxheWVyLCB0eXBlLCBjYWxsYmFjay5oaWphY2tlZCB8fCBjYWxsYmFjaywgY2FwdHVyZSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cm12LmNhbGwobGF5ZXIsIHR5cGUsIGNhbGxiYWNrLCBjYXB0dXJlKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblxuXHRcdFx0bGF5ZXIuYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGNhbGxiYWNrLCBjYXB0dXJlKSB7XG5cdFx0XHRcdHZhciBhZHYgPSBOb2RlLnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVyO1xuXHRcdFx0XHRpZiAodHlwZSA9PT0gJ2NsaWNrJykge1xuXHRcdFx0XHRcdGFkdi5jYWxsKGxheWVyLCB0eXBlLCBjYWxsYmFjay5oaWphY2tlZCB8fCAoY2FsbGJhY2suaGlqYWNrZWQgPSBmdW5jdGlvbihldmVudCkge1xuXHRcdFx0XHRcdFx0aWYgKCFldmVudC5wcm9wYWdhdGlvblN0b3BwZWQpIHtcblx0XHRcdFx0XHRcdFx0Y2FsbGJhY2soZXZlbnQpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pLCBjYXB0dXJlKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRhZHYuY2FsbChsYXllciwgdHlwZSwgY2FsbGJhY2ssIGNhcHR1cmUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdC8vIElmIGEgaGFuZGxlciBpcyBhbHJlYWR5IGRlY2xhcmVkIGluIHRoZSBlbGVtZW50J3Mgb25jbGljayBhdHRyaWJ1dGUsIGl0IHdpbGwgYmUgZmlyZWQgYmVmb3JlXG5cdFx0Ly8gRmFzdENsaWNrJ3Mgb25DbGljayBoYW5kbGVyLiBGaXggdGhpcyBieSBwdWxsaW5nIG91dCB0aGUgdXNlci1kZWZpbmVkIGhhbmRsZXIgZnVuY3Rpb24gYW5kXG5cdFx0Ly8gYWRkaW5nIGl0IGFzIGxpc3RlbmVyLlxuXHRcdGlmICh0eXBlb2YgbGF5ZXIub25jbGljayA9PT0gJ2Z1bmN0aW9uJykge1xuXG5cdFx0XHQvLyBBbmRyb2lkIGJyb3dzZXIgb24gYXQgbGVhc3QgMy4yIHJlcXVpcmVzIGEgbmV3IHJlZmVyZW5jZSB0byB0aGUgZnVuY3Rpb24gaW4gbGF5ZXIub25jbGlja1xuXHRcdFx0Ly8gLSB0aGUgb2xkIG9uZSB3b24ndCB3b3JrIGlmIHBhc3NlZCB0byBhZGRFdmVudExpc3RlbmVyIGRpcmVjdGx5LlxuXHRcdFx0b2xkT25DbGljayA9IGxheWVyLm9uY2xpY2s7XG5cdFx0XHRsYXllci5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0XHRcdG9sZE9uQ2xpY2soZXZlbnQpO1xuXHRcdFx0fSwgZmFsc2UpO1xuXHRcdFx0bGF5ZXIub25jbGljayA9IG51bGw7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCogV2luZG93cyBQaG9uZSA4LjEgZmFrZXMgdXNlciBhZ2VudCBzdHJpbmcgdG8gbG9vayBsaWtlIEFuZHJvaWQgYW5kIGlQaG9uZS5cblx0KlxuXHQqIEB0eXBlIGJvb2xlYW5cblx0Ki9cblx0dmFyIGRldmljZUlzV2luZG93c1Bob25lID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKFwiV2luZG93cyBQaG9uZVwiKSA+PSAwO1xuXG5cdC8qKlxuXHQgKiBBbmRyb2lkIHJlcXVpcmVzIGV4Y2VwdGlvbnMuXG5cdCAqXG5cdCAqIEB0eXBlIGJvb2xlYW5cblx0ICovXG5cdHZhciBkZXZpY2VJc0FuZHJvaWQgPSBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YoJ0FuZHJvaWQnKSA+IDAgJiYgIWRldmljZUlzV2luZG93c1Bob25lO1xuXG5cblx0LyoqXG5cdCAqIGlPUyByZXF1aXJlcyBleGNlcHRpb25zLlxuXHQgKlxuXHQgKiBAdHlwZSBib29sZWFuXG5cdCAqL1xuXHR2YXIgZGV2aWNlSXNJT1MgPSAvaVAoYWR8aG9uZXxvZCkvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkgJiYgIWRldmljZUlzV2luZG93c1Bob25lO1xuXG5cblx0LyoqXG5cdCAqIGlPUyA0IHJlcXVpcmVzIGFuIGV4Y2VwdGlvbiBmb3Igc2VsZWN0IGVsZW1lbnRzLlxuXHQgKlxuXHQgKiBAdHlwZSBib29sZWFuXG5cdCAqL1xuXHR2YXIgZGV2aWNlSXNJT1M0ID0gZGV2aWNlSXNJT1MgJiYgKC9PUyA0X1xcZChfXFxkKT8vKS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpO1xuXG5cblx0LyoqXG5cdCAqIGlPUyA2LjAtNy4qIHJlcXVpcmVzIHRoZSB0YXJnZXQgZWxlbWVudCB0byBiZSBtYW51YWxseSBkZXJpdmVkXG5cdCAqXG5cdCAqIEB0eXBlIGJvb2xlYW5cblx0ICovXG5cdHZhciBkZXZpY2VJc0lPU1dpdGhCYWRUYXJnZXQgPSBkZXZpY2VJc0lPUyAmJiAoL09TIFs2LTddX1xcZC8pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCk7XG5cblx0LyoqXG5cdCAqIEJsYWNrQmVycnkgcmVxdWlyZXMgZXhjZXB0aW9ucy5cblx0ICpcblx0ICogQHR5cGUgYm9vbGVhblxuXHQgKi9cblx0dmFyIGRldmljZUlzQmxhY2tCZXJyeTEwID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5pbmRleE9mKCdCQjEwJykgPiAwO1xuXG5cdC8qKlxuXHQgKiBWYWxpZCB0eXBlcyBmb3IgdGV4dCBpbnB1dHNcblx0ICpcblx0ICogQHR5cGUgYXJyYXlcblx0ICovXG5cdHZhciB0ZXh0RmllbGRzID0gWydlbWFpbCcsICdudW1iZXInLCAncGFzc3dvcmQnLCAnc2VhcmNoJywgJ3RlbCcsICd0ZXh0JywgJ3VybCddO1xuXG5cdC8qKlxuXHQgKiBEZXRlcm1pbmUgd2hldGhlciBhIGdpdmVuIGVsZW1lbnQgcmVxdWlyZXMgYSBuYXRpdmUgY2xpY2suXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnRUYXJnZXR8RWxlbWVudH0gdGFyZ2V0IFRhcmdldCBET00gZWxlbWVudFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBlbGVtZW50IG5lZWRzIGEgbmF0aXZlIGNsaWNrXG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm5lZWRzQ2xpY2sgPSBmdW5jdGlvbih0YXJnZXQpIHtcblx0XHRzd2l0Y2ggKHRhcmdldC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSB7XG5cblx0XHQvLyBEb24ndCBzZW5kIGEgc3ludGhldGljIGNsaWNrIHRvIGRpc2FibGVkIGlucHV0cyAoaXNzdWUgIzYyKVxuXHRcdGNhc2UgJ2J1dHRvbic6XG5cdFx0Y2FzZSAnc2VsZWN0Jzpcblx0XHRjYXNlICd0ZXh0YXJlYSc6XG5cdFx0XHRpZiAodGFyZ2V0LmRpc2FibGVkKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRicmVhaztcblx0XHRjYXNlICdpbnB1dCc6XG5cblx0XHRcdC8vIEZpbGUgaW5wdXRzIG5lZWQgcmVhbCBjbGlja3Mgb24gaU9TIDYgZHVlIHRvIGEgYnJvd3NlciBidWcgKGlzc3VlICM2OClcblx0XHRcdGlmICgoZGV2aWNlSXNJT1MgJiYgdGFyZ2V0LnR5cGUgPT09ICdmaWxlJykgfHwgdGFyZ2V0LmRpc2FibGVkKSB7XG5cdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRicmVhaztcblx0XHRjYXNlICdsYWJlbCc6XG5cdFx0Y2FzZSAnaWZyYW1lJzogLy8gaU9TOCBob21lc2NyZWVuIGFwcHMgY2FuIHByZXZlbnQgZXZlbnRzIGJ1YmJsaW5nIGludG8gZnJhbWVzXG5cdFx0Y2FzZSAndmlkZW8nOlxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuICgvXFxibmVlZHNjbGlja1xcYi8pLnRlc3QodGFyZ2V0LmNsYXNzTmFtZSk7XG5cdH07XG5cblxuXHQvKipcblx0ICogRGV0ZXJtaW5lIHdoZXRoZXIgYSBnaXZlbiBlbGVtZW50IHJlcXVpcmVzIGEgY2FsbCB0byBmb2N1cyB0byBzaW11bGF0ZSBjbGljayBpbnRvIGVsZW1lbnQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnRUYXJnZXR8RWxlbWVudH0gdGFyZ2V0IFRhcmdldCBET00gZWxlbWVudFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIGlmIHRoZSBlbGVtZW50IHJlcXVpcmVzIGEgY2FsbCB0byBmb2N1cyB0byBzaW11bGF0ZSBuYXRpdmUgY2xpY2suXG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm5lZWRzRm9jdXMgPSBmdW5jdGlvbih0YXJnZXQpIHtcblx0XHRzd2l0Y2ggKHRhcmdldC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpKSB7XG5cdFx0Y2FzZSAndGV4dGFyZWEnOlxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0Y2FzZSAnc2VsZWN0Jzpcblx0XHRcdHJldHVybiAhZGV2aWNlSXNBbmRyb2lkO1xuXHRcdGNhc2UgJ2lucHV0Jzpcblx0XHRcdHN3aXRjaCAodGFyZ2V0LnR5cGUpIHtcblx0XHRcdGNhc2UgJ2J1dHRvbic6XG5cdFx0XHRjYXNlICdjaGVja2JveCc6XG5cdFx0XHRjYXNlICdmaWxlJzpcblx0XHRcdGNhc2UgJ2ltYWdlJzpcblx0XHRcdGNhc2UgJ3JhZGlvJzpcblx0XHRcdGNhc2UgJ3N1Ym1pdCc6XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTm8gcG9pbnQgaW4gYXR0ZW1wdGluZyB0byBmb2N1cyBkaXNhYmxlZCBpbnB1dHNcblx0XHRcdHJldHVybiAhdGFyZ2V0LmRpc2FibGVkICYmICF0YXJnZXQucmVhZE9ubHk7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdHJldHVybiAoL1xcYm5lZWRzZm9jdXNcXGIvKS50ZXN0KHRhcmdldC5jbGFzc05hbWUpO1xuXHRcdH1cblx0fTtcblxuXG5cdC8qKlxuXHQgKiBTZW5kIGEgY2xpY2sgZXZlbnQgdG8gdGhlIHNwZWNpZmllZCBlbGVtZW50LlxuXHQgKlxuXHQgKiBAcGFyYW0ge0V2ZW50VGFyZ2V0fEVsZW1lbnR9IHRhcmdldEVsZW1lbnRcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUuc2VuZENsaWNrID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCwgZXZlbnQpIHtcblx0XHR2YXIgY2xpY2tFdmVudCwgdG91Y2g7XG5cblx0XHQvLyBPbiBzb21lIEFuZHJvaWQgZGV2aWNlcyBhY3RpdmVFbGVtZW50IG5lZWRzIHRvIGJlIGJsdXJyZWQgb3RoZXJ3aXNlIHRoZSBzeW50aGV0aWMgY2xpY2sgd2lsbCBoYXZlIG5vIGVmZmVjdCAoIzI0KVxuXHRcdGlmIChkb2N1bWVudC5hY3RpdmVFbGVtZW50ICYmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgIT09IHRhcmdldEVsZW1lbnQpIHtcblx0XHRcdGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQuYmx1cigpO1xuXHRcdH1cblxuXHRcdHRvdWNoID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF07XG5cblx0XHQvLyBTeW50aGVzaXNlIGEgY2xpY2sgZXZlbnQsIHdpdGggYW4gZXh0cmEgYXR0cmlidXRlIHNvIGl0IGNhbiBiZSB0cmFja2VkXG5cdFx0Y2xpY2tFdmVudCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50cycpO1xuXHRcdGNsaWNrRXZlbnQuaW5pdE1vdXNlRXZlbnQodGhpcy5kZXRlcm1pbmVFdmVudFR5cGUodGFyZ2V0RWxlbWVudCksIHRydWUsIHRydWUsIHdpbmRvdywgMSwgdG91Y2guc2NyZWVuWCwgdG91Y2guc2NyZWVuWSwgdG91Y2guY2xpZW50WCwgdG91Y2guY2xpZW50WSwgZmFsc2UsIGZhbHNlLCBmYWxzZSwgZmFsc2UsIDAsIG51bGwpO1xuXHRcdGNsaWNrRXZlbnQuZm9yd2FyZGVkVG91Y2hFdmVudCA9IHRydWU7XG5cdFx0dGFyZ2V0RWxlbWVudC5kaXNwYXRjaEV2ZW50KGNsaWNrRXZlbnQpO1xuXHR9O1xuXG5cdEZhc3RDbGljay5wcm90b3R5cGUuZGV0ZXJtaW5lRXZlbnRUeXBlID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCkge1xuXG5cdFx0Ly9Jc3N1ZSAjMTU5OiBBbmRyb2lkIENocm9tZSBTZWxlY3QgQm94IGRvZXMgbm90IG9wZW4gd2l0aCBhIHN5bnRoZXRpYyBjbGljayBldmVudFxuXHRcdGlmIChkZXZpY2VJc0FuZHJvaWQgJiYgdGFyZ2V0RWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdzZWxlY3QnKSB7XG5cdFx0XHRyZXR1cm4gJ21vdXNlZG93bic7XG5cdFx0fVxuXG5cdFx0cmV0dXJuICdjbGljayc7XG5cdH07XG5cblxuXHQvKipcblx0ICogQHBhcmFtIHtFdmVudFRhcmdldHxFbGVtZW50fSB0YXJnZXRFbGVtZW50XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLmZvY3VzID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCkge1xuXHRcdHZhciBsZW5ndGg7XG5cblx0XHQvLyBJc3N1ZSAjMTYwOiBvbiBpT1MgNywgc29tZSBpbnB1dCBlbGVtZW50cyAoZS5nLiBkYXRlIGRhdGV0aW1lIG1vbnRoKSB0aHJvdyBhIHZhZ3VlIFR5cGVFcnJvciBvbiBzZXRTZWxlY3Rpb25SYW5nZS4gVGhlc2UgZWxlbWVudHMgZG9uJ3QgaGF2ZSBhbiBpbnRlZ2VyIHZhbHVlIGZvciB0aGUgc2VsZWN0aW9uU3RhcnQgYW5kIHNlbGVjdGlvbkVuZCBwcm9wZXJ0aWVzLCBidXQgdW5mb3J0dW5hdGVseSB0aGF0IGNhbid0IGJlIHVzZWQgZm9yIGRldGVjdGlvbiBiZWNhdXNlIGFjY2Vzc2luZyB0aGUgcHJvcGVydGllcyBhbHNvIHRocm93cyBhIFR5cGVFcnJvci4gSnVzdCBjaGVjayB0aGUgdHlwZSBpbnN0ZWFkLiBGaWxlZCBhcyBBcHBsZSBidWcgIzE1MTIyNzI0LlxuXHRcdGlmIChkZXZpY2VJc0lPUyAmJiB0YXJnZXRFbGVtZW50LnNldFNlbGVjdGlvblJhbmdlICYmIHRhcmdldEVsZW1lbnQudHlwZS5pbmRleE9mKCdkYXRlJykgIT09IDAgJiYgdGFyZ2V0RWxlbWVudC50eXBlICE9PSAndGltZScgJiYgdGFyZ2V0RWxlbWVudC50eXBlICE9PSAnbW9udGgnICYmIHRhcmdldEVsZW1lbnQudHlwZSAhPT0gJ2VtYWlsJyAmJiB0YXJnZXRFbGVtZW50LnR5cGUgIT09ICdudW1iZXInKSB7XG5cdFx0XHRsZW5ndGggPSB0YXJnZXRFbGVtZW50LnZhbHVlLmxlbmd0aDtcblx0XHRcdHRhcmdldEVsZW1lbnQuc2V0U2VsZWN0aW9uUmFuZ2UobGVuZ3RoLCBsZW5ndGgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0YXJnZXRFbGVtZW50LmZvY3VzKCk7XG5cdFx0fVxuXHR9O1xuXG5cblx0LyoqXG5cdCAqIENoZWNrIHdoZXRoZXIgdGhlIGdpdmVuIHRhcmdldCBlbGVtZW50IGlzIGEgY2hpbGQgb2YgYSBzY3JvbGxhYmxlIGxheWVyIGFuZCBpZiBzbywgc2V0IGEgZmxhZyBvbiBpdC5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudFRhcmdldHxFbGVtZW50fSB0YXJnZXRFbGVtZW50XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLnVwZGF0ZVNjcm9sbFBhcmVudCA9IGZ1bmN0aW9uKHRhcmdldEVsZW1lbnQpIHtcblx0XHR2YXIgc2Nyb2xsUGFyZW50LCBwYXJlbnRFbGVtZW50O1xuXG5cdFx0c2Nyb2xsUGFyZW50ID0gdGFyZ2V0RWxlbWVudC5mYXN0Q2xpY2tTY3JvbGxQYXJlbnQ7XG5cblx0XHQvLyBBdHRlbXB0IHRvIGRpc2NvdmVyIHdoZXRoZXIgdGhlIHRhcmdldCBlbGVtZW50IGlzIGNvbnRhaW5lZCB3aXRoaW4gYSBzY3JvbGxhYmxlIGxheWVyLiBSZS1jaGVjayBpZiB0aGVcblx0XHQvLyB0YXJnZXQgZWxlbWVudCB3YXMgbW92ZWQgdG8gYW5vdGhlciBwYXJlbnQuXG5cdFx0aWYgKCFzY3JvbGxQYXJlbnQgfHwgIXNjcm9sbFBhcmVudC5jb250YWlucyh0YXJnZXRFbGVtZW50KSkge1xuXHRcdFx0cGFyZW50RWxlbWVudCA9IHRhcmdldEVsZW1lbnQ7XG5cdFx0XHRkbyB7XG5cdFx0XHRcdGlmIChwYXJlbnRFbGVtZW50LnNjcm9sbEhlaWdodCA+IHBhcmVudEVsZW1lbnQub2Zmc2V0SGVpZ2h0KSB7XG5cdFx0XHRcdFx0c2Nyb2xsUGFyZW50ID0gcGFyZW50RWxlbWVudDtcblx0XHRcdFx0XHR0YXJnZXRFbGVtZW50LmZhc3RDbGlja1Njcm9sbFBhcmVudCA9IHBhcmVudEVsZW1lbnQ7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRwYXJlbnRFbGVtZW50ID0gcGFyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50O1xuXHRcdFx0fSB3aGlsZSAocGFyZW50RWxlbWVudCk7XG5cdFx0fVxuXG5cdFx0Ly8gQWx3YXlzIHVwZGF0ZSB0aGUgc2Nyb2xsIHRvcCB0cmFja2VyIGlmIHBvc3NpYmxlLlxuXHRcdGlmIChzY3JvbGxQYXJlbnQpIHtcblx0XHRcdHNjcm9sbFBhcmVudC5mYXN0Q2xpY2tMYXN0U2Nyb2xsVG9wID0gc2Nyb2xsUGFyZW50LnNjcm9sbFRvcDtcblx0XHR9XG5cdH07XG5cblxuXHQvKipcblx0ICogQHBhcmFtIHtFdmVudFRhcmdldH0gdGFyZ2V0RWxlbWVudFxuXHQgKiBAcmV0dXJucyB7RWxlbWVudHxFdmVudFRhcmdldH1cblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUuZ2V0VGFyZ2V0RWxlbWVudEZyb21FdmVudFRhcmdldCA9IGZ1bmN0aW9uKGV2ZW50VGFyZ2V0KSB7XG5cblx0XHQvLyBPbiBzb21lIG9sZGVyIGJyb3dzZXJzIChub3RhYmx5IFNhZmFyaSBvbiBpT1MgNC4xIC0gc2VlIGlzc3VlICM1NikgdGhlIGV2ZW50IHRhcmdldCBtYXkgYmUgYSB0ZXh0IG5vZGUuXG5cdFx0aWYgKGV2ZW50VGFyZ2V0Lm5vZGVUeXBlID09PSBOb2RlLlRFWFRfTk9ERSkge1xuXHRcdFx0cmV0dXJuIGV2ZW50VGFyZ2V0LnBhcmVudE5vZGU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50VGFyZ2V0O1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIEBwYXJhbSB7RXZlbnRUYXJnZXR9IHRhcmdldEVsZW1lbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLmlzVGV4dEZpZWxkID0gZnVuY3Rpb24odGFyZ2V0RWxlbWVudCkge1xuXHRcdHJldHVybiAoXG5cdFx0XHR0YXJnZXRFbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ3RleHRhcmVhJ1xuXHRcdFx0fHwgdGV4dEZpZWxkcy5pbmRleE9mKHRhcmdldEVsZW1lbnQudHlwZSkgIT09IC0xXG5cdFx0KTtcblx0fTtcblxuXHQvKipcblx0ICogT24gdG91Y2ggc3RhcnQsIHJlY29yZCB0aGUgcG9zaXRpb24gYW5kIHNjcm9sbCBvZmZzZXQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnR9IGV2ZW50XG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxuXHQgKi9cblx0RmFzdENsaWNrLnByb3RvdHlwZS5vblRvdWNoU3RhcnQgPSBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciB0YXJnZXRFbGVtZW50LCB0b3VjaCwgc2VsZWN0aW9uO1xuXG5cdFx0Ly8gSWdub3JlIG11bHRpcGxlIHRvdWNoZXMsIG90aGVyd2lzZSBwaW5jaC10by16b29tIGlzIHByZXZlbnRlZCBpZiBib3RoIGZpbmdlcnMgYXJlIG9uIHRoZSBGYXN0Q2xpY2sgZWxlbWVudCAoaXNzdWUgIzExMSkuXG5cdFx0aWYgKGV2ZW50LnRhcmdldFRvdWNoZXMubGVuZ3RoID4gMSkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0dGFyZ2V0RWxlbWVudCA9IHRoaXMuZ2V0VGFyZ2V0RWxlbWVudEZyb21FdmVudFRhcmdldChldmVudC50YXJnZXQpO1xuXHRcdHRvdWNoID0gZXZlbnQudGFyZ2V0VG91Y2hlc1swXTtcblxuXHRcdC8vIElnbm9yZSB0b3VjaGVzIG9uIGNvbnRlbnRlZGl0YWJsZSBlbGVtZW50cyB0byBwcmV2ZW50IGNvbmZsaWN0IHdpdGggdGV4dCBzZWxlY3Rpb24uXG5cdFx0Ly8gKEZvciBkZXRhaWxzOiBodHRwczovL2dpdGh1Yi5jb20vZnRsYWJzL2Zhc3RjbGljay9wdWxsLzIxMSApXG5cdFx0aWYgKHRhcmdldEVsZW1lbnQuaXNDb250ZW50RWRpdGFibGUpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdGlmIChkZXZpY2VJc0lPUykge1xuXHRcdFx0Ly8gSWdub3JlIHRvdWNoc3RhcnQgaW4gZm9jdXNlZCB0ZXh0IGZpZWxkXG5cdFx0XHQvLyBBbGxvd3Mgbm9ybWFsIHRleHQgc2VsZWN0aW9uIGFuZCBjb21tYW5kcyAoc2VsZWN0L3Bhc3RlL2N1dCkgd2hlbiBhIGZpZWxkIGhhcyBmb2N1cywgd2hpbGUgc3RpbGwgYWxsb3dpbmcgZmFzdCB0YXAtdG8tZm9jdXMuXG5cdFx0XHQvLyBXaXRob3V0IHRoaXMgZml4LCB1c2VyIG5lZWRzIHRvIHRhcC1hbmQtaG9sZCBhIHRleHQgZmllbGQgZm9yIGNvbnRleHQgbWVudSwgYW5kIGRvdWJsZS10YXAgdG8gc2VsZWN0IHRleHQgZG9lc24ndCB3b3JrIGF0IGFsbC5cblx0XHRcdGlmICh0YXJnZXRFbGVtZW50ID09PSBkb2N1bWVudC5hY3RpdmVFbGVtZW50ICYmIHRoaXMuaXNUZXh0RmllbGQodGFyZ2V0RWxlbWVudCkpIHtcblx0XHRcdCAgcmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cblx0XHRcdGlmICghZGV2aWNlSXNJT1M0KSB7XG5cblx0XHRcdFx0Ly8gV2VpcmQgdGhpbmdzIGhhcHBlbiBvbiBpT1Mgd2hlbiBhbiBhbGVydCBvciBjb25maXJtIGRpYWxvZyBpcyBvcGVuZWQgZnJvbSBhIGNsaWNrIGV2ZW50IGNhbGxiYWNrIChpc3N1ZSAjMjMpOlxuXHRcdFx0XHQvLyB3aGVuIHRoZSB1c2VyIG5leHQgdGFwcyBhbnl3aGVyZSBlbHNlIG9uIHRoZSBwYWdlLCBuZXcgdG91Y2hzdGFydCBhbmQgdG91Y2hlbmQgZXZlbnRzIGFyZSBkaXNwYXRjaGVkXG5cdFx0XHRcdC8vIHdpdGggdGhlIHNhbWUgaWRlbnRpZmllciBhcyB0aGUgdG91Y2ggZXZlbnQgdGhhdCBwcmV2aW91c2x5IHRyaWdnZXJlZCB0aGUgY2xpY2sgdGhhdCB0cmlnZ2VyZWQgdGhlIGFsZXJ0LlxuXHRcdFx0XHQvLyBTYWRseSwgdGhlcmUgaXMgYW4gaXNzdWUgb24gaU9TIDQgdGhhdCBjYXVzZXMgc29tZSBub3JtYWwgdG91Y2ggZXZlbnRzIHRvIGhhdmUgdGhlIHNhbWUgaWRlbnRpZmllciBhcyBhblxuXHRcdFx0XHQvLyBpbW1lZGlhdGVseSBwcmVjZWVkaW5nIHRvdWNoIGV2ZW50IChpc3N1ZSAjNTIpLCBzbyB0aGlzIGZpeCBpcyB1bmF2YWlsYWJsZSBvbiB0aGF0IHBsYXRmb3JtLlxuXHRcdFx0XHQvLyBJc3N1ZSAxMjA6IHRvdWNoLmlkZW50aWZpZXIgaXMgMCB3aGVuIENocm9tZSBkZXYgdG9vbHMgJ0VtdWxhdGUgdG91Y2ggZXZlbnRzJyBpcyBzZXQgd2l0aCBhbiBpT1MgZGV2aWNlIFVBIHN0cmluZyxcblx0XHRcdFx0Ly8gd2hpY2ggY2F1c2VzIGFsbCB0b3VjaCBldmVudHMgdG8gYmUgaWdub3JlZC4gQXMgdGhpcyBibG9jayBvbmx5IGFwcGxpZXMgdG8gaU9TLCBhbmQgaU9TIGlkZW50aWZpZXJzIGFyZSBhbHdheXMgbG9uZyxcblx0XHRcdFx0Ly8gcmFuZG9tIGludGVnZXJzLCBpdCdzIHNhZmUgdG8gdG8gY29udGludWUgaWYgdGhlIGlkZW50aWZpZXIgaXMgMCBoZXJlLlxuXHRcdFx0XHRpZiAodG91Y2guaWRlbnRpZmllciAmJiB0b3VjaC5pZGVudGlmaWVyID09PSB0aGlzLmxhc3RUb3VjaElkZW50aWZpZXIpIHtcblx0XHRcdFx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHRoaXMubGFzdFRvdWNoSWRlbnRpZmllciA9IHRvdWNoLmlkZW50aWZpZXI7XG5cblx0XHRcdFx0Ly8gSWYgdGhlIHRhcmdldCBlbGVtZW50IGlzIGEgY2hpbGQgb2YgYSBzY3JvbGxhYmxlIGxheWVyICh1c2luZyAtd2Via2l0LW92ZXJmbG93LXNjcm9sbGluZzogdG91Y2gpIGFuZDpcblx0XHRcdFx0Ly8gMSkgdGhlIHVzZXIgZG9lcyBhIGZsaW5nIHNjcm9sbCBvbiB0aGUgc2Nyb2xsYWJsZSBsYXllclxuXHRcdFx0XHQvLyAyKSB0aGUgdXNlciBzdG9wcyB0aGUgZmxpbmcgc2Nyb2xsIHdpdGggYW5vdGhlciB0YXBcblx0XHRcdFx0Ly8gdGhlbiB0aGUgZXZlbnQudGFyZ2V0IG9mIHRoZSBsYXN0ICd0b3VjaGVuZCcgZXZlbnQgd2lsbCBiZSB0aGUgZWxlbWVudCB0aGF0IHdhcyB1bmRlciB0aGUgdXNlcidzIGZpbmdlclxuXHRcdFx0XHQvLyB3aGVuIHRoZSBmbGluZyBzY3JvbGwgd2FzIHN0YXJ0ZWQsIGNhdXNpbmcgRmFzdENsaWNrIHRvIHNlbmQgYSBjbGljayBldmVudCB0byB0aGF0IGxheWVyIC0gdW5sZXNzIGEgY2hlY2tcblx0XHRcdFx0Ly8gaXMgbWFkZSB0byBlbnN1cmUgdGhhdCBhIHBhcmVudCBsYXllciB3YXMgbm90IHNjcm9sbGVkIGJlZm9yZSBzZW5kaW5nIGEgc3ludGhldGljIGNsaWNrIChpc3N1ZSAjNDIpLlxuXHRcdFx0XHR0aGlzLnVwZGF0ZVNjcm9sbFBhcmVudCh0YXJnZXRFbGVtZW50KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHR0aGlzLnRyYWNraW5nQ2xpY2sgPSB0cnVlO1xuXHRcdHRoaXMudHJhY2tpbmdDbGlja1N0YXJ0ID0gZXZlbnQudGltZVN0YW1wO1xuXHRcdHRoaXMudGFyZ2V0RWxlbWVudCA9IHRhcmdldEVsZW1lbnQ7XG5cblx0XHR0aGlzLnRvdWNoU3RhcnRYID0gdG91Y2gucGFnZVg7XG5cdFx0dGhpcy50b3VjaFN0YXJ0WSA9IHRvdWNoLnBhZ2VZO1xuXG5cdFx0Ly8gUHJldmVudCBwaGFudG9tIGNsaWNrcyBvbiBmYXN0IGRvdWJsZS10YXAgKGlzc3VlICMzNilcblx0XHRpZiAoKGV2ZW50LnRpbWVTdGFtcCAtIHRoaXMubGFzdENsaWNrVGltZSkgPCB0aGlzLnRhcERlbGF5ICYmIChldmVudC50aW1lU3RhbXAgLSB0aGlzLmxhc3RDbGlja1RpbWUpID4gLTEpIHtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH07XG5cblxuXHQvKipcblx0ICogQmFzZWQgb24gYSB0b3VjaG1vdmUgZXZlbnQgb2JqZWN0LCBjaGVjayB3aGV0aGVyIHRoZSB0b3VjaCBoYXMgbW92ZWQgcGFzdCBhIGJvdW5kYXJ5IHNpbmNlIGl0IHN0YXJ0ZWQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7RXZlbnR9IGV2ZW50XG5cdCAqIEByZXR1cm5zIHtib29sZWFufVxuXHQgKi9cblx0RmFzdENsaWNrLnByb3RvdHlwZS50b3VjaEhhc01vdmVkID0gZnVuY3Rpb24oZXZlbnQpIHtcblx0XHR2YXIgdG91Y2ggPSBldmVudC5jaGFuZ2VkVG91Y2hlc1swXSwgYm91bmRhcnkgPSB0aGlzLnRvdWNoQm91bmRhcnk7XG5cblx0XHRpZiAoTWF0aC5hYnModG91Y2gucGFnZVggLSB0aGlzLnRvdWNoU3RhcnRYKSA+IGJvdW5kYXJ5IHx8IE1hdGguYWJzKHRvdWNoLnBhZ2VZIC0gdGhpcy50b3VjaFN0YXJ0WSkgPiBib3VuZGFyeSkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIFVwZGF0ZSB0aGUgbGFzdCBwb3NpdGlvbi5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uVG91Y2hNb3ZlID0gZnVuY3Rpb24oZXZlbnQpIHtcblx0XHRpZiAoIXRoaXMudHJhY2tpbmdDbGljaykge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgdGhlIHRvdWNoIGhhcyBtb3ZlZCwgY2FuY2VsIHRoZSBjbGljayB0cmFja2luZ1xuXHRcdGlmICh0aGlzLnRhcmdldEVsZW1lbnQgIT09IHRoaXMuZ2V0VGFyZ2V0RWxlbWVudEZyb21FdmVudFRhcmdldChldmVudC50YXJnZXQpIHx8IHRoaXMudG91Y2hIYXNNb3ZlZChldmVudCkpIHtcblx0XHRcdHRoaXMudHJhY2tpbmdDbGljayA9IGZhbHNlO1xuXHRcdFx0dGhpcy50YXJnZXRFbGVtZW50ID0gbnVsbDtcblx0XHR9XG5cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBBdHRlbXB0IHRvIGZpbmQgdGhlIGxhYmVsbGVkIGNvbnRyb2wgZm9yIHRoZSBnaXZlbiBsYWJlbCBlbGVtZW50LlxuXHQgKlxuXHQgKiBAcGFyYW0ge0V2ZW50VGFyZ2V0fEhUTUxMYWJlbEVsZW1lbnR9IGxhYmVsRWxlbWVudFxuXHQgKiBAcmV0dXJucyB7RWxlbWVudHxudWxsfVxuXHQgKi9cblx0RmFzdENsaWNrLnByb3RvdHlwZS5maW5kQ29udHJvbCA9IGZ1bmN0aW9uKGxhYmVsRWxlbWVudCkge1xuXG5cdFx0Ly8gRmFzdCBwYXRoIGZvciBuZXdlciBicm93c2VycyBzdXBwb3J0aW5nIHRoZSBIVE1MNSBjb250cm9sIGF0dHJpYnV0ZVxuXHRcdGlmIChsYWJlbEVsZW1lbnQuY29udHJvbCAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRyZXR1cm4gbGFiZWxFbGVtZW50LmNvbnRyb2w7XG5cdFx0fVxuXG5cdFx0Ly8gQWxsIGJyb3dzZXJzIHVuZGVyIHRlc3QgdGhhdCBzdXBwb3J0IHRvdWNoIGV2ZW50cyBhbHNvIHN1cHBvcnQgdGhlIEhUTUw1IGh0bWxGb3IgYXR0cmlidXRlXG5cdFx0aWYgKGxhYmVsRWxlbWVudC5odG1sRm9yKSB7XG5cdFx0XHRyZXR1cm4gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQobGFiZWxFbGVtZW50Lmh0bWxGb3IpO1xuXHRcdH1cblxuXHRcdC8vIElmIG5vIGZvciBhdHRyaWJ1dGUgZXhpc3RzLCBhdHRlbXB0IHRvIHJldHJpZXZlIHRoZSBmaXJzdCBsYWJlbGxhYmxlIGRlc2NlbmRhbnQgZWxlbWVudFxuXHRcdC8vIHRoZSBsaXN0IG9mIHdoaWNoIGlzIGRlZmluZWQgaGVyZTogaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDUvZm9ybXMuaHRtbCNjYXRlZ29yeS1sYWJlbFxuXHRcdHJldHVybiBsYWJlbEVsZW1lbnQucXVlcnlTZWxlY3RvcignYnV0dG9uLCBpbnB1dDpub3QoW3R5cGU9aGlkZGVuXSksIGtleWdlbiwgbWV0ZXIsIG91dHB1dCwgcHJvZ3Jlc3MsIHNlbGVjdCwgdGV4dGFyZWEnKTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBPbiB0b3VjaCBlbmQsIGRldGVybWluZSB3aGV0aGVyIHRvIHNlbmQgYSBjbGljayBldmVudCBhdCBvbmNlLlxuXHQgKlxuXHQgKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuXHQgKiBAcmV0dXJucyB7Ym9vbGVhbn1cblx0ICovXG5cdEZhc3RDbGljay5wcm90b3R5cGUub25Ub3VjaEVuZCA9IGZ1bmN0aW9uKGV2ZW50KSB7XG5cdFx0dmFyIGZvckVsZW1lbnQsIHRyYWNraW5nQ2xpY2tTdGFydCwgdGFyZ2V0VGFnTmFtZSwgc2Nyb2xsUGFyZW50LCB0b3VjaCwgdGFyZ2V0RWxlbWVudCA9IHRoaXMudGFyZ2V0RWxlbWVudDtcblxuXHRcdGlmICghdGhpcy50cmFja2luZ0NsaWNrKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBQcmV2ZW50IHBoYW50b20gY2xpY2tzIG9uIGZhc3QgZG91YmxlLXRhcCAoaXNzdWUgIzM2KVxuXHRcdGlmICgoZXZlbnQudGltZVN0YW1wIC0gdGhpcy5sYXN0Q2xpY2tUaW1lKSA8IHRoaXMudGFwRGVsYXkgJiYgKGV2ZW50LnRpbWVTdGFtcCAtIHRoaXMubGFzdENsaWNrVGltZSkgPiAtMSkge1xuXHRcdFx0dGhpcy5jYW5jZWxOZXh0Q2xpY2sgPSB0cnVlO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKChldmVudC50aW1lU3RhbXAgLSB0aGlzLnRyYWNraW5nQ2xpY2tTdGFydCkgPiB0aGlzLnRhcFRpbWVvdXQpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIFJlc2V0IHRvIHByZXZlbnQgd3JvbmcgY2xpY2sgY2FuY2VsIG9uIGlucHV0IChpc3N1ZSAjMTU2KS5cblx0XHR0aGlzLmNhbmNlbE5leHRDbGljayA9IGZhbHNlO1xuXG5cdFx0dGhpcy5sYXN0Q2xpY2tUaW1lID0gZXZlbnQudGltZVN0YW1wO1xuXG5cdFx0dHJhY2tpbmdDbGlja1N0YXJ0ID0gdGhpcy50cmFja2luZ0NsaWNrU3RhcnQ7XG5cdFx0dGhpcy50cmFja2luZ0NsaWNrID0gZmFsc2U7XG5cdFx0dGhpcy50cmFja2luZ0NsaWNrU3RhcnQgPSAwO1xuXG5cdFx0Ly8gT24gc29tZSBpT1MgZGV2aWNlcywgdGhlIHRhcmdldEVsZW1lbnQgc3VwcGxpZWQgd2l0aCB0aGUgZXZlbnQgaXMgaW52YWxpZCBpZiB0aGUgbGF5ZXJcblx0XHQvLyBpcyBwZXJmb3JtaW5nIGEgdHJhbnNpdGlvbiBvciBzY3JvbGwsIGFuZCBoYXMgdG8gYmUgcmUtZGV0ZWN0ZWQgbWFudWFsbHkuIE5vdGUgdGhhdFxuXHRcdC8vIGZvciB0aGlzIHRvIGZ1bmN0aW9uIGNvcnJlY3RseSwgaXQgbXVzdCBiZSBjYWxsZWQgKmFmdGVyKiB0aGUgZXZlbnQgdGFyZ2V0IGlzIGNoZWNrZWQhXG5cdFx0Ly8gU2VlIGlzc3VlICM1NzsgYWxzbyBmaWxlZCBhcyByZGFyOi8vMTMwNDg1ODkgLlxuXHRcdGlmIChkZXZpY2VJc0lPU1dpdGhCYWRUYXJnZXQpIHtcblx0XHRcdHRvdWNoID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF07XG5cblx0XHRcdC8vIEluIGNlcnRhaW4gY2FzZXMgYXJndW1lbnRzIG9mIGVsZW1lbnRGcm9tUG9pbnQgY2FuIGJlIG5lZ2F0aXZlLCBzbyBwcmV2ZW50IHNldHRpbmcgdGFyZ2V0RWxlbWVudCB0byBudWxsXG5cdFx0XHR0YXJnZXRFbGVtZW50ID0gZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludCh0b3VjaC5wYWdlWCAtIHdpbmRvdy5wYWdlWE9mZnNldCwgdG91Y2gucGFnZVkgLSB3aW5kb3cucGFnZVlPZmZzZXQpIHx8IHRhcmdldEVsZW1lbnQ7XG5cdFx0XHR0YXJnZXRFbGVtZW50LmZhc3RDbGlja1Njcm9sbFBhcmVudCA9IHRoaXMudGFyZ2V0RWxlbWVudC5mYXN0Q2xpY2tTY3JvbGxQYXJlbnQ7XG5cdFx0fVxuXG5cdFx0dGFyZ2V0VGFnTmFtZSA9IHRhcmdldEVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdGlmICh0YXJnZXRUYWdOYW1lID09PSAnbGFiZWwnKSB7XG5cdFx0XHRmb3JFbGVtZW50ID0gdGhpcy5maW5kQ29udHJvbCh0YXJnZXRFbGVtZW50KTtcblx0XHRcdGlmIChmb3JFbGVtZW50KSB7XG5cdFx0XHRcdHRoaXMuZm9jdXModGFyZ2V0RWxlbWVudCk7XG5cdFx0XHRcdGlmIChkZXZpY2VJc0FuZHJvaWQpIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0YXJnZXRFbGVtZW50ID0gZm9yRWxlbWVudDtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKHRoaXMubmVlZHNGb2N1cyh0YXJnZXRFbGVtZW50KSkge1xuXG5cdFx0XHQvLyBDYXNlIDE6IElmIHRoZSB0b3VjaCBzdGFydGVkIGEgd2hpbGUgYWdvIChiZXN0IGd1ZXNzIGlzIDEwMG1zIGJhc2VkIG9uIHRlc3RzIGZvciBpc3N1ZSAjMzYpIHRoZW4gZm9jdXMgd2lsbCBiZSB0cmlnZ2VyZWQgYW55d2F5LiBSZXR1cm4gZWFybHkgYW5kIHVuc2V0IHRoZSB0YXJnZXQgZWxlbWVudCByZWZlcmVuY2Ugc28gdGhhdCB0aGUgc3Vic2VxdWVudCBjbGljayB3aWxsIGJlIGFsbG93ZWQgdGhyb3VnaC5cblx0XHRcdC8vIENhc2UgMjogV2l0aG91dCB0aGlzIGV4Y2VwdGlvbiBmb3IgaW5wdXQgZWxlbWVudHMgdGFwcGVkIHdoZW4gdGhlIGRvY3VtZW50IGlzIGNvbnRhaW5lZCBpbiBhbiBpZnJhbWUsIHRoZW4gYW55IGlucHV0dGVkIHRleHQgd29uJ3QgYmUgdmlzaWJsZSBldmVuIHRob3VnaCB0aGUgdmFsdWUgYXR0cmlidXRlIGlzIHVwZGF0ZWQgYXMgdGhlIHVzZXIgdHlwZXMgKGlzc3VlICMzNykuXG5cdFx0XHRpZiAoKGV2ZW50LnRpbWVTdGFtcCAtIHRyYWNraW5nQ2xpY2tTdGFydCkgPiAxMDAgfHwgKGRldmljZUlzSU9TICYmIHdpbmRvdy50b3AgIT09IHdpbmRvdyAmJiB0YXJnZXRUYWdOYW1lID09PSAnaW5wdXQnKSkge1xuXHRcdFx0XHR0aGlzLnRhcmdldEVsZW1lbnQgPSBudWxsO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuZm9jdXModGFyZ2V0RWxlbWVudCk7XG5cdFx0XHR0aGlzLnNlbmRDbGljayh0YXJnZXRFbGVtZW50LCBldmVudCk7XG5cblx0XHRcdC8vIFNlbGVjdCBlbGVtZW50cyBuZWVkIHRoZSBldmVudCB0byBnbyB0aHJvdWdoIG9uIGlPUyA0LCBvdGhlcndpc2UgdGhlIHNlbGVjdG9yIG1lbnUgd29uJ3Qgb3Blbi5cblx0XHRcdC8vIEFsc28gdGhpcyBicmVha3Mgb3BlbmluZyBzZWxlY3RzIHdoZW4gVm9pY2VPdmVyIGlzIGFjdGl2ZSBvbiBpT1M2LCBpT1M3IChhbmQgcG9zc2libHkgb3RoZXJzKVxuXHRcdFx0aWYgKCFkZXZpY2VJc0lPUzQgfHwgdGFyZ2V0VGFnTmFtZSAhPT0gJ3NlbGVjdCcpIHtcblx0XHRcdFx0dGhpcy50YXJnZXRFbGVtZW50ID0gbnVsbDtcblx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblxuXHRcdGlmIChkZXZpY2VJc0lPUyAmJiAhZGV2aWNlSXNJT1M0KSB7XG5cblx0XHRcdC8vIERvbid0IHNlbmQgYSBzeW50aGV0aWMgY2xpY2sgZXZlbnQgaWYgdGhlIHRhcmdldCBlbGVtZW50IGlzIGNvbnRhaW5lZCB3aXRoaW4gYSBwYXJlbnQgbGF5ZXIgdGhhdCB3YXMgc2Nyb2xsZWRcblx0XHRcdC8vIGFuZCB0aGlzIHRhcCBpcyBiZWluZyB1c2VkIHRvIHN0b3AgdGhlIHNjcm9sbGluZyAodXN1YWxseSBpbml0aWF0ZWQgYnkgYSBmbGluZyAtIGlzc3VlICM0MikuXG5cdFx0XHRzY3JvbGxQYXJlbnQgPSB0YXJnZXRFbGVtZW50LmZhc3RDbGlja1Njcm9sbFBhcmVudDtcblx0XHRcdGlmIChzY3JvbGxQYXJlbnQgJiYgc2Nyb2xsUGFyZW50LmZhc3RDbGlja0xhc3RTY3JvbGxUb3AgIT09IHNjcm9sbFBhcmVudC5zY3JvbGxUb3ApIHtcblx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUHJldmVudCB0aGUgYWN0dWFsIGNsaWNrIGZyb20gZ29pbmcgdGhvdWdoIC0gdW5sZXNzIHRoZSB0YXJnZXQgbm9kZSBpcyBtYXJrZWQgYXMgcmVxdWlyaW5nXG5cdFx0Ly8gcmVhbCBjbGlja3Mgb3IgaWYgaXQgaXMgaW4gdGhlIHdoaXRlbGlzdCBpbiB3aGljaCBjYXNlIG9ubHkgbm9uLXByb2dyYW1tYXRpYyBjbGlja3MgYXJlIHBlcm1pdHRlZC5cblx0XHRpZiAoIXRoaXMubmVlZHNDbGljayh0YXJnZXRFbGVtZW50KSkge1xuXHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdHRoaXMuc2VuZENsaWNrKHRhcmdldEVsZW1lbnQsIGV2ZW50KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH07XG5cblxuXHQvKipcblx0ICogT24gdG91Y2ggY2FuY2VsLCBzdG9wIHRyYWNraW5nIHRoZSBjbGljay5cblx0ICpcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uVG91Y2hDYW5jZWwgPSBmdW5jdGlvbigpIHtcblx0XHR0aGlzLnRyYWNraW5nQ2xpY2sgPSBmYWxzZTtcblx0XHR0aGlzLnRhcmdldEVsZW1lbnQgPSBudWxsO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIERldGVybWluZSBtb3VzZSBldmVudHMgd2hpY2ggc2hvdWxkIGJlIHBlcm1pdHRlZC5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uTW91c2UgPSBmdW5jdGlvbihldmVudCkge1xuXG5cdFx0Ly8gSWYgYSB0YXJnZXQgZWxlbWVudCB3YXMgbmV2ZXIgc2V0IChiZWNhdXNlIGEgdG91Y2ggZXZlbnQgd2FzIG5ldmVyIGZpcmVkKSBhbGxvdyB0aGUgZXZlbnRcblx0XHRpZiAoIXRoaXMudGFyZ2V0RWxlbWVudCkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKGV2ZW50LmZvcndhcmRlZFRvdWNoRXZlbnQpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIFByb2dyYW1tYXRpY2FsbHkgZ2VuZXJhdGVkIGV2ZW50cyB0YXJnZXRpbmcgYSBzcGVjaWZpYyBlbGVtZW50IHNob3VsZCBiZSBwZXJtaXR0ZWRcblx0XHRpZiAoIWV2ZW50LmNhbmNlbGFibGUpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdC8vIERlcml2ZSBhbmQgY2hlY2sgdGhlIHRhcmdldCBlbGVtZW50IHRvIHNlZSB3aGV0aGVyIHRoZSBtb3VzZSBldmVudCBuZWVkcyB0byBiZSBwZXJtaXR0ZWQ7XG5cdFx0Ly8gdW5sZXNzIGV4cGxpY2l0bHkgZW5hYmxlZCwgcHJldmVudCBub24tdG91Y2ggY2xpY2sgZXZlbnRzIGZyb20gdHJpZ2dlcmluZyBhY3Rpb25zLFxuXHRcdC8vIHRvIHByZXZlbnQgZ2hvc3QvZG91YmxlY2xpY2tzLlxuXHRcdGlmICghdGhpcy5uZWVkc0NsaWNrKHRoaXMudGFyZ2V0RWxlbWVudCkgfHwgdGhpcy5jYW5jZWxOZXh0Q2xpY2spIHtcblxuXHRcdFx0Ly8gUHJldmVudCBhbnkgdXNlci1hZGRlZCBsaXN0ZW5lcnMgZGVjbGFyZWQgb24gRmFzdENsaWNrIGVsZW1lbnQgZnJvbSBiZWluZyBmaXJlZC5cblx0XHRcdGlmIChldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24pIHtcblx0XHRcdFx0ZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdC8vIFBhcnQgb2YgdGhlIGhhY2sgZm9yIGJyb3dzZXJzIHRoYXQgZG9uJ3Qgc3VwcG9ydCBFdmVudCNzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24gKGUuZy4gQW5kcm9pZCAyKVxuXHRcdFx0XHRldmVudC5wcm9wYWdhdGlvblN0b3BwZWQgPSB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDYW5jZWwgdGhlIGV2ZW50XG5cdFx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHQvLyBJZiB0aGUgbW91c2UgZXZlbnQgaXMgcGVybWl0dGVkLCByZXR1cm4gdHJ1ZSBmb3IgdGhlIGFjdGlvbiB0byBnbyB0aHJvdWdoLlxuXHRcdHJldHVybiB0cnVlO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIE9uIGFjdHVhbCBjbGlja3MsIGRldGVybWluZSB3aGV0aGVyIHRoaXMgaXMgYSB0b3VjaC1nZW5lcmF0ZWQgY2xpY2ssIGEgY2xpY2sgYWN0aW9uIG9jY3VycmluZ1xuXHQgKiBuYXR1cmFsbHkgYWZ0ZXIgYSBkZWxheSBhZnRlciBhIHRvdWNoICh3aGljaCBuZWVkcyB0byBiZSBjYW5jZWxsZWQgdG8gYXZvaWQgZHVwbGljYXRpb24pLCBvclxuXHQgKiBhbiBhY3R1YWwgY2xpY2sgd2hpY2ggc2hvdWxkIGJlIHBlcm1pdHRlZC5cblx0ICpcblx0ICogQHBhcmFtIHtFdmVudH0gZXZlbnRcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLm9uQ2xpY2sgPSBmdW5jdGlvbihldmVudCkge1xuXHRcdHZhciBwZXJtaXR0ZWQ7XG5cblx0XHQvLyBJdCdzIHBvc3NpYmxlIGZvciBhbm90aGVyIEZhc3RDbGljay1saWtlIGxpYnJhcnkgZGVsaXZlcmVkIHdpdGggdGhpcmQtcGFydHkgY29kZSB0byBmaXJlIGEgY2xpY2sgZXZlbnQgYmVmb3JlIEZhc3RDbGljayBkb2VzIChpc3N1ZSAjNDQpLiBJbiB0aGF0IGNhc2UsIHNldCB0aGUgY2xpY2stdHJhY2tpbmcgZmxhZyBiYWNrIHRvIGZhbHNlIGFuZCByZXR1cm4gZWFybHkuIFRoaXMgd2lsbCBjYXVzZSBvblRvdWNoRW5kIHRvIHJldHVybiBlYXJseS5cblx0XHRpZiAodGhpcy50cmFja2luZ0NsaWNrKSB7XG5cdFx0XHR0aGlzLnRhcmdldEVsZW1lbnQgPSBudWxsO1xuXHRcdFx0dGhpcy50cmFja2luZ0NsaWNrID0gZmFsc2U7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBWZXJ5IG9kZCBiZWhhdmlvdXIgb24gaU9TIChpc3N1ZSAjMTgpOiBpZiBhIHN1Ym1pdCBlbGVtZW50IGlzIHByZXNlbnQgaW5zaWRlIGEgZm9ybSBhbmQgdGhlIHVzZXIgaGl0cyBlbnRlciBpbiB0aGUgaU9TIHNpbXVsYXRvciBvciBjbGlja3MgdGhlIEdvIGJ1dHRvbiBvbiB0aGUgcG9wLXVwIE9TIGtleWJvYXJkIHRoZSBhIGtpbmQgb2YgJ2Zha2UnIGNsaWNrIGV2ZW50IHdpbGwgYmUgdHJpZ2dlcmVkIHdpdGggdGhlIHN1Ym1pdC10eXBlIGlucHV0IGVsZW1lbnQgYXMgdGhlIHRhcmdldC5cblx0XHRpZiAoZXZlbnQudGFyZ2V0LnR5cGUgPT09ICdzdWJtaXQnICYmIGV2ZW50LmRldGFpbCA9PT0gMCkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0cGVybWl0dGVkID0gdGhpcy5vbk1vdXNlKGV2ZW50KTtcblxuXHRcdC8vIE9ubHkgdW5zZXQgdGFyZ2V0RWxlbWVudCBpZiB0aGUgY2xpY2sgaXMgbm90IHBlcm1pdHRlZC4gVGhpcyB3aWxsIGVuc3VyZSB0aGF0IHRoZSBjaGVjayBmb3IgIXRhcmdldEVsZW1lbnQgaW4gb25Nb3VzZSBmYWlscyBhbmQgdGhlIGJyb3dzZXIncyBjbGljayBkb2Vzbid0IGdvIHRocm91Z2guXG5cdFx0aWYgKCFwZXJtaXR0ZWQpIHtcblx0XHRcdHRoaXMudGFyZ2V0RWxlbWVudCA9IG51bGw7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgY2xpY2tzIGFyZSBwZXJtaXR0ZWQsIHJldHVybiB0cnVlIGZvciB0aGUgYWN0aW9uIHRvIGdvIHRocm91Z2guXG5cdFx0cmV0dXJuIHBlcm1pdHRlZDtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBSZW1vdmUgYWxsIEZhc3RDbGljaydzIGV2ZW50IGxpc3RlbmVycy5cblx0ICpcblx0ICogQHJldHVybnMge3ZvaWR9XG5cdCAqL1xuXHRGYXN0Q2xpY2sucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbigpIHtcblx0XHR2YXIgbGF5ZXIgPSB0aGlzLmxheWVyO1xuXG5cdFx0aWYgKGRldmljZUlzQW5kcm9pZCkge1xuXHRcdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VvdmVyJywgdGhpcy5vbk1vdXNlLCB0cnVlKTtcblx0XHRcdGxheWVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHRoaXMub25Nb3VzZSwgdHJ1ZSk7XG5cdFx0XHRsYXllci5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5vbk1vdXNlLCB0cnVlKTtcblx0XHR9XG5cblx0XHRsYXllci5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMub25DbGljaywgdHJ1ZSk7XG5cdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIHRoaXMub25Ub3VjaFN0YXJ0LCBmYWxzZSk7XG5cdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgdGhpcy5vblRvdWNoTW92ZSwgZmFsc2UpO1xuXHRcdGxheWVyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgdGhpcy5vblRvdWNoRW5kLCBmYWxzZSk7XG5cdFx0bGF5ZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hjYW5jZWwnLCB0aGlzLm9uVG91Y2hDYW5jZWwsIGZhbHNlKTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBDaGVjayB3aGV0aGVyIEZhc3RDbGljayBpcyBuZWVkZWQuXG5cdCAqXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbGF5ZXIgVGhlIGxheWVyIHRvIGxpc3RlbiBvblxuXHQgKi9cblx0RmFzdENsaWNrLm5vdE5lZWRlZCA9IGZ1bmN0aW9uKGxheWVyKSB7XG5cdFx0dmFyIG1ldGFWaWV3cG9ydDtcblx0XHR2YXIgY2hyb21lVmVyc2lvbjtcblx0XHR2YXIgYmxhY2tiZXJyeVZlcnNpb247XG5cdFx0dmFyIGZpcmVmb3hWZXJzaW9uO1xuXG5cdFx0Ly8gRGV2aWNlcyB0aGF0IGRvbid0IHN1cHBvcnQgdG91Y2ggZG9uJ3QgbmVlZCBGYXN0Q2xpY2tcblx0XHRpZiAodHlwZW9mIHdpbmRvdy5vbnRvdWNoc3RhcnQgPT09ICd1bmRlZmluZWQnKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBDaHJvbWUgdmVyc2lvbiAtIHplcm8gZm9yIG90aGVyIGJyb3dzZXJzXG5cdFx0Y2hyb21lVmVyc2lvbiA9ICsoL0Nocm9tZVxcLyhbMC05XSspLy5leGVjKG5hdmlnYXRvci51c2VyQWdlbnQpIHx8IFssMF0pWzFdO1xuXG5cdFx0aWYgKGNocm9tZVZlcnNpb24pIHtcblxuXHRcdFx0aWYgKGRldmljZUlzQW5kcm9pZCkge1xuXHRcdFx0XHRtZXRhVmlld3BvcnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdtZXRhW25hbWU9dmlld3BvcnRdJyk7XG5cblx0XHRcdFx0aWYgKG1ldGFWaWV3cG9ydCkge1xuXHRcdFx0XHRcdC8vIENocm9tZSBvbiBBbmRyb2lkIHdpdGggdXNlci1zY2FsYWJsZT1cIm5vXCIgZG9lc24ndCBuZWVkIEZhc3RDbGljayAoaXNzdWUgIzg5KVxuXHRcdFx0XHRcdGlmIChtZXRhVmlld3BvcnQuY29udGVudC5pbmRleE9mKCd1c2VyLXNjYWxhYmxlPW5vJykgIT09IC0xKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0Ly8gQ2hyb21lIDMyIGFuZCBhYm92ZSB3aXRoIHdpZHRoPWRldmljZS13aWR0aCBvciBsZXNzIGRvbid0IG5lZWQgRmFzdENsaWNrXG5cdFx0XHRcdFx0aWYgKGNocm9tZVZlcnNpb24gPiAzMSAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsV2lkdGggPD0gd2luZG93Lm91dGVyV2lkdGgpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBDaHJvbWUgZGVza3RvcCBkb2Vzbid0IG5lZWQgRmFzdENsaWNrIChpc3N1ZSAjMTUpXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoZGV2aWNlSXNCbGFja0JlcnJ5MTApIHtcblx0XHRcdGJsYWNrYmVycnlWZXJzaW9uID0gbmF2aWdhdG9yLnVzZXJBZ2VudC5tYXRjaCgvVmVyc2lvblxcLyhbMC05XSopXFwuKFswLTldKikvKTtcblxuXHRcdFx0Ly8gQmxhY2tCZXJyeSAxMC4zKyBkb2VzIG5vdCByZXF1aXJlIEZhc3RjbGljayBsaWJyYXJ5LlxuXHRcdFx0Ly8gaHR0cHM6Ly9naXRodWIuY29tL2Z0bGFicy9mYXN0Y2xpY2svaXNzdWVzLzI1MVxuXHRcdFx0aWYgKGJsYWNrYmVycnlWZXJzaW9uWzFdID49IDEwICYmIGJsYWNrYmVycnlWZXJzaW9uWzJdID49IDMpIHtcblx0XHRcdFx0bWV0YVZpZXdwb3J0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignbWV0YVtuYW1lPXZpZXdwb3J0XScpO1xuXG5cdFx0XHRcdGlmIChtZXRhVmlld3BvcnQpIHtcblx0XHRcdFx0XHQvLyB1c2VyLXNjYWxhYmxlPW5vIGVsaW1pbmF0ZXMgY2xpY2sgZGVsYXkuXG5cdFx0XHRcdFx0aWYgKG1ldGFWaWV3cG9ydC5jb250ZW50LmluZGV4T2YoJ3VzZXItc2NhbGFibGU9bm8nKSAhPT0gLTEpIHtcblx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQvLyB3aWR0aD1kZXZpY2Utd2lkdGggKG9yIGxlc3MgdGhhbiBkZXZpY2Utd2lkdGgpIGVsaW1pbmF0ZXMgY2xpY2sgZGVsYXkuXG5cdFx0XHRcdFx0aWYgKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxXaWR0aCA8PSB3aW5kb3cub3V0ZXJXaWR0aCkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gSUUxMCB3aXRoIC1tcy10b3VjaC1hY3Rpb246IG5vbmUgb3IgbWFuaXB1bGF0aW9uLCB3aGljaCBkaXNhYmxlcyBkb3VibGUtdGFwLXRvLXpvb20gKGlzc3VlICM5Nylcblx0XHRpZiAobGF5ZXIuc3R5bGUubXNUb3VjaEFjdGlvbiA9PT0gJ25vbmUnIHx8IGxheWVyLnN0eWxlLnRvdWNoQWN0aW9uID09PSAnbWFuaXB1bGF0aW9uJykge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Ly8gRmlyZWZveCB2ZXJzaW9uIC0gemVybyBmb3Igb3RoZXIgYnJvd3NlcnNcblx0XHRmaXJlZm94VmVyc2lvbiA9ICsoL0ZpcmVmb3hcXC8oWzAtOV0rKS8uZXhlYyhuYXZpZ2F0b3IudXNlckFnZW50KSB8fCBbLDBdKVsxXTtcblxuXHRcdGlmIChmaXJlZm94VmVyc2lvbiA+PSAyNykge1xuXHRcdFx0Ly8gRmlyZWZveCAyNysgZG9lcyBub3QgaGF2ZSB0YXAgZGVsYXkgaWYgdGhlIGNvbnRlbnQgaXMgbm90IHpvb21hYmxlIC0gaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9OTIyODk2XG5cblx0XHRcdG1ldGFWaWV3cG9ydCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ21ldGFbbmFtZT12aWV3cG9ydF0nKTtcblx0XHRcdGlmIChtZXRhVmlld3BvcnQgJiYgKG1ldGFWaWV3cG9ydC5jb250ZW50LmluZGV4T2YoJ3VzZXItc2NhbGFibGU9bm8nKSAhPT0gLTEgfHwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFdpZHRoIDw9IHdpbmRvdy5vdXRlcldpZHRoKSkge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBJRTExOiBwcmVmaXhlZCAtbXMtdG91Y2gtYWN0aW9uIGlzIG5vIGxvbmdlciBzdXBwb3J0ZWQgYW5kIGl0J3MgcmVjb21lbmRlZCB0byB1c2Ugbm9uLXByZWZpeGVkIHZlcnNpb25cblx0XHQvLyBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvd2luZG93cy9hcHBzL0hoNzY3MzEzLmFzcHhcblx0XHRpZiAobGF5ZXIuc3R5bGUudG91Y2hBY3Rpb24gPT09ICdub25lJyB8fCBsYXllci5zdHlsZS50b3VjaEFjdGlvbiA9PT0gJ21hbmlwdWxhdGlvbicpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblxuXHRcdHJldHVybiBmYWxzZTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBGYWN0b3J5IG1ldGhvZCBmb3IgY3JlYXRpbmcgYSBGYXN0Q2xpY2sgb2JqZWN0XG5cdCAqXG5cdCAqIEBwYXJhbSB7RWxlbWVudH0gbGF5ZXIgVGhlIGxheWVyIHRvIGxpc3RlbiBvblxuXHQgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dIFRoZSBvcHRpb25zIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0c1xuXHQgKi9cblx0RmFzdENsaWNrLmF0dGFjaCA9IGZ1bmN0aW9uKGxheWVyLCBvcHRpb25zKSB7XG5cdFx0cmV0dXJuIG5ldyBGYXN0Q2xpY2sobGF5ZXIsIG9wdGlvbnMpO1xuXHR9O1xuXG5cblx0aWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09ICdvYmplY3QnICYmIGRlZmluZS5hbWQpIHtcblxuXHRcdC8vIEFNRC4gUmVnaXN0ZXIgYXMgYW4gYW5vbnltb3VzIG1vZHVsZS5cblx0XHRkZWZpbmUoZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gRmFzdENsaWNrO1xuXHRcdH0pO1xuXHR9IGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSB7XG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBGYXN0Q2xpY2suYXR0YWNoO1xuXHRcdG1vZHVsZS5leHBvcnRzLkZhc3RDbGljayA9IEZhc3RDbGljaztcblx0fSBlbHNlIHtcblx0XHR3aW5kb3cuRmFzdENsaWNrID0gRmFzdENsaWNrO1xuXHR9XG59KCkpO1xuIiwiLy8gRm9yIEBvbnNlbnVpL2N1c3RvbS1lbGVtZW50c1xuaWYgKHdpbmRvdy5jdXN0b21FbGVtZW50cykgeyAvLyBldmVuIGlmIG5hdGl2ZSBDRTEgaW1wbCBleGlzdHMsIHVzZSBwb2x5ZmlsbFxuICAgIHdpbmRvdy5jdXN0b21FbGVtZW50cy5mb3JjZVBvbHlmaWxsID0gdHJ1ZTtcbn1cbiIsIi8vIGh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2lzc3Vlcy84NiNpc3N1ZWNvbW1lbnQtMTE1NzU5MDI4XG52YXIgZ2xvYmFsID0gbW9kdWxlLmV4cG9ydHMgPSB0eXBlb2Ygd2luZG93ICE9ICd1bmRlZmluZWQnICYmIHdpbmRvdy5NYXRoID09IE1hdGhcbiAgPyB3aW5kb3cgOiB0eXBlb2Ygc2VsZiAhPSAndW5kZWZpbmVkJyAmJiBzZWxmLk1hdGggPT0gTWF0aCA/IHNlbGZcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jXG4gIDogRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTtcbmlmICh0eXBlb2YgX19nID09ICdudW1iZXInKSBfX2cgPSBnbG9iYWw7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW5kZWZcbiIsInZhciBjb3JlID0gbW9kdWxlLmV4cG9ydHMgPSB7IHZlcnNpb246ICcyLjUuMScgfTtcbmlmICh0eXBlb2YgX19lID09ICdudW1iZXInKSBfX2UgPSBjb3JlOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gdHlwZW9mIGl0ID09PSAnb2JqZWN0JyA/IGl0ICE9PSBudWxsIDogdHlwZW9mIGl0ID09PSAnZnVuY3Rpb24nO1xufTtcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgaWYgKCFpc09iamVjdChpdCkpIHRocm93IFR5cGVFcnJvcihpdCArICcgaXMgbm90IGFuIG9iamVjdCEnKTtcbiAgcmV0dXJuIGl0O1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGV4ZWMpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gISFleGVjKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufTtcbiIsIi8vIFRoYW5rJ3MgSUU4IGZvciBoaXMgZnVubnkgZGVmaW5lUHJvcGVydHlcbm1vZHVsZS5leHBvcnRzID0gIXJlcXVpcmUoJy4vX2ZhaWxzJykoZnVuY3Rpb24gKCkge1xuICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCAnYScsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pLmEgIT0gNztcbn0pO1xuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgZG9jdW1lbnQgPSByZXF1aXJlKCcuL19nbG9iYWwnKS5kb2N1bWVudDtcbi8vIHR5cGVvZiBkb2N1bWVudC5jcmVhdGVFbGVtZW50IGlzICdvYmplY3QnIGluIG9sZCBJRVxudmFyIGlzID0gaXNPYmplY3QoZG9jdW1lbnQpICYmIGlzT2JqZWN0KGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIGlzID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChpdCkgOiB7fTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9ICFyZXF1aXJlKCcuL19kZXNjcmlwdG9ycycpICYmICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShyZXF1aXJlKCcuL19kb20tY3JlYXRlJykoJ2RpdicpLCAnYScsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pLmEgIT0gNztcbn0pO1xuIiwiLy8gNy4xLjEgVG9QcmltaXRpdmUoaW5wdXQgWywgUHJlZmVycmVkVHlwZV0pXG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL19pcy1vYmplY3QnKTtcbi8vIGluc3RlYWQgb2YgdGhlIEVTNiBzcGVjIHZlcnNpb24sIHdlIGRpZG4ndCBpbXBsZW1lbnQgQEB0b1ByaW1pdGl2ZSBjYXNlXG4vLyBhbmQgdGhlIHNlY29uZCBhcmd1bWVudCAtIGZsYWcgLSBwcmVmZXJyZWQgdHlwZSBpcyBhIHN0cmluZ1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQsIFMpIHtcbiAgaWYgKCFpc09iamVjdChpdCkpIHJldHVybiBpdDtcbiAgdmFyIGZuLCB2YWw7XG4gIGlmIChTICYmIHR5cGVvZiAoZm4gPSBpdC50b1N0cmluZykgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNPYmplY3QodmFsID0gZm4uY2FsbChpdCkpKSByZXR1cm4gdmFsO1xuICBpZiAodHlwZW9mIChmbiA9IGl0LnZhbHVlT2YpID09ICdmdW5jdGlvbicgJiYgIWlzT2JqZWN0KHZhbCA9IGZuLmNhbGwoaXQpKSkgcmV0dXJuIHZhbDtcbiAgaWYgKCFTICYmIHR5cGVvZiAoZm4gPSBpdC50b1N0cmluZykgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNPYmplY3QodmFsID0gZm4uY2FsbChpdCkpKSByZXR1cm4gdmFsO1xuICB0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjb252ZXJ0IG9iamVjdCB0byBwcmltaXRpdmUgdmFsdWVcIik7XG59O1xuIiwidmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG52YXIgSUU4X0RPTV9ERUZJTkUgPSByZXF1aXJlKCcuL19pZTgtZG9tLWRlZmluZScpO1xudmFyIHRvUHJpbWl0aXZlID0gcmVxdWlyZSgnLi9fdG8tcHJpbWl0aXZlJyk7XG52YXIgZFAgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG5cbmV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBPYmplY3QuZGVmaW5lUHJvcGVydHkgOiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKSB7XG4gIGFuT2JqZWN0KE8pO1xuICBQID0gdG9QcmltaXRpdmUoUCwgdHJ1ZSk7XG4gIGFuT2JqZWN0KEF0dHJpYnV0ZXMpO1xuICBpZiAoSUU4X0RPTV9ERUZJTkUpIHRyeSB7XG4gICAgcmV0dXJuIGRQKE8sIFAsIEF0dHJpYnV0ZXMpO1xuICB9IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cbiAgaWYgKCdnZXQnIGluIEF0dHJpYnV0ZXMgfHwgJ3NldCcgaW4gQXR0cmlidXRlcykgdGhyb3cgVHlwZUVycm9yKCdBY2Nlc3NvcnMgbm90IHN1cHBvcnRlZCEnKTtcbiAgaWYgKCd2YWx1ZScgaW4gQXR0cmlidXRlcykgT1tQXSA9IEF0dHJpYnV0ZXMudmFsdWU7XG4gIHJldHVybiBPO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGJpdG1hcCwgdmFsdWUpIHtcbiAgcmV0dXJuIHtcbiAgICBlbnVtZXJhYmxlOiAhKGJpdG1hcCAmIDEpLFxuICAgIGNvbmZpZ3VyYWJsZTogIShiaXRtYXAgJiAyKSxcbiAgICB3cml0YWJsZTogIShiaXRtYXAgJiA0KSxcbiAgICB2YWx1ZTogdmFsdWVcbiAgfTtcbn07XG4iLCJ2YXIgZFAgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKTtcbnZhciBjcmVhdGVEZXNjID0gcmVxdWlyZSgnLi9fcHJvcGVydHktZGVzYycpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19kZXNjcmlwdG9ycycpID8gZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkge1xuICByZXR1cm4gZFAuZihvYmplY3QsIGtleSwgY3JlYXRlRGVzYygxLCB2YWx1ZSkpO1xufSA6IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgb2JqZWN0W2tleV0gPSB2YWx1ZTtcbiAgcmV0dXJuIG9iamVjdDtcbn07XG4iLCJ2YXIgaGFzT3duUHJvcGVydHkgPSB7fS5oYXNPd25Qcm9wZXJ0eTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0LCBrZXkpIHtcbiAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwoaXQsIGtleSk7XG59O1xuIiwidmFyIGlkID0gMDtcbnZhciBweCA9IE1hdGgucmFuZG9tKCk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuICdTeW1ib2woJy5jb25jYXQoa2V5ID09PSB1bmRlZmluZWQgPyAnJyA6IGtleSwgJylfJywgKCsraWQgKyBweCkudG9TdHJpbmcoMzYpKTtcbn07XG4iLCJ2YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi9fZ2xvYmFsJyk7XG52YXIgaGlkZSA9IHJlcXVpcmUoJy4vX2hpZGUnKTtcbnZhciBoYXMgPSByZXF1aXJlKCcuL19oYXMnKTtcbnZhciBTUkMgPSByZXF1aXJlKCcuL191aWQnKSgnc3JjJyk7XG52YXIgVE9fU1RSSU5HID0gJ3RvU3RyaW5nJztcbnZhciAkdG9TdHJpbmcgPSBGdW5jdGlvbltUT19TVFJJTkddO1xudmFyIFRQTCA9ICgnJyArICR0b1N0cmluZykuc3BsaXQoVE9fU1RSSU5HKTtcblxucmVxdWlyZSgnLi9fY29yZScpLmluc3BlY3RTb3VyY2UgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuICR0b1N0cmluZy5jYWxsKGl0KTtcbn07XG5cbihtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChPLCBrZXksIHZhbCwgc2FmZSkge1xuICB2YXIgaXNGdW5jdGlvbiA9IHR5cGVvZiB2YWwgPT0gJ2Z1bmN0aW9uJztcbiAgaWYgKGlzRnVuY3Rpb24pIGhhcyh2YWwsICduYW1lJykgfHwgaGlkZSh2YWwsICduYW1lJywga2V5KTtcbiAgaWYgKE9ba2V5XSA9PT0gdmFsKSByZXR1cm47XG4gIGlmIChpc0Z1bmN0aW9uKSBoYXModmFsLCBTUkMpIHx8IGhpZGUodmFsLCBTUkMsIE9ba2V5XSA/ICcnICsgT1trZXldIDogVFBMLmpvaW4oU3RyaW5nKGtleSkpKTtcbiAgaWYgKE8gPT09IGdsb2JhbCkge1xuICAgIE9ba2V5XSA9IHZhbDtcbiAgfSBlbHNlIGlmICghc2FmZSkge1xuICAgIGRlbGV0ZSBPW2tleV07XG4gICAgaGlkZShPLCBrZXksIHZhbCk7XG4gIH0gZWxzZSBpZiAoT1trZXldKSB7XG4gICAgT1trZXldID0gdmFsO1xuICB9IGVsc2Uge1xuICAgIGhpZGUoTywga2V5LCB2YWwpO1xuICB9XG4vLyBhZGQgZmFrZSBGdW5jdGlvbiN0b1N0cmluZyBmb3IgY29ycmVjdCB3b3JrIHdyYXBwZWQgbWV0aG9kcyAvIGNvbnN0cnVjdG9ycyB3aXRoIG1ldGhvZHMgbGlrZSBMb0Rhc2ggaXNOYXRpdmVcbn0pKEZ1bmN0aW9uLnByb3RvdHlwZSwgVE9fU1RSSU5HLCBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgcmV0dXJuIHR5cGVvZiB0aGlzID09ICdmdW5jdGlvbicgJiYgdGhpc1tTUkNdIHx8ICR0b1N0cmluZy5jYWxsKHRoaXMpO1xufSk7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAodHlwZW9mIGl0ICE9ICdmdW5jdGlvbicpIHRocm93IFR5cGVFcnJvcihpdCArICcgaXMgbm90IGEgZnVuY3Rpb24hJyk7XG4gIHJldHVybiBpdDtcbn07XG4iLCIvLyBvcHRpb25hbCAvIHNpbXBsZSBjb250ZXh0IGJpbmRpbmdcbnZhciBhRnVuY3Rpb24gPSByZXF1aXJlKCcuL19hLWZ1bmN0aW9uJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChmbiwgdGhhdCwgbGVuZ3RoKSB7XG4gIGFGdW5jdGlvbihmbik7XG4gIGlmICh0aGF0ID09PSB1bmRlZmluZWQpIHJldHVybiBmbjtcbiAgc3dpdGNoIChsZW5ndGgpIHtcbiAgICBjYXNlIDE6IHJldHVybiBmdW5jdGlvbiAoYSkge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSk7XG4gICAgfTtcbiAgICBjYXNlIDI6IHJldHVybiBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSwgYik7XG4gICAgfTtcbiAgICBjYXNlIDM6IHJldHVybiBmdW5jdGlvbiAoYSwgYiwgYykge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSwgYiwgYyk7XG4gICAgfTtcbiAgfVxuICByZXR1cm4gZnVuY3Rpb24gKC8qIC4uLmFyZ3MgKi8pIHtcbiAgICByZXR1cm4gZm4uYXBwbHkodGhhdCwgYXJndW1lbnRzKTtcbiAgfTtcbn07XG4iLCJ2YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi9fZ2xvYmFsJyk7XG52YXIgY29yZSA9IHJlcXVpcmUoJy4vX2NvcmUnKTtcbnZhciBoaWRlID0gcmVxdWlyZSgnLi9faGlkZScpO1xudmFyIHJlZGVmaW5lID0gcmVxdWlyZSgnLi9fcmVkZWZpbmUnKTtcbnZhciBjdHggPSByZXF1aXJlKCcuL19jdHgnKTtcbnZhciBQUk9UT1RZUEUgPSAncHJvdG90eXBlJztcblxudmFyICRleHBvcnQgPSBmdW5jdGlvbiAodHlwZSwgbmFtZSwgc291cmNlKSB7XG4gIHZhciBJU19GT1JDRUQgPSB0eXBlICYgJGV4cG9ydC5GO1xuICB2YXIgSVNfR0xPQkFMID0gdHlwZSAmICRleHBvcnQuRztcbiAgdmFyIElTX1NUQVRJQyA9IHR5cGUgJiAkZXhwb3J0LlM7XG4gIHZhciBJU19QUk9UTyA9IHR5cGUgJiAkZXhwb3J0LlA7XG4gIHZhciBJU19CSU5EID0gdHlwZSAmICRleHBvcnQuQjtcbiAgdmFyIHRhcmdldCA9IElTX0dMT0JBTCA/IGdsb2JhbCA6IElTX1NUQVRJQyA/IGdsb2JhbFtuYW1lXSB8fCAoZ2xvYmFsW25hbWVdID0ge30pIDogKGdsb2JhbFtuYW1lXSB8fCB7fSlbUFJPVE9UWVBFXTtcbiAgdmFyIGV4cG9ydHMgPSBJU19HTE9CQUwgPyBjb3JlIDogY29yZVtuYW1lXSB8fCAoY29yZVtuYW1lXSA9IHt9KTtcbiAgdmFyIGV4cFByb3RvID0gZXhwb3J0c1tQUk9UT1RZUEVdIHx8IChleHBvcnRzW1BST1RPVFlQRV0gPSB7fSk7XG4gIHZhciBrZXksIG93biwgb3V0LCBleHA7XG4gIGlmIChJU19HTE9CQUwpIHNvdXJjZSA9IG5hbWU7XG4gIGZvciAoa2V5IGluIHNvdXJjZSkge1xuICAgIC8vIGNvbnRhaW5zIGluIG5hdGl2ZVxuICAgIG93biA9ICFJU19GT1JDRUQgJiYgdGFyZ2V0ICYmIHRhcmdldFtrZXldICE9PSB1bmRlZmluZWQ7XG4gICAgLy8gZXhwb3J0IG5hdGl2ZSBvciBwYXNzZWRcbiAgICBvdXQgPSAob3duID8gdGFyZ2V0IDogc291cmNlKVtrZXldO1xuICAgIC8vIGJpbmQgdGltZXJzIHRvIGdsb2JhbCBmb3IgY2FsbCBmcm9tIGV4cG9ydCBjb250ZXh0XG4gICAgZXhwID0gSVNfQklORCAmJiBvd24gPyBjdHgob3V0LCBnbG9iYWwpIDogSVNfUFJPVE8gJiYgdHlwZW9mIG91dCA9PSAnZnVuY3Rpb24nID8gY3R4KEZ1bmN0aW9uLmNhbGwsIG91dCkgOiBvdXQ7XG4gICAgLy8gZXh0ZW5kIGdsb2JhbFxuICAgIGlmICh0YXJnZXQpIHJlZGVmaW5lKHRhcmdldCwga2V5LCBvdXQsIHR5cGUgJiAkZXhwb3J0LlUpO1xuICAgIC8vIGV4cG9ydFxuICAgIGlmIChleHBvcnRzW2tleV0gIT0gb3V0KSBoaWRlKGV4cG9ydHMsIGtleSwgZXhwKTtcbiAgICBpZiAoSVNfUFJPVE8gJiYgZXhwUHJvdG9ba2V5XSAhPSBvdXQpIGV4cFByb3RvW2tleV0gPSBvdXQ7XG4gIH1cbn07XG5nbG9iYWwuY29yZSA9IGNvcmU7XG4vLyB0eXBlIGJpdG1hcFxuJGV4cG9ydC5GID0gMTsgICAvLyBmb3JjZWRcbiRleHBvcnQuRyA9IDI7ICAgLy8gZ2xvYmFsXG4kZXhwb3J0LlMgPSA0OyAgIC8vIHN0YXRpY1xuJGV4cG9ydC5QID0gODsgICAvLyBwcm90b1xuJGV4cG9ydC5CID0gMTY7ICAvLyBiaW5kXG4kZXhwb3J0LlcgPSAzMjsgIC8vIHdyYXBcbiRleHBvcnQuVSA9IDY0OyAgLy8gc2FmZVxuJGV4cG9ydC5SID0gMTI4OyAvLyByZWFsIHByb3RvIG1ldGhvZCBmb3IgYGxpYnJhcnlgXG5tb2R1bGUuZXhwb3J0cyA9ICRleHBvcnQ7XG4iLCJleHBvcnRzLmYgPSB7fS5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcbiIsInZhciB0b1N0cmluZyA9IHt9LnRvU3RyaW5nO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gdG9TdHJpbmcuY2FsbChpdCkuc2xpY2UoOCwgLTEpO1xufTtcbiIsIi8vIGZhbGxiYWNrIGZvciBub24tYXJyYXktbGlrZSBFUzMgYW5kIG5vbi1lbnVtZXJhYmxlIG9sZCBWOCBzdHJpbmdzXG52YXIgY29mID0gcmVxdWlyZSgnLi9fY29mJyk7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcHJvdG90eXBlLWJ1aWx0aW5zXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdCgneicpLnByb3BlcnR5SXNFbnVtZXJhYmxlKDApID8gT2JqZWN0IDogZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBjb2YoaXQpID09ICdTdHJpbmcnID8gaXQuc3BsaXQoJycpIDogT2JqZWN0KGl0KTtcbn07XG4iLCIvLyA3LjIuMSBSZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGFyZ3VtZW50KVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgaWYgKGl0ID09IHVuZGVmaW5lZCkgdGhyb3cgVHlwZUVycm9yKFwiQ2FuJ3QgY2FsbCBtZXRob2Qgb24gIFwiICsgaXQpO1xuICByZXR1cm4gaXQ7XG59O1xuIiwiLy8gdG8gaW5kZXhlZCBvYmplY3QsIHRvT2JqZWN0IHdpdGggZmFsbGJhY2sgZm9yIG5vbi1hcnJheS1saWtlIEVTMyBzdHJpbmdzXG52YXIgSU9iamVjdCA9IHJlcXVpcmUoJy4vX2lvYmplY3QnKTtcbnZhciBkZWZpbmVkID0gcmVxdWlyZSgnLi9fZGVmaW5lZCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIElPYmplY3QoZGVmaW5lZChpdCkpO1xufTtcbiIsInZhciBwSUUgPSByZXF1aXJlKCcuL19vYmplY3QtcGllJyk7XG52YXIgY3JlYXRlRGVzYyA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcbnZhciB0b0lPYmplY3QgPSByZXF1aXJlKCcuL190by1pb2JqZWN0Jyk7XG52YXIgdG9QcmltaXRpdmUgPSByZXF1aXJlKCcuL190by1wcmltaXRpdmUnKTtcbnZhciBoYXMgPSByZXF1aXJlKCcuL19oYXMnKTtcbnZhciBJRThfRE9NX0RFRklORSA9IHJlcXVpcmUoJy4vX2llOC1kb20tZGVmaW5lJyk7XG52YXIgZ09QRCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7XG5cbmV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBnT1BEIDogZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE8sIFApIHtcbiAgTyA9IHRvSU9iamVjdChPKTtcbiAgUCA9IHRvUHJpbWl0aXZlKFAsIHRydWUpO1xuICBpZiAoSUU4X0RPTV9ERUZJTkUpIHRyeSB7XG4gICAgcmV0dXJuIGdPUEQoTywgUCk7XG4gIH0gY2F0Y2ggKGUpIHsgLyogZW1wdHkgKi8gfVxuICBpZiAoaGFzKE8sIFApKSByZXR1cm4gY3JlYXRlRGVzYyghcElFLmYuY2FsbChPLCBQKSwgT1tQXSk7XG59O1xuIiwiLy8gV29ya3Mgd2l0aCBfX3Byb3RvX18gb25seS4gT2xkIHY4IGNhbid0IHdvcmsgd2l0aCBudWxsIHByb3RvIG9iamVjdHMuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90byAqL1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgYW5PYmplY3QgPSByZXF1aXJlKCcuL19hbi1vYmplY3QnKTtcbnZhciBjaGVjayA9IGZ1bmN0aW9uIChPLCBwcm90bykge1xuICBhbk9iamVjdChPKTtcbiAgaWYgKCFpc09iamVjdChwcm90bykgJiYgcHJvdG8gIT09IG51bGwpIHRocm93IFR5cGVFcnJvcihwcm90byArIFwiOiBjYW4ndCBzZXQgYXMgcHJvdG90eXBlIVwiKTtcbn07XG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgc2V0OiBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHwgKCdfX3Byb3RvX18nIGluIHt9ID8gLy8gZXNsaW50LWRpc2FibGUtbGluZVxuICAgIGZ1bmN0aW9uICh0ZXN0LCBidWdneSwgc2V0KSB7XG4gICAgICB0cnkge1xuICAgICAgICBzZXQgPSByZXF1aXJlKCcuL19jdHgnKShGdW5jdGlvbi5jYWxsLCByZXF1aXJlKCcuL19vYmplY3QtZ29wZCcpLmYoT2JqZWN0LnByb3RvdHlwZSwgJ19fcHJvdG9fXycpLnNldCwgMik7XG4gICAgICAgIHNldCh0ZXN0LCBbXSk7XG4gICAgICAgIGJ1Z2d5ID0gISh0ZXN0IGluc3RhbmNlb2YgQXJyYXkpO1xuICAgICAgfSBjYXRjaCAoZSkgeyBidWdneSA9IHRydWU7IH1cbiAgICAgIHJldHVybiBmdW5jdGlvbiBzZXRQcm90b3R5cGVPZihPLCBwcm90bykge1xuICAgICAgICBjaGVjayhPLCBwcm90byk7XG4gICAgICAgIGlmIChidWdneSkgTy5fX3Byb3RvX18gPSBwcm90bztcbiAgICAgICAgZWxzZSBzZXQoTywgcHJvdG8pO1xuICAgICAgICByZXR1cm4gTztcbiAgICAgIH07XG4gICAgfSh7fSwgZmFsc2UpIDogdW5kZWZpbmVkKSxcbiAgY2hlY2s6IGNoZWNrXG59O1xuIiwiLy8gMTkuMS4zLjE5IE9iamVjdC5zZXRQcm90b3R5cGVPZihPLCBwcm90bylcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG4kZXhwb3J0KCRleHBvcnQuUywgJ09iamVjdCcsIHsgc2V0UHJvdG90eXBlT2Y6IHJlcXVpcmUoJy4vX3NldC1wcm90bycpLnNldCB9KTtcbiIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5zZXQtcHJvdG90eXBlLW9mJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5PYmplY3Quc2V0UHJvdG90eXBlT2Y7XG4iLCJ2YXIgZ2xvYmFsID0gcmVxdWlyZSgnLi9fZ2xvYmFsJyk7XG52YXIgU0hBUkVEID0gJ19fY29yZS1qc19zaGFyZWRfXyc7XG52YXIgc3RvcmUgPSBnbG9iYWxbU0hBUkVEXSB8fCAoZ2xvYmFsW1NIQVJFRF0gPSB7fSk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuIHN0b3JlW2tleV0gfHwgKHN0b3JlW2tleV0gPSB7fSk7XG59O1xuIiwidmFyIHN0b3JlID0gcmVxdWlyZSgnLi9fc2hhcmVkJykoJ3drcycpO1xudmFyIHVpZCA9IHJlcXVpcmUoJy4vX3VpZCcpO1xudmFyIFN5bWJvbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLlN5bWJvbDtcbnZhciBVU0VfU1lNQk9MID0gdHlwZW9mIFN5bWJvbCA9PSAnZnVuY3Rpb24nO1xuXG52YXIgJGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gIHJldHVybiBzdG9yZVtuYW1lXSB8fCAoc3RvcmVbbmFtZV0gPVxuICAgIFVTRV9TWU1CT0wgJiYgU3ltYm9sW25hbWVdIHx8IChVU0VfU1lNQk9MID8gU3ltYm9sIDogdWlkKSgnU3ltYm9sLicgKyBuYW1lKSk7XG59O1xuXG4kZXhwb3J0cy5zdG9yZSA9IHN0b3JlO1xuIiwiLy8gZ2V0dGluZyB0YWcgZnJvbSAxOS4xLjMuNiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nKClcbnZhciBjb2YgPSByZXF1aXJlKCcuL19jb2YnKTtcbnZhciBUQUcgPSByZXF1aXJlKCcuL193a3MnKSgndG9TdHJpbmdUYWcnKTtcbi8vIEVTMyB3cm9uZyBoZXJlXG52YXIgQVJHID0gY29mKGZ1bmN0aW9uICgpIHsgcmV0dXJuIGFyZ3VtZW50czsgfSgpKSA9PSAnQXJndW1lbnRzJztcblxuLy8gZmFsbGJhY2sgZm9yIElFMTEgU2NyaXB0IEFjY2VzcyBEZW5pZWQgZXJyb3JcbnZhciB0cnlHZXQgPSBmdW5jdGlvbiAoaXQsIGtleSkge1xuICB0cnkge1xuICAgIHJldHVybiBpdFtrZXldO1xuICB9IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHZhciBPLCBULCBCO1xuICByZXR1cm4gaXQgPT09IHVuZGVmaW5lZCA/ICdVbmRlZmluZWQnIDogaXQgPT09IG51bGwgPyAnTnVsbCdcbiAgICAvLyBAQHRvU3RyaW5nVGFnIGNhc2VcbiAgICA6IHR5cGVvZiAoVCA9IHRyeUdldChPID0gT2JqZWN0KGl0KSwgVEFHKSkgPT0gJ3N0cmluZycgPyBUXG4gICAgLy8gYnVpbHRpblRhZyBjYXNlXG4gICAgOiBBUkcgPyBjb2YoTylcbiAgICAvLyBFUzMgYXJndW1lbnRzIGZhbGxiYWNrXG4gICAgOiAoQiA9IGNvZihPKSkgPT0gJ09iamVjdCcgJiYgdHlwZW9mIE8uY2FsbGVlID09ICdmdW5jdGlvbicgPyAnQXJndW1lbnRzJyA6IEI7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuLy8gMTkuMS4zLjYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZygpXG52YXIgY2xhc3NvZiA9IHJlcXVpcmUoJy4vX2NsYXNzb2YnKTtcbnZhciB0ZXN0ID0ge307XG50ZXN0W3JlcXVpcmUoJy4vX3drcycpKCd0b1N0cmluZ1RhZycpXSA9ICd6JztcbmlmICh0ZXN0ICsgJycgIT0gJ1tvYmplY3Qgel0nKSB7XG4gIHJlcXVpcmUoJy4vX3JlZGVmaW5lJykoT2JqZWN0LnByb3RvdHlwZSwgJ3RvU3RyaW5nJywgZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuICdbb2JqZWN0ICcgKyBjbGFzc29mKHRoaXMpICsgJ10nO1xuICB9LCB0cnVlKTtcbn1cbiIsIi8vIDcuMS40IFRvSW50ZWdlclxudmFyIGNlaWwgPSBNYXRoLmNlaWw7XG52YXIgZmxvb3IgPSBNYXRoLmZsb29yO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIGlzTmFOKGl0ID0gK2l0KSA/IDAgOiAoaXQgPiAwID8gZmxvb3IgOiBjZWlsKShpdCk7XG59O1xuIiwidmFyIHRvSW50ZWdlciA9IHJlcXVpcmUoJy4vX3RvLWludGVnZXInKTtcbnZhciBkZWZpbmVkID0gcmVxdWlyZSgnLi9fZGVmaW5lZCcpO1xuLy8gdHJ1ZSAgLT4gU3RyaW5nI2F0XG4vLyBmYWxzZSAtPiBTdHJpbmcjY29kZVBvaW50QXRcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFRPX1NUUklORykge1xuICByZXR1cm4gZnVuY3Rpb24gKHRoYXQsIHBvcykge1xuICAgIHZhciBzID0gU3RyaW5nKGRlZmluZWQodGhhdCkpO1xuICAgIHZhciBpID0gdG9JbnRlZ2VyKHBvcyk7XG4gICAgdmFyIGwgPSBzLmxlbmd0aDtcbiAgICB2YXIgYSwgYjtcbiAgICBpZiAoaSA8IDAgfHwgaSA+PSBsKSByZXR1cm4gVE9fU1RSSU5HID8gJycgOiB1bmRlZmluZWQ7XG4gICAgYSA9IHMuY2hhckNvZGVBdChpKTtcbiAgICByZXR1cm4gYSA8IDB4ZDgwMCB8fCBhID4gMHhkYmZmIHx8IGkgKyAxID09PSBsIHx8IChiID0gcy5jaGFyQ29kZUF0KGkgKyAxKSkgPCAweGRjMDAgfHwgYiA+IDB4ZGZmZlxuICAgICAgPyBUT19TVFJJTkcgPyBzLmNoYXJBdChpKSA6IGFcbiAgICAgIDogVE9fU1RSSU5HID8gcy5zbGljZShpLCBpICsgMikgOiAoYSAtIDB4ZDgwMCA8PCAxMCkgKyAoYiAtIDB4ZGMwMCkgKyAweDEwMDAwO1xuICB9O1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZmFsc2U7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHt9O1xuIiwiLy8gNy4xLjE1IFRvTGVuZ3RoXG52YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi9fdG8taW50ZWdlcicpO1xudmFyIG1pbiA9IE1hdGgubWluO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIGl0ID4gMCA/IG1pbih0b0ludGVnZXIoaXQpLCAweDFmZmZmZmZmZmZmZmZmKSA6IDA7IC8vIHBvdygyLCA1MykgLSAxID09IDkwMDcxOTkyNTQ3NDA5OTFcbn07XG4iLCJ2YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi9fdG8taW50ZWdlcicpO1xudmFyIG1heCA9IE1hdGgubWF4O1xudmFyIG1pbiA9IE1hdGgubWluO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaW5kZXgsIGxlbmd0aCkge1xuICBpbmRleCA9IHRvSW50ZWdlcihpbmRleCk7XG4gIHJldHVybiBpbmRleCA8IDAgPyBtYXgoaW5kZXggKyBsZW5ndGgsIDApIDogbWluKGluZGV4LCBsZW5ndGgpO1xufTtcbiIsIi8vIGZhbHNlIC0+IEFycmF5I2luZGV4T2Zcbi8vIHRydWUgIC0+IEFycmF5I2luY2x1ZGVzXG52YXIgdG9JT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJyk7XG52YXIgdG9BYnNvbHV0ZUluZGV4ID0gcmVxdWlyZSgnLi9fdG8tYWJzb2x1dGUtaW5kZXgnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKElTX0lOQ0xVREVTKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoJHRoaXMsIGVsLCBmcm9tSW5kZXgpIHtcbiAgICB2YXIgTyA9IHRvSU9iamVjdCgkdGhpcyk7XG4gICAgdmFyIGxlbmd0aCA9IHRvTGVuZ3RoKE8ubGVuZ3RoKTtcbiAgICB2YXIgaW5kZXggPSB0b0Fic29sdXRlSW5kZXgoZnJvbUluZGV4LCBsZW5ndGgpO1xuICAgIHZhciB2YWx1ZTtcbiAgICAvLyBBcnJheSNpbmNsdWRlcyB1c2VzIFNhbWVWYWx1ZVplcm8gZXF1YWxpdHkgYWxnb3JpdGhtXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZVxuICAgIGlmIChJU19JTkNMVURFUyAmJiBlbCAhPSBlbCkgd2hpbGUgKGxlbmd0aCA+IGluZGV4KSB7XG4gICAgICB2YWx1ZSA9IE9baW5kZXgrK107XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1jb21wYXJlXG4gICAgICBpZiAodmFsdWUgIT0gdmFsdWUpIHJldHVybiB0cnVlO1xuICAgIC8vIEFycmF5I2luZGV4T2YgaWdub3JlcyBob2xlcywgQXJyYXkjaW5jbHVkZXMgLSBub3RcbiAgICB9IGVsc2UgZm9yICg7bGVuZ3RoID4gaW5kZXg7IGluZGV4KyspIGlmIChJU19JTkNMVURFUyB8fCBpbmRleCBpbiBPKSB7XG4gICAgICBpZiAoT1tpbmRleF0gPT09IGVsKSByZXR1cm4gSVNfSU5DTFVERVMgfHwgaW5kZXggfHwgMDtcbiAgICB9IHJldHVybiAhSVNfSU5DTFVERVMgJiYgLTE7XG4gIH07XG59O1xuIiwidmFyIHNoYXJlZCA9IHJlcXVpcmUoJy4vX3NoYXJlZCcpKCdrZXlzJyk7XG52YXIgdWlkID0gcmVxdWlyZSgnLi9fdWlkJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuIHNoYXJlZFtrZXldIHx8IChzaGFyZWRba2V5XSA9IHVpZChrZXkpKTtcbn07XG4iLCJ2YXIgaGFzID0gcmVxdWlyZSgnLi9faGFzJyk7XG52YXIgdG9JT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpO1xudmFyIGFycmF5SW5kZXhPZiA9IHJlcXVpcmUoJy4vX2FycmF5LWluY2x1ZGVzJykoZmFsc2UpO1xudmFyIElFX1BST1RPID0gcmVxdWlyZSgnLi9fc2hhcmVkLWtleScpKCdJRV9QUk9UTycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmplY3QsIG5hbWVzKSB7XG4gIHZhciBPID0gdG9JT2JqZWN0KG9iamVjdCk7XG4gIHZhciBpID0gMDtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICB2YXIga2V5O1xuICBmb3IgKGtleSBpbiBPKSBpZiAoa2V5ICE9IElFX1BST1RPKSBoYXMoTywga2V5KSAmJiByZXN1bHQucHVzaChrZXkpO1xuICAvLyBEb24ndCBlbnVtIGJ1ZyAmIGhpZGRlbiBrZXlzXG4gIHdoaWxlIChuYW1lcy5sZW5ndGggPiBpKSBpZiAoaGFzKE8sIGtleSA9IG5hbWVzW2krK10pKSB7XG4gICAgfmFycmF5SW5kZXhPZihyZXN1bHQsIGtleSkgfHwgcmVzdWx0LnB1c2goa2V5KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufTtcbiIsIi8vIElFIDgtIGRvbid0IGVudW0gYnVnIGtleXNcbm1vZHVsZS5leHBvcnRzID0gKFxuICAnY29uc3RydWN0b3IsaGFzT3duUHJvcGVydHksaXNQcm90b3R5cGVPZixwcm9wZXJ0eUlzRW51bWVyYWJsZSx0b0xvY2FsZVN0cmluZyx0b1N0cmluZyx2YWx1ZU9mJ1xuKS5zcGxpdCgnLCcpO1xuIiwiLy8gMTkuMS4yLjE0IC8gMTUuMi4zLjE0IE9iamVjdC5rZXlzKE8pXG52YXIgJGtleXMgPSByZXF1aXJlKCcuL19vYmplY3Qta2V5cy1pbnRlcm5hbCcpO1xudmFyIGVudW1CdWdLZXlzID0gcmVxdWlyZSgnLi9fZW51bS1idWcta2V5cycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIGtleXMoTykge1xuICByZXR1cm4gJGtleXMoTywgZW51bUJ1Z0tleXMpO1xufTtcbiIsInZhciBkUCA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpO1xudmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG52YXIgZ2V0S2V5cyA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKSA/IE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzIDogZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyhPLCBQcm9wZXJ0aWVzKSB7XG4gIGFuT2JqZWN0KE8pO1xuICB2YXIga2V5cyA9IGdldEtleXMoUHJvcGVydGllcyk7XG4gIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgdmFyIGkgPSAwO1xuICB2YXIgUDtcbiAgd2hpbGUgKGxlbmd0aCA+IGkpIGRQLmYoTywgUCA9IGtleXNbaSsrXSwgUHJvcGVydGllc1tQXSk7XG4gIHJldHVybiBPO1xufTtcbiIsInZhciBkb2N1bWVudCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLmRvY3VtZW50O1xubW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudCAmJiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4iLCIvLyAxOS4xLjIuMiAvIDE1LjIuMy41IE9iamVjdC5jcmVhdGUoTyBbLCBQcm9wZXJ0aWVzXSlcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpO1xudmFyIGRQcyA9IHJlcXVpcmUoJy4vX29iamVjdC1kcHMnKTtcbnZhciBlbnVtQnVnS2V5cyA9IHJlcXVpcmUoJy4vX2VudW0tYnVnLWtleXMnKTtcbnZhciBJRV9QUk9UTyA9IHJlcXVpcmUoJy4vX3NoYXJlZC1rZXknKSgnSUVfUFJPVE8nKTtcbnZhciBFbXB0eSA9IGZ1bmN0aW9uICgpIHsgLyogZW1wdHkgKi8gfTtcbnZhciBQUk9UT1RZUEUgPSAncHJvdG90eXBlJztcblxuLy8gQ3JlYXRlIG9iamVjdCB3aXRoIGZha2UgYG51bGxgIHByb3RvdHlwZTogdXNlIGlmcmFtZSBPYmplY3Qgd2l0aCBjbGVhcmVkIHByb3RvdHlwZVxudmFyIGNyZWF0ZURpY3QgPSBmdW5jdGlvbiAoKSB7XG4gIC8vIFRocmFzaCwgd2FzdGUgYW5kIHNvZG9teTogSUUgR0MgYnVnXG4gIHZhciBpZnJhbWUgPSByZXF1aXJlKCcuL19kb20tY3JlYXRlJykoJ2lmcmFtZScpO1xuICB2YXIgaSA9IGVudW1CdWdLZXlzLmxlbmd0aDtcbiAgdmFyIGx0ID0gJzwnO1xuICB2YXIgZ3QgPSAnPic7XG4gIHZhciBpZnJhbWVEb2N1bWVudDtcbiAgaWZyYW1lLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gIHJlcXVpcmUoJy4vX2h0bWwnKS5hcHBlbmRDaGlsZChpZnJhbWUpO1xuICBpZnJhbWUuc3JjID0gJ2phdmFzY3JpcHQ6JzsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1zY3JpcHQtdXJsXG4gIC8vIGNyZWF0ZURpY3QgPSBpZnJhbWUuY29udGVudFdpbmRvdy5PYmplY3Q7XG4gIC8vIGh0bWwucmVtb3ZlQ2hpbGQoaWZyYW1lKTtcbiAgaWZyYW1lRG9jdW1lbnQgPSBpZnJhbWUuY29udGVudFdpbmRvdy5kb2N1bWVudDtcbiAgaWZyYW1lRG9jdW1lbnQub3BlbigpO1xuICBpZnJhbWVEb2N1bWVudC53cml0ZShsdCArICdzY3JpcHQnICsgZ3QgKyAnZG9jdW1lbnQuRj1PYmplY3QnICsgbHQgKyAnL3NjcmlwdCcgKyBndCk7XG4gIGlmcmFtZURvY3VtZW50LmNsb3NlKCk7XG4gIGNyZWF0ZURpY3QgPSBpZnJhbWVEb2N1bWVudC5GO1xuICB3aGlsZSAoaS0tKSBkZWxldGUgY3JlYXRlRGljdFtQUk9UT1RZUEVdW2VudW1CdWdLZXlzW2ldXTtcbiAgcmV0dXJuIGNyZWF0ZURpY3QoKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gT2JqZWN0LmNyZWF0ZSB8fCBmdW5jdGlvbiBjcmVhdGUoTywgUHJvcGVydGllcykge1xuICB2YXIgcmVzdWx0O1xuICBpZiAoTyAhPT0gbnVsbCkge1xuICAgIEVtcHR5W1BST1RPVFlQRV0gPSBhbk9iamVjdChPKTtcbiAgICByZXN1bHQgPSBuZXcgRW1wdHkoKTtcbiAgICBFbXB0eVtQUk9UT1RZUEVdID0gbnVsbDtcbiAgICAvLyBhZGQgXCJfX3Byb3RvX19cIiBmb3IgT2JqZWN0LmdldFByb3RvdHlwZU9mIHBvbHlmaWxsXG4gICAgcmVzdWx0W0lFX1BST1RPXSA9IE87XG4gIH0gZWxzZSByZXN1bHQgPSBjcmVhdGVEaWN0KCk7XG4gIHJldHVybiBQcm9wZXJ0aWVzID09PSB1bmRlZmluZWQgPyByZXN1bHQgOiBkUHMocmVzdWx0LCBQcm9wZXJ0aWVzKTtcbn07XG4iLCJ2YXIgZGVmID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJykuZjtcbnZhciBoYXMgPSByZXF1aXJlKCcuL19oYXMnKTtcbnZhciBUQUcgPSByZXF1aXJlKCcuL193a3MnKSgndG9TdHJpbmdUYWcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQsIHRhZywgc3RhdCkge1xuICBpZiAoaXQgJiYgIWhhcyhpdCA9IHN0YXQgPyBpdCA6IGl0LnByb3RvdHlwZSwgVEFHKSkgZGVmKGl0LCBUQUcsIHsgY29uZmlndXJhYmxlOiB0cnVlLCB2YWx1ZTogdGFnIH0pO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBjcmVhdGUgPSByZXF1aXJlKCcuL19vYmplY3QtY3JlYXRlJyk7XG52YXIgZGVzY3JpcHRvciA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcbnZhciBzZXRUb1N0cmluZ1RhZyA9IHJlcXVpcmUoJy4vX3NldC10by1zdHJpbmctdGFnJyk7XG52YXIgSXRlcmF0b3JQcm90b3R5cGUgPSB7fTtcblxuLy8gMjUuMS4yLjEuMSAlSXRlcmF0b3JQcm90b3R5cGUlW0BAaXRlcmF0b3JdKClcbnJlcXVpcmUoJy4vX2hpZGUnKShJdGVyYXRvclByb3RvdHlwZSwgcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJyksIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgTkFNRSwgbmV4dCkge1xuICBDb25zdHJ1Y3Rvci5wcm90b3R5cGUgPSBjcmVhdGUoSXRlcmF0b3JQcm90b3R5cGUsIHsgbmV4dDogZGVzY3JpcHRvcigxLCBuZXh0KSB9KTtcbiAgc2V0VG9TdHJpbmdUYWcoQ29uc3RydWN0b3IsIE5BTUUgKyAnIEl0ZXJhdG9yJyk7XG59O1xuIiwiLy8gNy4xLjEzIFRvT2JqZWN0KGFyZ3VtZW50KVxudmFyIGRlZmluZWQgPSByZXF1aXJlKCcuL19kZWZpbmVkJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gT2JqZWN0KGRlZmluZWQoaXQpKTtcbn07XG4iLCIvLyAxOS4xLjIuOSAvIDE1LjIuMy4yIE9iamVjdC5nZXRQcm90b3R5cGVPZihPKVxudmFyIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0Jyk7XG52YXIgSUVfUFJPVE8gPSByZXF1aXJlKCcuL19zaGFyZWQta2V5JykoJ0lFX1BST1RPJyk7XG52YXIgT2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5nZXRQcm90b3R5cGVPZiB8fCBmdW5jdGlvbiAoTykge1xuICBPID0gdG9PYmplY3QoTyk7XG4gIGlmIChoYXMoTywgSUVfUFJPVE8pKSByZXR1cm4gT1tJRV9QUk9UT107XG4gIGlmICh0eXBlb2YgTy5jb25zdHJ1Y3RvciA9PSAnZnVuY3Rpb24nICYmIE8gaW5zdGFuY2VvZiBPLmNvbnN0cnVjdG9yKSB7XG4gICAgcmV0dXJuIE8uY29uc3RydWN0b3IucHJvdG90eXBlO1xuICB9IHJldHVybiBPIGluc3RhbmNlb2YgT2JqZWN0ID8gT2JqZWN0UHJvdG8gOiBudWxsO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBMSUJSQVJZID0gcmVxdWlyZSgnLi9fbGlicmFyeScpO1xudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcbnZhciByZWRlZmluZSA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lJyk7XG52YXIgaGlkZSA9IHJlcXVpcmUoJy4vX2hpZGUnKTtcbnZhciBoYXMgPSByZXF1aXJlKCcuL19oYXMnKTtcbnZhciBJdGVyYXRvcnMgPSByZXF1aXJlKCcuL19pdGVyYXRvcnMnKTtcbnZhciAkaXRlckNyZWF0ZSA9IHJlcXVpcmUoJy4vX2l0ZXItY3JlYXRlJyk7XG52YXIgc2V0VG9TdHJpbmdUYWcgPSByZXF1aXJlKCcuL19zZXQtdG8tc3RyaW5nLXRhZycpO1xudmFyIGdldFByb3RvdHlwZU9mID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdwbycpO1xudmFyIElURVJBVE9SID0gcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJyk7XG52YXIgQlVHR1kgPSAhKFtdLmtleXMgJiYgJ25leHQnIGluIFtdLmtleXMoKSk7IC8vIFNhZmFyaSBoYXMgYnVnZ3kgaXRlcmF0b3JzIHcvbyBgbmV4dGBcbnZhciBGRl9JVEVSQVRPUiA9ICdAQGl0ZXJhdG9yJztcbnZhciBLRVlTID0gJ2tleXMnO1xudmFyIFZBTFVFUyA9ICd2YWx1ZXMnO1xuXG52YXIgcmV0dXJuVGhpcyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKEJhc2UsIE5BTUUsIENvbnN0cnVjdG9yLCBuZXh0LCBERUZBVUxULCBJU19TRVQsIEZPUkNFRCkge1xuICAkaXRlckNyZWF0ZShDb25zdHJ1Y3RvciwgTkFNRSwgbmV4dCk7XG4gIHZhciBnZXRNZXRob2QgPSBmdW5jdGlvbiAoa2luZCkge1xuICAgIGlmICghQlVHR1kgJiYga2luZCBpbiBwcm90bykgcmV0dXJuIHByb3RvW2tpbmRdO1xuICAgIHN3aXRjaCAoa2luZCkge1xuICAgICAgY2FzZSBLRVlTOiByZXR1cm4gZnVuY3Rpb24ga2V5cygpIHsgcmV0dXJuIG5ldyBDb25zdHJ1Y3Rvcih0aGlzLCBraW5kKTsgfTtcbiAgICAgIGNhc2UgVkFMVUVTOiByZXR1cm4gZnVuY3Rpb24gdmFsdWVzKCkgeyByZXR1cm4gbmV3IENvbnN0cnVjdG9yKHRoaXMsIGtpbmQpOyB9O1xuICAgIH0gcmV0dXJuIGZ1bmN0aW9uIGVudHJpZXMoKSB7IHJldHVybiBuZXcgQ29uc3RydWN0b3IodGhpcywga2luZCk7IH07XG4gIH07XG4gIHZhciBUQUcgPSBOQU1FICsgJyBJdGVyYXRvcic7XG4gIHZhciBERUZfVkFMVUVTID0gREVGQVVMVCA9PSBWQUxVRVM7XG4gIHZhciBWQUxVRVNfQlVHID0gZmFsc2U7XG4gIHZhciBwcm90byA9IEJhc2UucHJvdG90eXBlO1xuICB2YXIgJG5hdGl2ZSA9IHByb3RvW0lURVJBVE9SXSB8fCBwcm90b1tGRl9JVEVSQVRPUl0gfHwgREVGQVVMVCAmJiBwcm90b1tERUZBVUxUXTtcbiAgdmFyICRkZWZhdWx0ID0gJG5hdGl2ZSB8fCBnZXRNZXRob2QoREVGQVVMVCk7XG4gIHZhciAkZW50cmllcyA9IERFRkFVTFQgPyAhREVGX1ZBTFVFUyA/ICRkZWZhdWx0IDogZ2V0TWV0aG9kKCdlbnRyaWVzJykgOiB1bmRlZmluZWQ7XG4gIHZhciAkYW55TmF0aXZlID0gTkFNRSA9PSAnQXJyYXknID8gcHJvdG8uZW50cmllcyB8fCAkbmF0aXZlIDogJG5hdGl2ZTtcbiAgdmFyIG1ldGhvZHMsIGtleSwgSXRlcmF0b3JQcm90b3R5cGU7XG4gIC8vIEZpeCBuYXRpdmVcbiAgaWYgKCRhbnlOYXRpdmUpIHtcbiAgICBJdGVyYXRvclByb3RvdHlwZSA9IGdldFByb3RvdHlwZU9mKCRhbnlOYXRpdmUuY2FsbChuZXcgQmFzZSgpKSk7XG4gICAgaWYgKEl0ZXJhdG9yUHJvdG90eXBlICE9PSBPYmplY3QucHJvdG90eXBlICYmIEl0ZXJhdG9yUHJvdG90eXBlLm5leHQpIHtcbiAgICAgIC8vIFNldCBAQHRvU3RyaW5nVGFnIHRvIG5hdGl2ZSBpdGVyYXRvcnNcbiAgICAgIHNldFRvU3RyaW5nVGFnKEl0ZXJhdG9yUHJvdG90eXBlLCBUQUcsIHRydWUpO1xuICAgICAgLy8gZml4IGZvciBzb21lIG9sZCBlbmdpbmVzXG4gICAgICBpZiAoIUxJQlJBUlkgJiYgIWhhcyhJdGVyYXRvclByb3RvdHlwZSwgSVRFUkFUT1IpKSBoaWRlKEl0ZXJhdG9yUHJvdG90eXBlLCBJVEVSQVRPUiwgcmV0dXJuVGhpcyk7XG4gICAgfVxuICB9XG4gIC8vIGZpeCBBcnJheSN7dmFsdWVzLCBAQGl0ZXJhdG9yfS5uYW1lIGluIFY4IC8gRkZcbiAgaWYgKERFRl9WQUxVRVMgJiYgJG5hdGl2ZSAmJiAkbmF0aXZlLm5hbWUgIT09IFZBTFVFUykge1xuICAgIFZBTFVFU19CVUcgPSB0cnVlO1xuICAgICRkZWZhdWx0ID0gZnVuY3Rpb24gdmFsdWVzKCkgeyByZXR1cm4gJG5hdGl2ZS5jYWxsKHRoaXMpOyB9O1xuICB9XG4gIC8vIERlZmluZSBpdGVyYXRvclxuICBpZiAoKCFMSUJSQVJZIHx8IEZPUkNFRCkgJiYgKEJVR0dZIHx8IFZBTFVFU19CVUcgfHwgIXByb3RvW0lURVJBVE9SXSkpIHtcbiAgICBoaWRlKHByb3RvLCBJVEVSQVRPUiwgJGRlZmF1bHQpO1xuICB9XG4gIC8vIFBsdWcgZm9yIGxpYnJhcnlcbiAgSXRlcmF0b3JzW05BTUVdID0gJGRlZmF1bHQ7XG4gIEl0ZXJhdG9yc1tUQUddID0gcmV0dXJuVGhpcztcbiAgaWYgKERFRkFVTFQpIHtcbiAgICBtZXRob2RzID0ge1xuICAgICAgdmFsdWVzOiBERUZfVkFMVUVTID8gJGRlZmF1bHQgOiBnZXRNZXRob2QoVkFMVUVTKSxcbiAgICAgIGtleXM6IElTX1NFVCA/ICRkZWZhdWx0IDogZ2V0TWV0aG9kKEtFWVMpLFxuICAgICAgZW50cmllczogJGVudHJpZXNcbiAgICB9O1xuICAgIGlmIChGT1JDRUQpIGZvciAoa2V5IGluIG1ldGhvZHMpIHtcbiAgICAgIGlmICghKGtleSBpbiBwcm90bykpIHJlZGVmaW5lKHByb3RvLCBrZXksIG1ldGhvZHNba2V5XSk7XG4gICAgfSBlbHNlICRleHBvcnQoJGV4cG9ydC5QICsgJGV4cG9ydC5GICogKEJVR0dZIHx8IFZBTFVFU19CVUcpLCBOQU1FLCBtZXRob2RzKTtcbiAgfVxuICByZXR1cm4gbWV0aG9kcztcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJGF0ID0gcmVxdWlyZSgnLi9fc3RyaW5nLWF0JykodHJ1ZSk7XG5cbi8vIDIxLjEuMy4yNyBTdHJpbmcucHJvdG90eXBlW0BAaXRlcmF0b3JdKClcbnJlcXVpcmUoJy4vX2l0ZXItZGVmaW5lJykoU3RyaW5nLCAnU3RyaW5nJywgZnVuY3Rpb24gKGl0ZXJhdGVkKSB7XG4gIHRoaXMuX3QgPSBTdHJpbmcoaXRlcmF0ZWQpOyAvLyB0YXJnZXRcbiAgdGhpcy5faSA9IDA7ICAgICAgICAgICAgICAgIC8vIG5leHQgaW5kZXhcbi8vIDIxLjEuNS4yLjEgJVN0cmluZ0l0ZXJhdG9yUHJvdG90eXBlJS5uZXh0KClcbn0sIGZ1bmN0aW9uICgpIHtcbiAgdmFyIE8gPSB0aGlzLl90O1xuICB2YXIgaW5kZXggPSB0aGlzLl9pO1xuICB2YXIgcG9pbnQ7XG4gIGlmIChpbmRleCA+PSBPLmxlbmd0aCkgcmV0dXJuIHsgdmFsdWU6IHVuZGVmaW5lZCwgZG9uZTogdHJ1ZSB9O1xuICBwb2ludCA9ICRhdChPLCBpbmRleCk7XG4gIHRoaXMuX2kgKz0gcG9pbnQubGVuZ3RoO1xuICByZXR1cm4geyB2YWx1ZTogcG9pbnQsIGRvbmU6IGZhbHNlIH07XG59KTtcbiIsIi8vIDIyLjEuMy4zMSBBcnJheS5wcm90b3R5cGVbQEB1bnNjb3BhYmxlc11cbnZhciBVTlNDT1BBQkxFUyA9IHJlcXVpcmUoJy4vX3drcycpKCd1bnNjb3BhYmxlcycpO1xudmFyIEFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGU7XG5pZiAoQXJyYXlQcm90b1tVTlNDT1BBQkxFU10gPT0gdW5kZWZpbmVkKSByZXF1aXJlKCcuL19oaWRlJykoQXJyYXlQcm90bywgVU5TQ09QQUJMRVMsIHt9KTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSkge1xuICBBcnJheVByb3RvW1VOU0NPUEFCTEVTXVtrZXldID0gdHJ1ZTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChkb25lLCB2YWx1ZSkge1xuICByZXR1cm4geyB2YWx1ZTogdmFsdWUsIGRvbmU6ICEhZG9uZSB9O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBhZGRUb1Vuc2NvcGFibGVzID0gcmVxdWlyZSgnLi9fYWRkLXRvLXVuc2NvcGFibGVzJyk7XG52YXIgc3RlcCA9IHJlcXVpcmUoJy4vX2l0ZXItc3RlcCcpO1xudmFyIEl0ZXJhdG9ycyA9IHJlcXVpcmUoJy4vX2l0ZXJhdG9ycycpO1xudmFyIHRvSU9iamVjdCA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKTtcblxuLy8gMjIuMS4zLjQgQXJyYXkucHJvdG90eXBlLmVudHJpZXMoKVxuLy8gMjIuMS4zLjEzIEFycmF5LnByb3RvdHlwZS5rZXlzKClcbi8vIDIyLjEuMy4yOSBBcnJheS5wcm90b3R5cGUudmFsdWVzKClcbi8vIDIyLjEuMy4zMCBBcnJheS5wcm90b3R5cGVbQEBpdGVyYXRvcl0oKVxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19pdGVyLWRlZmluZScpKEFycmF5LCAnQXJyYXknLCBmdW5jdGlvbiAoaXRlcmF0ZWQsIGtpbmQpIHtcbiAgdGhpcy5fdCA9IHRvSU9iamVjdChpdGVyYXRlZCk7IC8vIHRhcmdldFxuICB0aGlzLl9pID0gMDsgICAgICAgICAgICAgICAgICAgLy8gbmV4dCBpbmRleFxuICB0aGlzLl9rID0ga2luZDsgICAgICAgICAgICAgICAgLy8ga2luZFxuLy8gMjIuMS41LjIuMSAlQXJyYXlJdGVyYXRvclByb3RvdHlwZSUubmV4dCgpXG59LCBmdW5jdGlvbiAoKSB7XG4gIHZhciBPID0gdGhpcy5fdDtcbiAgdmFyIGtpbmQgPSB0aGlzLl9rO1xuICB2YXIgaW5kZXggPSB0aGlzLl9pKys7XG4gIGlmICghTyB8fCBpbmRleCA+PSBPLmxlbmd0aCkge1xuICAgIHRoaXMuX3QgPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHN0ZXAoMSk7XG4gIH1cbiAgaWYgKGtpbmQgPT0gJ2tleXMnKSByZXR1cm4gc3RlcCgwLCBpbmRleCk7XG4gIGlmIChraW5kID09ICd2YWx1ZXMnKSByZXR1cm4gc3RlcCgwLCBPW2luZGV4XSk7XG4gIHJldHVybiBzdGVwKDAsIFtpbmRleCwgT1tpbmRleF1dKTtcbn0sICd2YWx1ZXMnKTtcblxuLy8gYXJndW1lbnRzTGlzdFtAQGl0ZXJhdG9yXSBpcyAlQXJyYXlQcm90b192YWx1ZXMlICg5LjQuNC42LCA5LjQuNC43KVxuSXRlcmF0b3JzLkFyZ3VtZW50cyA9IEl0ZXJhdG9ycy5BcnJheTtcblxuYWRkVG9VbnNjb3BhYmxlcygna2V5cycpO1xuYWRkVG9VbnNjb3BhYmxlcygndmFsdWVzJyk7XG5hZGRUb1Vuc2NvcGFibGVzKCdlbnRyaWVzJyk7XG4iLCJ2YXIgJGl0ZXJhdG9ycyA9IHJlcXVpcmUoJy4vZXM2LmFycmF5Lml0ZXJhdG9yJyk7XG52YXIgZ2V0S2V5cyA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJyk7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuL19yZWRlZmluZScpO1xudmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpO1xudmFyIGhpZGUgPSByZXF1aXJlKCcuL19oaWRlJyk7XG52YXIgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJyk7XG52YXIgd2tzID0gcmVxdWlyZSgnLi9fd2tzJyk7XG52YXIgSVRFUkFUT1IgPSB3a3MoJ2l0ZXJhdG9yJyk7XG52YXIgVE9fU1RSSU5HX1RBRyA9IHdrcygndG9TdHJpbmdUYWcnKTtcbnZhciBBcnJheVZhbHVlcyA9IEl0ZXJhdG9ycy5BcnJheTtcblxudmFyIERPTUl0ZXJhYmxlcyA9IHtcbiAgQ1NTUnVsZUxpc3Q6IHRydWUsIC8vIFRPRE86IE5vdCBzcGVjIGNvbXBsaWFudCwgc2hvdWxkIGJlIGZhbHNlLlxuICBDU1NTdHlsZURlY2xhcmF0aW9uOiBmYWxzZSxcbiAgQ1NTVmFsdWVMaXN0OiBmYWxzZSxcbiAgQ2xpZW50UmVjdExpc3Q6IGZhbHNlLFxuICBET01SZWN0TGlzdDogZmFsc2UsXG4gIERPTVN0cmluZ0xpc3Q6IGZhbHNlLFxuICBET01Ub2tlbkxpc3Q6IHRydWUsXG4gIERhdGFUcmFuc2Zlckl0ZW1MaXN0OiBmYWxzZSxcbiAgRmlsZUxpc3Q6IGZhbHNlLFxuICBIVE1MQWxsQ29sbGVjdGlvbjogZmFsc2UsXG4gIEhUTUxDb2xsZWN0aW9uOiBmYWxzZSxcbiAgSFRNTEZvcm1FbGVtZW50OiBmYWxzZSxcbiAgSFRNTFNlbGVjdEVsZW1lbnQ6IGZhbHNlLFxuICBNZWRpYUxpc3Q6IHRydWUsIC8vIFRPRE86IE5vdCBzcGVjIGNvbXBsaWFudCwgc2hvdWxkIGJlIGZhbHNlLlxuICBNaW1lVHlwZUFycmF5OiBmYWxzZSxcbiAgTmFtZWROb2RlTWFwOiBmYWxzZSxcbiAgTm9kZUxpc3Q6IHRydWUsXG4gIFBhaW50UmVxdWVzdExpc3Q6IGZhbHNlLFxuICBQbHVnaW46IGZhbHNlLFxuICBQbHVnaW5BcnJheTogZmFsc2UsXG4gIFNWR0xlbmd0aExpc3Q6IGZhbHNlLFxuICBTVkdOdW1iZXJMaXN0OiBmYWxzZSxcbiAgU1ZHUGF0aFNlZ0xpc3Q6IGZhbHNlLFxuICBTVkdQb2ludExpc3Q6IGZhbHNlLFxuICBTVkdTdHJpbmdMaXN0OiBmYWxzZSxcbiAgU1ZHVHJhbnNmb3JtTGlzdDogZmFsc2UsXG4gIFNvdXJjZUJ1ZmZlckxpc3Q6IGZhbHNlLFxuICBTdHlsZVNoZWV0TGlzdDogdHJ1ZSwgLy8gVE9ETzogTm90IHNwZWMgY29tcGxpYW50LCBzaG91bGQgYmUgZmFsc2UuXG4gIFRleHRUcmFja0N1ZUxpc3Q6IGZhbHNlLFxuICBUZXh0VHJhY2tMaXN0OiBmYWxzZSxcbiAgVG91Y2hMaXN0OiBmYWxzZVxufTtcblxuZm9yICh2YXIgY29sbGVjdGlvbnMgPSBnZXRLZXlzKERPTUl0ZXJhYmxlcyksIGkgPSAwOyBpIDwgY29sbGVjdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgdmFyIE5BTUUgPSBjb2xsZWN0aW9uc1tpXTtcbiAgdmFyIGV4cGxpY2l0ID0gRE9NSXRlcmFibGVzW05BTUVdO1xuICB2YXIgQ29sbGVjdGlvbiA9IGdsb2JhbFtOQU1FXTtcbiAgdmFyIHByb3RvID0gQ29sbGVjdGlvbiAmJiBDb2xsZWN0aW9uLnByb3RvdHlwZTtcbiAgdmFyIGtleTtcbiAgaWYgKHByb3RvKSB7XG4gICAgaWYgKCFwcm90b1tJVEVSQVRPUl0pIGhpZGUocHJvdG8sIElURVJBVE9SLCBBcnJheVZhbHVlcyk7XG4gICAgaWYgKCFwcm90b1tUT19TVFJJTkdfVEFHXSkgaGlkZShwcm90bywgVE9fU1RSSU5HX1RBRywgTkFNRSk7XG4gICAgSXRlcmF0b3JzW05BTUVdID0gQXJyYXlWYWx1ZXM7XG4gICAgaWYgKGV4cGxpY2l0KSBmb3IgKGtleSBpbiAkaXRlcmF0b3JzKSBpZiAoIXByb3RvW2tleV0pIHJlZGVmaW5lKHByb3RvLCBrZXksICRpdGVyYXRvcnNba2V5XSwgdHJ1ZSk7XG4gIH1cbn1cbiIsInZhciByZWRlZmluZSA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh0YXJnZXQsIHNyYywgc2FmZSkge1xuICBmb3IgKHZhciBrZXkgaW4gc3JjKSByZWRlZmluZSh0YXJnZXQsIGtleSwgc3JjW2tleV0sIHNhZmUpO1xuICByZXR1cm4gdGFyZ2V0O1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0LCBDb25zdHJ1Y3RvciwgbmFtZSwgZm9yYmlkZGVuRmllbGQpIHtcbiAgaWYgKCEoaXQgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikgfHwgKGZvcmJpZGRlbkZpZWxkICE9PSB1bmRlZmluZWQgJiYgZm9yYmlkZGVuRmllbGQgaW4gaXQpKSB7XG4gICAgdGhyb3cgVHlwZUVycm9yKG5hbWUgKyAnOiBpbmNvcnJlY3QgaW52b2NhdGlvbiEnKTtcbiAgfSByZXR1cm4gaXQ7XG59O1xuIiwiLy8gY2FsbCBzb21ldGhpbmcgb24gaXRlcmF0b3Igc3RlcCB3aXRoIHNhZmUgY2xvc2luZyBvbiBlcnJvclxudmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdGVyYXRvciwgZm4sIHZhbHVlLCBlbnRyaWVzKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGVudHJpZXMgPyBmbihhbk9iamVjdCh2YWx1ZSlbMF0sIHZhbHVlWzFdKSA6IGZuKHZhbHVlKTtcbiAgLy8gNy40LjYgSXRlcmF0b3JDbG9zZShpdGVyYXRvciwgY29tcGxldGlvbilcbiAgfSBjYXRjaCAoZSkge1xuICAgIHZhciByZXQgPSBpdGVyYXRvclsncmV0dXJuJ107XG4gICAgaWYgKHJldCAhPT0gdW5kZWZpbmVkKSBhbk9iamVjdChyZXQuY2FsbChpdGVyYXRvcikpO1xuICAgIHRocm93IGU7XG4gIH1cbn07XG4iLCIvLyBjaGVjayBvbiBkZWZhdWx0IEFycmF5IGl0ZXJhdG9yXG52YXIgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJyk7XG52YXIgSVRFUkFUT1IgPSByZXF1aXJlKCcuL193a3MnKSgnaXRlcmF0b3InKTtcbnZhciBBcnJheVByb3RvID0gQXJyYXkucHJvdG90eXBlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gaXQgIT09IHVuZGVmaW5lZCAmJiAoSXRlcmF0b3JzLkFycmF5ID09PSBpdCB8fCBBcnJheVByb3RvW0lURVJBVE9SXSA9PT0gaXQpO1xufTtcbiIsInZhciBjbGFzc29mID0gcmVxdWlyZSgnLi9fY2xhc3NvZicpO1xudmFyIElURVJBVE9SID0gcmVxdWlyZSgnLi9fd2tzJykoJ2l0ZXJhdG9yJyk7XG52YXIgSXRlcmF0b3JzID0gcmVxdWlyZSgnLi9faXRlcmF0b3JzJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vX2NvcmUnKS5nZXRJdGVyYXRvck1ldGhvZCA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAoaXQgIT0gdW5kZWZpbmVkKSByZXR1cm4gaXRbSVRFUkFUT1JdXG4gICAgfHwgaXRbJ0BAaXRlcmF0b3InXVxuICAgIHx8IEl0ZXJhdG9yc1tjbGFzc29mKGl0KV07XG59O1xuIiwidmFyIGN0eCA9IHJlcXVpcmUoJy4vX2N0eCcpO1xudmFyIGNhbGwgPSByZXF1aXJlKCcuL19pdGVyLWNhbGwnKTtcbnZhciBpc0FycmF5SXRlciA9IHJlcXVpcmUoJy4vX2lzLWFycmF5LWl0ZXInKTtcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJyk7XG52YXIgZ2V0SXRlckZuID0gcmVxdWlyZSgnLi9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QnKTtcbnZhciBCUkVBSyA9IHt9O1xudmFyIFJFVFVSTiA9IHt9O1xudmFyIGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdGVyYWJsZSwgZW50cmllcywgZm4sIHRoYXQsIElURVJBVE9SKSB7XG4gIHZhciBpdGVyRm4gPSBJVEVSQVRPUiA/IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGl0ZXJhYmxlOyB9IDogZ2V0SXRlckZuKGl0ZXJhYmxlKTtcbiAgdmFyIGYgPSBjdHgoZm4sIHRoYXQsIGVudHJpZXMgPyAyIDogMSk7XG4gIHZhciBpbmRleCA9IDA7XG4gIHZhciBsZW5ndGgsIHN0ZXAsIGl0ZXJhdG9yLCByZXN1bHQ7XG4gIGlmICh0eXBlb2YgaXRlckZuICE9ICdmdW5jdGlvbicpIHRocm93IFR5cGVFcnJvcihpdGVyYWJsZSArICcgaXMgbm90IGl0ZXJhYmxlIScpO1xuICAvLyBmYXN0IGNhc2UgZm9yIGFycmF5cyB3aXRoIGRlZmF1bHQgaXRlcmF0b3JcbiAgaWYgKGlzQXJyYXlJdGVyKGl0ZXJGbikpIGZvciAobGVuZ3RoID0gdG9MZW5ndGgoaXRlcmFibGUubGVuZ3RoKTsgbGVuZ3RoID4gaW5kZXg7IGluZGV4KyspIHtcbiAgICByZXN1bHQgPSBlbnRyaWVzID8gZihhbk9iamVjdChzdGVwID0gaXRlcmFibGVbaW5kZXhdKVswXSwgc3RlcFsxXSkgOiBmKGl0ZXJhYmxlW2luZGV4XSk7XG4gICAgaWYgKHJlc3VsdCA9PT0gQlJFQUsgfHwgcmVzdWx0ID09PSBSRVRVUk4pIHJldHVybiByZXN1bHQ7XG4gIH0gZWxzZSBmb3IgKGl0ZXJhdG9yID0gaXRlckZuLmNhbGwoaXRlcmFibGUpOyAhKHN0ZXAgPSBpdGVyYXRvci5uZXh0KCkpLmRvbmU7KSB7XG4gICAgcmVzdWx0ID0gY2FsbChpdGVyYXRvciwgZiwgc3RlcC52YWx1ZSwgZW50cmllcyk7XG4gICAgaWYgKHJlc3VsdCA9PT0gQlJFQUsgfHwgcmVzdWx0ID09PSBSRVRVUk4pIHJldHVybiByZXN1bHQ7XG4gIH1cbn07XG5leHBvcnRzLkJSRUFLID0gQlJFQUs7XG5leHBvcnRzLlJFVFVSTiA9IFJFVFVSTjtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuL19nbG9iYWwnKTtcbnZhciBkUCA9IHJlcXVpcmUoJy4vX29iamVjdC1kcCcpO1xudmFyIERFU0NSSVBUT1JTID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKTtcbnZhciBTUEVDSUVTID0gcmVxdWlyZSgnLi9fd2tzJykoJ3NwZWNpZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoS0VZKSB7XG4gIHZhciBDID0gZ2xvYmFsW0tFWV07XG4gIGlmIChERVNDUklQVE9SUyAmJiBDICYmICFDW1NQRUNJRVNdKSBkUC5mKEMsIFNQRUNJRVMsIHtcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9XG4gIH0pO1xufTtcbiIsInZhciBNRVRBID0gcmVxdWlyZSgnLi9fdWlkJykoJ21ldGEnKTtcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xudmFyIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpO1xudmFyIHNldERlc2MgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mO1xudmFyIGlkID0gMDtcbnZhciBpc0V4dGVuc2libGUgPSBPYmplY3QuaXNFeHRlbnNpYmxlIHx8IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRydWU7XG59O1xudmFyIEZSRUVaRSA9ICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGlzRXh0ZW5zaWJsZShPYmplY3QucHJldmVudEV4dGVuc2lvbnMoe30pKTtcbn0pO1xudmFyIHNldE1ldGEgPSBmdW5jdGlvbiAoaXQpIHtcbiAgc2V0RGVzYyhpdCwgTUVUQSwgeyB2YWx1ZToge1xuICAgIGk6ICdPJyArICsraWQsIC8vIG9iamVjdCBJRFxuICAgIHc6IHt9ICAgICAgICAgIC8vIHdlYWsgY29sbGVjdGlvbnMgSURzXG4gIH0gfSk7XG59O1xudmFyIGZhc3RLZXkgPSBmdW5jdGlvbiAoaXQsIGNyZWF0ZSkge1xuICAvLyByZXR1cm4gcHJpbWl0aXZlIHdpdGggcHJlZml4XG4gIGlmICghaXNPYmplY3QoaXQpKSByZXR1cm4gdHlwZW9mIGl0ID09ICdzeW1ib2wnID8gaXQgOiAodHlwZW9mIGl0ID09ICdzdHJpbmcnID8gJ1MnIDogJ1AnKSArIGl0O1xuICBpZiAoIWhhcyhpdCwgTUVUQSkpIHtcbiAgICAvLyBjYW4ndCBzZXQgbWV0YWRhdGEgdG8gdW5jYXVnaHQgZnJvemVuIG9iamVjdFxuICAgIGlmICghaXNFeHRlbnNpYmxlKGl0KSkgcmV0dXJuICdGJztcbiAgICAvLyBub3QgbmVjZXNzYXJ5IHRvIGFkZCBtZXRhZGF0YVxuICAgIGlmICghY3JlYXRlKSByZXR1cm4gJ0UnO1xuICAgIC8vIGFkZCBtaXNzaW5nIG1ldGFkYXRhXG4gICAgc2V0TWV0YShpdCk7XG4gIC8vIHJldHVybiBvYmplY3QgSURcbiAgfSByZXR1cm4gaXRbTUVUQV0uaTtcbn07XG52YXIgZ2V0V2VhayA9IGZ1bmN0aW9uIChpdCwgY3JlYXRlKSB7XG4gIGlmICghaGFzKGl0LCBNRVRBKSkge1xuICAgIC8vIGNhbid0IHNldCBtZXRhZGF0YSB0byB1bmNhdWdodCBmcm96ZW4gb2JqZWN0XG4gICAgaWYgKCFpc0V4dGVuc2libGUoaXQpKSByZXR1cm4gdHJ1ZTtcbiAgICAvLyBub3QgbmVjZXNzYXJ5IHRvIGFkZCBtZXRhZGF0YVxuICAgIGlmICghY3JlYXRlKSByZXR1cm4gZmFsc2U7XG4gICAgLy8gYWRkIG1pc3NpbmcgbWV0YWRhdGFcbiAgICBzZXRNZXRhKGl0KTtcbiAgLy8gcmV0dXJuIGhhc2ggd2VhayBjb2xsZWN0aW9ucyBJRHNcbiAgfSByZXR1cm4gaXRbTUVUQV0udztcbn07XG4vLyBhZGQgbWV0YWRhdGEgb24gZnJlZXplLWZhbWlseSBtZXRob2RzIGNhbGxpbmdcbnZhciBvbkZyZWV6ZSA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAoRlJFRVpFICYmIG1ldGEuTkVFRCAmJiBpc0V4dGVuc2libGUoaXQpICYmICFoYXMoaXQsIE1FVEEpKSBzZXRNZXRhKGl0KTtcbiAgcmV0dXJuIGl0O1xufTtcbnZhciBtZXRhID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIEtFWTogTUVUQSxcbiAgTkVFRDogZmFsc2UsXG4gIGZhc3RLZXk6IGZhc3RLZXksXG4gIGdldFdlYWs6IGdldFdlYWssXG4gIG9uRnJlZXplOiBvbkZyZWV6ZVxufTtcbiIsInZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQsIFRZUEUpIHtcbiAgaWYgKCFpc09iamVjdChpdCkgfHwgaXQuX3QgIT09IFRZUEUpIHRocm93IFR5cGVFcnJvcignSW5jb21wYXRpYmxlIHJlY2VpdmVyLCAnICsgVFlQRSArICcgcmVxdWlyZWQhJyk7XG4gIHJldHVybiBpdDtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgZFAgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mO1xudmFyIGNyZWF0ZSA9IHJlcXVpcmUoJy4vX29iamVjdC1jcmVhdGUnKTtcbnZhciByZWRlZmluZUFsbCA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpO1xudmFyIGN0eCA9IHJlcXVpcmUoJy4vX2N0eCcpO1xudmFyIGFuSW5zdGFuY2UgPSByZXF1aXJlKCcuL19hbi1pbnN0YW5jZScpO1xudmFyIGZvck9mID0gcmVxdWlyZSgnLi9fZm9yLW9mJyk7XG52YXIgJGl0ZXJEZWZpbmUgPSByZXF1aXJlKCcuL19pdGVyLWRlZmluZScpO1xudmFyIHN0ZXAgPSByZXF1aXJlKCcuL19pdGVyLXN0ZXAnKTtcbnZhciBzZXRTcGVjaWVzID0gcmVxdWlyZSgnLi9fc2V0LXNwZWNpZXMnKTtcbnZhciBERVNDUklQVE9SUyA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJyk7XG52YXIgZmFzdEtleSA9IHJlcXVpcmUoJy4vX21ldGEnKS5mYXN0S2V5O1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnLi9fdmFsaWRhdGUtY29sbGVjdGlvbicpO1xudmFyIFNJWkUgPSBERVNDUklQVE9SUyA/ICdfcycgOiAnc2l6ZSc7XG5cbnZhciBnZXRFbnRyeSA9IGZ1bmN0aW9uICh0aGF0LCBrZXkpIHtcbiAgLy8gZmFzdCBjYXNlXG4gIHZhciBpbmRleCA9IGZhc3RLZXkoa2V5KTtcbiAgdmFyIGVudHJ5O1xuICBpZiAoaW5kZXggIT09ICdGJykgcmV0dXJuIHRoYXQuX2lbaW5kZXhdO1xuICAvLyBmcm96ZW4gb2JqZWN0IGNhc2VcbiAgZm9yIChlbnRyeSA9IHRoYXQuX2Y7IGVudHJ5OyBlbnRyeSA9IGVudHJ5Lm4pIHtcbiAgICBpZiAoZW50cnkuayA9PSBrZXkpIHJldHVybiBlbnRyeTtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGdldENvbnN0cnVjdG9yOiBmdW5jdGlvbiAod3JhcHBlciwgTkFNRSwgSVNfTUFQLCBBRERFUikge1xuICAgIHZhciBDID0gd3JhcHBlcihmdW5jdGlvbiAodGhhdCwgaXRlcmFibGUpIHtcbiAgICAgIGFuSW5zdGFuY2UodGhhdCwgQywgTkFNRSwgJ19pJyk7XG4gICAgICB0aGF0Ll90ID0gTkFNRTsgICAgICAgICAvLyBjb2xsZWN0aW9uIHR5cGVcbiAgICAgIHRoYXQuX2kgPSBjcmVhdGUobnVsbCk7IC8vIGluZGV4XG4gICAgICB0aGF0Ll9mID0gdW5kZWZpbmVkOyAgICAvLyBmaXJzdCBlbnRyeVxuICAgICAgdGhhdC5fbCA9IHVuZGVmaW5lZDsgICAgLy8gbGFzdCBlbnRyeVxuICAgICAgdGhhdFtTSVpFXSA9IDA7ICAgICAgICAgLy8gc2l6ZVxuICAgICAgaWYgKGl0ZXJhYmxlICE9IHVuZGVmaW5lZCkgZm9yT2YoaXRlcmFibGUsIElTX01BUCwgdGhhdFtBRERFUl0sIHRoYXQpO1xuICAgIH0pO1xuICAgIHJlZGVmaW5lQWxsKEMucHJvdG90eXBlLCB7XG4gICAgICAvLyAyMy4xLjMuMSBNYXAucHJvdG90eXBlLmNsZWFyKClcbiAgICAgIC8vIDIzLjIuMy4yIFNldC5wcm90b3R5cGUuY2xlYXIoKVxuICAgICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICBmb3IgKHZhciB0aGF0ID0gdmFsaWRhdGUodGhpcywgTkFNRSksIGRhdGEgPSB0aGF0Ll9pLCBlbnRyeSA9IHRoYXQuX2Y7IGVudHJ5OyBlbnRyeSA9IGVudHJ5Lm4pIHtcbiAgICAgICAgICBlbnRyeS5yID0gdHJ1ZTtcbiAgICAgICAgICBpZiAoZW50cnkucCkgZW50cnkucCA9IGVudHJ5LnAubiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICBkZWxldGUgZGF0YVtlbnRyeS5pXTtcbiAgICAgICAgfVxuICAgICAgICB0aGF0Ll9mID0gdGhhdC5fbCA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhhdFtTSVpFXSA9IDA7XG4gICAgICB9LFxuICAgICAgLy8gMjMuMS4zLjMgTWFwLnByb3RvdHlwZS5kZWxldGUoa2V5KVxuICAgICAgLy8gMjMuMi4zLjQgU2V0LnByb3RvdHlwZS5kZWxldGUodmFsdWUpXG4gICAgICAnZGVsZXRlJzogZnVuY3Rpb24gKGtleSkge1xuICAgICAgICB2YXIgdGhhdCA9IHZhbGlkYXRlKHRoaXMsIE5BTUUpO1xuICAgICAgICB2YXIgZW50cnkgPSBnZXRFbnRyeSh0aGF0LCBrZXkpO1xuICAgICAgICBpZiAoZW50cnkpIHtcbiAgICAgICAgICB2YXIgbmV4dCA9IGVudHJ5Lm47XG4gICAgICAgICAgdmFyIHByZXYgPSBlbnRyeS5wO1xuICAgICAgICAgIGRlbGV0ZSB0aGF0Ll9pW2VudHJ5LmldO1xuICAgICAgICAgIGVudHJ5LnIgPSB0cnVlO1xuICAgICAgICAgIGlmIChwcmV2KSBwcmV2Lm4gPSBuZXh0O1xuICAgICAgICAgIGlmIChuZXh0KSBuZXh0LnAgPSBwcmV2O1xuICAgICAgICAgIGlmICh0aGF0Ll9mID09IGVudHJ5KSB0aGF0Ll9mID0gbmV4dDtcbiAgICAgICAgICBpZiAodGhhdC5fbCA9PSBlbnRyeSkgdGhhdC5fbCA9IHByZXY7XG4gICAgICAgICAgdGhhdFtTSVpFXS0tO1xuICAgICAgICB9IHJldHVybiAhIWVudHJ5O1xuICAgICAgfSxcbiAgICAgIC8vIDIzLjIuMy42IFNldC5wcm90b3R5cGUuZm9yRWFjaChjYWxsYmFja2ZuLCB0aGlzQXJnID0gdW5kZWZpbmVkKVxuICAgICAgLy8gMjMuMS4zLjUgTWFwLnByb3RvdHlwZS5mb3JFYWNoKGNhbGxiYWNrZm4sIHRoaXNBcmcgPSB1bmRlZmluZWQpXG4gICAgICBmb3JFYWNoOiBmdW5jdGlvbiBmb3JFYWNoKGNhbGxiYWNrZm4gLyogLCB0aGF0ID0gdW5kZWZpbmVkICovKSB7XG4gICAgICAgIHZhbGlkYXRlKHRoaXMsIE5BTUUpO1xuICAgICAgICB2YXIgZiA9IGN0eChjYWxsYmFja2ZuLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCwgMyk7XG4gICAgICAgIHZhciBlbnRyeTtcbiAgICAgICAgd2hpbGUgKGVudHJ5ID0gZW50cnkgPyBlbnRyeS5uIDogdGhpcy5fZikge1xuICAgICAgICAgIGYoZW50cnkudiwgZW50cnkuaywgdGhpcyk7XG4gICAgICAgICAgLy8gcmV2ZXJ0IHRvIHRoZSBsYXN0IGV4aXN0aW5nIGVudHJ5XG4gICAgICAgICAgd2hpbGUgKGVudHJ5ICYmIGVudHJ5LnIpIGVudHJ5ID0gZW50cnkucDtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIC8vIDIzLjEuMy43IE1hcC5wcm90b3R5cGUuaGFzKGtleSlcbiAgICAgIC8vIDIzLjIuMy43IFNldC5wcm90b3R5cGUuaGFzKHZhbHVlKVxuICAgICAgaGFzOiBmdW5jdGlvbiBoYXMoa2V5KSB7XG4gICAgICAgIHJldHVybiAhIWdldEVudHJ5KHZhbGlkYXRlKHRoaXMsIE5BTUUpLCBrZXkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChERVNDUklQVE9SUykgZFAoQy5wcm90b3R5cGUsICdzaXplJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB2YWxpZGF0ZSh0aGlzLCBOQU1FKVtTSVpFXTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gQztcbiAgfSxcbiAgZGVmOiBmdW5jdGlvbiAodGhhdCwga2V5LCB2YWx1ZSkge1xuICAgIHZhciBlbnRyeSA9IGdldEVudHJ5KHRoYXQsIGtleSk7XG4gICAgdmFyIHByZXYsIGluZGV4O1xuICAgIC8vIGNoYW5nZSBleGlzdGluZyBlbnRyeVxuICAgIGlmIChlbnRyeSkge1xuICAgICAgZW50cnkudiA9IHZhbHVlO1xuICAgIC8vIGNyZWF0ZSBuZXcgZW50cnlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhhdC5fbCA9IGVudHJ5ID0ge1xuICAgICAgICBpOiBpbmRleCA9IGZhc3RLZXkoa2V5LCB0cnVlKSwgLy8gPC0gaW5kZXhcbiAgICAgICAgazoga2V5LCAgICAgICAgICAgICAgICAgICAgICAgIC8vIDwtIGtleVxuICAgICAgICB2OiB2YWx1ZSwgICAgICAgICAgICAgICAgICAgICAgLy8gPC0gdmFsdWVcbiAgICAgICAgcDogcHJldiA9IHRoYXQuX2wsICAgICAgICAgICAgIC8vIDwtIHByZXZpb3VzIGVudHJ5XG4gICAgICAgIG46IHVuZGVmaW5lZCwgICAgICAgICAgICAgICAgICAvLyA8LSBuZXh0IGVudHJ5XG4gICAgICAgIHI6IGZhbHNlICAgICAgICAgICAgICAgICAgICAgICAvLyA8LSByZW1vdmVkXG4gICAgICB9O1xuICAgICAgaWYgKCF0aGF0Ll9mKSB0aGF0Ll9mID0gZW50cnk7XG4gICAgICBpZiAocHJldikgcHJldi5uID0gZW50cnk7XG4gICAgICB0aGF0W1NJWkVdKys7XG4gICAgICAvLyBhZGQgdG8gaW5kZXhcbiAgICAgIGlmIChpbmRleCAhPT0gJ0YnKSB0aGF0Ll9pW2luZGV4XSA9IGVudHJ5O1xuICAgIH0gcmV0dXJuIHRoYXQ7XG4gIH0sXG4gIGdldEVudHJ5OiBnZXRFbnRyeSxcbiAgc2V0U3Ryb25nOiBmdW5jdGlvbiAoQywgTkFNRSwgSVNfTUFQKSB7XG4gICAgLy8gYWRkIC5rZXlzLCAudmFsdWVzLCAuZW50cmllcywgW0BAaXRlcmF0b3JdXG4gICAgLy8gMjMuMS4zLjQsIDIzLjEuMy44LCAyMy4xLjMuMTEsIDIzLjEuMy4xMiwgMjMuMi4zLjUsIDIzLjIuMy44LCAyMy4yLjMuMTAsIDIzLjIuMy4xMVxuICAgICRpdGVyRGVmaW5lKEMsIE5BTUUsIGZ1bmN0aW9uIChpdGVyYXRlZCwga2luZCkge1xuICAgICAgdGhpcy5fdCA9IHZhbGlkYXRlKGl0ZXJhdGVkLCBOQU1FKTsgLy8gdGFyZ2V0XG4gICAgICB0aGlzLl9rID0ga2luZDsgICAgICAgICAgICAgICAgICAgICAvLyBraW5kXG4gICAgICB0aGlzLl9sID0gdW5kZWZpbmVkOyAgICAgICAgICAgICAgICAvLyBwcmV2aW91c1xuICAgIH0sIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciB0aGF0ID0gdGhpcztcbiAgICAgIHZhciBraW5kID0gdGhhdC5faztcbiAgICAgIHZhciBlbnRyeSA9IHRoYXQuX2w7XG4gICAgICAvLyByZXZlcnQgdG8gdGhlIGxhc3QgZXhpc3RpbmcgZW50cnlcbiAgICAgIHdoaWxlIChlbnRyeSAmJiBlbnRyeS5yKSBlbnRyeSA9IGVudHJ5LnA7XG4gICAgICAvLyBnZXQgbmV4dCBlbnRyeVxuICAgICAgaWYgKCF0aGF0Ll90IHx8ICEodGhhdC5fbCA9IGVudHJ5ID0gZW50cnkgPyBlbnRyeS5uIDogdGhhdC5fdC5fZikpIHtcbiAgICAgICAgLy8gb3IgZmluaXNoIHRoZSBpdGVyYXRpb25cbiAgICAgICAgdGhhdC5fdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgcmV0dXJuIHN0ZXAoMSk7XG4gICAgICB9XG4gICAgICAvLyByZXR1cm4gc3RlcCBieSBraW5kXG4gICAgICBpZiAoa2luZCA9PSAna2V5cycpIHJldHVybiBzdGVwKDAsIGVudHJ5LmspO1xuICAgICAgaWYgKGtpbmQgPT0gJ3ZhbHVlcycpIHJldHVybiBzdGVwKDAsIGVudHJ5LnYpO1xuICAgICAgcmV0dXJuIHN0ZXAoMCwgW2VudHJ5LmssIGVudHJ5LnZdKTtcbiAgICB9LCBJU19NQVAgPyAnZW50cmllcycgOiAndmFsdWVzJywgIUlTX01BUCwgdHJ1ZSk7XG5cbiAgICAvLyBhZGQgW0BAc3BlY2llc10sIDIzLjEuMi4yLCAyMy4yLjIuMlxuICAgIHNldFNwZWNpZXMoTkFNRSk7XG4gIH1cbn07XG4iLCJ2YXIgSVRFUkFUT1IgPSByZXF1aXJlKCcuL193a3MnKSgnaXRlcmF0b3InKTtcbnZhciBTQUZFX0NMT1NJTkcgPSBmYWxzZTtcblxudHJ5IHtcbiAgdmFyIHJpdGVyID0gWzddW0lURVJBVE9SXSgpO1xuICByaXRlclsncmV0dXJuJ10gPSBmdW5jdGlvbiAoKSB7IFNBRkVfQ0xPU0lORyA9IHRydWU7IH07XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby10aHJvdy1saXRlcmFsXG4gIEFycmF5LmZyb20ocml0ZXIsIGZ1bmN0aW9uICgpIHsgdGhyb3cgMjsgfSk7XG59IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZXhlYywgc2tpcENsb3NpbmcpIHtcbiAgaWYgKCFza2lwQ2xvc2luZyAmJiAhU0FGRV9DTE9TSU5HKSByZXR1cm4gZmFsc2U7XG4gIHZhciBzYWZlID0gZmFsc2U7XG4gIHRyeSB7XG4gICAgdmFyIGFyciA9IFs3XTtcbiAgICB2YXIgaXRlciA9IGFycltJVEVSQVRPUl0oKTtcbiAgICBpdGVyLm5leHQgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB7IGRvbmU6IHNhZmUgPSB0cnVlIH07IH07XG4gICAgYXJyW0lURVJBVE9SXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIGl0ZXI7IH07XG4gICAgZXhlYyhhcnIpO1xuICB9IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cbiAgcmV0dXJuIHNhZmU7XG59O1xuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgc2V0UHJvdG90eXBlT2YgPSByZXF1aXJlKCcuL19zZXQtcHJvdG8nKS5zZXQ7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh0aGF0LCB0YXJnZXQsIEMpIHtcbiAgdmFyIFMgPSB0YXJnZXQuY29uc3RydWN0b3I7XG4gIHZhciBQO1xuICBpZiAoUyAhPT0gQyAmJiB0eXBlb2YgUyA9PSAnZnVuY3Rpb24nICYmIChQID0gUy5wcm90b3R5cGUpICE9PSBDLnByb3RvdHlwZSAmJiBpc09iamVjdChQKSAmJiBzZXRQcm90b3R5cGVPZikge1xuICAgIHNldFByb3RvdHlwZU9mKHRoYXQsIFApO1xuICB9IHJldHVybiB0aGF0O1xufTtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuL19nbG9iYWwnKTtcbnZhciAkZXhwb3J0ID0gcmVxdWlyZSgnLi9fZXhwb3J0Jyk7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuL19yZWRlZmluZScpO1xudmFyIHJlZGVmaW5lQWxsID0gcmVxdWlyZSgnLi9fcmVkZWZpbmUtYWxsJyk7XG52YXIgbWV0YSA9IHJlcXVpcmUoJy4vX21ldGEnKTtcbnZhciBmb3JPZiA9IHJlcXVpcmUoJy4vX2Zvci1vZicpO1xudmFyIGFuSW5zdGFuY2UgPSByZXF1aXJlKCcuL19hbi1pbnN0YW5jZScpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgZmFpbHMgPSByZXF1aXJlKCcuL19mYWlscycpO1xudmFyICRpdGVyRGV0ZWN0ID0gcmVxdWlyZSgnLi9faXRlci1kZXRlY3QnKTtcbnZhciBzZXRUb1N0cmluZ1RhZyA9IHJlcXVpcmUoJy4vX3NldC10by1zdHJpbmctdGFnJyk7XG52YXIgaW5oZXJpdElmUmVxdWlyZWQgPSByZXF1aXJlKCcuL19pbmhlcml0LWlmLXJlcXVpcmVkJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKE5BTUUsIHdyYXBwZXIsIG1ldGhvZHMsIGNvbW1vbiwgSVNfTUFQLCBJU19XRUFLKSB7XG4gIHZhciBCYXNlID0gZ2xvYmFsW05BTUVdO1xuICB2YXIgQyA9IEJhc2U7XG4gIHZhciBBRERFUiA9IElTX01BUCA/ICdzZXQnIDogJ2FkZCc7XG4gIHZhciBwcm90byA9IEMgJiYgQy5wcm90b3R5cGU7XG4gIHZhciBPID0ge307XG4gIHZhciBmaXhNZXRob2QgPSBmdW5jdGlvbiAoS0VZKSB7XG4gICAgdmFyIGZuID0gcHJvdG9bS0VZXTtcbiAgICByZWRlZmluZShwcm90bywgS0VZLFxuICAgICAgS0VZID09ICdkZWxldGUnID8gZnVuY3Rpb24gKGEpIHtcbiAgICAgICAgcmV0dXJuIElTX1dFQUsgJiYgIWlzT2JqZWN0KGEpID8gZmFsc2UgOiBmbi5jYWxsKHRoaXMsIGEgPT09IDAgPyAwIDogYSk7XG4gICAgICB9IDogS0VZID09ICdoYXMnID8gZnVuY3Rpb24gaGFzKGEpIHtcbiAgICAgICAgcmV0dXJuIElTX1dFQUsgJiYgIWlzT2JqZWN0KGEpID8gZmFsc2UgOiBmbi5jYWxsKHRoaXMsIGEgPT09IDAgPyAwIDogYSk7XG4gICAgICB9IDogS0VZID09ICdnZXQnID8gZnVuY3Rpb24gZ2V0KGEpIHtcbiAgICAgICAgcmV0dXJuIElTX1dFQUsgJiYgIWlzT2JqZWN0KGEpID8gdW5kZWZpbmVkIDogZm4uY2FsbCh0aGlzLCBhID09PSAwID8gMCA6IGEpO1xuICAgICAgfSA6IEtFWSA9PSAnYWRkJyA/IGZ1bmN0aW9uIGFkZChhKSB7IGZuLmNhbGwodGhpcywgYSA9PT0gMCA/IDAgOiBhKTsgcmV0dXJuIHRoaXM7IH1cbiAgICAgICAgOiBmdW5jdGlvbiBzZXQoYSwgYikgeyBmbi5jYWxsKHRoaXMsIGEgPT09IDAgPyAwIDogYSwgYik7IHJldHVybiB0aGlzOyB9XG4gICAgKTtcbiAgfTtcbiAgaWYgKHR5cGVvZiBDICE9ICdmdW5jdGlvbicgfHwgIShJU19XRUFLIHx8IHByb3RvLmZvckVhY2ggJiYgIWZhaWxzKGZ1bmN0aW9uICgpIHtcbiAgICBuZXcgQygpLmVudHJpZXMoKS5uZXh0KCk7XG4gIH0pKSkge1xuICAgIC8vIGNyZWF0ZSBjb2xsZWN0aW9uIGNvbnN0cnVjdG9yXG4gICAgQyA9IGNvbW1vbi5nZXRDb25zdHJ1Y3Rvcih3cmFwcGVyLCBOQU1FLCBJU19NQVAsIEFEREVSKTtcbiAgICByZWRlZmluZUFsbChDLnByb3RvdHlwZSwgbWV0aG9kcyk7XG4gICAgbWV0YS5ORUVEID0gdHJ1ZTtcbiAgfSBlbHNlIHtcbiAgICB2YXIgaW5zdGFuY2UgPSBuZXcgQygpO1xuICAgIC8vIGVhcmx5IGltcGxlbWVudGF0aW9ucyBub3Qgc3VwcG9ydHMgY2hhaW5pbmdcbiAgICB2YXIgSEFTTlRfQ0hBSU5JTkcgPSBpbnN0YW5jZVtBRERFUl0oSVNfV0VBSyA/IHt9IDogLTAsIDEpICE9IGluc3RhbmNlO1xuICAgIC8vIFY4IH4gIENocm9taXVtIDQwLSB3ZWFrLWNvbGxlY3Rpb25zIHRocm93cyBvbiBwcmltaXRpdmVzLCBidXQgc2hvdWxkIHJldHVybiBmYWxzZVxuICAgIHZhciBUSFJPV1NfT05fUFJJTUlUSVZFUyA9IGZhaWxzKGZ1bmN0aW9uICgpIHsgaW5zdGFuY2UuaGFzKDEpOyB9KTtcbiAgICAvLyBtb3N0IGVhcmx5IGltcGxlbWVudGF0aW9ucyBkb2Vzbid0IHN1cHBvcnRzIGl0ZXJhYmxlcywgbW9zdCBtb2Rlcm4gLSBub3QgY2xvc2UgaXQgY29ycmVjdGx5XG4gICAgdmFyIEFDQ0VQVF9JVEVSQUJMRVMgPSAkaXRlckRldGVjdChmdW5jdGlvbiAoaXRlcikgeyBuZXcgQyhpdGVyKTsgfSk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tbmV3XG4gICAgLy8gZm9yIGVhcmx5IGltcGxlbWVudGF0aW9ucyAtMCBhbmQgKzAgbm90IHRoZSBzYW1lXG4gICAgdmFyIEJVR0dZX1pFUk8gPSAhSVNfV0VBSyAmJiBmYWlscyhmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBWOCB+IENocm9taXVtIDQyLSBmYWlscyBvbmx5IHdpdGggNSsgZWxlbWVudHNcbiAgICAgIHZhciAkaW5zdGFuY2UgPSBuZXcgQygpO1xuICAgICAgdmFyIGluZGV4ID0gNTtcbiAgICAgIHdoaWxlIChpbmRleC0tKSAkaW5zdGFuY2VbQURERVJdKGluZGV4LCBpbmRleCk7XG4gICAgICByZXR1cm4gISRpbnN0YW5jZS5oYXMoLTApO1xuICAgIH0pO1xuICAgIGlmICghQUNDRVBUX0lURVJBQkxFUykge1xuICAgICAgQyA9IHdyYXBwZXIoZnVuY3Rpb24gKHRhcmdldCwgaXRlcmFibGUpIHtcbiAgICAgICAgYW5JbnN0YW5jZSh0YXJnZXQsIEMsIE5BTUUpO1xuICAgICAgICB2YXIgdGhhdCA9IGluaGVyaXRJZlJlcXVpcmVkKG5ldyBCYXNlKCksIHRhcmdldCwgQyk7XG4gICAgICAgIGlmIChpdGVyYWJsZSAhPSB1bmRlZmluZWQpIGZvck9mKGl0ZXJhYmxlLCBJU19NQVAsIHRoYXRbQURERVJdLCB0aGF0KTtcbiAgICAgICAgcmV0dXJuIHRoYXQ7XG4gICAgICB9KTtcbiAgICAgIEMucHJvdG90eXBlID0gcHJvdG87XG4gICAgICBwcm90by5jb25zdHJ1Y3RvciA9IEM7XG4gICAgfVxuICAgIGlmIChUSFJPV1NfT05fUFJJTUlUSVZFUyB8fCBCVUdHWV9aRVJPKSB7XG4gICAgICBmaXhNZXRob2QoJ2RlbGV0ZScpO1xuICAgICAgZml4TWV0aG9kKCdoYXMnKTtcbiAgICAgIElTX01BUCAmJiBmaXhNZXRob2QoJ2dldCcpO1xuICAgIH1cbiAgICBpZiAoQlVHR1lfWkVSTyB8fCBIQVNOVF9DSEFJTklORykgZml4TWV0aG9kKEFEREVSKTtcbiAgICAvLyB3ZWFrIGNvbGxlY3Rpb25zIHNob3VsZCBub3QgY29udGFpbnMgLmNsZWFyIG1ldGhvZFxuICAgIGlmIChJU19XRUFLICYmIHByb3RvLmNsZWFyKSBkZWxldGUgcHJvdG8uY2xlYXI7XG4gIH1cblxuICBzZXRUb1N0cmluZ1RhZyhDLCBOQU1FKTtcblxuICBPW05BTUVdID0gQztcbiAgJGV4cG9ydCgkZXhwb3J0LkcgKyAkZXhwb3J0LlcgKyAkZXhwb3J0LkYgKiAoQyAhPSBCYXNlKSwgTyk7XG5cbiAgaWYgKCFJU19XRUFLKSBjb21tb24uc2V0U3Ryb25nKEMsIE5BTUUsIElTX01BUCk7XG5cbiAgcmV0dXJuIEM7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIHN0cm9uZyA9IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24tc3Ryb25nJyk7XG52YXIgdmFsaWRhdGUgPSByZXF1aXJlKCcuL192YWxpZGF0ZS1jb2xsZWN0aW9uJyk7XG52YXIgU0VUID0gJ1NldCc7XG5cbi8vIDIzLjIgU2V0IE9iamVjdHNcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29sbGVjdGlvbicpKFNFVCwgZnVuY3Rpb24gKGdldCkge1xuICByZXR1cm4gZnVuY3Rpb24gU2V0KCkgeyByZXR1cm4gZ2V0KHRoaXMsIGFyZ3VtZW50cy5sZW5ndGggPiAwID8gYXJndW1lbnRzWzBdIDogdW5kZWZpbmVkKTsgfTtcbn0sIHtcbiAgLy8gMjMuMi4zLjEgU2V0LnByb3RvdHlwZS5hZGQodmFsdWUpXG4gIGFkZDogZnVuY3Rpb24gYWRkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHN0cm9uZy5kZWYodmFsaWRhdGUodGhpcywgU0VUKSwgdmFsdWUgPSB2YWx1ZSA9PT0gMCA/IDAgOiB2YWx1ZSwgdmFsdWUpO1xuICB9XG59LCBzdHJvbmcpO1xuIiwidmFyIGZvck9mID0gcmVxdWlyZSgnLi9fZm9yLW9mJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0ZXIsIElURVJBVE9SKSB7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgZm9yT2YoaXRlciwgZmFsc2UsIHJlc3VsdC5wdXNoLCByZXN1bHQsIElURVJBVE9SKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG4iLCIvLyBodHRwczovL2dpdGh1Yi5jb20vRGF2aWRCcnVhbnQvTWFwLVNldC5wcm90b3R5cGUudG9KU09OXG52YXIgY2xhc3NvZiA9IHJlcXVpcmUoJy4vX2NsYXNzb2YnKTtcbnZhciBmcm9tID0gcmVxdWlyZSgnLi9fYXJyYXktZnJvbS1pdGVyYWJsZScpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoTkFNRSkge1xuICByZXR1cm4gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgIGlmIChjbGFzc29mKHRoaXMpICE9IE5BTUUpIHRocm93IFR5cGVFcnJvcihOQU1FICsgXCIjdG9KU09OIGlzbid0IGdlbmVyaWNcIik7XG4gICAgcmV0dXJuIGZyb20odGhpcyk7XG4gIH07XG59O1xuIiwiLy8gaHR0cHM6Ly9naXRodWIuY29tL0RhdmlkQnJ1YW50L01hcC1TZXQucHJvdG90eXBlLnRvSlNPTlxudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcblxuJGV4cG9ydCgkZXhwb3J0LlAgKyAkZXhwb3J0LlIsICdTZXQnLCB7IHRvSlNPTjogcmVxdWlyZSgnLi9fY29sbGVjdGlvbi10by1qc29uJykoJ1NldCcpIH0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuLy8gaHR0cHM6Ly90YzM5LmdpdGh1Yi5pby9wcm9wb3NhbC1zZXRtYXAtb2Zmcm9tL1xudmFyICRleHBvcnQgPSByZXF1aXJlKCcuL19leHBvcnQnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoQ09MTEVDVElPTikge1xuICAkZXhwb3J0KCRleHBvcnQuUywgQ09MTEVDVElPTiwgeyBvZjogZnVuY3Rpb24gb2YoKSB7XG4gICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgdmFyIEEgPSBBcnJheShsZW5ndGgpO1xuICAgIHdoaWxlIChsZW5ndGgtLSkgQVtsZW5ndGhdID0gYXJndW1lbnRzW2xlbmd0aF07XG4gICAgcmV0dXJuIG5ldyB0aGlzKEEpO1xuICB9IH0pO1xufTtcbiIsIi8vIGh0dHBzOi8vdGMzOS5naXRodWIuaW8vcHJvcG9zYWwtc2V0bWFwLW9mZnJvbS8jc2VjLXNldC5vZlxucmVxdWlyZSgnLi9fc2V0LWNvbGxlY3Rpb24tb2YnKSgnU2V0Jyk7XG4iLCIndXNlIHN0cmljdCc7XG4vLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL3Byb3Bvc2FsLXNldG1hcC1vZmZyb20vXG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xudmFyIGFGdW5jdGlvbiA9IHJlcXVpcmUoJy4vX2EtZnVuY3Rpb24nKTtcbnZhciBjdHggPSByZXF1aXJlKCcuL19jdHgnKTtcbnZhciBmb3JPZiA9IHJlcXVpcmUoJy4vX2Zvci1vZicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChDT0xMRUNUSU9OKSB7XG4gICRleHBvcnQoJGV4cG9ydC5TLCBDT0xMRUNUSU9OLCB7IGZyb206IGZ1bmN0aW9uIGZyb20oc291cmNlIC8qICwgbWFwRm4sIHRoaXNBcmcgKi8pIHtcbiAgICB2YXIgbWFwRm4gPSBhcmd1bWVudHNbMV07XG4gICAgdmFyIG1hcHBpbmcsIEEsIG4sIGNiO1xuICAgIGFGdW5jdGlvbih0aGlzKTtcbiAgICBtYXBwaW5nID0gbWFwRm4gIT09IHVuZGVmaW5lZDtcbiAgICBpZiAobWFwcGluZykgYUZ1bmN0aW9uKG1hcEZuKTtcbiAgICBpZiAoc291cmNlID09IHVuZGVmaW5lZCkgcmV0dXJuIG5ldyB0aGlzKCk7XG4gICAgQSA9IFtdO1xuICAgIGlmIChtYXBwaW5nKSB7XG4gICAgICBuID0gMDtcbiAgICAgIGNiID0gY3R4KG1hcEZuLCBhcmd1bWVudHNbMl0sIDIpO1xuICAgICAgZm9yT2Yoc291cmNlLCBmYWxzZSwgZnVuY3Rpb24gKG5leHRJdGVtKSB7XG4gICAgICAgIEEucHVzaChjYihuZXh0SXRlbSwgbisrKSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yT2Yoc291cmNlLCBmYWxzZSwgQS5wdXNoLCBBKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyB0aGlzKEEpO1xuICB9IH0pO1xufTtcbiIsIi8vIGh0dHBzOi8vdGMzOS5naXRodWIuaW8vcHJvcG9zYWwtc2V0bWFwLW9mZnJvbS8jc2VjLXNldC5mcm9tXG5yZXF1aXJlKCcuL19zZXQtY29sbGVjdGlvbi1mcm9tJykoJ1NldCcpO1xuIiwicmVxdWlyZSgnLi4vbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZycpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM2LnNldCcpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcuc2V0LnRvLWpzb24nKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM3LnNldC5vZicpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcuc2V0LmZyb20nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9fY29yZScpLlNldDtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciBzdHJvbmcgPSByZXF1aXJlKCcuL19jb2xsZWN0aW9uLXN0cm9uZycpO1xudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnLi9fdmFsaWRhdGUtY29sbGVjdGlvbicpO1xudmFyIE1BUCA9ICdNYXAnO1xuXG4vLyAyMy4xIE1hcCBPYmplY3RzXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vX2NvbGxlY3Rpb24nKShNQVAsIGZ1bmN0aW9uIChnZXQpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIE1hcCgpIHsgcmV0dXJuIGdldCh0aGlzLCBhcmd1bWVudHMubGVuZ3RoID4gMCA/IGFyZ3VtZW50c1swXSA6IHVuZGVmaW5lZCk7IH07XG59LCB7XG4gIC8vIDIzLjEuMy42IE1hcC5wcm90b3R5cGUuZ2V0KGtleSlcbiAgZ2V0OiBmdW5jdGlvbiBnZXQoa2V5KSB7XG4gICAgdmFyIGVudHJ5ID0gc3Ryb25nLmdldEVudHJ5KHZhbGlkYXRlKHRoaXMsIE1BUCksIGtleSk7XG4gICAgcmV0dXJuIGVudHJ5ICYmIGVudHJ5LnY7XG4gIH0sXG4gIC8vIDIzLjEuMy45IE1hcC5wcm90b3R5cGUuc2V0KGtleSwgdmFsdWUpXG4gIHNldDogZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUpIHtcbiAgICByZXR1cm4gc3Ryb25nLmRlZih2YWxpZGF0ZSh0aGlzLCBNQVApLCBrZXkgPT09IDAgPyAwIDoga2V5LCB2YWx1ZSk7XG4gIH1cbn0sIHN0cm9uZywgdHJ1ZSk7XG4iLCIvLyBodHRwczovL2dpdGh1Yi5jb20vRGF2aWRCcnVhbnQvTWFwLVNldC5wcm90b3R5cGUudG9KU09OXG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUCArICRleHBvcnQuUiwgJ01hcCcsIHsgdG9KU09OOiByZXF1aXJlKCcuL19jb2xsZWN0aW9uLXRvLWpzb24nKSgnTWFwJykgfSk7XG4iLCIvLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL3Byb3Bvc2FsLXNldG1hcC1vZmZyb20vI3NlYy1tYXAub2ZcbnJlcXVpcmUoJy4vX3NldC1jb2xsZWN0aW9uLW9mJykoJ01hcCcpO1xuIiwiLy8gaHR0cHM6Ly90YzM5LmdpdGh1Yi5pby9wcm9wb3NhbC1zZXRtYXAtb2Zmcm9tLyNzZWMtbWFwLmZyb21cbnJlcXVpcmUoJy4vX3NldC1jb2xsZWN0aW9uLWZyb20nKSgnTWFwJyk7XG4iLCJyZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5vYmplY3QudG8tc3RyaW5nJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi5zdHJpbmcuaXRlcmF0b3InKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvd2ViLmRvbS5pdGVyYWJsZScpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczYubWFwJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNy5tYXAudG8tanNvbicpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcubWFwLm9mJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNy5tYXAuZnJvbScpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi9tb2R1bGVzL19jb3JlJykuTWFwO1xuIiwiLy8gNy4yLjIgSXNBcnJheShhcmd1bWVudClcbnZhciBjb2YgPSByZXF1aXJlKCcuL19jb2YnKTtcbm1vZHVsZS5leHBvcnRzID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiBpc0FycmF5KGFyZykge1xuICByZXR1cm4gY29mKGFyZykgPT0gJ0FycmF5Jztcbn07XG4iLCJ2YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL19pcy1vYmplY3QnKTtcbnZhciBpc0FycmF5ID0gcmVxdWlyZSgnLi9faXMtYXJyYXknKTtcbnZhciBTUEVDSUVTID0gcmVxdWlyZSgnLi9fd2tzJykoJ3NwZWNpZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob3JpZ2luYWwpIHtcbiAgdmFyIEM7XG4gIGlmIChpc0FycmF5KG9yaWdpbmFsKSkge1xuICAgIEMgPSBvcmlnaW5hbC5jb25zdHJ1Y3RvcjtcbiAgICAvLyBjcm9zcy1yZWFsbSBmYWxsYmFja1xuICAgIGlmICh0eXBlb2YgQyA9PSAnZnVuY3Rpb24nICYmIChDID09PSBBcnJheSB8fCBpc0FycmF5KEMucHJvdG90eXBlKSkpIEMgPSB1bmRlZmluZWQ7XG4gICAgaWYgKGlzT2JqZWN0KEMpKSB7XG4gICAgICBDID0gQ1tTUEVDSUVTXTtcbiAgICAgIGlmIChDID09PSBudWxsKSBDID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfSByZXR1cm4gQyA9PT0gdW5kZWZpbmVkID8gQXJyYXkgOiBDO1xufTtcbiIsIi8vIDkuNC4yLjMgQXJyYXlTcGVjaWVzQ3JlYXRlKG9yaWdpbmFsQXJyYXksIGxlbmd0aClcbnZhciBzcGVjaWVzQ29uc3RydWN0b3IgPSByZXF1aXJlKCcuL19hcnJheS1zcGVjaWVzLWNvbnN0cnVjdG9yJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9yaWdpbmFsLCBsZW5ndGgpIHtcbiAgcmV0dXJuIG5ldyAoc3BlY2llc0NvbnN0cnVjdG9yKG9yaWdpbmFsKSkobGVuZ3RoKTtcbn07XG4iLCIvLyAwIC0+IEFycmF5I2ZvckVhY2hcbi8vIDEgLT4gQXJyYXkjbWFwXG4vLyAyIC0+IEFycmF5I2ZpbHRlclxuLy8gMyAtPiBBcnJheSNzb21lXG4vLyA0IC0+IEFycmF5I2V2ZXJ5XG4vLyA1IC0+IEFycmF5I2ZpbmRcbi8vIDYgLT4gQXJyYXkjZmluZEluZGV4XG52YXIgY3R4ID0gcmVxdWlyZSgnLi9fY3R4Jyk7XG52YXIgSU9iamVjdCA9IHJlcXVpcmUoJy4vX2lvYmplY3QnKTtcbnZhciB0b09iamVjdCA9IHJlcXVpcmUoJy4vX3RvLW9iamVjdCcpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJyk7XG52YXIgYXNjID0gcmVxdWlyZSgnLi9fYXJyYXktc3BlY2llcy1jcmVhdGUnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKFRZUEUsICRjcmVhdGUpIHtcbiAgdmFyIElTX01BUCA9IFRZUEUgPT0gMTtcbiAgdmFyIElTX0ZJTFRFUiA9IFRZUEUgPT0gMjtcbiAgdmFyIElTX1NPTUUgPSBUWVBFID09IDM7XG4gIHZhciBJU19FVkVSWSA9IFRZUEUgPT0gNDtcbiAgdmFyIElTX0ZJTkRfSU5ERVggPSBUWVBFID09IDY7XG4gIHZhciBOT19IT0xFUyA9IFRZUEUgPT0gNSB8fCBJU19GSU5EX0lOREVYO1xuICB2YXIgY3JlYXRlID0gJGNyZWF0ZSB8fCBhc2M7XG4gIHJldHVybiBmdW5jdGlvbiAoJHRoaXMsIGNhbGxiYWNrZm4sIHRoYXQpIHtcbiAgICB2YXIgTyA9IHRvT2JqZWN0KCR0aGlzKTtcbiAgICB2YXIgc2VsZiA9IElPYmplY3QoTyk7XG4gICAgdmFyIGYgPSBjdHgoY2FsbGJhY2tmbiwgdGhhdCwgMyk7XG4gICAgdmFyIGxlbmd0aCA9IHRvTGVuZ3RoKHNlbGYubGVuZ3RoKTtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHZhciByZXN1bHQgPSBJU19NQVAgPyBjcmVhdGUoJHRoaXMsIGxlbmd0aCkgOiBJU19GSUxURVIgPyBjcmVhdGUoJHRoaXMsIDApIDogdW5kZWZpbmVkO1xuICAgIHZhciB2YWwsIHJlcztcbiAgICBmb3IgKDtsZW5ndGggPiBpbmRleDsgaW5kZXgrKykgaWYgKE5PX0hPTEVTIHx8IGluZGV4IGluIHNlbGYpIHtcbiAgICAgIHZhbCA9IHNlbGZbaW5kZXhdO1xuICAgICAgcmVzID0gZih2YWwsIGluZGV4LCBPKTtcbiAgICAgIGlmIChUWVBFKSB7XG4gICAgICAgIGlmIChJU19NQVApIHJlc3VsdFtpbmRleF0gPSByZXM7ICAgLy8gbWFwXG4gICAgICAgIGVsc2UgaWYgKHJlcykgc3dpdGNoIChUWVBFKSB7XG4gICAgICAgICAgY2FzZSAzOiByZXR1cm4gdHJ1ZTsgICAgICAgICAgICAgLy8gc29tZVxuICAgICAgICAgIGNhc2UgNTogcmV0dXJuIHZhbDsgICAgICAgICAgICAgIC8vIGZpbmRcbiAgICAgICAgICBjYXNlIDY6IHJldHVybiBpbmRleDsgICAgICAgICAgICAvLyBmaW5kSW5kZXhcbiAgICAgICAgICBjYXNlIDI6IHJlc3VsdC5wdXNoKHZhbCk7ICAgICAgICAvLyBmaWx0ZXJcbiAgICAgICAgfSBlbHNlIGlmIChJU19FVkVSWSkgcmV0dXJuIGZhbHNlOyAvLyBldmVyeVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gSVNfRklORF9JTkRFWCA/IC0xIDogSVNfU09NRSB8fCBJU19FVkVSWSA/IElTX0VWRVJZIDogcmVzdWx0O1xuICB9O1xufTtcbiIsImV4cG9ydHMuZiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHM7XG4iLCIndXNlIHN0cmljdCc7XG4vLyAxOS4xLjIuMSBPYmplY3QuYXNzaWduKHRhcmdldCwgc291cmNlLCAuLi4pXG52YXIgZ2V0S2V5cyA9IHJlcXVpcmUoJy4vX29iamVjdC1rZXlzJyk7XG52YXIgZ09QUyA9IHJlcXVpcmUoJy4vX29iamVjdC1nb3BzJyk7XG52YXIgcElFID0gcmVxdWlyZSgnLi9fb2JqZWN0LXBpZScpO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0Jyk7XG52YXIgSU9iamVjdCA9IHJlcXVpcmUoJy4vX2lvYmplY3QnKTtcbnZhciAkYXNzaWduID0gT2JqZWN0LmFzc2lnbjtcblxuLy8gc2hvdWxkIHdvcmsgd2l0aCBzeW1ib2xzIGFuZCBzaG91bGQgaGF2ZSBkZXRlcm1pbmlzdGljIHByb3BlcnR5IG9yZGVyIChWOCBidWcpXG5tb2R1bGUuZXhwb3J0cyA9ICEkYXNzaWduIHx8IHJlcXVpcmUoJy4vX2ZhaWxzJykoZnVuY3Rpb24gKCkge1xuICB2YXIgQSA9IHt9O1xuICB2YXIgQiA9IHt9O1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW5kZWZcbiAgdmFyIFMgPSBTeW1ib2woKTtcbiAgdmFyIEsgPSAnYWJjZGVmZ2hpamtsbW5vcHFyc3QnO1xuICBBW1NdID0gNztcbiAgSy5zcGxpdCgnJykuZm9yRWFjaChmdW5jdGlvbiAoaykgeyBCW2tdID0gazsgfSk7XG4gIHJldHVybiAkYXNzaWduKHt9LCBBKVtTXSAhPSA3IHx8IE9iamVjdC5rZXlzKCRhc3NpZ24oe30sIEIpKS5qb2luKCcnKSAhPSBLO1xufSkgPyBmdW5jdGlvbiBhc3NpZ24odGFyZ2V0LCBzb3VyY2UpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bnVzZWQtdmFyc1xuICB2YXIgVCA9IHRvT2JqZWN0KHRhcmdldCk7XG4gIHZhciBhTGVuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgdmFyIGluZGV4ID0gMTtcbiAgdmFyIGdldFN5bWJvbHMgPSBnT1BTLmY7XG4gIHZhciBpc0VudW0gPSBwSUUuZjtcbiAgd2hpbGUgKGFMZW4gPiBpbmRleCkge1xuICAgIHZhciBTID0gSU9iamVjdChhcmd1bWVudHNbaW5kZXgrK10pO1xuICAgIHZhciBrZXlzID0gZ2V0U3ltYm9scyA/IGdldEtleXMoUykuY29uY2F0KGdldFN5bWJvbHMoUykpIDogZ2V0S2V5cyhTKTtcbiAgICB2YXIgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgdmFyIGogPSAwO1xuICAgIHZhciBrZXk7XG4gICAgd2hpbGUgKGxlbmd0aCA+IGopIGlmIChpc0VudW0uY2FsbChTLCBrZXkgPSBrZXlzW2orK10pKSBUW2tleV0gPSBTW2tleV07XG4gIH0gcmV0dXJuIFQ7XG59IDogJGFzc2lnbjtcbiIsIid1c2Ugc3RyaWN0JztcbnZhciByZWRlZmluZUFsbCA9IHJlcXVpcmUoJy4vX3JlZGVmaW5lLWFsbCcpO1xudmFyIGdldFdlYWsgPSByZXF1aXJlKCcuL19tZXRhJykuZ2V0V2VhaztcbnZhciBhbk9iamVjdCA9IHJlcXVpcmUoJy4vX2FuLW9iamVjdCcpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9faXMtb2JqZWN0Jyk7XG52YXIgYW5JbnN0YW5jZSA9IHJlcXVpcmUoJy4vX2FuLWluc3RhbmNlJyk7XG52YXIgZm9yT2YgPSByZXF1aXJlKCcuL19mb3Itb2YnKTtcbnZhciBjcmVhdGVBcnJheU1ldGhvZCA9IHJlcXVpcmUoJy4vX2FycmF5LW1ldGhvZHMnKTtcbnZhciAkaGFzID0gcmVxdWlyZSgnLi9faGFzJyk7XG52YXIgdmFsaWRhdGUgPSByZXF1aXJlKCcuL192YWxpZGF0ZS1jb2xsZWN0aW9uJyk7XG52YXIgYXJyYXlGaW5kID0gY3JlYXRlQXJyYXlNZXRob2QoNSk7XG52YXIgYXJyYXlGaW5kSW5kZXggPSBjcmVhdGVBcnJheU1ldGhvZCg2KTtcbnZhciBpZCA9IDA7XG5cbi8vIGZhbGxiYWNrIGZvciB1bmNhdWdodCBmcm96ZW4ga2V5c1xudmFyIHVuY2F1Z2h0RnJvemVuU3RvcmUgPSBmdW5jdGlvbiAodGhhdCkge1xuICByZXR1cm4gdGhhdC5fbCB8fCAodGhhdC5fbCA9IG5ldyBVbmNhdWdodEZyb3plblN0b3JlKCkpO1xufTtcbnZhciBVbmNhdWdodEZyb3plblN0b3JlID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmEgPSBbXTtcbn07XG52YXIgZmluZFVuY2F1Z2h0RnJvemVuID0gZnVuY3Rpb24gKHN0b3JlLCBrZXkpIHtcbiAgcmV0dXJuIGFycmF5RmluZChzdG9yZS5hLCBmdW5jdGlvbiAoaXQpIHtcbiAgICByZXR1cm4gaXRbMF0gPT09IGtleTtcbiAgfSk7XG59O1xuVW5jYXVnaHRGcm96ZW5TdG9yZS5wcm90b3R5cGUgPSB7XG4gIGdldDogZnVuY3Rpb24gKGtleSkge1xuICAgIHZhciBlbnRyeSA9IGZpbmRVbmNhdWdodEZyb3plbih0aGlzLCBrZXkpO1xuICAgIGlmIChlbnRyeSkgcmV0dXJuIGVudHJ5WzFdO1xuICB9LFxuICBoYXM6IGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4gISFmaW5kVW5jYXVnaHRGcm96ZW4odGhpcywga2V5KTtcbiAgfSxcbiAgc2V0OiBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xuICAgIHZhciBlbnRyeSA9IGZpbmRVbmNhdWdodEZyb3plbih0aGlzLCBrZXkpO1xuICAgIGlmIChlbnRyeSkgZW50cnlbMV0gPSB2YWx1ZTtcbiAgICBlbHNlIHRoaXMuYS5wdXNoKFtrZXksIHZhbHVlXSk7XG4gIH0sXG4gICdkZWxldGUnOiBmdW5jdGlvbiAoa2V5KSB7XG4gICAgdmFyIGluZGV4ID0gYXJyYXlGaW5kSW5kZXgodGhpcy5hLCBmdW5jdGlvbiAoaXQpIHtcbiAgICAgIHJldHVybiBpdFswXSA9PT0ga2V5O1xuICAgIH0pO1xuICAgIGlmICh+aW5kZXgpIHRoaXMuYS5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIHJldHVybiAhIX5pbmRleDtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGdldENvbnN0cnVjdG9yOiBmdW5jdGlvbiAod3JhcHBlciwgTkFNRSwgSVNfTUFQLCBBRERFUikge1xuICAgIHZhciBDID0gd3JhcHBlcihmdW5jdGlvbiAodGhhdCwgaXRlcmFibGUpIHtcbiAgICAgIGFuSW5zdGFuY2UodGhhdCwgQywgTkFNRSwgJ19pJyk7XG4gICAgICB0aGF0Ll90ID0gTkFNRTsgICAgICAvLyBjb2xsZWN0aW9uIHR5cGVcbiAgICAgIHRoYXQuX2kgPSBpZCsrOyAgICAgIC8vIGNvbGxlY3Rpb24gaWRcbiAgICAgIHRoYXQuX2wgPSB1bmRlZmluZWQ7IC8vIGxlYWsgc3RvcmUgZm9yIHVuY2F1Z2h0IGZyb3plbiBvYmplY3RzXG4gICAgICBpZiAoaXRlcmFibGUgIT0gdW5kZWZpbmVkKSBmb3JPZihpdGVyYWJsZSwgSVNfTUFQLCB0aGF0W0FEREVSXSwgdGhhdCk7XG4gICAgfSk7XG4gICAgcmVkZWZpbmVBbGwoQy5wcm90b3R5cGUsIHtcbiAgICAgIC8vIDIzLjMuMy4yIFdlYWtNYXAucHJvdG90eXBlLmRlbGV0ZShrZXkpXG4gICAgICAvLyAyMy40LjMuMyBXZWFrU2V0LnByb3RvdHlwZS5kZWxldGUodmFsdWUpXG4gICAgICAnZGVsZXRlJzogZnVuY3Rpb24gKGtleSkge1xuICAgICAgICBpZiAoIWlzT2JqZWN0KGtleSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgdmFyIGRhdGEgPSBnZXRXZWFrKGtleSk7XG4gICAgICAgIGlmIChkYXRhID09PSB0cnVlKSByZXR1cm4gdW5jYXVnaHRGcm96ZW5TdG9yZSh2YWxpZGF0ZSh0aGlzLCBOQU1FKSlbJ2RlbGV0ZSddKGtleSk7XG4gICAgICAgIHJldHVybiBkYXRhICYmICRoYXMoZGF0YSwgdGhpcy5faSkgJiYgZGVsZXRlIGRhdGFbdGhpcy5faV07XG4gICAgICB9LFxuICAgICAgLy8gMjMuMy4zLjQgV2Vha01hcC5wcm90b3R5cGUuaGFzKGtleSlcbiAgICAgIC8vIDIzLjQuMy40IFdlYWtTZXQucHJvdG90eXBlLmhhcyh2YWx1ZSlcbiAgICAgIGhhczogZnVuY3Rpb24gaGFzKGtleSkge1xuICAgICAgICBpZiAoIWlzT2JqZWN0KGtleSkpIHJldHVybiBmYWxzZTtcbiAgICAgICAgdmFyIGRhdGEgPSBnZXRXZWFrKGtleSk7XG4gICAgICAgIGlmIChkYXRhID09PSB0cnVlKSByZXR1cm4gdW5jYXVnaHRGcm96ZW5TdG9yZSh2YWxpZGF0ZSh0aGlzLCBOQU1FKSkuaGFzKGtleSk7XG4gICAgICAgIHJldHVybiBkYXRhICYmICRoYXMoZGF0YSwgdGhpcy5faSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIEM7XG4gIH0sXG4gIGRlZjogZnVuY3Rpb24gKHRoYXQsIGtleSwgdmFsdWUpIHtcbiAgICB2YXIgZGF0YSA9IGdldFdlYWsoYW5PYmplY3Qoa2V5KSwgdHJ1ZSk7XG4gICAgaWYgKGRhdGEgPT09IHRydWUpIHVuY2F1Z2h0RnJvemVuU3RvcmUodGhhdCkuc2V0KGtleSwgdmFsdWUpO1xuICAgIGVsc2UgZGF0YVt0aGF0Ll9pXSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGF0O1xuICB9LFxuICB1ZnN0b3JlOiB1bmNhdWdodEZyb3plblN0b3JlXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xudmFyIGVhY2ggPSByZXF1aXJlKCcuL19hcnJheS1tZXRob2RzJykoMCk7XG52YXIgcmVkZWZpbmUgPSByZXF1aXJlKCcuL19yZWRlZmluZScpO1xudmFyIG1ldGEgPSByZXF1aXJlKCcuL19tZXRhJyk7XG52YXIgYXNzaWduID0gcmVxdWlyZSgnLi9fb2JqZWN0LWFzc2lnbicpO1xudmFyIHdlYWsgPSByZXF1aXJlKCcuL19jb2xsZWN0aW9uLXdlYWsnKTtcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xudmFyIGZhaWxzID0gcmVxdWlyZSgnLi9fZmFpbHMnKTtcbnZhciB2YWxpZGF0ZSA9IHJlcXVpcmUoJy4vX3ZhbGlkYXRlLWNvbGxlY3Rpb24nKTtcbnZhciBXRUFLX01BUCA9ICdXZWFrTWFwJztcbnZhciBnZXRXZWFrID0gbWV0YS5nZXRXZWFrO1xudmFyIGlzRXh0ZW5zaWJsZSA9IE9iamVjdC5pc0V4dGVuc2libGU7XG52YXIgdW5jYXVnaHRGcm96ZW5TdG9yZSA9IHdlYWsudWZzdG9yZTtcbnZhciB0bXAgPSB7fTtcbnZhciBJbnRlcm5hbE1hcDtcblxudmFyIHdyYXBwZXIgPSBmdW5jdGlvbiAoZ2V0KSB7XG4gIHJldHVybiBmdW5jdGlvbiBXZWFrTWFwKCkge1xuICAgIHJldHVybiBnZXQodGhpcywgYXJndW1lbnRzLmxlbmd0aCA+IDAgPyBhcmd1bWVudHNbMF0gOiB1bmRlZmluZWQpO1xuICB9O1xufTtcblxudmFyIG1ldGhvZHMgPSB7XG4gIC8vIDIzLjMuMy4zIFdlYWtNYXAucHJvdG90eXBlLmdldChrZXkpXG4gIGdldDogZnVuY3Rpb24gZ2V0KGtleSkge1xuICAgIGlmIChpc09iamVjdChrZXkpKSB7XG4gICAgICB2YXIgZGF0YSA9IGdldFdlYWsoa2V5KTtcbiAgICAgIGlmIChkYXRhID09PSB0cnVlKSByZXR1cm4gdW5jYXVnaHRGcm96ZW5TdG9yZSh2YWxpZGF0ZSh0aGlzLCBXRUFLX01BUCkpLmdldChrZXkpO1xuICAgICAgcmV0dXJuIGRhdGEgPyBkYXRhW3RoaXMuX2ldIDogdW5kZWZpbmVkO1xuICAgIH1cbiAgfSxcbiAgLy8gMjMuMy4zLjUgV2Vha01hcC5wcm90b3R5cGUuc2V0KGtleSwgdmFsdWUpXG4gIHNldDogZnVuY3Rpb24gc2V0KGtleSwgdmFsdWUpIHtcbiAgICByZXR1cm4gd2Vhay5kZWYodmFsaWRhdGUodGhpcywgV0VBS19NQVApLCBrZXksIHZhbHVlKTtcbiAgfVxufTtcblxuLy8gMjMuMyBXZWFrTWFwIE9iamVjdHNcbnZhciAkV2Vha01hcCA9IG1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29sbGVjdGlvbicpKFdFQUtfTUFQLCB3cmFwcGVyLCBtZXRob2RzLCB3ZWFrLCB0cnVlLCB0cnVlKTtcblxuLy8gSUUxMSBXZWFrTWFwIGZyb3plbiBrZXlzIGZpeFxuaWYgKGZhaWxzKGZ1bmN0aW9uICgpIHsgcmV0dXJuIG5ldyAkV2Vha01hcCgpLnNldCgoT2JqZWN0LmZyZWV6ZSB8fCBPYmplY3QpKHRtcCksIDcpLmdldCh0bXApICE9IDc7IH0pKSB7XG4gIEludGVybmFsTWFwID0gd2Vhay5nZXRDb25zdHJ1Y3Rvcih3cmFwcGVyLCBXRUFLX01BUCk7XG4gIGFzc2lnbihJbnRlcm5hbE1hcC5wcm90b3R5cGUsIG1ldGhvZHMpO1xuICBtZXRhLk5FRUQgPSB0cnVlO1xuICBlYWNoKFsnZGVsZXRlJywgJ2hhcycsICdnZXQnLCAnc2V0J10sIGZ1bmN0aW9uIChrZXkpIHtcbiAgICB2YXIgcHJvdG8gPSAkV2Vha01hcC5wcm90b3R5cGU7XG4gICAgdmFyIG1ldGhvZCA9IHByb3RvW2tleV07XG4gICAgcmVkZWZpbmUocHJvdG8sIGtleSwgZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgIC8vIHN0b3JlIGZyb3plbiBvYmplY3RzIG9uIGludGVybmFsIHdlYWttYXAgc2hpbVxuICAgICAgaWYgKGlzT2JqZWN0KGEpICYmICFpc0V4dGVuc2libGUoYSkpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9mKSB0aGlzLl9mID0gbmV3IEludGVybmFsTWFwKCk7XG4gICAgICAgIHZhciByZXN1bHQgPSB0aGlzLl9mW2tleV0oYSwgYik7XG4gICAgICAgIHJldHVybiBrZXkgPT0gJ3NldCcgPyB0aGlzIDogcmVzdWx0O1xuICAgICAgLy8gc3RvcmUgYWxsIHRoZSByZXN0IG9uIG5hdGl2ZSB3ZWFrbWFwXG4gICAgICB9IHJldHVybiBtZXRob2QuY2FsbCh0aGlzLCBhLCBiKTtcbiAgICB9KTtcbiAgfSk7XG59XG4iLCIvLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL3Byb3Bvc2FsLXNldG1hcC1vZmZyb20vI3NlYy13ZWFrbWFwLm9mXG5yZXF1aXJlKCcuL19zZXQtY29sbGVjdGlvbi1vZicpKCdXZWFrTWFwJyk7XG4iLCIvLyBodHRwczovL3RjMzkuZ2l0aHViLmlvL3Byb3Bvc2FsLXNldG1hcC1vZmZyb20vI3NlYy13ZWFrbWFwLmZyb21cbnJlcXVpcmUoJy4vX3NldC1jb2xsZWN0aW9uLWZyb20nKSgnV2Vha01hcCcpO1xuIiwicmVxdWlyZSgnLi4vbW9kdWxlcy9lczYub2JqZWN0LnRvLXN0cmluZycpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy93ZWIuZG9tLml0ZXJhYmxlJyk7XG5yZXF1aXJlKCcuLi9tb2R1bGVzL2VzNi53ZWFrLW1hcCcpO1xucmVxdWlyZSgnLi4vbW9kdWxlcy9lczcud2Vhay1tYXAub2YnKTtcbnJlcXVpcmUoJy4uL21vZHVsZXMvZXM3LndlYWstbWFwLmZyb20nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vbW9kdWxlcy9fY29yZScpLldlYWtNYXA7XG4iLCIndXNlIHN0cmljdCc7XG52YXIgJGRlZmluZVByb3BlcnR5ID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJyk7XG52YXIgY3JlYXRlRGVzYyA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqZWN0LCBpbmRleCwgdmFsdWUpIHtcbiAgaWYgKGluZGV4IGluIG9iamVjdCkgJGRlZmluZVByb3BlcnR5LmYob2JqZWN0LCBpbmRleCwgY3JlYXRlRGVzYygwLCB2YWx1ZSkpO1xuICBlbHNlIG9iamVjdFtpbmRleF0gPSB2YWx1ZTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG52YXIgY3R4ID0gcmVxdWlyZSgnLi9fY3R4Jyk7XG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xudmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8tb2JqZWN0Jyk7XG52YXIgY2FsbCA9IHJlcXVpcmUoJy4vX2l0ZXItY2FsbCcpO1xudmFyIGlzQXJyYXlJdGVyID0gcmVxdWlyZSgnLi9faXMtYXJyYXktaXRlcicpO1xudmFyIHRvTGVuZ3RoID0gcmVxdWlyZSgnLi9fdG8tbGVuZ3RoJyk7XG52YXIgY3JlYXRlUHJvcGVydHkgPSByZXF1aXJlKCcuL19jcmVhdGUtcHJvcGVydHknKTtcbnZhciBnZXRJdGVyRm4gPSByZXF1aXJlKCcuL2NvcmUuZ2V0LWl0ZXJhdG9yLW1ldGhvZCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiAqICFyZXF1aXJlKCcuL19pdGVyLWRldGVjdCcpKGZ1bmN0aW9uIChpdGVyKSB7IEFycmF5LmZyb20oaXRlcik7IH0pLCAnQXJyYXknLCB7XG4gIC8vIDIyLjEuMi4xIEFycmF5LmZyb20oYXJyYXlMaWtlLCBtYXBmbiA9IHVuZGVmaW5lZCwgdGhpc0FyZyA9IHVuZGVmaW5lZClcbiAgZnJvbTogZnVuY3Rpb24gZnJvbShhcnJheUxpa2UgLyogLCBtYXBmbiA9IHVuZGVmaW5lZCwgdGhpc0FyZyA9IHVuZGVmaW5lZCAqLykge1xuICAgIHZhciBPID0gdG9PYmplY3QoYXJyYXlMaWtlKTtcbiAgICB2YXIgQyA9IHR5cGVvZiB0aGlzID09ICdmdW5jdGlvbicgPyB0aGlzIDogQXJyYXk7XG4gICAgdmFyIGFMZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgIHZhciBtYXBmbiA9IGFMZW4gPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkO1xuICAgIHZhciBtYXBwaW5nID0gbWFwZm4gIT09IHVuZGVmaW5lZDtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHZhciBpdGVyRm4gPSBnZXRJdGVyRm4oTyk7XG4gICAgdmFyIGxlbmd0aCwgcmVzdWx0LCBzdGVwLCBpdGVyYXRvcjtcbiAgICBpZiAobWFwcGluZykgbWFwZm4gPSBjdHgobWFwZm4sIGFMZW4gPiAyID8gYXJndW1lbnRzWzJdIDogdW5kZWZpbmVkLCAyKTtcbiAgICAvLyBpZiBvYmplY3QgaXNuJ3QgaXRlcmFibGUgb3IgaXQncyBhcnJheSB3aXRoIGRlZmF1bHQgaXRlcmF0b3IgLSB1c2Ugc2ltcGxlIGNhc2VcbiAgICBpZiAoaXRlckZuICE9IHVuZGVmaW5lZCAmJiAhKEMgPT0gQXJyYXkgJiYgaXNBcnJheUl0ZXIoaXRlckZuKSkpIHtcbiAgICAgIGZvciAoaXRlcmF0b3IgPSBpdGVyRm4uY2FsbChPKSwgcmVzdWx0ID0gbmV3IEMoKTsgIShzdGVwID0gaXRlcmF0b3IubmV4dCgpKS5kb25lOyBpbmRleCsrKSB7XG4gICAgICAgIGNyZWF0ZVByb3BlcnR5KHJlc3VsdCwgaW5kZXgsIG1hcHBpbmcgPyBjYWxsKGl0ZXJhdG9yLCBtYXBmbiwgW3N0ZXAudmFsdWUsIGluZGV4XSwgdHJ1ZSkgOiBzdGVwLnZhbHVlKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGVuZ3RoID0gdG9MZW5ndGgoTy5sZW5ndGgpO1xuICAgICAgZm9yIChyZXN1bHQgPSBuZXcgQyhsZW5ndGgpOyBsZW5ndGggPiBpbmRleDsgaW5kZXgrKykge1xuICAgICAgICBjcmVhdGVQcm9wZXJ0eShyZXN1bHQsIGluZGV4LCBtYXBwaW5nID8gbWFwZm4oT1tpbmRleF0sIGluZGV4KSA6IE9baW5kZXhdKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmVzdWx0Lmxlbmd0aCA9IGluZGV4O1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn0pO1xuIiwicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi8uLi9tb2R1bGVzL2VzNi5hcnJheS5mcm9tJyk7XG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4uLy4uL21vZHVsZXMvX2NvcmUnKS5BcnJheS5mcm9tO1xuIiwiY29uc3QgcmVzZXJ2ZWRUYWdMaXN0ID0gbmV3IFNldChbXG4gICdhbm5vdGF0aW9uLXhtbCcsXG4gICdjb2xvci1wcm9maWxlJyxcbiAgJ2ZvbnQtZmFjZScsXG4gICdmb250LWZhY2Utc3JjJyxcbiAgJ2ZvbnQtZmFjZS11cmknLFxuICAnZm9udC1mYWNlLWZvcm1hdCcsXG4gICdmb250LWZhY2UtbmFtZScsXG4gICdtaXNzaW5nLWdseXBoJyxcbl0pO1xuXG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhbE5hbWVcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEN1c3RvbUVsZW1lbnROYW1lKGxvY2FsTmFtZSkge1xuICBjb25zdCByZXNlcnZlZCA9IHJlc2VydmVkVGFnTGlzdC5oYXMobG9jYWxOYW1lKTtcbiAgY29uc3QgdmFsaWRGb3JtID0gL15bYS16XVsuMC05X2Etel0qLVtcXC0uMC05X2Etel0qJC8udGVzdChsb2NhbE5hbWUpO1xuICByZXR1cm4gIXJlc2VydmVkICYmIHZhbGlkRm9ybTtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHshTm9kZX0gbm9kZVxuICogQHJldHVybiB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQ29ubmVjdGVkKG5vZGUpIHtcbiAgLy8gVXNlIGBOb2RlI2lzQ29ubmVjdGVkYCwgaWYgZGVmaW5lZC5cbiAgY29uc3QgbmF0aXZlVmFsdWUgPSBub2RlLmlzQ29ubmVjdGVkO1xuICBpZiAobmF0aXZlVmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBuYXRpdmVWYWx1ZTtcbiAgfVxuXG4gIC8qKiBAdHlwZSB7P05vZGV8dW5kZWZpbmVkfSAqL1xuICBsZXQgY3VycmVudCA9IG5vZGU7XG4gIHdoaWxlIChjdXJyZW50ICYmICEoY3VycmVudC5fX0NFX2lzSW1wb3J0RG9jdW1lbnQgfHwgY3VycmVudCBpbnN0YW5jZW9mIERvY3VtZW50KSkge1xuICAgIGN1cnJlbnQgPSBjdXJyZW50LnBhcmVudE5vZGUgfHwgKHdpbmRvdy5TaGFkb3dSb290ICYmIGN1cnJlbnQgaW5zdGFuY2VvZiBTaGFkb3dSb290ID8gY3VycmVudC5ob3N0IDogdW5kZWZpbmVkKTtcbiAgfVxuICByZXR1cm4gISEoY3VycmVudCAmJiAoY3VycmVudC5fX0NFX2lzSW1wb3J0RG9jdW1lbnQgfHwgY3VycmVudCBpbnN0YW5jZW9mIERvY3VtZW50KSk7XG59XG5cbi8qKlxuICogQHBhcmFtIHshTm9kZX0gcm9vdFxuICogQHBhcmFtIHshTm9kZX0gc3RhcnRcbiAqIEByZXR1cm4gez9Ob2RlfVxuICovXG5mdW5jdGlvbiBuZXh0U2libGluZ09yQW5jZXN0b3JTaWJsaW5nKHJvb3QsIHN0YXJ0KSB7XG4gIGxldCBub2RlID0gc3RhcnQ7XG4gIHdoaWxlIChub2RlICYmIG5vZGUgIT09IHJvb3QgJiYgIW5vZGUubmV4dFNpYmxpbmcpIHtcbiAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlO1xuICB9XG4gIHJldHVybiAoIW5vZGUgfHwgbm9kZSA9PT0gcm9vdCkgPyBudWxsIDogbm9kZS5uZXh0U2libGluZztcbn1cblxuLyoqXG4gKiBAcGFyYW0geyFOb2RlfSByb290XG4gKiBAcGFyYW0geyFOb2RlfSBzdGFydFxuICogQHJldHVybiB7P05vZGV9XG4gKi9cbmZ1bmN0aW9uIG5leHROb2RlKHJvb3QsIHN0YXJ0KSB7XG4gIHJldHVybiBzdGFydC5maXJzdENoaWxkID8gc3RhcnQuZmlyc3RDaGlsZCA6IG5leHRTaWJsaW5nT3JBbmNlc3RvclNpYmxpbmcocm9vdCwgc3RhcnQpO1xufVxuXG4vKipcbiAqIEBwYXJhbSB7IU5vZGV9IHJvb3RcbiAqIEBwYXJhbSB7IWZ1bmN0aW9uKCFFbGVtZW50KX0gY2FsbGJhY2tcbiAqIEBwYXJhbSB7IVNldDxOb2RlPj19IHZpc2l0ZWRJbXBvcnRzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3YWxrRGVlcERlc2NlbmRhbnRFbGVtZW50cyhyb290LCBjYWxsYmFjaywgdmlzaXRlZEltcG9ydHMgPSBuZXcgU2V0KCkpIHtcbiAgbGV0IG5vZGUgPSByb290O1xuICB3aGlsZSAobm9kZSkge1xuICAgIGlmIChub2RlLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xuICAgICAgY29uc3QgZWxlbWVudCA9IC8qKiBAdHlwZSB7IUVsZW1lbnR9ICovKG5vZGUpO1xuXG4gICAgICBjYWxsYmFjayhlbGVtZW50KTtcblxuICAgICAgY29uc3QgbG9jYWxOYW1lID0gZWxlbWVudC5sb2NhbE5hbWU7XG4gICAgICBpZiAobG9jYWxOYW1lID09PSAnbGluaycgJiYgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3JlbCcpID09PSAnaW1wb3J0Jykge1xuICAgICAgICAvLyBJZiB0aGlzIGltcG9ydCAocG9seWZpbGxlZCBvciBub3QpIGhhcyBpdCdzIHJvb3Qgbm9kZSBhdmFpbGFibGUsXG4gICAgICAgIC8vIHdhbGsgaXQuXG4gICAgICAgIGNvbnN0IGltcG9ydE5vZGUgPSAvKiogQHR5cGUgeyFOb2RlfSAqLyAoZWxlbWVudC5pbXBvcnQpO1xuICAgICAgICBpZiAoaW1wb3J0Tm9kZSBpbnN0YW5jZW9mIE5vZGUgJiYgIXZpc2l0ZWRJbXBvcnRzLmhhcyhpbXBvcnROb2RlKSkge1xuICAgICAgICAgIC8vIFByZXZlbnQgbXVsdGlwbGUgd2Fsa3Mgb2YgdGhlIHNhbWUgaW1wb3J0IHJvb3QuXG4gICAgICAgICAgdmlzaXRlZEltcG9ydHMuYWRkKGltcG9ydE5vZGUpO1xuXG4gICAgICAgICAgZm9yIChsZXQgY2hpbGQgPSBpbXBvcnROb2RlLmZpcnN0Q2hpbGQ7IGNoaWxkOyBjaGlsZCA9IGNoaWxkLm5leHRTaWJsaW5nKSB7XG4gICAgICAgICAgICB3YWxrRGVlcERlc2NlbmRhbnRFbGVtZW50cyhjaGlsZCwgY2FsbGJhY2ssIHZpc2l0ZWRJbXBvcnRzKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZ25vcmUgZGVzY2VuZGFudHMgb2YgaW1wb3J0IGxpbmtzIHRvIHByZXZlbnQgYXR0ZW1wdGluZyB0byB3YWxrIHRoZVxuICAgICAgICAvLyBlbGVtZW50cyBjcmVhdGVkIGJ5IHRoZSBIVE1MIEltcG9ydHMgcG9seWZpbGwgdGhhdCB3ZSBqdXN0IHdhbGtlZFxuICAgICAgICAvLyBhYm92ZS5cbiAgICAgICAgbm9kZSA9IG5leHRTaWJsaW5nT3JBbmNlc3RvclNpYmxpbmcocm9vdCwgZWxlbWVudCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfSBlbHNlIGlmIChsb2NhbE5hbWUgPT09ICd0ZW1wbGF0ZScpIHtcbiAgICAgICAgLy8gSWdub3JlIGRlc2NlbmRhbnRzIG9mIHRlbXBsYXRlcy4gVGhlcmUgc2hvdWxkbid0IGJlIGFueSBkZXNjZW5kYW50c1xuICAgICAgICAvLyBiZWNhdXNlIHRoZXkgd2lsbCBiZSBtb3ZlZCBpbnRvIGAuY29udGVudGAgZHVyaW5nIGNvbnN0cnVjdGlvbiBpblxuICAgICAgICAvLyBicm93c2VycyB0aGF0IHN1cHBvcnQgdGVtcGxhdGUgYnV0LCBpbiBjYXNlIHRoZXkgZXhpc3QgYW5kIGFyZSBzdGlsbFxuICAgICAgICAvLyB3YWl0aW5nIHRvIGJlIG1vdmVkIGJ5IGEgcG9seWZpbGwsIHRoZXkgd2lsbCBiZSBpZ25vcmVkLlxuICAgICAgICBub2RlID0gbmV4dFNpYmxpbmdPckFuY2VzdG9yU2libGluZyhyb290LCBlbGVtZW50KTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIC8vIFdhbGsgc2hhZG93IHJvb3RzLlxuICAgICAgY29uc3Qgc2hhZG93Um9vdCA9IGVsZW1lbnQuX19DRV9zaGFkb3dSb290O1xuICAgICAgaWYgKHNoYWRvd1Jvb3QpIHtcbiAgICAgICAgZm9yIChsZXQgY2hpbGQgPSBzaGFkb3dSb290LmZpcnN0Q2hpbGQ7IGNoaWxkOyBjaGlsZCA9IGNoaWxkLm5leHRTaWJsaW5nKSB7XG4gICAgICAgICAgd2Fsa0RlZXBEZXNjZW5kYW50RWxlbWVudHMoY2hpbGQsIGNhbGxiYWNrLCB2aXNpdGVkSW1wb3J0cyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBub2RlID0gbmV4dE5vZGUocm9vdCwgbm9kZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBVc2VkIHRvIHN1cHByZXNzIENsb3N1cmUncyBcIk1vZGlmeWluZyB0aGUgcHJvdG90eXBlIGlzIG9ubHkgYWxsb3dlZCBpZiB0aGVcbiAqIGNvbnN0cnVjdG9yIGlzIGluIHRoZSBzYW1lIHNjb3BlXCIgd2FybmluZyB3aXRob3V0IHVzaW5nXG4gKiBgQHN1cHByZXNzIHtuZXdDaGVja1R5cGVzLCBkdXBsaWNhdGV9YCBiZWNhdXNlIGBuZXdDaGVja1R5cGVzYCBpcyB0b28gYnJvYWQuXG4gKlxuICogQHBhcmFtIHshT2JqZWN0fSBkZXN0aW5hdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFByb3BlcnR5VW5jaGVja2VkKGRlc3RpbmF0aW9uLCBuYW1lLCB2YWx1ZSkge1xuICBkZXN0aW5hdGlvbltuYW1lXSA9IHZhbHVlO1xufVxuIiwiLyoqXG4gKiBAZW51bSB7bnVtYmVyfVxuICovXG5jb25zdCBDdXN0b21FbGVtZW50U3RhdGUgPSB7XG4gIGN1c3RvbTogMSxcbiAgZmFpbGVkOiAyLFxufTtcblxuZXhwb3J0IGRlZmF1bHQgQ3VzdG9tRWxlbWVudFN0YXRlO1xuIiwiaW1wb3J0ICogYXMgVXRpbGl0aWVzIGZyb20gJy4vVXRpbGl0aWVzLmpzJztcbmltcG9ydCBDRVN0YXRlIGZyb20gJy4vQ3VzdG9tRWxlbWVudFN0YXRlLmpzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ3VzdG9tRWxlbWVudEludGVybmFscyB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8qKiBAdHlwZSB7IU1hcDxzdHJpbmcsICFDdXN0b21FbGVtZW50RGVmaW5pdGlvbj59ICovXG4gICAgdGhpcy5fbG9jYWxOYW1lVG9EZWZpbml0aW9uID0gbmV3IE1hcCgpO1xuXG4gICAgLyoqIEB0eXBlIHshTWFwPCFGdW5jdGlvbiwgIUN1c3RvbUVsZW1lbnREZWZpbml0aW9uPn0gKi9cbiAgICB0aGlzLl9jb25zdHJ1Y3RvclRvRGVmaW5pdGlvbiA9IG5ldyBNYXAoKTtcblxuICAgIC8qKiBAdHlwZSB7IUFycmF5PCFmdW5jdGlvbighTm9kZSk+fSAqL1xuICAgIHRoaXMuX3BhdGNoZXMgPSBbXTtcblxuICAgIC8qKiBAdHlwZSB7Ym9vbGVhbn0gKi9cbiAgICB0aGlzLl9oYXNQYXRjaGVzID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IGxvY2FsTmFtZVxuICAgKiBAcGFyYW0geyFDdXN0b21FbGVtZW50RGVmaW5pdGlvbn0gZGVmaW5pdGlvblxuICAgKi9cbiAgc2V0RGVmaW5pdGlvbihsb2NhbE5hbWUsIGRlZmluaXRpb24pIHtcbiAgICB0aGlzLl9sb2NhbE5hbWVUb0RlZmluaXRpb24uc2V0KGxvY2FsTmFtZSwgZGVmaW5pdGlvbik7XG4gICAgdGhpcy5fY29uc3RydWN0b3JUb0RlZmluaXRpb24uc2V0KGRlZmluaXRpb24uY29uc3RydWN0b3IsIGRlZmluaXRpb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhbE5hbWVcbiAgICogQHJldHVybiB7IUN1c3RvbUVsZW1lbnREZWZpbml0aW9ufHVuZGVmaW5lZH1cbiAgICovXG4gIGxvY2FsTmFtZVRvRGVmaW5pdGlvbihsb2NhbE5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5fbG9jYWxOYW1lVG9EZWZpbml0aW9uLmdldChsb2NhbE5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBjb25zdHJ1Y3RvclxuICAgKiBAcmV0dXJuIHshQ3VzdG9tRWxlbWVudERlZmluaXRpb258dW5kZWZpbmVkfVxuICAgKi9cbiAgY29uc3RydWN0b3JUb0RlZmluaXRpb24oY29uc3RydWN0b3IpIHtcbiAgICByZXR1cm4gdGhpcy5fY29uc3RydWN0b3JUb0RlZmluaXRpb24uZ2V0KGNvbnN0cnVjdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFmdW5jdGlvbighTm9kZSl9IGxpc3RlbmVyXG4gICAqL1xuICBhZGRQYXRjaChsaXN0ZW5lcikge1xuICAgIHRoaXMuX2hhc1BhdGNoZXMgPSB0cnVlO1xuICAgIHRoaXMuX3BhdGNoZXMucHVzaChsaXN0ZW5lcik7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHshTm9kZX0gbm9kZVxuICAgKi9cbiAgcGF0Y2hUcmVlKG5vZGUpIHtcbiAgICBpZiAoIXRoaXMuX2hhc1BhdGNoZXMpIHJldHVybjtcblxuICAgIFV0aWxpdGllcy53YWxrRGVlcERlc2NlbmRhbnRFbGVtZW50cyhub2RlLCBlbGVtZW50ID0+IHRoaXMucGF0Y2goZWxlbWVudCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAgICovXG4gIHBhdGNoKG5vZGUpIHtcbiAgICBpZiAoIXRoaXMuX2hhc1BhdGNoZXMpIHJldHVybjtcblxuICAgIGlmIChub2RlLl9fQ0VfcGF0Y2hlZCkgcmV0dXJuO1xuICAgIG5vZGUuX19DRV9wYXRjaGVkID0gdHJ1ZTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fcGF0Y2hlcy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5fcGF0Y2hlc1tpXShub2RlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHshTm9kZX0gcm9vdFxuICAgKi9cbiAgY29ubmVjdFRyZWUocm9vdCkge1xuICAgIGNvbnN0IGVsZW1lbnRzID0gW107XG5cbiAgICBVdGlsaXRpZXMud2Fsa0RlZXBEZXNjZW5kYW50RWxlbWVudHMocm9vdCwgZWxlbWVudCA9PiBlbGVtZW50cy5wdXNoKGVsZW1lbnQpKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSBlbGVtZW50c1tpXTtcbiAgICAgIGlmIChlbGVtZW50Ll9fQ0Vfc3RhdGUgPT09IENFU3RhdGUuY3VzdG9tKSB7XG4gICAgICAgIGlmIChVdGlsaXRpZXMuaXNDb25uZWN0ZWQoZWxlbWVudCkpIHtcbiAgICAgICAgICB0aGlzLmNvbm5lY3RlZENhbGxiYWNrKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnVwZ3JhZGVFbGVtZW50KGVsZW1lbnQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFOb2RlfSByb290XG4gICAqL1xuICBkaXNjb25uZWN0VHJlZShyb290KSB7XG4gICAgY29uc3QgZWxlbWVudHMgPSBbXTtcblxuICAgIFV0aWxpdGllcy53YWxrRGVlcERlc2NlbmRhbnRFbGVtZW50cyhyb290LCBlbGVtZW50ID0+IGVsZW1lbnRzLnB1c2goZWxlbWVudCkpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBlbGVtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgZWxlbWVudCA9IGVsZW1lbnRzW2ldO1xuICAgICAgaWYgKGVsZW1lbnQuX19DRV9zdGF0ZSA9PT0gQ0VTdGF0ZS5jdXN0b20pIHtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0ZWRDYWxsYmFjayhlbGVtZW50KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBncmFkZXMgYWxsIHVuY3VzdG9taXplZCBjdXN0b20gZWxlbWVudHMgYXQgYW5kIGJlbG93IGEgcm9vdCBub2RlIGZvclxuICAgKiB3aGljaCB0aGVyZSBpcyBhIGRlZmluaXRpb24uIFdoZW4gY3VzdG9tIGVsZW1lbnQgcmVhY3Rpb24gY2FsbGJhY2tzIGFyZVxuICAgKiBhc3N1bWVkIHRvIGJlIGNhbGxlZCBzeW5jaHJvbm91c2x5ICh3aGljaCwgYnkgdGhlIGN1cnJlbnQgRE9NIC8gSFRNTCBzcGVjXG4gICAqIGRlZmluaXRpb25zLCB0aGV5IGFyZSAqbm90KiksIGNhbGxiYWNrcyBmb3IgYm90aCBlbGVtZW50cyBjdXN0b21pemVkXG4gICAqIHN5bmNocm9ub3VzbHkgYnkgdGhlIHBhcnNlciBhbmQgZWxlbWVudHMgYmVpbmcgdXBncmFkZWQgb2NjdXIgaW4gdGhlIHNhbWVcbiAgICogcmVsYXRpdmUgb3JkZXIuXG4gICAqXG4gICAqIE5PVEU6IFRoaXMgZnVuY3Rpb24sIHdoZW4gdXNlZCB0byBzaW11bGF0ZSB0aGUgY29uc3RydWN0aW9uIG9mIGEgdHJlZSB0aGF0XG4gICAqIGlzIGFscmVhZHkgY3JlYXRlZCBidXQgbm90IGN1c3RvbWl6ZWQgKGkuZS4gYnkgdGhlIHBhcnNlciksIGRvZXMgKm5vdCpcbiAgICogcHJldmVudCB0aGUgZWxlbWVudCBmcm9tIHJlYWRpbmcgdGhlICdmaW5hbCcgKHRydWUpIHN0YXRlIG9mIHRoZSB0cmVlLiBGb3JcbiAgICogZXhhbXBsZSwgdGhlIGVsZW1lbnQsIGR1cmluZyB0cnVseSBzeW5jaHJvbm91cyBwYXJzaW5nIC8gY29uc3RydWN0aW9uIHdvdWxkXG4gICAqIHNlZSB0aGF0IGl0IGNvbnRhaW5zIG5vIGNoaWxkcmVuIGFzIHRoZXkgaGF2ZSBub3QgeWV0IGJlZW4gaW5zZXJ0ZWQuXG4gICAqIEhvd2V2ZXIsIHRoaXMgZnVuY3Rpb24gZG9lcyBub3QgbW9kaWZ5IHRoZSB0cmVlLCB0aGUgZWxlbWVudCB3aWxsXG4gICAqIChpbmNvcnJlY3RseSkgaGF2ZSBjaGlsZHJlbi4gQWRkaXRpb25hbGx5LCBzZWxmLW1vZGlmaWNhdGlvbiByZXN0cmljdGlvbnNcbiAgICogZm9yIGN1c3RvbSBlbGVtZW50IGNvbnN0cnVjdG9ycyBpbXBvc2VkIGJ5IHRoZSBET00gc3BlYyBhcmUgKm5vdCogZW5mb3JjZWQuXG4gICAqXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgbmVzdGVkIGxpc3Qgc2hvd3MgdGhlIHN0ZXBzIGV4dGVuZGluZyBkb3duIGZyb20gdGhlIEhUTUxcbiAgICogc3BlYydzIHBhcnNpbmcgc2VjdGlvbiB0aGF0IGNhdXNlIGVsZW1lbnRzIHRvIGJlIHN5bmNocm9ub3VzbHkgY3JlYXRlZCBhbmRcbiAgICogdXBncmFkZWQ6XG4gICAqXG4gICAqIFRoZSBcImluIGJvZHlcIiBpbnNlcnRpb24gbW9kZTpcbiAgICogaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc3ludGF4Lmh0bWwjcGFyc2luZy1tYWluLWluYm9keVxuICAgKiAtIFN3aXRjaCBvbiB0b2tlbjpcbiAgICogICAuLiBvdGhlciBjYXNlcyAuLlxuICAgKiAgIC0+IEFueSBvdGhlciBzdGFydCB0YWdcbiAgICogICAgICAtIFtJbnNlcnQgYW4gSFRNTCBlbGVtZW50XShiZWxvdykgZm9yIHRoZSB0b2tlbi5cbiAgICpcbiAgICogSW5zZXJ0IGFuIEhUTUwgZWxlbWVudDpcbiAgICogaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc3ludGF4Lmh0bWwjaW5zZXJ0LWFuLWh0bWwtZWxlbWVudFxuICAgKiAtIEluc2VydCBhIGZvcmVpZ24gZWxlbWVudCBmb3IgdGhlIHRva2VuIGluIHRoZSBIVE1MIG5hbWVzcGFjZTpcbiAgICogICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9zeW50YXguaHRtbCNpbnNlcnQtYS1mb3JlaWduLWVsZW1lbnRcbiAgICogICAtIENyZWF0ZSBhbiBlbGVtZW50IGZvciBhIHRva2VuOlxuICAgKiAgICAgaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc3ludGF4Lmh0bWwjY3JlYXRlLWFuLWVsZW1lbnQtZm9yLXRoZS10b2tlblxuICAgKiAgICAgLSBXaWxsIGV4ZWN1dGUgc2NyaXB0IGZsYWcgaXMgdHJ1ZT9cbiAgICogICAgICAgLSAoRWxlbWVudCBxdWV1ZSBwdXNoZWQgdG8gdGhlIGN1c3RvbSBlbGVtZW50IHJlYWN0aW9ucyBzdGFjay4pXG4gICAqICAgICAtIENyZWF0ZSBhbiBlbGVtZW50OlxuICAgKiAgICAgICBodHRwczovL2RvbS5zcGVjLndoYXR3Zy5vcmcvI2NvbmNlcHQtY3JlYXRlLWVsZW1lbnRcbiAgICogICAgICAgLSBTeW5jIENFIGZsYWcgaXMgdHJ1ZT9cbiAgICogICAgICAgICAtIENvbnN0cnVjdG9yIGNhbGxlZC5cbiAgICogICAgICAgICAtIFNlbGYtbW9kaWZpY2F0aW9uIHJlc3RyaWN0aW9ucyBlbmZvcmNlZC5cbiAgICogICAgICAgLSBTeW5jIENFIGZsYWcgaXMgZmFsc2U/XG4gICAqICAgICAgICAgLSAoVXBncmFkZSByZWFjdGlvbiBlbnF1ZXVlZC4pXG4gICAqICAgICAtIEF0dHJpYnV0ZXMgYXBwZW5kZWQgdG8gZWxlbWVudC5cbiAgICogICAgICAgKGBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2tgIHJlYWN0aW9ucyBlbnF1ZXVlZC4pXG4gICAqICAgICAtIFdpbGwgZXhlY3V0ZSBzY3JpcHQgZmxhZyBpcyB0cnVlP1xuICAgKiAgICAgICAtIChFbGVtZW50IHF1ZXVlIHBvcHBlZCBmcm9tIHRoZSBjdXN0b20gZWxlbWVudCByZWFjdGlvbnMgc3RhY2suXG4gICAqICAgICAgICAgUmVhY3Rpb25zIGluIHRoZSBwb3BwZWQgc3RhY2sgYXJlIGludm9rZWQuKVxuICAgKiAgIC0gKEVsZW1lbnQgcXVldWUgcHVzaGVkIHRvIHRoZSBjdXN0b20gZWxlbWVudCByZWFjdGlvbnMgc3RhY2suKVxuICAgKiAgIC0gSW5zZXJ0IHRoZSBlbGVtZW50OlxuICAgKiAgICAgaHR0cHM6Ly9kb20uc3BlYy53aGF0d2cub3JnLyNjb25jZXB0LW5vZGUtaW5zZXJ0XG4gICAqICAgICAtIFNoYWRvdy1pbmNsdWRpbmcgZGVzY2VuZGFudHMgYXJlIGNvbm5lY3RlZC4gRHVyaW5nIHBhcnNpbmdcbiAgICogICAgICAgY29uc3RydWN0aW9uLCB0aGVyZSBhcmUgbm8gc2hhZG93LSpleGNsdWRpbmcqIGRlc2NlbmRhbnRzLlxuICAgKiAgICAgICBIb3dldmVyLCB0aGUgY29uc3RydWN0b3IgbWF5IGhhdmUgdmFsaWRseSBhdHRhY2hlZCBhIHNoYWRvd1xuICAgKiAgICAgICB0cmVlIHRvIGl0c2VsZiBhbmQgYWRkZWQgZGVzY2VuZGFudHMgdG8gdGhhdCBzaGFkb3cgdHJlZS5cbiAgICogICAgICAgKGBjb25uZWN0ZWRDYWxsYmFja2AgcmVhY3Rpb25zIGVucXVldWVkLilcbiAgICogICAtIChFbGVtZW50IHF1ZXVlIHBvcHBlZCBmcm9tIHRoZSBjdXN0b20gZWxlbWVudCByZWFjdGlvbnMgc3RhY2suXG4gICAqICAgICBSZWFjdGlvbnMgaW4gdGhlIHBvcHBlZCBzdGFjayBhcmUgaW52b2tlZC4pXG4gICAqXG4gICAqIEBwYXJhbSB7IU5vZGV9IHJvb3RcbiAgICogQHBhcmFtIHshU2V0PE5vZGU+PX0gdmlzaXRlZEltcG9ydHNcbiAgICovXG4gIHBhdGNoQW5kVXBncmFkZVRyZWUocm9vdCwgdmlzaXRlZEltcG9ydHMgPSBuZXcgU2V0KCkpIHtcbiAgICBjb25zdCBlbGVtZW50cyA9IFtdO1xuXG4gICAgY29uc3QgZ2F0aGVyRWxlbWVudHMgPSBlbGVtZW50ID0+IHtcbiAgICAgIGlmIChlbGVtZW50LmxvY2FsTmFtZSA9PT0gJ2xpbmsnICYmIGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdyZWwnKSA9PT0gJ2ltcG9ydCcpIHtcbiAgICAgICAgLy8gVGhlIEhUTUwgSW1wb3J0cyBwb2x5ZmlsbCBzZXRzIGEgZGVzY2VuZGFudCBlbGVtZW50IG9mIHRoZSBsaW5rIHRvXG4gICAgICAgIC8vIHRoZSBgaW1wb3J0YCBwcm9wZXJ0eSwgc3BlY2lmaWNhbGx5IHRoaXMgaXMgKm5vdCogYSBEb2N1bWVudC5cbiAgICAgICAgY29uc3QgaW1wb3J0Tm9kZSA9IC8qKiBAdHlwZSB7P05vZGV9ICovIChlbGVtZW50LmltcG9ydCk7XG5cbiAgICAgICAgaWYgKGltcG9ydE5vZGUgaW5zdGFuY2VvZiBOb2RlICYmIGltcG9ydE5vZGUucmVhZHlTdGF0ZSA9PT0gJ2NvbXBsZXRlJykge1xuICAgICAgICAgIGltcG9ydE5vZGUuX19DRV9pc0ltcG9ydERvY3VtZW50ID0gdHJ1ZTtcblxuICAgICAgICAgIC8vIENvbm5lY3RlZCBsaW5rcyBhcmUgYXNzb2NpYXRlZCB3aXRoIHRoZSByZWdpc3RyeS5cbiAgICAgICAgICBpbXBvcnROb2RlLl9fQ0VfaGFzUmVnaXN0cnkgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIElmIHRoaXMgbGluaydzIGltcG9ydCByb290IGlzIG5vdCBhdmFpbGFibGUsIGl0cyBjb250ZW50cyBjYW4ndCBiZVxuICAgICAgICAgIC8vIHdhbGtlZC4gV2FpdCBmb3IgJ2xvYWQnIGFuZCB3YWxrIGl0IHdoZW4gaXQncyByZWFkeS5cbiAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBpbXBvcnROb2RlID0gLyoqIEB0eXBlIHshTm9kZX0gKi8gKGVsZW1lbnQuaW1wb3J0KTtcblxuICAgICAgICAgICAgaWYgKGltcG9ydE5vZGUuX19DRV9kb2N1bWVudExvYWRIYW5kbGVkKSByZXR1cm47XG4gICAgICAgICAgICBpbXBvcnROb2RlLl9fQ0VfZG9jdW1lbnRMb2FkSGFuZGxlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIGltcG9ydE5vZGUuX19DRV9pc0ltcG9ydERvY3VtZW50ID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gQ29ubmVjdGVkIGxpbmtzIGFyZSBhc3NvY2lhdGVkIHdpdGggdGhlIHJlZ2lzdHJ5LlxuICAgICAgICAgICAgaW1wb3J0Tm9kZS5fX0NFX2hhc1JlZ2lzdHJ5ID0gdHJ1ZTtcblxuICAgICAgICAgICAgLy8gQ2xvbmUgdGhlIGB2aXNpdGVkSW1wb3J0c2Agc2V0IHRoYXQgd2FzIHBvcHVsYXRlZCBzeW5jIGR1cmluZ1xuICAgICAgICAgICAgLy8gdGhlIGBwYXRjaEFuZFVwZ3JhZGVUcmVlYCBjYWxsIHRoYXQgY2F1c2VkIHRoaXMgJ2xvYWQnIGhhbmRsZXIgdG9cbiAgICAgICAgICAgIC8vIGJlIGFkZGVkLiBUaGVuLCByZW1vdmUgKnRoaXMqIGxpbmsncyBpbXBvcnQgbm9kZSBzbyB0aGF0IHdlIGNhblxuICAgICAgICAgICAgLy8gd2FsayB0aGF0IGltcG9ydCBhZ2FpbiwgZXZlbiBpZiBpdCB3YXMgcGFydGlhbGx5IHdhbGtlZCBsYXRlclxuICAgICAgICAgICAgLy8gZHVyaW5nIHRoZSBzYW1lIGBwYXRjaEFuZFVwZ3JhZGVUcmVlYCBjYWxsLlxuICAgICAgICAgICAgY29uc3QgY2xvbmVkVmlzaXRlZEltcG9ydHMgPSBuZXcgU2V0KHZpc2l0ZWRJbXBvcnRzKTtcbiAgICAgICAgICAgIHZpc2l0ZWRJbXBvcnRzLmRlbGV0ZShpbXBvcnROb2RlKTtcblxuICAgICAgICAgICAgdGhpcy5wYXRjaEFuZFVwZ3JhZGVUcmVlKGltcG9ydE5vZGUsIHZpc2l0ZWRJbXBvcnRzKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWxlbWVudHMucHVzaChlbGVtZW50KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgLy8gYHdhbGtEZWVwRGVzY2VuZGFudEVsZW1lbnRzYCBwb3B1bGF0ZXMgKGFuZCBpbnRlcm5hbGx5IGNoZWNrcyBhZ2FpbnN0KVxuICAgIC8vIGB2aXNpdGVkSW1wb3J0c2Agd2hlbiB0cmF2ZXJzaW5nIGEgbG9hZGVkIGltcG9ydC5cbiAgICBVdGlsaXRpZXMud2Fsa0RlZXBEZXNjZW5kYW50RWxlbWVudHMocm9vdCwgZ2F0aGVyRWxlbWVudHMsIHZpc2l0ZWRJbXBvcnRzKTtcblxuICAgIGlmICh0aGlzLl9oYXNQYXRjaGVzKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXMucGF0Y2goZWxlbWVudHNbaV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZWxlbWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMudXBncmFkZUVsZW1lbnQoZWxlbWVudHNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gICAqL1xuICB1cGdyYWRlRWxlbWVudChlbGVtZW50KSB7XG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gZWxlbWVudC5fX0NFX3N0YXRlO1xuICAgIGlmIChjdXJyZW50U3RhdGUgIT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gICAgY29uc3QgZGVmaW5pdGlvbiA9IHRoaXMubG9jYWxOYW1lVG9EZWZpbml0aW9uKGVsZW1lbnQubG9jYWxOYW1lKTtcbiAgICBpZiAoIWRlZmluaXRpb24pIHJldHVybjtcblxuICAgIGRlZmluaXRpb24uY29uc3RydWN0aW9uU3RhY2sucHVzaChlbGVtZW50KTtcblxuICAgIGNvbnN0IGNvbnN0cnVjdG9yID0gZGVmaW5pdGlvbi5jb25zdHJ1Y3RvcjtcbiAgICB0cnkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyAoY29uc3RydWN0b3IpKCk7XG4gICAgICAgIGlmIChyZXN1bHQgIT09IGVsZW1lbnQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBjdXN0b20gZWxlbWVudCBjb25zdHJ1Y3RvciBkaWQgbm90IHByb2R1Y2UgdGhlIGVsZW1lbnQgYmVpbmcgdXBncmFkZWQuJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIGRlZmluaXRpb24uY29uc3RydWN0aW9uU3RhY2sucG9wKCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZWxlbWVudC5fX0NFX3N0YXRlID0gQ0VTdGF0ZS5mYWlsZWQ7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIGVsZW1lbnQuX19DRV9zdGF0ZSA9IENFU3RhdGUuY3VzdG9tO1xuICAgIGVsZW1lbnQuX19DRV9kZWZpbml0aW9uID0gZGVmaW5pdGlvbjtcblxuICAgIGlmIChkZWZpbml0aW9uLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaykge1xuICAgICAgY29uc3Qgb2JzZXJ2ZWRBdHRyaWJ1dGVzID0gZGVmaW5pdGlvbi5vYnNlcnZlZEF0dHJpYnV0ZXM7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9ic2VydmVkQXR0cmlidXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBuYW1lID0gb2JzZXJ2ZWRBdHRyaWJ1dGVzW2ldO1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKG5hbWUpO1xuICAgICAgICBpZiAodmFsdWUgIT09IG51bGwpIHtcbiAgICAgICAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhlbGVtZW50LCBuYW1lLCBudWxsLCB2YWx1ZSwgbnVsbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoVXRpbGl0aWVzLmlzQ29ubmVjdGVkKGVsZW1lbnQpKSB7XG4gICAgICB0aGlzLmNvbm5lY3RlZENhbGxiYWNrKGVsZW1lbnQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gICAqL1xuICBjb25uZWN0ZWRDYWxsYmFjayhlbGVtZW50KSB7XG4gICAgY29uc3QgZGVmaW5pdGlvbiA9IGVsZW1lbnQuX19DRV9kZWZpbml0aW9uO1xuICAgIGlmIChkZWZpbml0aW9uLmNvbm5lY3RlZENhbGxiYWNrKSB7XG4gICAgICBkZWZpbml0aW9uLmNvbm5lY3RlZENhbGxiYWNrLmNhbGwoZWxlbWVudCk7XG4gICAgfVxuXG4gICAgZWxlbWVudC5fX0NFX2lzQ29ubmVjdGVkQ2FsbGJhY2tDYWxsZWQgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAgICovXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKGVsZW1lbnQpIHtcbiAgICBpZiAoIWVsZW1lbnQuX19DRV9pc0Nvbm5lY3RlZENhbGxiYWNrQ2FsbGVkKSB7XG4gICAgICB0aGlzLmNvbm5lY3RlZENhbGxiYWNrKGVsZW1lbnQpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmluaXRpb24gPSBlbGVtZW50Ll9fQ0VfZGVmaW5pdGlvbjtcbiAgICBpZiAoZGVmaW5pdGlvbi5kaXNjb25uZWN0ZWRDYWxsYmFjaykge1xuICAgICAgZGVmaW5pdGlvbi5kaXNjb25uZWN0ZWRDYWxsYmFjay5jYWxsKGVsZW1lbnQpO1xuICAgIH1cblxuICAgIGVsZW1lbnQuX19DRV9pc0Nvbm5lY3RlZENhbGxiYWNrQ2FsbGVkID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUVsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHs/c3RyaW5nfSBvbGRWYWx1ZVxuICAgKiBAcGFyYW0gez9zdHJpbmd9IG5ld1ZhbHVlXG4gICAqIEBwYXJhbSB7P3N0cmluZ30gbmFtZXNwYWNlXG4gICAqL1xuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2soZWxlbWVudCwgbmFtZSwgb2xkVmFsdWUsIG5ld1ZhbHVlLCBuYW1lc3BhY2UpIHtcbiAgICBjb25zdCBkZWZpbml0aW9uID0gZWxlbWVudC5fX0NFX2RlZmluaXRpb247XG4gICAgaWYgKFxuICAgICAgZGVmaW5pdGlvbi5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sgJiZcbiAgICAgIGRlZmluaXRpb24ub2JzZXJ2ZWRBdHRyaWJ1dGVzLmluZGV4T2YobmFtZSkgPiAtMVxuICAgICkge1xuICAgICAgZGVmaW5pdGlvbi5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2suY2FsbChlbGVtZW50LCBuYW1lLCBvbGRWYWx1ZSwgbmV3VmFsdWUsIG5hbWVzcGFjZSk7XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQgQ3VzdG9tRWxlbWVudEludGVybmFscyBmcm9tICcuL0N1c3RvbUVsZW1lbnRJbnRlcm5hbHMuanMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBEb2N1bWVudENvbnN0cnVjdGlvbk9ic2VydmVyIHtcbiAgY29uc3RydWN0b3IoaW50ZXJuYWxzLCBkb2MpIHtcbiAgICAvKipcbiAgICAgKiBAdHlwZSB7IUN1c3RvbUVsZW1lbnRJbnRlcm5hbHN9XG4gICAgICovXG4gICAgdGhpcy5faW50ZXJuYWxzID0gaW50ZXJuYWxzO1xuXG4gICAgLyoqXG4gICAgICogQHR5cGUgeyFEb2N1bWVudH1cbiAgICAgKi9cbiAgICB0aGlzLl9kb2N1bWVudCA9IGRvYztcblxuICAgIC8qKlxuICAgICAqIEB0eXBlIHtNdXRhdGlvbk9ic2VydmVyfHVuZGVmaW5lZH1cbiAgICAgKi9cbiAgICB0aGlzLl9vYnNlcnZlciA9IHVuZGVmaW5lZDtcblxuXG4gICAgLy8gU2ltdWxhdGUgdHJlZSBjb25zdHJ1Y3Rpb24gZm9yIGFsbCBjdXJyZW50bHkgYWNjZXNzaWJsZSBub2RlcyBpbiB0aGVcbiAgICAvLyBkb2N1bWVudC5cbiAgICB0aGlzLl9pbnRlcm5hbHMucGF0Y2hBbmRVcGdyYWRlVHJlZSh0aGlzLl9kb2N1bWVudCk7XG5cbiAgICBpZiAodGhpcy5fZG9jdW1lbnQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnKSB7XG4gICAgICB0aGlzLl9vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKHRoaXMuX2hhbmRsZU11dGF0aW9ucy5iaW5kKHRoaXMpKTtcblxuICAgICAgLy8gTm9kZXMgY3JlYXRlZCBieSB0aGUgcGFyc2VyIGFyZSBnaXZlbiB0byB0aGUgb2JzZXJ2ZXIgKmJlZm9yZSogdGhlIG5leHRcbiAgICAgIC8vIHRhc2sgcnVucy4gSW5saW5lIHNjcmlwdHMgYXJlIHJ1biBpbiBhIG5ldyB0YXNrLiBUaGlzIG1lYW5zIHRoYXQgdGhlXG4gICAgICAvLyBvYnNlcnZlciB3aWxsIGJlIGFibGUgdG8gaGFuZGxlIHRoZSBuZXdseSBwYXJzZWQgbm9kZXMgYmVmb3JlIHRoZSBpbmxpbmVcbiAgICAgIC8vIHNjcmlwdCBpcyBydW4uXG4gICAgICB0aGlzLl9vYnNlcnZlci5vYnNlcnZlKHRoaXMuX2RvY3VtZW50LCB7XG4gICAgICAgIGNoaWxkTGlzdDogdHJ1ZSxcbiAgICAgICAgc3VidHJlZTogdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGRpc2Nvbm5lY3QoKSB7XG4gICAgaWYgKHRoaXMuX29ic2VydmVyKSB7XG4gICAgICB0aGlzLl9vYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7IUFycmF5PCFNdXRhdGlvblJlY29yZD59IG11dGF0aW9uc1xuICAgKi9cbiAgX2hhbmRsZU11dGF0aW9ucyhtdXRhdGlvbnMpIHtcbiAgICAvLyBPbmNlIHRoZSBkb2N1bWVudCdzIGByZWFkeVN0YXRlYCBpcyAnaW50ZXJhY3RpdmUnIG9yICdjb21wbGV0ZScsIGFsbCBuZXdcbiAgICAvLyBub2RlcyBjcmVhdGVkIHdpdGhpbiB0aGF0IGRvY3VtZW50IHdpbGwgYmUgdGhlIHJlc3VsdCBvZiBzY3JpcHQgYW5kXG4gICAgLy8gc2hvdWxkIGJlIGhhbmRsZWQgYnkgcGF0Y2hpbmcuXG4gICAgY29uc3QgcmVhZHlTdGF0ZSA9IHRoaXMuX2RvY3VtZW50LnJlYWR5U3RhdGU7XG4gICAgaWYgKHJlYWR5U3RhdGUgPT09ICdpbnRlcmFjdGl2ZScgfHwgcmVhZHlTdGF0ZSA9PT0gJ2NvbXBsZXRlJykge1xuICAgICAgdGhpcy5kaXNjb25uZWN0KCk7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtdXRhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGFkZGVkTm9kZXMgPSBtdXRhdGlvbnNbaV0uYWRkZWROb2RlcztcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgYWRkZWROb2Rlcy5sZW5ndGg7IGorKykge1xuICAgICAgICBjb25zdCBub2RlID0gYWRkZWROb2Rlc1tqXTtcbiAgICAgICAgdGhpcy5faW50ZXJuYWxzLnBhdGNoQW5kVXBncmFkZVRyZWUobm9kZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCIvKipcbiAqIEB0ZW1wbGF0ZSBUXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERlZmVycmVkIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7VHx1bmRlZmluZWR9XG4gICAgICovXG4gICAgdGhpcy5fdmFsdWUgPSB1bmRlZmluZWQ7XG5cbiAgICAvKipcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEB0eXBlIHtGdW5jdGlvbnx1bmRlZmluZWR9XG4gICAgICovXG4gICAgdGhpcy5fcmVzb2x2ZSA9IHVuZGVmaW5lZDtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFQcm9taXNlPFQ+fVxuICAgICAqL1xuICAgIHRoaXMuX3Byb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHRoaXMuX3Jlc29sdmUgPSByZXNvbHZlO1xuXG4gICAgICBpZiAodGhpcy5fdmFsdWUpIHtcbiAgICAgICAgcmVzb2x2ZSh0aGlzLl92YWx1ZSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtUfSB2YWx1ZVxuICAgKi9cbiAgcmVzb2x2ZSh2YWx1ZSkge1xuICAgIGlmICh0aGlzLl92YWx1ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBbHJlYWR5IHJlc29sdmVkLicpO1xuICAgIH1cblxuICAgIHRoaXMuX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAodGhpcy5fcmVzb2x2ZSkge1xuICAgICAgdGhpcy5fcmVzb2x2ZSh2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4geyFQcm9taXNlPFQ+fVxuICAgKi9cbiAgdG9Qcm9taXNlKCkge1xuICAgIHJldHVybiB0aGlzLl9wcm9taXNlO1xuICB9XG59XG4iLCJpbXBvcnQgQ3VzdG9tRWxlbWVudEludGVybmFscyBmcm9tICcuL0N1c3RvbUVsZW1lbnRJbnRlcm5hbHMuanMnO1xuaW1wb3J0IERvY3VtZW50Q29uc3RydWN0aW9uT2JzZXJ2ZXIgZnJvbSAnLi9Eb2N1bWVudENvbnN0cnVjdGlvbk9ic2VydmVyLmpzJztcbmltcG9ydCBEZWZlcnJlZCBmcm9tICcuL0RlZmVycmVkLmpzJztcbmltcG9ydCAqIGFzIFV0aWxpdGllcyBmcm9tICcuL1V0aWxpdGllcy5qcyc7XG5cbi8qKlxuICogQHVucmVzdHJpY3RlZFxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDdXN0b21FbGVtZW50UmVnaXN0cnkge1xuXG4gIC8qKlxuICAgKiBAcGFyYW0geyFDdXN0b21FbGVtZW50SW50ZXJuYWxzfSBpbnRlcm5hbHNcbiAgICovXG4gIGNvbnN0cnVjdG9yKGludGVybmFscykge1xuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgdGhpcy5fZWxlbWVudERlZmluaXRpb25Jc1J1bm5pbmcgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFDdXN0b21FbGVtZW50SW50ZXJuYWxzfVxuICAgICAqL1xuICAgIHRoaXMuX2ludGVybmFscyA9IGludGVybmFscztcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFNYXA8c3RyaW5nLCAhRGVmZXJyZWQ8dW5kZWZpbmVkPj59XG4gICAgICovXG4gICAgdGhpcy5fd2hlbkRlZmluZWREZWZlcnJlZCA9IG5ldyBNYXAoKTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBkZWZhdWx0IGZsdXNoIGNhbGxiYWNrIHRyaWdnZXJzIHRoZSBkb2N1bWVudCB3YWxrIHN5bmNocm9ub3VzbHkuXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7IUZ1bmN0aW9ufVxuICAgICAqL1xuICAgIHRoaXMuX2ZsdXNoQ2FsbGJhY2sgPSBmbiA9PiBmbigpO1xuXG4gICAgLyoqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICB0aGlzLl9mbHVzaFBlbmRpbmcgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFBcnJheTxzdHJpbmc+fVxuICAgICAqL1xuICAgIHRoaXMuX3VuZmx1c2hlZExvY2FsTmFtZXMgPSBbXTtcblxuICAgIC8qKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHR5cGUgeyFEb2N1bWVudENvbnN0cnVjdGlvbk9ic2VydmVyfVxuICAgICAqL1xuICAgIHRoaXMuX2RvY3VtZW50Q29uc3RydWN0aW9uT2JzZXJ2ZXIgPSBuZXcgRG9jdW1lbnRDb25zdHJ1Y3Rpb25PYnNlcnZlcihpbnRlcm5hbHMsIGRvY3VtZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbG9jYWxOYW1lXG4gICAqIEBwYXJhbSB7IUZ1bmN0aW9ufSBjb25zdHJ1Y3RvclxuICAgKi9cbiAgZGVmaW5lKGxvY2FsTmFtZSwgY29uc3RydWN0b3IpIHtcbiAgICBpZiAoIShjb25zdHJ1Y3RvciBpbnN0YW5jZW9mIEZ1bmN0aW9uKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQ3VzdG9tIGVsZW1lbnQgY29uc3RydWN0b3JzIG11c3QgYmUgZnVuY3Rpb25zLicpO1xuICAgIH1cblxuICAgIGlmICghVXRpbGl0aWVzLmlzVmFsaWRDdXN0b21FbGVtZW50TmFtZShsb2NhbE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoYFRoZSBlbGVtZW50IG5hbWUgJyR7bG9jYWxOYW1lfScgaXMgbm90IHZhbGlkLmApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9pbnRlcm5hbHMubG9jYWxOYW1lVG9EZWZpbml0aW9uKGxvY2FsTmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQSBjdXN0b20gZWxlbWVudCB3aXRoIG5hbWUgJyR7bG9jYWxOYW1lfScgaGFzIGFscmVhZHkgYmVlbiBkZWZpbmVkLmApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9lbGVtZW50RGVmaW5pdGlvbklzUnVubmluZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBIGN1c3RvbSBlbGVtZW50IGlzIGFscmVhZHkgYmVpbmcgZGVmaW5lZC4nKTtcbiAgICB9XG4gICAgdGhpcy5fZWxlbWVudERlZmluaXRpb25Jc1J1bm5pbmcgPSB0cnVlO1xuXG4gICAgbGV0IGNvbm5lY3RlZENhbGxiYWNrO1xuICAgIGxldCBkaXNjb25uZWN0ZWRDYWxsYmFjaztcbiAgICBsZXQgYWRvcHRlZENhbGxiYWNrO1xuICAgIGxldCBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2s7XG4gICAgbGV0IG9ic2VydmVkQXR0cmlidXRlcztcbiAgICB0cnkge1xuICAgICAgLyoqIEB0eXBlIHshT2JqZWN0fSAqL1xuICAgICAgY29uc3QgcHJvdG90eXBlID0gY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgaWYgKCEocHJvdG90eXBlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUaGUgY3VzdG9tIGVsZW1lbnQgY29uc3RydWN0b3JcXCdzIHByb3RvdHlwZSBpcyBub3QgYW4gb2JqZWN0LicpO1xuICAgICAgfVxuXG4gICAgICBmdW5jdGlvbiBnZXRDYWxsYmFjayhuYW1lKSB7XG4gICAgICAgIGNvbnN0IGNhbGxiYWNrVmFsdWUgPSBwcm90b3R5cGVbbmFtZV07XG4gICAgICAgIGlmIChjYWxsYmFja1ZhbHVlICE9PSB1bmRlZmluZWQgJiYgIShjYWxsYmFja1ZhbHVlIGluc3RhbmNlb2YgRnVuY3Rpb24pKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgJyR7bmFtZX0nIGNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2FsbGJhY2tWYWx1ZTtcbiAgICAgIH1cblxuICAgICAgY29ubmVjdGVkQ2FsbGJhY2sgPSBnZXRDYWxsYmFjaygnY29ubmVjdGVkQ2FsbGJhY2snKTtcbiAgICAgIGRpc2Nvbm5lY3RlZENhbGxiYWNrID0gZ2V0Q2FsbGJhY2soJ2Rpc2Nvbm5lY3RlZENhbGxiYWNrJyk7XG4gICAgICBhZG9wdGVkQ2FsbGJhY2sgPSBnZXRDYWxsYmFjaygnYWRvcHRlZENhbGxiYWNrJyk7XG4gICAgICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sgPSBnZXRDYWxsYmFjaygnYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrJyk7XG4gICAgICBvYnNlcnZlZEF0dHJpYnV0ZXMgPSBjb25zdHJ1Y3Rvclsnb2JzZXJ2ZWRBdHRyaWJ1dGVzJ10gfHwgW107XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLl9lbGVtZW50RGVmaW5pdGlvbklzUnVubmluZyA9IGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmluaXRpb24gPSB7XG4gICAgICBsb2NhbE5hbWUsXG4gICAgICBjb25zdHJ1Y3RvcixcbiAgICAgIGNvbm5lY3RlZENhbGxiYWNrLFxuICAgICAgZGlzY29ubmVjdGVkQ2FsbGJhY2ssXG4gICAgICBhZG9wdGVkQ2FsbGJhY2ssXG4gICAgICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2ssXG4gICAgICBvYnNlcnZlZEF0dHJpYnV0ZXMsXG4gICAgICBjb25zdHJ1Y3Rpb25TdGFjazogW10sXG4gICAgfTtcblxuICAgIHRoaXMuX2ludGVybmFscy5zZXREZWZpbml0aW9uKGxvY2FsTmFtZSwgZGVmaW5pdGlvbik7XG5cbiAgICB0aGlzLl91bmZsdXNoZWRMb2NhbE5hbWVzLnB1c2gobG9jYWxOYW1lKTtcblxuICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgY2FsbGVkIHRoZSBmbHVzaCBjYWxsYmFjayBhbmQgaXQgaGFzbid0IGNhbGxlZCBiYWNrIHlldCxcbiAgICAvLyBkb24ndCBjYWxsIGl0IGFnYWluLlxuICAgIGlmICghdGhpcy5fZmx1c2hQZW5kaW5nKSB7XG4gICAgICB0aGlzLl9mbHVzaFBlbmRpbmcgPSB0cnVlO1xuICAgICAgdGhpcy5fZmx1c2hDYWxsYmFjaygoKSA9PiB0aGlzLl9mbHVzaCgpKTtcbiAgICB9XG4gIH1cblxuICBfZmx1c2goKSB7XG4gICAgLy8gSWYgbm8gbmV3IGRlZmluaXRpb25zIHdlcmUgZGVmaW5lZCwgZG9uJ3QgYXR0ZW1wdCB0byBmbHVzaC4gVGhpcyBjb3VsZFxuICAgIC8vIGhhcHBlbiBpZiBhIGZsdXNoIGNhbGxiYWNrIGtlZXBzIHRoZSBmdW5jdGlvbiBpdCBpcyBnaXZlbiBhbmQgY2FsbHMgaXRcbiAgICAvLyBtdWx0aXBsZSB0aW1lcy5cbiAgICBpZiAodGhpcy5fZmx1c2hQZW5kaW5nID09PSBmYWxzZSkgcmV0dXJuO1xuXG4gICAgdGhpcy5fZmx1c2hQZW5kaW5nID0gZmFsc2U7XG4gICAgdGhpcy5faW50ZXJuYWxzLnBhdGNoQW5kVXBncmFkZVRyZWUoZG9jdW1lbnQpO1xuXG4gICAgd2hpbGUgKHRoaXMuX3VuZmx1c2hlZExvY2FsTmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgbG9jYWxOYW1lID0gdGhpcy5fdW5mbHVzaGVkTG9jYWxOYW1lcy5zaGlmdCgpO1xuICAgICAgY29uc3QgZGVmZXJyZWQgPSB0aGlzLl93aGVuRGVmaW5lZERlZmVycmVkLmdldChsb2NhbE5hbWUpO1xuICAgICAgaWYgKGRlZmVycmVkKSB7XG4gICAgICAgIGRlZmVycmVkLnJlc29sdmUodW5kZWZpbmVkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtzdHJpbmd9IGxvY2FsTmFtZVxuICAgKiBAcmV0dXJuIHtGdW5jdGlvbnx1bmRlZmluZWR9XG4gICAqL1xuICBnZXQobG9jYWxOYW1lKSB7XG4gICAgY29uc3QgZGVmaW5pdGlvbiA9IHRoaXMuX2ludGVybmFscy5sb2NhbE5hbWVUb0RlZmluaXRpb24obG9jYWxOYW1lKTtcbiAgICBpZiAoZGVmaW5pdGlvbikge1xuICAgICAgcmV0dXJuIGRlZmluaXRpb24uY29uc3RydWN0b3I7XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbG9jYWxOYW1lXG4gICAqIEByZXR1cm4geyFQcm9taXNlPHVuZGVmaW5lZD59XG4gICAqL1xuICB3aGVuRGVmaW5lZChsb2NhbE5hbWUpIHtcbiAgICBpZiAoIVV0aWxpdGllcy5pc1ZhbGlkQ3VzdG9tRWxlbWVudE5hbWUobG9jYWxOYW1lKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBTeW50YXhFcnJvcihgJyR7bG9jYWxOYW1lfScgaXMgbm90IGEgdmFsaWQgY3VzdG9tIGVsZW1lbnQgbmFtZS5gKSk7XG4gICAgfVxuXG4gICAgY29uc3QgcHJpb3IgPSB0aGlzLl93aGVuRGVmaW5lZERlZmVycmVkLmdldChsb2NhbE5hbWUpO1xuICAgIGlmIChwcmlvcikge1xuICAgICAgcmV0dXJuIHByaW9yLnRvUHJvbWlzZSgpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmVycmVkID0gbmV3IERlZmVycmVkKCk7XG4gICAgdGhpcy5fd2hlbkRlZmluZWREZWZlcnJlZC5zZXQobG9jYWxOYW1lLCBkZWZlcnJlZCk7XG5cbiAgICBjb25zdCBkZWZpbml0aW9uID0gdGhpcy5faW50ZXJuYWxzLmxvY2FsTmFtZVRvRGVmaW5pdGlvbihsb2NhbE5hbWUpO1xuICAgIC8vIFJlc29sdmUgaW1tZWRpYXRlbHkgb25seSBpZiB0aGUgZ2l2ZW4gbG9jYWwgbmFtZSBoYXMgYSBkZWZpbml0aW9uICphbmQqXG4gICAgLy8gdGhlIGZ1bGwgZG9jdW1lbnQgd2FsayB0byB1cGdyYWRlIGVsZW1lbnRzIHdpdGggdGhhdCBsb2NhbCBuYW1lIGhhc1xuICAgIC8vIGFscmVhZHkgaGFwcGVuZWQuXG4gICAgaWYgKGRlZmluaXRpb24gJiYgdGhpcy5fdW5mbHVzaGVkTG9jYWxOYW1lcy5pbmRleE9mKGxvY2FsTmFtZSkgPT09IC0xKSB7XG4gICAgICBkZWZlcnJlZC5yZXNvbHZlKHVuZGVmaW5lZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlZmVycmVkLnRvUHJvbWlzZSgpO1xuICB9XG5cbiAgcG9seWZpbGxXcmFwRmx1c2hDYWxsYmFjayhvdXRlcikge1xuICAgIHRoaXMuX2RvY3VtZW50Q29uc3RydWN0aW9uT2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgIGNvbnN0IGlubmVyID0gdGhpcy5fZmx1c2hDYWxsYmFjaztcbiAgICB0aGlzLl9mbHVzaENhbGxiYWNrID0gZmx1c2ggPT4gb3V0ZXIoKCkgPT4gaW5uZXIoZmx1c2gpKTtcbiAgfVxufVxuXG4vLyBDbG9zdXJlIGNvbXBpbGVyIGV4cG9ydHMuXG53aW5kb3dbJ0N1c3RvbUVsZW1lbnRSZWdpc3RyeSddID0gQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5O1xuQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5LnByb3RvdHlwZVsnZGVmaW5lJ10gPSBDdXN0b21FbGVtZW50UmVnaXN0cnkucHJvdG90eXBlLmRlZmluZTtcbkN1c3RvbUVsZW1lbnRSZWdpc3RyeS5wcm90b3R5cGVbJ2dldCddID0gQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5LnByb3RvdHlwZS5nZXQ7XG5DdXN0b21FbGVtZW50UmVnaXN0cnkucHJvdG90eXBlWyd3aGVuRGVmaW5lZCddID0gQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5LnByb3RvdHlwZS53aGVuRGVmaW5lZDtcbkN1c3RvbUVsZW1lbnRSZWdpc3RyeS5wcm90b3R5cGVbJ3BvbHlmaWxsV3JhcEZsdXNoQ2FsbGJhY2snXSA9IEN1c3RvbUVsZW1lbnRSZWdpc3RyeS5wcm90b3R5cGUucG9seWZpbGxXcmFwRmx1c2hDYWxsYmFjaztcbiIsImV4cG9ydCBkZWZhdWx0IHtcbiAgRG9jdW1lbnRfY3JlYXRlRWxlbWVudDogd2luZG93LkRvY3VtZW50LnByb3RvdHlwZS5jcmVhdGVFbGVtZW50LFxuICBEb2N1bWVudF9jcmVhdGVFbGVtZW50TlM6IHdpbmRvdy5Eb2N1bWVudC5wcm90b3R5cGUuY3JlYXRlRWxlbWVudE5TLFxuICBEb2N1bWVudF9pbXBvcnROb2RlOiB3aW5kb3cuRG9jdW1lbnQucHJvdG90eXBlLmltcG9ydE5vZGUsXG4gIERvY3VtZW50X3ByZXBlbmQ6IHdpbmRvdy5Eb2N1bWVudC5wcm90b3R5cGVbJ3ByZXBlbmQnXSxcbiAgRG9jdW1lbnRfYXBwZW5kOiB3aW5kb3cuRG9jdW1lbnQucHJvdG90eXBlWydhcHBlbmQnXSxcbiAgTm9kZV9jbG9uZU5vZGU6IHdpbmRvdy5Ob2RlLnByb3RvdHlwZS5jbG9uZU5vZGUsXG4gIE5vZGVfYXBwZW5kQ2hpbGQ6IHdpbmRvdy5Ob2RlLnByb3RvdHlwZS5hcHBlbmRDaGlsZCxcbiAgTm9kZV9pbnNlcnRCZWZvcmU6IHdpbmRvdy5Ob2RlLnByb3RvdHlwZS5pbnNlcnRCZWZvcmUsXG4gIE5vZGVfcmVtb3ZlQ2hpbGQ6IHdpbmRvdy5Ob2RlLnByb3RvdHlwZS5yZW1vdmVDaGlsZCxcbiAgTm9kZV9yZXBsYWNlQ2hpbGQ6IHdpbmRvdy5Ob2RlLnByb3RvdHlwZS5yZXBsYWNlQ2hpbGQsXG4gIE5vZGVfdGV4dENvbnRlbnQ6IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iod2luZG93Lk5vZGUucHJvdG90eXBlLCAndGV4dENvbnRlbnQnKSxcbiAgRWxlbWVudF9hdHRhY2hTaGFkb3c6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZVsnYXR0YWNoU2hhZG93J10sXG4gIEVsZW1lbnRfaW5uZXJIVE1MOiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZSwgJ2lubmVySFRNTCcpLFxuICBFbGVtZW50X2dldEF0dHJpYnV0ZTogd2luZG93LkVsZW1lbnQucHJvdG90eXBlLmdldEF0dHJpYnV0ZSxcbiAgRWxlbWVudF9zZXRBdHRyaWJ1dGU6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZS5zZXRBdHRyaWJ1dGUsXG4gIEVsZW1lbnRfcmVtb3ZlQXR0cmlidXRlOiB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGUucmVtb3ZlQXR0cmlidXRlLFxuICBFbGVtZW50X2dldEF0dHJpYnV0ZU5TOiB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGUuZ2V0QXR0cmlidXRlTlMsXG4gIEVsZW1lbnRfc2V0QXR0cmlidXRlTlM6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZS5zZXRBdHRyaWJ1dGVOUyxcbiAgRWxlbWVudF9yZW1vdmVBdHRyaWJ1dGVOUzogd2luZG93LkVsZW1lbnQucHJvdG90eXBlLnJlbW92ZUF0dHJpYnV0ZU5TLFxuICBFbGVtZW50X2luc2VydEFkamFjZW50RWxlbWVudDogd2luZG93LkVsZW1lbnQucHJvdG90eXBlWydpbnNlcnRBZGphY2VudEVsZW1lbnQnXSxcbiAgRWxlbWVudF9wcmVwZW5kOiB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGVbJ3ByZXBlbmQnXSxcbiAgRWxlbWVudF9hcHBlbmQ6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZVsnYXBwZW5kJ10sXG4gIEVsZW1lbnRfYmVmb3JlOiB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGVbJ2JlZm9yZSddLFxuICBFbGVtZW50X2FmdGVyOiB3aW5kb3cuRWxlbWVudC5wcm90b3R5cGVbJ2FmdGVyJ10sXG4gIEVsZW1lbnRfcmVwbGFjZVdpdGg6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZVsncmVwbGFjZVdpdGgnXSxcbiAgRWxlbWVudF9yZW1vdmU6IHdpbmRvdy5FbGVtZW50LnByb3RvdHlwZVsncmVtb3ZlJ10sXG4gIEhUTUxFbGVtZW50OiB3aW5kb3cuSFRNTEVsZW1lbnQsXG4gIEhUTUxFbGVtZW50X2lubmVySFRNTDogT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih3aW5kb3cuSFRNTEVsZW1lbnQucHJvdG90eXBlLCAnaW5uZXJIVE1MJyksXG4gIEhUTUxFbGVtZW50X2luc2VydEFkamFjZW50RWxlbWVudDogd2luZG93LkhUTUxFbGVtZW50LnByb3RvdHlwZVsnaW5zZXJ0QWRqYWNlbnRFbGVtZW50J10sXG59O1xuIiwiLyoqXG4gKiBUaGlzIGNsYXNzIGV4aXN0cyBvbmx5IHRvIHdvcmsgYXJvdW5kIENsb3N1cmUncyBsYWNrIG9mIGEgd2F5IHRvIGRlc2NyaWJlXG4gKiBzaW5nbGV0b25zLiBJdCByZXByZXNlbnRzIHRoZSAnYWxyZWFkeSBjb25zdHJ1Y3RlZCBtYXJrZXInIHVzZWQgaW4gY3VzdG9tXG4gKiBlbGVtZW50IGNvbnN0cnVjdGlvbiBzdGFja3MuXG4gKlxuICogaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy8jY29uY2VwdC1hbHJlYWR5LWNvbnN0cnVjdGVkLW1hcmtlclxuICovXG5jbGFzcyBBbHJlYWR5Q29uc3RydWN0ZWRNYXJrZXIge31cblxuZXhwb3J0IGRlZmF1bHQgbmV3IEFscmVhZHlDb25zdHJ1Y3RlZE1hcmtlcigpO1xuIiwiaW1wb3J0IE5hdGl2ZSBmcm9tICcuL05hdGl2ZS5qcyc7XG5pbXBvcnQgQ3VzdG9tRWxlbWVudEludGVybmFscyBmcm9tICcuLi9DdXN0b21FbGVtZW50SW50ZXJuYWxzLmpzJztcbmltcG9ydCBDRVN0YXRlIGZyb20gJy4uL0N1c3RvbUVsZW1lbnRTdGF0ZS5qcyc7XG5pbXBvcnQgQWxyZWFkeUNvbnN0cnVjdGVkTWFya2VyIGZyb20gJy4uL0FscmVhZHlDb25zdHJ1Y3RlZE1hcmtlci5qcyc7XG5cbi8qKlxuICogQHBhcmFtIHshQ3VzdG9tRWxlbWVudEludGVybmFsc30gaW50ZXJuYWxzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGludGVybmFscykge1xuICB3aW5kb3dbJ0hUTUxFbGVtZW50J10gPSAoZnVuY3Rpb24oKSB7XG4gICAgLyoqXG4gICAgICogQHR5cGUge2Z1bmN0aW9uKG5ldzogSFRNTEVsZW1lbnQpOiAhSFRNTEVsZW1lbnR9XG4gICAgICovXG4gICAgZnVuY3Rpb24gSFRNTEVsZW1lbnQoKSB7XG4gICAgICAvLyBUaGlzIHNob3VsZCByZWFsbHkgYmUgYG5ldy50YXJnZXRgIGJ1dCBgbmV3LnRhcmdldGAgY2FuJ3QgYmUgZW11bGF0ZWRcbiAgICAgIC8vIGluIEVTNS4gQXNzdW1pbmcgdGhlIHVzZXIga2VlcHMgdGhlIGRlZmF1bHQgdmFsdWUgb2YgdGhlIGNvbnN0cnVjdG9yJ3NcbiAgICAgIC8vIHByb3RvdHlwZSdzIGBjb25zdHJ1Y3RvcmAgcHJvcGVydHksIHRoaXMgaXMgZXF1aXZhbGVudC5cbiAgICAgIC8qKiBAdHlwZSB7IUZ1bmN0aW9ufSAqL1xuICAgICAgY29uc3QgY29uc3RydWN0b3IgPSB0aGlzLmNvbnN0cnVjdG9yO1xuXG4gICAgICBjb25zdCBkZWZpbml0aW9uID0gaW50ZXJuYWxzLmNvbnN0cnVjdG9yVG9EZWZpbml0aW9uKGNvbnN0cnVjdG9yKTtcbiAgICAgIGlmICghZGVmaW5pdGlvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBjdXN0b20gZWxlbWVudCBiZWluZyBjb25zdHJ1Y3RlZCB3YXMgbm90IHJlZ2lzdGVyZWQgd2l0aCBgY3VzdG9tRWxlbWVudHNgLicpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb25zdHJ1Y3Rpb25TdGFjayA9IGRlZmluaXRpb24uY29uc3RydWN0aW9uU3RhY2s7XG5cbiAgICAgIGlmIChjb25zdHJ1Y3Rpb25TdGFjay5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc3QgZWxlbWVudCA9IE5hdGl2ZS5Eb2N1bWVudF9jcmVhdGVFbGVtZW50LmNhbGwoZG9jdW1lbnQsIGRlZmluaXRpb24ubG9jYWxOYW1lKTtcbiAgICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKGVsZW1lbnQsIGNvbnN0cnVjdG9yLnByb3RvdHlwZSk7XG4gICAgICAgIGVsZW1lbnQuX19DRV9zdGF0ZSA9IENFU3RhdGUuY3VzdG9tO1xuICAgICAgICBlbGVtZW50Ll9fQ0VfZGVmaW5pdGlvbiA9IGRlZmluaXRpb247XG4gICAgICAgIGludGVybmFscy5wYXRjaChlbGVtZW50KTtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGxhc3RJbmRleCA9IGNvbnN0cnVjdGlvblN0YWNrLmxlbmd0aCAtIDE7XG4gICAgICBjb25zdCBlbGVtZW50ID0gY29uc3RydWN0aW9uU3RhY2tbbGFzdEluZGV4XTtcbiAgICAgIGlmIChlbGVtZW50ID09PSBBbHJlYWR5Q29uc3RydWN0ZWRNYXJrZXIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgSFRNTEVsZW1lbnQgY29uc3RydWN0b3Igd2FzIGVpdGhlciBjYWxsZWQgcmVlbnRyYW50bHkgZm9yIHRoaXMgY29uc3RydWN0b3Igb3IgY2FsbGVkIG11bHRpcGxlIHRpbWVzLicpO1xuICAgICAgfVxuICAgICAgY29uc3RydWN0aW9uU3RhY2tbbGFzdEluZGV4XSA9IEFscmVhZHlDb25zdHJ1Y3RlZE1hcmtlcjtcblxuICAgICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKGVsZW1lbnQsIGNvbnN0cnVjdG9yLnByb3RvdHlwZSk7XG4gICAgICBpbnRlcm5hbHMucGF0Y2goLyoqIEB0eXBlIHshSFRNTEVsZW1lbnR9ICovIChlbGVtZW50KSk7XG5cbiAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH1cblxuICAgIEhUTUxFbGVtZW50LnByb3RvdHlwZSA9IE5hdGl2ZS5IVE1MRWxlbWVudC5wcm90b3R5cGU7XG5cbiAgICByZXR1cm4gSFRNTEVsZW1lbnQ7XG4gIH0pKCk7XG59O1xuIiwiaW1wb3J0IEN1c3RvbUVsZW1lbnRJbnRlcm5hbHMgZnJvbSAnLi4vLi4vQ3VzdG9tRWxlbWVudEludGVybmFscy5qcyc7XG5pbXBvcnQgKiBhcyBVdGlsaXRpZXMgZnJvbSAnLi4vLi4vVXRpbGl0aWVzLmpzJztcblxuLyoqXG4gKiBAdHlwZWRlZiB7e1xuICogICBwcmVwZW5kOiAhZnVuY3Rpb24oLi4uKCFOb2RlfHN0cmluZykpLFxuICAqICBhcHBlbmQ6ICFmdW5jdGlvbiguLi4oIU5vZGV8c3RyaW5nKSksXG4gKiB9fVxuICovXG5sZXQgUGFyZW50Tm9kZU5hdGl2ZU1ldGhvZHM7XG5cbi8qKlxuICogQHBhcmFtIHshQ3VzdG9tRWxlbWVudEludGVybmFsc30gaW50ZXJuYWxzXG4gKiBAcGFyYW0geyFPYmplY3R9IGRlc3RpbmF0aW9uXG4gKiBAcGFyYW0geyFQYXJlbnROb2RlTmF0aXZlTWV0aG9kc30gYnVpbHRJblxuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnRlcm5hbHMsIGRlc3RpbmF0aW9uLCBidWlsdEluKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0gey4uLighTm9kZXxzdHJpbmcpfSBub2Rlc1xuICAgKi9cbiAgZGVzdGluYXRpb25bJ3ByZXBlbmQnXSA9IGZ1bmN0aW9uKC4uLm5vZGVzKSB7XG4gICAgLy8gVE9ETzogRml4IHRoaXMgZm9yIHdoZW4gb25lIG9mIGBub2Rlc2AgaXMgYSBEb2N1bWVudEZyYWdtZW50IVxuICAgIGNvbnN0IGNvbm5lY3RlZEJlZm9yZSA9IC8qKiBAdHlwZSB7IUFycmF5PCFOb2RlPn0gKi8gKG5vZGVzLmZpbHRlcihub2RlID0+IHtcbiAgICAgIC8vIERvY3VtZW50RnJhZ21lbnRzIGFyZSBub3QgY29ubmVjdGVkIGFuZCB3aWxsIG5vdCBiZSBhZGRlZCB0byB0aGUgbGlzdC5cbiAgICAgIHJldHVybiBub2RlIGluc3RhbmNlb2YgTm9kZSAmJiBVdGlsaXRpZXMuaXNDb25uZWN0ZWQobm9kZSk7XG4gICAgfSkpO1xuXG4gICAgYnVpbHRJbi5wcmVwZW5kLmFwcGx5KHRoaXMsIG5vZGVzKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29ubmVjdGVkQmVmb3JlLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUoY29ubmVjdGVkQmVmb3JlW2ldKTtcbiAgICB9XG5cbiAgICBpZiAoVXRpbGl0aWVzLmlzQ29ubmVjdGVkKHRoaXMpKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBFbGVtZW50KSB7XG4gICAgICAgICAgaW50ZXJuYWxzLmNvbm5lY3RUcmVlKG5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0gey4uLighTm9kZXxzdHJpbmcpfSBub2Rlc1xuICAgKi9cbiAgZGVzdGluYXRpb25bJ2FwcGVuZCddID0gZnVuY3Rpb24oLi4ubm9kZXMpIHtcbiAgICAvLyBUT0RPOiBGaXggdGhpcyBmb3Igd2hlbiBvbmUgb2YgYG5vZGVzYCBpcyBhIERvY3VtZW50RnJhZ21lbnQhXG4gICAgY29uc3QgY29ubmVjdGVkQmVmb3JlID0gLyoqIEB0eXBlIHshQXJyYXk8IU5vZGU+fSAqLyAobm9kZXMuZmlsdGVyKG5vZGUgPT4ge1xuICAgICAgLy8gRG9jdW1lbnRGcmFnbWVudHMgYXJlIG5vdCBjb25uZWN0ZWQgYW5kIHdpbGwgbm90IGJlIGFkZGVkIHRvIHRoZSBsaXN0LlxuICAgICAgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBOb2RlICYmIFV0aWxpdGllcy5pc0Nvbm5lY3RlZChub2RlKTtcbiAgICB9KSk7XG5cbiAgICBidWlsdEluLmFwcGVuZC5hcHBseSh0aGlzLCBub2Rlcyk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbm5lY3RlZEJlZm9yZS5sZW5ndGg7IGkrKykge1xuICAgICAgaW50ZXJuYWxzLmRpc2Nvbm5lY3RUcmVlKGNvbm5lY3RlZEJlZm9yZVtpXSk7XG4gICAgfVxuXG4gICAgaWYgKFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKSkge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBub2RlID0gbm9kZXNbaV07XG4gICAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgRWxlbWVudCkge1xuICAgICAgICAgIGludGVybmFscy5jb25uZWN0VHJlZShub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcbn07XG4iLCJpbXBvcnQgTmF0aXZlIGZyb20gJy4vTmF0aXZlLmpzJztcbmltcG9ydCBDdXN0b21FbGVtZW50SW50ZXJuYWxzIGZyb20gJy4uL0N1c3RvbUVsZW1lbnRJbnRlcm5hbHMuanMnO1xuaW1wb3J0ICogYXMgVXRpbGl0aWVzIGZyb20gJy4uL1V0aWxpdGllcy5qcyc7XG5cbmltcG9ydCBQYXRjaFBhcmVudE5vZGUgZnJvbSAnLi9JbnRlcmZhY2UvUGFyZW50Tm9kZS5qcyc7XG5cbi8qKlxuICogQHBhcmFtIHshQ3VzdG9tRWxlbWVudEludGVybmFsc30gaW50ZXJuYWxzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uKGludGVybmFscykge1xuICBVdGlsaXRpZXMuc2V0UHJvcGVydHlVbmNoZWNrZWQoRG9jdW1lbnQucHJvdG90eXBlLCAnY3JlYXRlRWxlbWVudCcsXG4gICAgLyoqXG4gICAgICogQHRoaXMge0RvY3VtZW50fVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsb2NhbE5hbWVcbiAgICAgKiBAcmV0dXJuIHshRWxlbWVudH1cbiAgICAgKi9cbiAgICBmdW5jdGlvbihsb2NhbE5hbWUpIHtcbiAgICAgIC8vIE9ubHkgY3JlYXRlIGN1c3RvbSBlbGVtZW50cyBpZiB0aGlzIGRvY3VtZW50IGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVnaXN0cnkuXG4gICAgICBpZiAodGhpcy5fX0NFX2hhc1JlZ2lzdHJ5KSB7XG4gICAgICAgIGNvbnN0IGRlZmluaXRpb24gPSBpbnRlcm5hbHMubG9jYWxOYW1lVG9EZWZpbml0aW9uKGxvY2FsTmFtZSk7XG4gICAgICAgIGlmIChkZWZpbml0aW9uKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyAoZGVmaW5pdGlvbi5jb25zdHJ1Y3RvcikoKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCByZXN1bHQgPSAvKiogQHR5cGUgeyFFbGVtZW50fSAqL1xuICAgICAgICAoTmF0aXZlLkRvY3VtZW50X2NyZWF0ZUVsZW1lbnQuY2FsbCh0aGlzLCBsb2NhbE5hbWUpKTtcbiAgICAgIGludGVybmFscy5wYXRjaChyZXN1bHQpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcblxuICBVdGlsaXRpZXMuc2V0UHJvcGVydHlVbmNoZWNrZWQoRG9jdW1lbnQucHJvdG90eXBlLCAnaW1wb3J0Tm9kZScsXG4gICAgLyoqXG4gICAgICogQHRoaXMge0RvY3VtZW50fVxuICAgICAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBkZWVwXG4gICAgICogQHJldHVybiB7IU5vZGV9XG4gICAgICovXG4gICAgZnVuY3Rpb24obm9kZSwgZGVlcCkge1xuICAgICAgY29uc3QgY2xvbmUgPSBOYXRpdmUuRG9jdW1lbnRfaW1wb3J0Tm9kZS5jYWxsKHRoaXMsIG5vZGUsIGRlZXApO1xuICAgICAgLy8gT25seSBjcmVhdGUgY3VzdG9tIGVsZW1lbnRzIGlmIHRoaXMgZG9jdW1lbnQgaXMgYXNzb2NpYXRlZCB3aXRoIHRoZSByZWdpc3RyeS5cbiAgICAgIGlmICghdGhpcy5fX0NFX2hhc1JlZ2lzdHJ5KSB7XG4gICAgICAgIGludGVybmFscy5wYXRjaFRyZWUoY2xvbmUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW50ZXJuYWxzLnBhdGNoQW5kVXBncmFkZVRyZWUoY2xvbmUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNsb25lO1xuICAgIH0pO1xuXG4gIGNvbnN0IE5TX0hUTUwgPSBcImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWxcIjtcblxuICBVdGlsaXRpZXMuc2V0UHJvcGVydHlVbmNoZWNrZWQoRG9jdW1lbnQucHJvdG90eXBlLCAnY3JlYXRlRWxlbWVudE5TJyxcbiAgICAvKipcbiAgICAgKiBAdGhpcyB7RG9jdW1lbnR9XG4gICAgICogQHBhcmFtIHs/c3RyaW5nfSBuYW1lc3BhY2VcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbG9jYWxOYW1lXG4gICAgICogQHJldHVybiB7IUVsZW1lbnR9XG4gICAgICovXG4gICAgZnVuY3Rpb24obmFtZXNwYWNlLCBsb2NhbE5hbWUpIHtcbiAgICAgIC8vIE9ubHkgY3JlYXRlIGN1c3RvbSBlbGVtZW50cyBpZiB0aGlzIGRvY3VtZW50IGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVnaXN0cnkuXG4gICAgICBpZiAodGhpcy5fX0NFX2hhc1JlZ2lzdHJ5ICYmIChuYW1lc3BhY2UgPT09IG51bGwgfHwgbmFtZXNwYWNlID09PSBOU19IVE1MKSkge1xuICAgICAgICBjb25zdCBkZWZpbml0aW9uID0gaW50ZXJuYWxzLmxvY2FsTmFtZVRvRGVmaW5pdGlvbihsb2NhbE5hbWUpO1xuICAgICAgICBpZiAoZGVmaW5pdGlvbikge1xuICAgICAgICAgIHJldHVybiBuZXcgKGRlZmluaXRpb24uY29uc3RydWN0b3IpKCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgcmVzdWx0ID0gLyoqIEB0eXBlIHshRWxlbWVudH0gKi9cbiAgICAgICAgKE5hdGl2ZS5Eb2N1bWVudF9jcmVhdGVFbGVtZW50TlMuY2FsbCh0aGlzLCBuYW1lc3BhY2UsIGxvY2FsTmFtZSkpO1xuICAgICAgaW50ZXJuYWxzLnBhdGNoKHJlc3VsdCk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pO1xuXG4gIFBhdGNoUGFyZW50Tm9kZShpbnRlcm5hbHMsIERvY3VtZW50LnByb3RvdHlwZSwge1xuICAgIHByZXBlbmQ6IE5hdGl2ZS5Eb2N1bWVudF9wcmVwZW5kLFxuICAgIGFwcGVuZDogTmF0aXZlLkRvY3VtZW50X2FwcGVuZCxcbiAgfSk7XG59O1xuIiwiaW1wb3J0IE5hdGl2ZSBmcm9tICcuL05hdGl2ZS5qcyc7XG5pbXBvcnQgQ3VzdG9tRWxlbWVudEludGVybmFscyBmcm9tICcuLi9DdXN0b21FbGVtZW50SW50ZXJuYWxzLmpzJztcbmltcG9ydCAqIGFzIFV0aWxpdGllcyBmcm9tICcuLi9VdGlsaXRpZXMuanMnO1xuXG4vKipcbiAqIEBwYXJhbSB7IUN1c3RvbUVsZW1lbnRJbnRlcm5hbHN9IGludGVybmFsc1xuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnRlcm5hbHMpIHtcbiAgLy8gYE5vZGUjbm9kZVZhbHVlYCBpcyBpbXBsZW1lbnRlZCBvbiBgQXR0cmAuXG4gIC8vIGBOb2RlI3RleHRDb250ZW50YCBpcyBpbXBsZW1lbnRlZCBvbiBgQXR0cmAsIGBFbGVtZW50YC5cblxuICBVdGlsaXRpZXMuc2V0UHJvcGVydHlVbmNoZWNrZWQoTm9kZS5wcm90b3R5cGUsICdpbnNlcnRCZWZvcmUnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtOb2RlfVxuICAgICAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAgICAgKiBAcGFyYW0gez9Ob2RlfSByZWZOb2RlXG4gICAgICogQHJldHVybiB7IU5vZGV9XG4gICAgICovXG4gICAgZnVuY3Rpb24obm9kZSwgcmVmTm9kZSkge1xuICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBEb2N1bWVudEZyYWdtZW50KSB7XG4gICAgICAgIGNvbnN0IGluc2VydGVkTm9kZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkobm9kZS5jaGlsZE5vZGVzKTtcbiAgICAgICAgY29uc3QgbmF0aXZlUmVzdWx0ID0gTmF0aXZlLk5vZGVfaW5zZXJ0QmVmb3JlLmNhbGwodGhpcywgbm9kZSwgcmVmTm9kZSk7XG5cbiAgICAgICAgLy8gRG9jdW1lbnRGcmFnbWVudHMgY2FuJ3QgYmUgY29ubmVjdGVkLCBzbyBgZGlzY29ubmVjdFRyZWVgIHdpbGwgbmV2ZXJcbiAgICAgICAgLy8gbmVlZCB0byBiZSBjYWxsZWQgb24gYSBEb2N1bWVudEZyYWdtZW50J3MgY2hpbGRyZW4gYWZ0ZXIgaW5zZXJ0aW5nIGl0LlxuXG4gICAgICAgIGlmIChVdGlsaXRpZXMuaXNDb25uZWN0ZWQodGhpcykpIHtcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluc2VydGVkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGludGVybmFscy5jb25uZWN0VHJlZShpbnNlcnRlZE5vZGVzW2ldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmF0aXZlUmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBub2RlV2FzQ29ubmVjdGVkID0gVXRpbGl0aWVzLmlzQ29ubmVjdGVkKG5vZGUpO1xuICAgICAgY29uc3QgbmF0aXZlUmVzdWx0ID0gTmF0aXZlLk5vZGVfaW5zZXJ0QmVmb3JlLmNhbGwodGhpcywgbm9kZSwgcmVmTm9kZSk7XG5cbiAgICAgIGlmIChub2RlV2FzQ29ubmVjdGVkKSB7XG4gICAgICAgIGludGVybmFscy5kaXNjb25uZWN0VHJlZShub2RlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKSkge1xuICAgICAgICBpbnRlcm5hbHMuY29ubmVjdFRyZWUobm9kZSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuYXRpdmVSZXN1bHQ7XG4gICAgfSk7XG5cbiAgVXRpbGl0aWVzLnNldFByb3BlcnR5VW5jaGVja2VkKE5vZGUucHJvdG90eXBlLCAnYXBwZW5kQ2hpbGQnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtOb2RlfVxuICAgICAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAgICAgKiBAcmV0dXJuIHshTm9kZX1cbiAgICAgKi9cbiAgICBmdW5jdGlvbihub2RlKSB7XG4gICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIERvY3VtZW50RnJhZ21lbnQpIHtcbiAgICAgICAgY29uc3QgaW5zZXJ0ZWROb2RlcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5hcHBseShub2RlLmNoaWxkTm9kZXMpO1xuICAgICAgICBjb25zdCBuYXRpdmVSZXN1bHQgPSBOYXRpdmUuTm9kZV9hcHBlbmRDaGlsZC5jYWxsKHRoaXMsIG5vZGUpO1xuXG4gICAgICAgIC8vIERvY3VtZW50RnJhZ21lbnRzIGNhbid0IGJlIGNvbm5lY3RlZCwgc28gYGRpc2Nvbm5lY3RUcmVlYCB3aWxsIG5ldmVyXG4gICAgICAgIC8vIG5lZWQgdG8gYmUgY2FsbGVkIG9uIGEgRG9jdW1lbnRGcmFnbWVudCdzIGNoaWxkcmVuIGFmdGVyIGluc2VydGluZyBpdC5cblxuICAgICAgICBpZiAoVXRpbGl0aWVzLmlzQ29ubmVjdGVkKHRoaXMpKSB7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnNlcnRlZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpbnRlcm5hbHMuY29ubmVjdFRyZWUoaW5zZXJ0ZWROb2Rlc1tpXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5hdGl2ZVJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgbm9kZVdhc0Nvbm5lY3RlZCA9IFV0aWxpdGllcy5pc0Nvbm5lY3RlZChub2RlKTtcbiAgICAgIGNvbnN0IG5hdGl2ZVJlc3VsdCA9IE5hdGl2ZS5Ob2RlX2FwcGVuZENoaWxkLmNhbGwodGhpcywgbm9kZSk7XG5cbiAgICAgIGlmIChub2RlV2FzQ29ubmVjdGVkKSB7XG4gICAgICAgIGludGVybmFscy5kaXNjb25uZWN0VHJlZShub2RlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKSkge1xuICAgICAgICBpbnRlcm5hbHMuY29ubmVjdFRyZWUobm9kZSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBuYXRpdmVSZXN1bHQ7XG4gICAgfSk7XG5cbiAgVXRpbGl0aWVzLnNldFByb3BlcnR5VW5jaGVja2VkKE5vZGUucHJvdG90eXBlLCAnY2xvbmVOb2RlJyxcbiAgICAvKipcbiAgICAgKiBAdGhpcyB7Tm9kZX1cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBkZWVwXG4gICAgICogQHJldHVybiB7IU5vZGV9XG4gICAgICovXG4gICAgZnVuY3Rpb24oZGVlcCkge1xuICAgICAgY29uc3QgY2xvbmUgPSBOYXRpdmUuTm9kZV9jbG9uZU5vZGUuY2FsbCh0aGlzLCBkZWVwKTtcbiAgICAgIC8vIE9ubHkgY3JlYXRlIGN1c3RvbSBlbGVtZW50cyBpZiB0aGlzIGVsZW1lbnQncyBvd25lciBkb2N1bWVudCBpc1xuICAgICAgLy8gYXNzb2NpYXRlZCB3aXRoIHRoZSByZWdpc3RyeS5cbiAgICAgIGlmICghdGhpcy5vd25lckRvY3VtZW50Ll9fQ0VfaGFzUmVnaXN0cnkpIHtcbiAgICAgICAgaW50ZXJuYWxzLnBhdGNoVHJlZShjbG9uZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpbnRlcm5hbHMucGF0Y2hBbmRVcGdyYWRlVHJlZShjbG9uZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY2xvbmU7XG4gICAgfSk7XG5cbiAgVXRpbGl0aWVzLnNldFByb3BlcnR5VW5jaGVja2VkKE5vZGUucHJvdG90eXBlLCAncmVtb3ZlQ2hpbGQnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtOb2RlfVxuICAgICAqIEBwYXJhbSB7IU5vZGV9IG5vZGVcbiAgICAgKiBAcmV0dXJuIHshTm9kZX1cbiAgICAgKi9cbiAgICBmdW5jdGlvbihub2RlKSB7XG4gICAgICBjb25zdCBub2RlV2FzQ29ubmVjdGVkID0gVXRpbGl0aWVzLmlzQ29ubmVjdGVkKG5vZGUpO1xuICAgICAgY29uc3QgbmF0aXZlUmVzdWx0ID0gTmF0aXZlLk5vZGVfcmVtb3ZlQ2hpbGQuY2FsbCh0aGlzLCBub2RlKTtcblxuICAgICAgaWYgKG5vZGVXYXNDb25uZWN0ZWQpIHtcbiAgICAgICAgaW50ZXJuYWxzLmRpc2Nvbm5lY3RUcmVlKG5vZGUpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbmF0aXZlUmVzdWx0O1xuICAgIH0pO1xuXG4gIFV0aWxpdGllcy5zZXRQcm9wZXJ0eVVuY2hlY2tlZChOb2RlLnByb3RvdHlwZSwgJ3JlcGxhY2VDaGlsZCcsXG4gICAgLyoqXG4gICAgICogQHRoaXMge05vZGV9XG4gICAgICogQHBhcmFtIHshTm9kZX0gbm9kZVRvSW5zZXJ0XG4gICAgICogQHBhcmFtIHshTm9kZX0gbm9kZVRvUmVtb3ZlXG4gICAgICogQHJldHVybiB7IU5vZGV9XG4gICAgICovXG4gICAgZnVuY3Rpb24obm9kZVRvSW5zZXJ0LCBub2RlVG9SZW1vdmUpIHtcbiAgICAgIGlmIChub2RlVG9JbnNlcnQgaW5zdGFuY2VvZiBEb2N1bWVudEZyYWdtZW50KSB7XG4gICAgICAgIGNvbnN0IGluc2VydGVkTm9kZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkobm9kZVRvSW5zZXJ0LmNoaWxkTm9kZXMpO1xuICAgICAgICBjb25zdCBuYXRpdmVSZXN1bHQgPSBOYXRpdmUuTm9kZV9yZXBsYWNlQ2hpbGQuY2FsbCh0aGlzLCBub2RlVG9JbnNlcnQsIG5vZGVUb1JlbW92ZSk7XG5cbiAgICAgICAgLy8gRG9jdW1lbnRGcmFnbWVudHMgY2FuJ3QgYmUgY29ubmVjdGVkLCBzbyBgZGlzY29ubmVjdFRyZWVgIHdpbGwgbmV2ZXJcbiAgICAgICAgLy8gbmVlZCB0byBiZSBjYWxsZWQgb24gYSBEb2N1bWVudEZyYWdtZW50J3MgY2hpbGRyZW4gYWZ0ZXIgaW5zZXJ0aW5nIGl0LlxuXG4gICAgICAgIGlmIChVdGlsaXRpZXMuaXNDb25uZWN0ZWQodGhpcykpIHtcbiAgICAgICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUobm9kZVRvUmVtb3ZlKTtcbiAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluc2VydGVkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGludGVybmFscy5jb25uZWN0VHJlZShpbnNlcnRlZE5vZGVzW2ldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmF0aXZlUmVzdWx0O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBub2RlVG9JbnNlcnRXYXNDb25uZWN0ZWQgPSBVdGlsaXRpZXMuaXNDb25uZWN0ZWQobm9kZVRvSW5zZXJ0KTtcbiAgICAgIGNvbnN0IG5hdGl2ZVJlc3VsdCA9IE5hdGl2ZS5Ob2RlX3JlcGxhY2VDaGlsZC5jYWxsKHRoaXMsIG5vZGVUb0luc2VydCwgbm9kZVRvUmVtb3ZlKTtcbiAgICAgIGNvbnN0IHRoaXNJc0Nvbm5lY3RlZCA9IFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKTtcblxuICAgICAgaWYgKHRoaXNJc0Nvbm5lY3RlZCkge1xuICAgICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUobm9kZVRvUmVtb3ZlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG5vZGVUb0luc2VydFdhc0Nvbm5lY3RlZCkge1xuICAgICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUobm9kZVRvSW5zZXJ0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXNJc0Nvbm5lY3RlZCkge1xuICAgICAgICBpbnRlcm5hbHMuY29ubmVjdFRyZWUobm9kZVRvSW5zZXJ0KTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG5hdGl2ZVJlc3VsdDtcbiAgICB9KTtcblxuXG4gIGZ1bmN0aW9uIHBhdGNoX3RleHRDb250ZW50KGRlc3RpbmF0aW9uLCBiYXNlRGVzY3JpcHRvcikge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkZXN0aW5hdGlvbiwgJ3RleHRDb250ZW50Jywge1xuICAgICAgZW51bWVyYWJsZTogYmFzZURlc2NyaXB0b3IuZW51bWVyYWJsZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIGdldDogYmFzZURlc2NyaXB0b3IuZ2V0LFxuICAgICAgc2V0OiAvKiogQHRoaXMge05vZGV9ICovIGZ1bmN0aW9uKGFzc2lnbmVkVmFsdWUpIHtcbiAgICAgICAgLy8gSWYgdGhpcyBpcyBhIHRleHQgbm9kZSB0aGVuIHRoZXJlIGFyZSBubyBub2RlcyB0byBkaXNjb25uZWN0LlxuICAgICAgICBpZiAodGhpcy5ub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcbiAgICAgICAgICBiYXNlRGVzY3JpcHRvci5zZXQuY2FsbCh0aGlzLCBhc3NpZ25lZFZhbHVlKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVtb3ZlZE5vZGVzID0gdW5kZWZpbmVkO1xuICAgICAgICAvLyBDaGVja2luZyBmb3IgYGZpcnN0Q2hpbGRgIGlzIGZhc3RlciB0aGFuIHJlYWRpbmcgYGNoaWxkTm9kZXMubGVuZ3RoYFxuICAgICAgICAvLyB0byBjb21wYXJlIHdpdGggMC5cbiAgICAgICAgaWYgKHRoaXMuZmlyc3RDaGlsZCkge1xuICAgICAgICAgIC8vIFVzaW5nIGBjaGlsZE5vZGVzYCBpcyBmYXN0ZXIgdGhhbiBgY2hpbGRyZW5gLCBldmVuIHRob3VnaCB3ZSBvbmx5XG4gICAgICAgICAgLy8gY2FyZSBhYm91dCBlbGVtZW50cy5cbiAgICAgICAgICBjb25zdCBjaGlsZE5vZGVzID0gdGhpcy5jaGlsZE5vZGVzO1xuICAgICAgICAgIGNvbnN0IGNoaWxkTm9kZXNMZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICBpZiAoY2hpbGROb2Rlc0xlbmd0aCA+IDAgJiYgVXRpbGl0aWVzLmlzQ29ubmVjdGVkKHRoaXMpKSB7XG4gICAgICAgICAgICAvLyBDb3B5aW5nIGFuIGFycmF5IGJ5IGl0ZXJhdGluZyBpcyBmYXN0ZXIgdGhhbiB1c2luZyBzbGljZS5cbiAgICAgICAgICAgIHJlbW92ZWROb2RlcyA9IG5ldyBBcnJheShjaGlsZE5vZGVzTGVuZ3RoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGROb2Rlc0xlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgIHJlbW92ZWROb2Rlc1tpXSA9IGNoaWxkTm9kZXNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgYmFzZURlc2NyaXB0b3Iuc2V0LmNhbGwodGhpcywgYXNzaWduZWRWYWx1ZSk7XG5cbiAgICAgICAgaWYgKHJlbW92ZWROb2Rlcykge1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVtb3ZlZE5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUocmVtb3ZlZE5vZGVzW2ldKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBpZiAoTmF0aXZlLk5vZGVfdGV4dENvbnRlbnQgJiYgTmF0aXZlLk5vZGVfdGV4dENvbnRlbnQuZ2V0KSB7XG4gICAgcGF0Y2hfdGV4dENvbnRlbnQoTm9kZS5wcm90b3R5cGUsIE5hdGl2ZS5Ob2RlX3RleHRDb250ZW50KTtcbiAgfSBlbHNlIHtcbiAgICBpbnRlcm5hbHMuYWRkUGF0Y2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgcGF0Y2hfdGV4dENvbnRlbnQoZWxlbWVudCwge1xuICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIC8vIE5PVEU6IFRoaXMgaW1wbGVtZW50YXRpb24gb2YgdGhlIGB0ZXh0Q29udGVudGAgZ2V0dGVyIGFzc3VtZXMgdGhhdFxuICAgICAgICAvLyB0ZXh0IG5vZGVzJyBgdGV4dENvbnRlbnRgIGdldHRlciB3aWxsIG5vdCBiZSBwYXRjaGVkLlxuICAgICAgICBnZXQ6IC8qKiBAdGhpcyB7Tm9kZX0gKi8gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgLyoqIEB0eXBlIHshQXJyYXk8c3RyaW5nPn0gKi9cbiAgICAgICAgICBjb25zdCBwYXJ0cyA9IFtdO1xuXG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHBhcnRzLnB1c2godGhpcy5jaGlsZE5vZGVzW2ldLnRleHRDb250ZW50KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcGFydHMuam9pbignJyk7XG4gICAgICAgIH0sXG4gICAgICAgIHNldDogLyoqIEB0aGlzIHtOb2RlfSAqLyBmdW5jdGlvbihhc3NpZ25lZFZhbHVlKSB7XG4gICAgICAgICAgd2hpbGUgKHRoaXMuZmlyc3RDaGlsZCkge1xuICAgICAgICAgICAgTmF0aXZlLk5vZGVfcmVtb3ZlQ2hpbGQuY2FsbCh0aGlzLCB0aGlzLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBOYXRpdmUuTm9kZV9hcHBlbmRDaGlsZC5jYWxsKHRoaXMsIGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGFzc2lnbmVkVmFsdWUpKTtcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG59O1xuIiwiaW1wb3J0IEN1c3RvbUVsZW1lbnRJbnRlcm5hbHMgZnJvbSAnLi4vLi4vQ3VzdG9tRWxlbWVudEludGVybmFscy5qcyc7XG5pbXBvcnQgKiBhcyBVdGlsaXRpZXMgZnJvbSAnLi4vLi4vVXRpbGl0aWVzLmpzJztcblxuLyoqXG4gKiBAdHlwZWRlZiB7e1xuICogICBiZWZvcmU6ICFmdW5jdGlvbiguLi4oIU5vZGV8c3RyaW5nKSksXG4gKiAgIGFmdGVyOiAhZnVuY3Rpb24oLi4uKCFOb2RlfHN0cmluZykpLFxuICogICByZXBsYWNlV2l0aDogIWZ1bmN0aW9uKC4uLighTm9kZXxzdHJpbmcpKSxcbiAqICAgcmVtb3ZlOiAhZnVuY3Rpb24oKSxcbiAqIH19XG4gKi9cbmxldCBDaGlsZE5vZGVOYXRpdmVNZXRob2RzO1xuXG4vKipcbiAqIEBwYXJhbSB7IUN1c3RvbUVsZW1lbnRJbnRlcm5hbHN9IGludGVybmFsc1xuICogQHBhcmFtIHshT2JqZWN0fSBkZXN0aW5hdGlvblxuICogQHBhcmFtIHshQ2hpbGROb2RlTmF0aXZlTWV0aG9kc30gYnVpbHRJblxuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnRlcm5hbHMsIGRlc3RpbmF0aW9uLCBidWlsdEluKSB7XG4gIC8qKlxuICAgKiBAcGFyYW0gey4uLighTm9kZXxzdHJpbmcpfSBub2Rlc1xuICAgKi9cbiAgZGVzdGluYXRpb25bJ2JlZm9yZSddID0gZnVuY3Rpb24oLi4ubm9kZXMpIHtcbiAgICAvLyBUT0RPOiBGaXggdGhpcyBmb3Igd2hlbiBvbmUgb2YgYG5vZGVzYCBpcyBhIERvY3VtZW50RnJhZ21lbnQhXG4gICAgY29uc3QgY29ubmVjdGVkQmVmb3JlID0gLyoqIEB0eXBlIHshQXJyYXk8IU5vZGU+fSAqLyAobm9kZXMuZmlsdGVyKG5vZGUgPT4ge1xuICAgICAgLy8gRG9jdW1lbnRGcmFnbWVudHMgYXJlIG5vdCBjb25uZWN0ZWQgYW5kIHdpbGwgbm90IGJlIGFkZGVkIHRvIHRoZSBsaXN0LlxuICAgICAgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBOb2RlICYmIFV0aWxpdGllcy5pc0Nvbm5lY3RlZChub2RlKTtcbiAgICB9KSk7XG5cbiAgICBidWlsdEluLmJlZm9yZS5hcHBseSh0aGlzLCBub2Rlcyk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbm5lY3RlZEJlZm9yZS5sZW5ndGg7IGkrKykge1xuICAgICAgaW50ZXJuYWxzLmRpc2Nvbm5lY3RUcmVlKGNvbm5lY3RlZEJlZm9yZVtpXSk7XG4gICAgfVxuXG4gICAgaWYgKFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKSkge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBub2RlID0gbm9kZXNbaV07XG4gICAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgRWxlbWVudCkge1xuICAgICAgICAgIGludGVybmFscy5jb25uZWN0VHJlZShub2RlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQHBhcmFtIHsuLi4oIU5vZGV8c3RyaW5nKX0gbm9kZXNcbiAgICovXG4gIGRlc3RpbmF0aW9uWydhZnRlciddID0gZnVuY3Rpb24oLi4ubm9kZXMpIHtcbiAgICAvLyBUT0RPOiBGaXggdGhpcyBmb3Igd2hlbiBvbmUgb2YgYG5vZGVzYCBpcyBhIERvY3VtZW50RnJhZ21lbnQhXG4gICAgY29uc3QgY29ubmVjdGVkQmVmb3JlID0gLyoqIEB0eXBlIHshQXJyYXk8IU5vZGU+fSAqLyAobm9kZXMuZmlsdGVyKG5vZGUgPT4ge1xuICAgICAgLy8gRG9jdW1lbnRGcmFnbWVudHMgYXJlIG5vdCBjb25uZWN0ZWQgYW5kIHdpbGwgbm90IGJlIGFkZGVkIHRvIHRoZSBsaXN0LlxuICAgICAgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBOb2RlICYmIFV0aWxpdGllcy5pc0Nvbm5lY3RlZChub2RlKTtcbiAgICB9KSk7XG5cbiAgICBidWlsdEluLmFmdGVyLmFwcGx5KHRoaXMsIG5vZGVzKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29ubmVjdGVkQmVmb3JlLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpbnRlcm5hbHMuZGlzY29ubmVjdFRyZWUoY29ubmVjdGVkQmVmb3JlW2ldKTtcbiAgICB9XG5cbiAgICBpZiAoVXRpbGl0aWVzLmlzQ29ubmVjdGVkKHRoaXMpKSB7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5vZGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBFbGVtZW50KSB7XG4gICAgICAgICAgaW50ZXJuYWxzLmNvbm5lY3RUcmVlKG5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBAcGFyYW0gey4uLighTm9kZXxzdHJpbmcpfSBub2Rlc1xuICAgKi9cbiAgZGVzdGluYXRpb25bJ3JlcGxhY2VXaXRoJ10gPSBmdW5jdGlvbiguLi5ub2Rlcykge1xuICAgIC8vIFRPRE86IEZpeCB0aGlzIGZvciB3aGVuIG9uZSBvZiBgbm9kZXNgIGlzIGEgRG9jdW1lbnRGcmFnbWVudCFcbiAgICBjb25zdCBjb25uZWN0ZWRCZWZvcmUgPSAvKiogQHR5cGUgeyFBcnJheTwhTm9kZT59ICovIChub2Rlcy5maWx0ZXIobm9kZSA9PiB7XG4gICAgICAvLyBEb2N1bWVudEZyYWdtZW50cyBhcmUgbm90IGNvbm5lY3RlZCBhbmQgd2lsbCBub3QgYmUgYWRkZWQgdG8gdGhlIGxpc3QuXG4gICAgICByZXR1cm4gbm9kZSBpbnN0YW5jZW9mIE5vZGUgJiYgVXRpbGl0aWVzLmlzQ29ubmVjdGVkKG5vZGUpO1xuICAgIH0pKTtcblxuICAgIGNvbnN0IHdhc0Nvbm5lY3RlZCA9IFV0aWxpdGllcy5pc0Nvbm5lY3RlZCh0aGlzKTtcblxuICAgIGJ1aWx0SW4ucmVwbGFjZVdpdGguYXBwbHkodGhpcywgbm9kZXMpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb25uZWN0ZWRCZWZvcmUubGVuZ3RoOyBpKyspIHtcbiAgICAgIGludGVybmFscy5kaXNjb25uZWN0VHJlZShjb25uZWN0ZWRCZWZvcmVbaV0pO1xuICAgIH1cblxuICAgIGlmICh3YXNDb25uZWN0ZWQpIHtcbiAgICAgIGludGVybmFscy5kaXNjb25uZWN0VHJlZSh0aGlzKTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3Qgbm9kZSA9IG5vZGVzW2ldO1xuICAgICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIEVsZW1lbnQpIHtcbiAgICAgICAgICBpbnRlcm5hbHMuY29ubmVjdFRyZWUobm9kZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgZGVzdGluYXRpb25bJ3JlbW92ZSddID0gZnVuY3Rpb24oKSB7XG4gICAgY29uc3Qgd2FzQ29ubmVjdGVkID0gVXRpbGl0aWVzLmlzQ29ubmVjdGVkKHRoaXMpO1xuXG4gICAgYnVpbHRJbi5yZW1vdmUuY2FsbCh0aGlzKTtcblxuICAgIGlmICh3YXNDb25uZWN0ZWQpIHtcbiAgICAgIGludGVybmFscy5kaXNjb25uZWN0VHJlZSh0aGlzKTtcbiAgICB9XG4gIH07XG59O1xuIiwiaW1wb3J0IE5hdGl2ZSBmcm9tICcuL05hdGl2ZS5qcyc7XG5pbXBvcnQgQ3VzdG9tRWxlbWVudEludGVybmFscyBmcm9tICcuLi9DdXN0b21FbGVtZW50SW50ZXJuYWxzLmpzJztcbmltcG9ydCBDRVN0YXRlIGZyb20gJy4uL0N1c3RvbUVsZW1lbnRTdGF0ZS5qcyc7XG5pbXBvcnQgKiBhcyBVdGlsaXRpZXMgZnJvbSAnLi4vVXRpbGl0aWVzLmpzJztcblxuaW1wb3J0IFBhdGNoUGFyZW50Tm9kZSBmcm9tICcuL0ludGVyZmFjZS9QYXJlbnROb2RlLmpzJztcbmltcG9ydCBQYXRjaENoaWxkTm9kZSBmcm9tICcuL0ludGVyZmFjZS9DaGlsZE5vZGUuanMnO1xuXG4vKipcbiAqIEBwYXJhbSB7IUN1c3RvbUVsZW1lbnRJbnRlcm5hbHN9IGludGVybmFsc1xuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbihpbnRlcm5hbHMpIHtcbiAgaWYgKE5hdGl2ZS5FbGVtZW50X2F0dGFjaFNoYWRvdykge1xuICAgIFV0aWxpdGllcy5zZXRQcm9wZXJ0eVVuY2hlY2tlZChFbGVtZW50LnByb3RvdHlwZSwgJ2F0dGFjaFNoYWRvdycsXG4gICAgICAvKipcbiAgICAgICAqIEB0aGlzIHtFbGVtZW50fVxuICAgICAgICogQHBhcmFtIHshe21vZGU6IHN0cmluZ319IGluaXRcbiAgICAgICAqIEByZXR1cm4ge1NoYWRvd1Jvb3R9XG4gICAgICAgKi9cbiAgICAgIGZ1bmN0aW9uKGluaXQpIHtcbiAgICAgICAgY29uc3Qgc2hhZG93Um9vdCA9IE5hdGl2ZS5FbGVtZW50X2F0dGFjaFNoYWRvdy5jYWxsKHRoaXMsIGluaXQpO1xuICAgICAgICB0aGlzLl9fQ0Vfc2hhZG93Um9vdCA9IHNoYWRvd1Jvb3Q7XG4gICAgICAgIHJldHVybiBzaGFkb3dSb290O1xuICAgICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS53YXJuKCdDdXN0b20gRWxlbWVudHM6IGBFbGVtZW50I2F0dGFjaFNoYWRvd2Agd2FzIG5vdCBwYXRjaGVkLicpO1xuICB9XG5cblxuICBmdW5jdGlvbiBwYXRjaF9pbm5lckhUTUwoZGVzdGluYXRpb24sIGJhc2VEZXNjcmlwdG9yKSB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRlc3RpbmF0aW9uLCAnaW5uZXJIVE1MJywge1xuICAgICAgZW51bWVyYWJsZTogYmFzZURlc2NyaXB0b3IuZW51bWVyYWJsZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIGdldDogYmFzZURlc2NyaXB0b3IuZ2V0LFxuICAgICAgc2V0OiAvKiogQHRoaXMge0VsZW1lbnR9ICovIGZ1bmN0aW9uKGh0bWxTdHJpbmcpIHtcbiAgICAgICAgY29uc3QgaXNDb25uZWN0ZWQgPSBVdGlsaXRpZXMuaXNDb25uZWN0ZWQodGhpcyk7XG5cbiAgICAgICAgLy8gTk9URTogSW4gSUUxMSwgd2hlbiB1c2luZyB0aGUgbmF0aXZlIGBpbm5lckhUTUxgIHNldHRlciwgYWxsIG5vZGVzXG4gICAgICAgIC8vIHRoYXQgd2VyZSBwcmV2aW91c2x5IGRlc2NlbmRhbnRzIG9mIHRoZSBjb250ZXh0IGVsZW1lbnQgaGF2ZSBhbGwgb2ZcbiAgICAgICAgLy8gdGhlaXIgY2hpbGRyZW4gcmVtb3ZlZCBhcyBwYXJ0IG9mIHRoZSBzZXQgLSB0aGUgZW50aXJlIHN1YnRyZWUgaXNcbiAgICAgICAgLy8gJ2Rpc2Fzc2VtYmxlZCcuIFRoaXMgd29yayBhcm91bmQgd2Fsa3MgdGhlIHN1YnRyZWUgKmJlZm9yZSogdXNpbmcgdGhlXG4gICAgICAgIC8vIG5hdGl2ZSBzZXR0ZXIuXG4gICAgICAgIC8qKiBAdHlwZSB7IUFycmF5PCFFbGVtZW50Pnx1bmRlZmluZWR9ICovXG4gICAgICAgIGxldCByZW1vdmVkRWxlbWVudHMgPSB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChpc0Nvbm5lY3RlZCkge1xuICAgICAgICAgIHJlbW92ZWRFbGVtZW50cyA9IFtdO1xuICAgICAgICAgIFV0aWxpdGllcy53YWxrRGVlcERlc2NlbmRhbnRFbGVtZW50cyh0aGlzLCBlbGVtZW50ID0+IHtcbiAgICAgICAgICAgIGlmIChlbGVtZW50ICE9PSB0aGlzKSB7XG4gICAgICAgICAgICAgIHJlbW92ZWRFbGVtZW50cy5wdXNoKGVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgYmFzZURlc2NyaXB0b3Iuc2V0LmNhbGwodGhpcywgaHRtbFN0cmluZyk7XG5cbiAgICAgICAgaWYgKHJlbW92ZWRFbGVtZW50cykge1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVtb3ZlZEVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBlbGVtZW50ID0gcmVtb3ZlZEVsZW1lbnRzW2ldO1xuICAgICAgICAgICAgaWYgKGVsZW1lbnQuX19DRV9zdGF0ZSA9PT0gQ0VTdGF0ZS5jdXN0b20pIHtcbiAgICAgICAgICAgICAgaW50ZXJuYWxzLmRpc2Nvbm5lY3RlZENhbGxiYWNrKGVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE9ubHkgY3JlYXRlIGN1c3RvbSBlbGVtZW50cyBpZiB0aGlzIGVsZW1lbnQncyBvd25lciBkb2N1bWVudCBpc1xuICAgICAgICAvLyBhc3NvY2lhdGVkIHdpdGggdGhlIHJlZ2lzdHJ5LlxuICAgICAgICBpZiAoIXRoaXMub3duZXJEb2N1bWVudC5fX0NFX2hhc1JlZ2lzdHJ5KSB7XG4gICAgICAgICAgaW50ZXJuYWxzLnBhdGNoVHJlZSh0aGlzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpbnRlcm5hbHMucGF0Y2hBbmRVcGdyYWRlVHJlZSh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaHRtbFN0cmluZztcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBpZiAoTmF0aXZlLkVsZW1lbnRfaW5uZXJIVE1MICYmIE5hdGl2ZS5FbGVtZW50X2lubmVySFRNTC5nZXQpIHtcbiAgICBwYXRjaF9pbm5lckhUTUwoRWxlbWVudC5wcm90b3R5cGUsIE5hdGl2ZS5FbGVtZW50X2lubmVySFRNTCk7XG4gIH0gZWxzZSBpZiAoTmF0aXZlLkhUTUxFbGVtZW50X2lubmVySFRNTCAmJiBOYXRpdmUuSFRNTEVsZW1lbnRfaW5uZXJIVE1MLmdldCkge1xuICAgIHBhdGNoX2lubmVySFRNTChIVE1MRWxlbWVudC5wcm90b3R5cGUsIE5hdGl2ZS5IVE1MRWxlbWVudF9pbm5lckhUTUwpO1xuICB9IGVsc2Uge1xuXG4gICAgLyoqIEB0eXBlIHtIVE1MRGl2RWxlbWVudH0gKi9cbiAgICBjb25zdCByYXdEaXYgPSBOYXRpdmUuRG9jdW1lbnRfY3JlYXRlRWxlbWVudC5jYWxsKGRvY3VtZW50LCAnZGl2Jyk7XG5cbiAgICBpbnRlcm5hbHMuYWRkUGF0Y2goZnVuY3Rpb24oZWxlbWVudCkge1xuICAgICAgcGF0Y2hfaW5uZXJIVE1MKGVsZW1lbnQsIHtcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAvLyBJbXBsZW1lbnRzIGdldHRpbmcgYGlubmVySFRNTGAgYnkgcGVyZm9ybWluZyBhbiB1bnBhdGNoZWQgYGNsb25lTm9kZWBcbiAgICAgICAgLy8gb2YgdGhlIGVsZW1lbnQgYW5kIHJldHVybmluZyB0aGUgcmVzdWx0aW5nIGVsZW1lbnQncyBgaW5uZXJIVE1MYC5cbiAgICAgICAgLy8gVE9ETzogSXMgdGhpcyB0b28gZXhwZW5zaXZlP1xuICAgICAgICBnZXQ6IC8qKiBAdGhpcyB7RWxlbWVudH0gKi8gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgcmV0dXJuIE5hdGl2ZS5Ob2RlX2Nsb25lTm9kZS5jYWxsKHRoaXMsIHRydWUpLmlubmVySFRNTDtcbiAgICAgICAgfSxcbiAgICAgICAgLy8gSW1wbGVtZW50cyBzZXR0aW5nIGBpbm5lckhUTUxgIGJ5IGNyZWF0aW5nIGFuIHVucGF0Y2hlZCBlbGVtZW50LFxuICAgICAgICAvLyBzZXR0aW5nIGBpbm5lckhUTUxgIG9mIHRoYXQgZWxlbWVudCBhbmQgcmVwbGFjaW5nIHRoZSB0YXJnZXRcbiAgICAgICAgLy8gZWxlbWVudCdzIGNoaWxkcmVuIHdpdGggdGhvc2Ugb2YgdGhlIHVucGF0Y2hlZCBlbGVtZW50LlxuICAgICAgICBzZXQ6IC8qKiBAdGhpcyB7RWxlbWVudH0gKi8gZnVuY3Rpb24oYXNzaWduZWRWYWx1ZSkge1xuICAgICAgICAgIC8vIE5PVEU6IHJlLXJvdXRlIHRvIGBjb250ZW50YCBmb3IgYHRlbXBsYXRlYCBlbGVtZW50cy5cbiAgICAgICAgICAvLyBXZSBuZWVkIHRvIGRvIHRoaXMgYmVjYXVzZSBgdGVtcGxhdGUuYXBwZW5kQ2hpbGRgIGRvZXMgbm90XG4gICAgICAgICAgLy8gcm91dGUgaW50byBgdGVtcGxhdGUuY29udGVudGAuXG4gICAgICAgICAgLyoqIEB0eXBlIHshTm9kZX0gKi9cbiAgICAgICAgICBjb25zdCBjb250ZW50ID0gdGhpcy5sb2NhbE5hbWUgPT09ICd0ZW1wbGF0ZScgPyAoLyoqIEB0eXBlIHshSFRNTFRlbXBsYXRlRWxlbWVudH0gKi8gKHRoaXMpKS5jb250ZW50IDogdGhpcztcbiAgICAgICAgICByYXdEaXYuaW5uZXJIVE1MID0gYXNzaWduZWRWYWx1ZTtcblxuICAgICAgICAgIHdoaWxlIChjb250ZW50LmNoaWxkTm9kZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgTmF0aXZlLk5vZGVfcmVtb3ZlQ2hpbGQuY2FsbChjb250ZW50LCBjb250ZW50LmNoaWxkTm9kZXNbMF0pO1xuICAgICAgICAgIH1cbiAgICAgICAgICB3aGlsZSAocmF3RGl2LmNoaWxkTm9kZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgTmF0aXZlLk5vZGVfYXBwZW5kQ2hpbGQuY2FsbChjb250ZW50LCByYXdEaXYuY2hpbGROb2Rlc1swXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuXG4gIFV0aWxpdGllcy5zZXRQcm9wZXJ0eVVuY2hlY2tlZChFbGVtZW50LnByb3RvdHlwZSwgJ3NldEF0dHJpYnV0ZScsXG4gICAgLyoqXG4gICAgICogQHRoaXMge0VsZW1lbnR9XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmV3VmFsdWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbihuYW1lLCBuZXdWYWx1ZSkge1xuICAgICAgLy8gRmFzdCBwYXRoIGZvciBub24tY3VzdG9tIGVsZW1lbnRzLlxuICAgICAgaWYgKHRoaXMuX19DRV9zdGF0ZSAhPT0gQ0VTdGF0ZS5jdXN0b20pIHtcbiAgICAgICAgcmV0dXJuIE5hdGl2ZS5FbGVtZW50X3NldEF0dHJpYnV0ZS5jYWxsKHRoaXMsIG5hbWUsIG5ld1ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb2xkVmFsdWUgPSBOYXRpdmUuRWxlbWVudF9nZXRBdHRyaWJ1dGUuY2FsbCh0aGlzLCBuYW1lKTtcbiAgICAgIE5hdGl2ZS5FbGVtZW50X3NldEF0dHJpYnV0ZS5jYWxsKHRoaXMsIG5hbWUsIG5ld1ZhbHVlKTtcbiAgICAgIG5ld1ZhbHVlID0gTmF0aXZlLkVsZW1lbnRfZ2V0QXR0cmlidXRlLmNhbGwodGhpcywgbmFtZSk7XG4gICAgICBpbnRlcm5hbHMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKHRoaXMsIG5hbWUsIG9sZFZhbHVlLCBuZXdWYWx1ZSwgbnVsbCk7XG4gICAgfSk7XG5cbiAgVXRpbGl0aWVzLnNldFByb3BlcnR5VW5jaGVja2VkKEVsZW1lbnQucHJvdG90eXBlLCAnc2V0QXR0cmlidXRlTlMnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtFbGVtZW50fVxuICAgICAqIEBwYXJhbSB7P3N0cmluZ30gbmFtZXNwYWNlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmV3VmFsdWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbihuYW1lc3BhY2UsIG5hbWUsIG5ld1ZhbHVlKSB7XG4gICAgICAvLyBGYXN0IHBhdGggZm9yIG5vbi1jdXN0b20gZWxlbWVudHMuXG4gICAgICBpZiAodGhpcy5fX0NFX3N0YXRlICE9PSBDRVN0YXRlLmN1c3RvbSkge1xuICAgICAgICByZXR1cm4gTmF0aXZlLkVsZW1lbnRfc2V0QXR0cmlidXRlTlMuY2FsbCh0aGlzLCBuYW1lc3BhY2UsIG5hbWUsIG5ld1ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb2xkVmFsdWUgPSBOYXRpdmUuRWxlbWVudF9nZXRBdHRyaWJ1dGVOUy5jYWxsKHRoaXMsIG5hbWVzcGFjZSwgbmFtZSk7XG4gICAgICBOYXRpdmUuRWxlbWVudF9zZXRBdHRyaWJ1dGVOUy5jYWxsKHRoaXMsIG5hbWVzcGFjZSwgbmFtZSwgbmV3VmFsdWUpO1xuICAgICAgbmV3VmFsdWUgPSBOYXRpdmUuRWxlbWVudF9nZXRBdHRyaWJ1dGVOUy5jYWxsKHRoaXMsIG5hbWVzcGFjZSwgbmFtZSk7XG4gICAgICBpbnRlcm5hbHMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKHRoaXMsIG5hbWUsIG9sZFZhbHVlLCBuZXdWYWx1ZSwgbmFtZXNwYWNlKTtcbiAgICB9KTtcblxuICBVdGlsaXRpZXMuc2V0UHJvcGVydHlVbmNoZWNrZWQoRWxlbWVudC5wcm90b3R5cGUsICdyZW1vdmVBdHRyaWJ1dGUnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtFbGVtZW50fVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAgICovXG4gICAgZnVuY3Rpb24obmFtZSkge1xuICAgICAgLy8gRmFzdCBwYXRoIGZvciBub24tY3VzdG9tIGVsZW1lbnRzLlxuICAgICAgaWYgKHRoaXMuX19DRV9zdGF0ZSAhPT0gQ0VTdGF0ZS5jdXN0b20pIHtcbiAgICAgICAgcmV0dXJuIE5hdGl2ZS5FbGVtZW50X3JlbW92ZUF0dHJpYnV0ZS5jYWxsKHRoaXMsIG5hbWUpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBvbGRWYWx1ZSA9IE5hdGl2ZS5FbGVtZW50X2dldEF0dHJpYnV0ZS5jYWxsKHRoaXMsIG5hbWUpO1xuICAgICAgTmF0aXZlLkVsZW1lbnRfcmVtb3ZlQXR0cmlidXRlLmNhbGwodGhpcywgbmFtZSk7XG4gICAgICBpZiAob2xkVmFsdWUgIT09IG51bGwpIHtcbiAgICAgICAgaW50ZXJuYWxzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayh0aGlzLCBuYW1lLCBvbGRWYWx1ZSwgbnVsbCwgbnVsbCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgVXRpbGl0aWVzLnNldFByb3BlcnR5VW5jaGVja2VkKEVsZW1lbnQucHJvdG90eXBlLCAncmVtb3ZlQXR0cmlidXRlTlMnLFxuICAgIC8qKlxuICAgICAqIEB0aGlzIHtFbGVtZW50fVxuICAgICAqIEBwYXJhbSB7P3N0cmluZ30gbmFtZXNwYWNlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbihuYW1lc3BhY2UsIG5hbWUpIHtcbiAgICAgIC8vIEZhc3QgcGF0aCBmb3Igbm9uLWN1c3RvbSBlbGVtZW50cy5cbiAgICAgIGlmICh0aGlzLl9fQ0Vfc3RhdGUgIT09IENFU3RhdGUuY3VzdG9tKSB7XG4gICAgICAgIHJldHVybiBOYXRpdmUuRWxlbWVudF9yZW1vdmVBdHRyaWJ1dGVOUy5jYWxsKHRoaXMsIG5hbWVzcGFjZSwgbmFtZSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG9sZFZhbHVlID0gTmF0aXZlLkVsZW1lbnRfZ2V0QXR0cmlidXRlTlMuY2FsbCh0aGlzLCBuYW1lc3BhY2UsIG5hbWUpO1xuICAgICAgTmF0aXZlLkVsZW1lbnRfcmVtb3ZlQXR0cmlidXRlTlMuY2FsbCh0aGlzLCBuYW1lc3BhY2UsIG5hbWUpO1xuICAgICAgLy8gSW4gb2xkZXIgYnJvd3NlcnMsIGBFbGVtZW50I2dldEF0dHJpYnV0ZU5TYCBtYXkgcmV0dXJuIHRoZSBlbXB0eSBzdHJpbmdcbiAgICAgIC8vIGluc3RlYWQgb2YgbnVsbCBpZiB0aGUgYXR0cmlidXRlIGRvZXMgbm90IGV4aXN0LiBGb3IgZGV0YWlscywgc2VlO1xuICAgICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0VsZW1lbnQvZ2V0QXR0cmlidXRlTlMjTm90ZXNcbiAgICAgIGNvbnN0IG5ld1ZhbHVlID0gTmF0aXZlLkVsZW1lbnRfZ2V0QXR0cmlidXRlTlMuY2FsbCh0aGlzLCBuYW1lc3BhY2UsIG5hbWUpO1xuICAgICAgaWYgKG9sZFZhbHVlICE9PSBuZXdWYWx1ZSkge1xuICAgICAgICBpbnRlcm5hbHMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKHRoaXMsIG5hbWUsIG9sZFZhbHVlLCBuZXdWYWx1ZSwgbmFtZXNwYWNlKTtcbiAgICAgIH1cbiAgICB9KTtcblxuXG4gIGZ1bmN0aW9uIHBhdGNoX2luc2VydEFkamFjZW50RWxlbWVudChkZXN0aW5hdGlvbiwgYmFzZU1ldGhvZCkge1xuICAgIFV0aWxpdGllcy5zZXRQcm9wZXJ0eVVuY2hlY2tlZChkZXN0aW5hdGlvbiwgJ2luc2VydEFkamFjZW50RWxlbWVudCcsXG4gICAgICAvKipcbiAgICAgICAqIEB0aGlzIHtFbGVtZW50fVxuICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHdoZXJlXG4gICAgICAgKiBAcGFyYW0geyFFbGVtZW50fSBlbGVtZW50XG4gICAgICAgKiBAcmV0dXJuIHs/RWxlbWVudH1cbiAgICAgICAqL1xuICAgICAgZnVuY3Rpb24od2hlcmUsIGVsZW1lbnQpIHtcbiAgICAgICAgY29uc3Qgd2FzQ29ubmVjdGVkID0gVXRpbGl0aWVzLmlzQ29ubmVjdGVkKGVsZW1lbnQpO1xuICAgICAgICBjb25zdCBpbnNlcnRlZEVsZW1lbnQgPSAvKiogQHR5cGUgeyFFbGVtZW50fSAqL1xuICAgICAgICAgIChiYXNlTWV0aG9kLmNhbGwodGhpcywgd2hlcmUsIGVsZW1lbnQpKTtcblxuICAgICAgICBpZiAod2FzQ29ubmVjdGVkKSB7XG4gICAgICAgICAgaW50ZXJuYWxzLmRpc2Nvbm5lY3RUcmVlKGVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFV0aWxpdGllcy5pc0Nvbm5lY3RlZChpbnNlcnRlZEVsZW1lbnQpKSB7XG4gICAgICAgICAgaW50ZXJuYWxzLmNvbm5lY3RUcmVlKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbnNlcnRlZEVsZW1lbnQ7XG4gICAgICB9KTtcbiAgfVxuXG4gIGlmIChOYXRpdmUuSFRNTEVsZW1lbnRfaW5zZXJ0QWRqYWNlbnRFbGVtZW50KSB7XG4gICAgcGF0Y2hfaW5zZXJ0QWRqYWNlbnRFbGVtZW50KEhUTUxFbGVtZW50LnByb3RvdHlwZSwgTmF0aXZlLkhUTUxFbGVtZW50X2luc2VydEFkamFjZW50RWxlbWVudCk7XG4gIH0gZWxzZSBpZiAoTmF0aXZlLkVsZW1lbnRfaW5zZXJ0QWRqYWNlbnRFbGVtZW50KSB7XG4gICAgcGF0Y2hfaW5zZXJ0QWRqYWNlbnRFbGVtZW50KEVsZW1lbnQucHJvdG90eXBlLCBOYXRpdmUuRWxlbWVudF9pbnNlcnRBZGphY2VudEVsZW1lbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbnNvbGUud2FybignQ3VzdG9tIEVsZW1lbnRzOiBgRWxlbWVudCNpbnNlcnRBZGphY2VudEVsZW1lbnRgIHdhcyBub3QgcGF0Y2hlZC4nKTtcbiAgfVxuXG5cbiAgUGF0Y2hQYXJlbnROb2RlKGludGVybmFscywgRWxlbWVudC5wcm90b3R5cGUsIHtcbiAgICBwcmVwZW5kOiBOYXRpdmUuRWxlbWVudF9wcmVwZW5kLFxuICAgIGFwcGVuZDogTmF0aXZlLkVsZW1lbnRfYXBwZW5kLFxuICB9KTtcblxuICBQYXRjaENoaWxkTm9kZShpbnRlcm5hbHMsIEVsZW1lbnQucHJvdG90eXBlLCB7XG4gICAgYmVmb3JlOiBOYXRpdmUuRWxlbWVudF9iZWZvcmUsXG4gICAgYWZ0ZXI6IE5hdGl2ZS5FbGVtZW50X2FmdGVyLFxuICAgIHJlcGxhY2VXaXRoOiBOYXRpdmUuRWxlbWVudF9yZXBsYWNlV2l0aCxcbiAgICByZW1vdmU6IE5hdGl2ZS5FbGVtZW50X3JlbW92ZSxcbiAgfSk7XG59O1xuIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IChjKSAyMDE2IFRoZSBQb2x5bWVyIFByb2plY3QgQXV0aG9ycy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqIFRoaXMgY29kZSBtYXkgb25seSBiZSB1c2VkIHVuZGVyIHRoZSBCU0Qgc3R5bGUgbGljZW5zZSBmb3VuZCBhdCBodHRwOi8vcG9seW1lci5naXRodWIuaW8vTElDRU5TRS50eHRcbiAqIFRoZSBjb21wbGV0ZSBzZXQgb2YgYXV0aG9ycyBtYXkgYmUgZm91bmQgYXQgaHR0cDovL3BvbHltZXIuZ2l0aHViLmlvL0FVVEhPUlMudHh0XG4gKiBUaGUgY29tcGxldGUgc2V0IG9mIGNvbnRyaWJ1dG9ycyBtYXkgYmUgZm91bmQgYXQgaHR0cDovL3BvbHltZXIuZ2l0aHViLmlvL0NPTlRSSUJVVE9SUy50eHRcbiAqIENvZGUgZGlzdHJpYnV0ZWQgYnkgR29vZ2xlIGFzIHBhcnQgb2YgdGhlIHBvbHltZXIgcHJvamVjdCBpcyBhbHNvXG4gKiBzdWJqZWN0IHRvIGFuIGFkZGl0aW9uYWwgSVAgcmlnaHRzIGdyYW50IGZvdW5kIGF0IGh0dHA6Ly9wb2x5bWVyLmdpdGh1Yi5pby9QQVRFTlRTLnR4dFxuICovXG5cbmltcG9ydCBDdXN0b21FbGVtZW50SW50ZXJuYWxzIGZyb20gJy4vQ3VzdG9tRWxlbWVudEludGVybmFscy5qcyc7XG5pbXBvcnQgQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5IGZyb20gJy4vQ3VzdG9tRWxlbWVudFJlZ2lzdHJ5LmpzJztcblxuaW1wb3J0IFBhdGNoSFRNTEVsZW1lbnQgZnJvbSAnLi9QYXRjaC9IVE1MRWxlbWVudC5qcyc7XG5pbXBvcnQgUGF0Y2hEb2N1bWVudCBmcm9tICcuL1BhdGNoL0RvY3VtZW50LmpzJztcbmltcG9ydCBQYXRjaE5vZGUgZnJvbSAnLi9QYXRjaC9Ob2RlLmpzJztcbmltcG9ydCBQYXRjaEVsZW1lbnQgZnJvbSAnLi9QYXRjaC9FbGVtZW50LmpzJztcblxuY29uc3QgcHJpb3JDdXN0b21FbGVtZW50cyA9IHdpbmRvd1snY3VzdG9tRWxlbWVudHMnXTtcblxuaWYgKCFwcmlvckN1c3RvbUVsZW1lbnRzIHx8XG4gICAgIHByaW9yQ3VzdG9tRWxlbWVudHNbJ2ZvcmNlUG9seWZpbGwnXSB8fFxuICAgICAodHlwZW9mIHByaW9yQ3VzdG9tRWxlbWVudHNbJ2RlZmluZSddICE9ICdmdW5jdGlvbicpIHx8XG4gICAgICh0eXBlb2YgcHJpb3JDdXN0b21FbGVtZW50c1snZ2V0J10gIT0gJ2Z1bmN0aW9uJykpIHtcbiAgLyoqIEB0eXBlIHshQ3VzdG9tRWxlbWVudEludGVybmFsc30gKi9cbiAgY29uc3QgaW50ZXJuYWxzID0gbmV3IEN1c3RvbUVsZW1lbnRJbnRlcm5hbHMoKTtcblxuICBQYXRjaEhUTUxFbGVtZW50KGludGVybmFscyk7XG4gIFBhdGNoRG9jdW1lbnQoaW50ZXJuYWxzKTtcbiAgUGF0Y2hOb2RlKGludGVybmFscyk7XG4gIFBhdGNoRWxlbWVudChpbnRlcm5hbHMpO1xuXG4gIC8vIFRoZSBtYWluIGRvY3VtZW50IGlzIGFsd2F5cyBhc3NvY2lhdGVkIHdpdGggdGhlIHJlZ2lzdHJ5LlxuICBkb2N1bWVudC5fX0NFX2hhc1JlZ2lzdHJ5ID0gdHJ1ZTtcblxuICAvKiogQHR5cGUgeyFDdXN0b21FbGVtZW50UmVnaXN0cnl9ICovXG4gIGNvbnN0IGN1c3RvbUVsZW1lbnRzID0gbmV3IEN1c3RvbUVsZW1lbnRSZWdpc3RyeShpbnRlcm5hbHMpO1xuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3aW5kb3csICdjdXN0b21FbGVtZW50cycsIHtcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICB2YWx1ZTogY3VzdG9tRWxlbWVudHMsXG4gIH0pO1xufVxuIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IChjKSAyMDE0IFRoZSBQb2x5bWVyIFByb2plY3QgQXV0aG9ycy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqIFRoaXMgY29kZSBtYXkgb25seSBiZSB1c2VkIHVuZGVyIHRoZSBCU0Qgc3R5bGUgbGljZW5zZSBmb3VuZCBhdCBodHRwOi8vcG9seW1lci5naXRodWIuaW8vTElDRU5TRS50eHRcbiAqIFRoZSBjb21wbGV0ZSBzZXQgb2YgYXV0aG9ycyBtYXkgYmUgZm91bmQgYXQgaHR0cDovL3BvbHltZXIuZ2l0aHViLmlvL0FVVEhPUlMudHh0XG4gKiBUaGUgY29tcGxldGUgc2V0IG9mIGNvbnRyaWJ1dG9ycyBtYXkgYmUgZm91bmQgYXQgaHR0cDovL3BvbHltZXIuZ2l0aHViLmlvL0NPTlRSSUJVVE9SUy50eHRcbiAqIENvZGUgZGlzdHJpYnV0ZWQgYnkgR29vZ2xlIGFzIHBhcnQgb2YgdGhlIHBvbHltZXIgcHJvamVjdCBpcyBhbHNvXG4gKiBzdWJqZWN0IHRvIGFuIGFkZGl0aW9uYWwgSVAgcmlnaHRzIGdyYW50IGZvdW5kIGF0IGh0dHA6Ly9wb2x5bWVyLmdpdGh1Yi5pby9QQVRFTlRTLnR4dFxuICovXG4vLyBAdmVyc2lvbiAwLjcuMjJcblxuKGZ1bmN0aW9uKGdsb2JhbCkge1xuICBpZiAoZ2xvYmFsLkpzTXV0YXRpb25PYnNlcnZlcikge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgcmVnaXN0cmF0aW9uc1RhYmxlID0gbmV3IFdlYWtNYXAoKTtcbiAgdmFyIHNldEltbWVkaWF0ZTtcbiAgaWYgKC9UcmlkZW50fEVkZ2UvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcbiAgICBzZXRJbW1lZGlhdGUgPSBzZXRUaW1lb3V0O1xuICB9IGVsc2UgaWYgKHdpbmRvdy5zZXRJbW1lZGlhdGUpIHtcbiAgICBzZXRJbW1lZGlhdGUgPSB3aW5kb3cuc2V0SW1tZWRpYXRlO1xuICB9IGVsc2Uge1xuICAgIHZhciBzZXRJbW1lZGlhdGVRdWV1ZSA9IFtdO1xuICAgIHZhciBzZW50aW5lbCA9IFN0cmluZyhNYXRoLnJhbmRvbSgpKTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgZnVuY3Rpb24oZSkge1xuICAgICAgaWYgKGUuZGF0YSA9PT0gc2VudGluZWwpIHtcbiAgICAgICAgdmFyIHF1ZXVlID0gc2V0SW1tZWRpYXRlUXVldWU7XG4gICAgICAgIHNldEltbWVkaWF0ZVF1ZXVlID0gW107XG4gICAgICAgIHF1ZXVlLmZvckVhY2goZnVuY3Rpb24oZnVuYykge1xuICAgICAgICAgIGZ1bmMoKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgc2V0SW1tZWRpYXRlID0gZnVuY3Rpb24oZnVuYykge1xuICAgICAgc2V0SW1tZWRpYXRlUXVldWUucHVzaChmdW5jKTtcbiAgICAgIHdpbmRvdy5wb3N0TWVzc2FnZShzZW50aW5lbCwgXCIqXCIpO1xuICAgIH07XG4gIH1cbiAgdmFyIGlzU2NoZWR1bGVkID0gZmFsc2U7XG4gIHZhciBzY2hlZHVsZWRPYnNlcnZlcnMgPSBbXTtcbiAgZnVuY3Rpb24gc2NoZWR1bGVDYWxsYmFjayhvYnNlcnZlcikge1xuICAgIHNjaGVkdWxlZE9ic2VydmVycy5wdXNoKG9ic2VydmVyKTtcbiAgICBpZiAoIWlzU2NoZWR1bGVkKSB7XG4gICAgICBpc1NjaGVkdWxlZCA9IHRydWU7XG4gICAgICBzZXRJbW1lZGlhdGUoZGlzcGF0Y2hDYWxsYmFja3MpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiB3cmFwSWZOZWVkZWQobm9kZSkge1xuICAgIHJldHVybiB3aW5kb3cuU2hhZG93RE9NUG9seWZpbGwgJiYgd2luZG93LlNoYWRvd0RPTVBvbHlmaWxsLndyYXBJZk5lZWRlZChub2RlKSB8fCBub2RlO1xuICB9XG4gIGZ1bmN0aW9uIGRpc3BhdGNoQ2FsbGJhY2tzKCkge1xuICAgIGlzU2NoZWR1bGVkID0gZmFsc2U7XG4gICAgdmFyIG9ic2VydmVycyA9IHNjaGVkdWxlZE9ic2VydmVycztcbiAgICBzY2hlZHVsZWRPYnNlcnZlcnMgPSBbXTtcbiAgICBvYnNlcnZlcnMuc29ydChmdW5jdGlvbihvMSwgbzIpIHtcbiAgICAgIHJldHVybiBvMS51aWRfIC0gbzIudWlkXztcbiAgICB9KTtcbiAgICB2YXIgYW55Tm9uRW1wdHkgPSBmYWxzZTtcbiAgICBvYnNlcnZlcnMuZm9yRWFjaChmdW5jdGlvbihvYnNlcnZlcikge1xuICAgICAgdmFyIHF1ZXVlID0gb2JzZXJ2ZXIudGFrZVJlY29yZHMoKTtcbiAgICAgIHJlbW92ZVRyYW5zaWVudE9ic2VydmVyc0ZvcihvYnNlcnZlcik7XG4gICAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIG9ic2VydmVyLmNhbGxiYWNrXyhxdWV1ZSwgb2JzZXJ2ZXIpO1xuICAgICAgICBhbnlOb25FbXB0eSA9IHRydWU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKGFueU5vbkVtcHR5KSBkaXNwYXRjaENhbGxiYWNrcygpO1xuICB9XG4gIGZ1bmN0aW9uIHJlbW92ZVRyYW5zaWVudE9ic2VydmVyc0ZvcihvYnNlcnZlcikge1xuICAgIG9ic2VydmVyLm5vZGVzXy5mb3JFYWNoKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIHZhciByZWdpc3RyYXRpb25zID0gcmVnaXN0cmF0aW9uc1RhYmxlLmdldChub2RlKTtcbiAgICAgIGlmICghcmVnaXN0cmF0aW9ucykgcmV0dXJuO1xuICAgICAgcmVnaXN0cmF0aW9ucy5mb3JFYWNoKGZ1bmN0aW9uKHJlZ2lzdHJhdGlvbikge1xuICAgICAgICBpZiAocmVnaXN0cmF0aW9uLm9ic2VydmVyID09PSBvYnNlcnZlcikgcmVnaXN0cmF0aW9uLnJlbW92ZVRyYW5zaWVudE9ic2VydmVycygpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgZnVuY3Rpb24gZm9yRWFjaEFuY2VzdG9yQW5kT2JzZXJ2ZXJFbnF1ZXVlUmVjb3JkKHRhcmdldCwgY2FsbGJhY2spIHtcbiAgICBmb3IgKHZhciBub2RlID0gdGFyZ2V0OyBub2RlOyBub2RlID0gbm9kZS5wYXJlbnROb2RlKSB7XG4gICAgICB2YXIgcmVnaXN0cmF0aW9ucyA9IHJlZ2lzdHJhdGlvbnNUYWJsZS5nZXQobm9kZSk7XG4gICAgICBpZiAocmVnaXN0cmF0aW9ucykge1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHJlZ2lzdHJhdGlvbnMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICB2YXIgcmVnaXN0cmF0aW9uID0gcmVnaXN0cmF0aW9uc1tqXTtcbiAgICAgICAgICB2YXIgb3B0aW9ucyA9IHJlZ2lzdHJhdGlvbi5vcHRpb25zO1xuICAgICAgICAgIGlmIChub2RlICE9PSB0YXJnZXQgJiYgIW9wdGlvbnMuc3VidHJlZSkgY29udGludWU7XG4gICAgICAgICAgdmFyIHJlY29yZCA9IGNhbGxiYWNrKG9wdGlvbnMpO1xuICAgICAgICAgIGlmIChyZWNvcmQpIHJlZ2lzdHJhdGlvbi5lbnF1ZXVlKHJlY29yZCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdmFyIHVpZENvdW50ZXIgPSAwO1xuICBmdW5jdGlvbiBKc011dGF0aW9uT2JzZXJ2ZXIoY2FsbGJhY2spIHtcbiAgICB0aGlzLmNhbGxiYWNrXyA9IGNhbGxiYWNrO1xuICAgIHRoaXMubm9kZXNfID0gW107XG4gICAgdGhpcy5yZWNvcmRzXyA9IFtdO1xuICAgIHRoaXMudWlkXyA9ICsrdWlkQ291bnRlcjtcbiAgfVxuICBKc011dGF0aW9uT2JzZXJ2ZXIucHJvdG90eXBlID0ge1xuICAgIG9ic2VydmU6IGZ1bmN0aW9uKHRhcmdldCwgb3B0aW9ucykge1xuICAgICAgdGFyZ2V0ID0gd3JhcElmTmVlZGVkKHRhcmdldCk7XG4gICAgICBpZiAoIW9wdGlvbnMuY2hpbGRMaXN0ICYmICFvcHRpb25zLmF0dHJpYnV0ZXMgJiYgIW9wdGlvbnMuY2hhcmFjdGVyRGF0YSB8fCBvcHRpb25zLmF0dHJpYnV0ZU9sZFZhbHVlICYmICFvcHRpb25zLmF0dHJpYnV0ZXMgfHwgb3B0aW9ucy5hdHRyaWJ1dGVGaWx0ZXIgJiYgb3B0aW9ucy5hdHRyaWJ1dGVGaWx0ZXIubGVuZ3RoICYmICFvcHRpb25zLmF0dHJpYnV0ZXMgfHwgb3B0aW9ucy5jaGFyYWN0ZXJEYXRhT2xkVmFsdWUgJiYgIW9wdGlvbnMuY2hhcmFjdGVyRGF0YSkge1xuICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoKTtcbiAgICAgIH1cbiAgICAgIHZhciByZWdpc3RyYXRpb25zID0gcmVnaXN0cmF0aW9uc1RhYmxlLmdldCh0YXJnZXQpO1xuICAgICAgaWYgKCFyZWdpc3RyYXRpb25zKSByZWdpc3RyYXRpb25zVGFibGUuc2V0KHRhcmdldCwgcmVnaXN0cmF0aW9ucyA9IFtdKTtcbiAgICAgIHZhciByZWdpc3RyYXRpb247XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlZ2lzdHJhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHJlZ2lzdHJhdGlvbnNbaV0ub2JzZXJ2ZXIgPT09IHRoaXMpIHtcbiAgICAgICAgICByZWdpc3RyYXRpb24gPSByZWdpc3RyYXRpb25zW2ldO1xuICAgICAgICAgIHJlZ2lzdHJhdGlvbi5yZW1vdmVMaXN0ZW5lcnMoKTtcbiAgICAgICAgICByZWdpc3RyYXRpb24ub3B0aW9ucyA9IG9wdGlvbnM7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICghcmVnaXN0cmF0aW9uKSB7XG4gICAgICAgIHJlZ2lzdHJhdGlvbiA9IG5ldyBSZWdpc3RyYXRpb24odGhpcywgdGFyZ2V0LCBvcHRpb25zKTtcbiAgICAgICAgcmVnaXN0cmF0aW9ucy5wdXNoKHJlZ2lzdHJhdGlvbik7XG4gICAgICAgIHRoaXMubm9kZXNfLnB1c2godGFyZ2V0KTtcbiAgICAgIH1cbiAgICAgIHJlZ2lzdHJhdGlvbi5hZGRMaXN0ZW5lcnMoKTtcbiAgICB9LFxuICAgIGRpc2Nvbm5lY3Q6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5ub2Rlc18uZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICAgIHZhciByZWdpc3RyYXRpb25zID0gcmVnaXN0cmF0aW9uc1RhYmxlLmdldChub2RlKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZWdpc3RyYXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHJlZ2lzdHJhdGlvbiA9IHJlZ2lzdHJhdGlvbnNbaV07XG4gICAgICAgICAgaWYgKHJlZ2lzdHJhdGlvbi5vYnNlcnZlciA9PT0gdGhpcykge1xuICAgICAgICAgICAgcmVnaXN0cmF0aW9uLnJlbW92ZUxpc3RlbmVycygpO1xuICAgICAgICAgICAgcmVnaXN0cmF0aW9ucy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sIHRoaXMpO1xuICAgICAgdGhpcy5yZWNvcmRzXyA9IFtdO1xuICAgIH0sXG4gICAgdGFrZVJlY29yZHM6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGNvcHlPZlJlY29yZHMgPSB0aGlzLnJlY29yZHNfO1xuICAgICAgdGhpcy5yZWNvcmRzXyA9IFtdO1xuICAgICAgcmV0dXJuIGNvcHlPZlJlY29yZHM7XG4gICAgfVxuICB9O1xuICBmdW5jdGlvbiBNdXRhdGlvblJlY29yZCh0eXBlLCB0YXJnZXQpIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgIHRoaXMuYWRkZWROb2RlcyA9IFtdO1xuICAgIHRoaXMucmVtb3ZlZE5vZGVzID0gW107XG4gICAgdGhpcy5wcmV2aW91c1NpYmxpbmcgPSBudWxsO1xuICAgIHRoaXMubmV4dFNpYmxpbmcgPSBudWxsO1xuICAgIHRoaXMuYXR0cmlidXRlTmFtZSA9IG51bGw7XG4gICAgdGhpcy5hdHRyaWJ1dGVOYW1lc3BhY2UgPSBudWxsO1xuICAgIHRoaXMub2xkVmFsdWUgPSBudWxsO1xuICB9XG4gIGZ1bmN0aW9uIGNvcHlNdXRhdGlvblJlY29yZChvcmlnaW5hbCkge1xuICAgIHZhciByZWNvcmQgPSBuZXcgTXV0YXRpb25SZWNvcmQob3JpZ2luYWwudHlwZSwgb3JpZ2luYWwudGFyZ2V0KTtcbiAgICByZWNvcmQuYWRkZWROb2RlcyA9IG9yaWdpbmFsLmFkZGVkTm9kZXMuc2xpY2UoKTtcbiAgICByZWNvcmQucmVtb3ZlZE5vZGVzID0gb3JpZ2luYWwucmVtb3ZlZE5vZGVzLnNsaWNlKCk7XG4gICAgcmVjb3JkLnByZXZpb3VzU2libGluZyA9IG9yaWdpbmFsLnByZXZpb3VzU2libGluZztcbiAgICByZWNvcmQubmV4dFNpYmxpbmcgPSBvcmlnaW5hbC5uZXh0U2libGluZztcbiAgICByZWNvcmQuYXR0cmlidXRlTmFtZSA9IG9yaWdpbmFsLmF0dHJpYnV0ZU5hbWU7XG4gICAgcmVjb3JkLmF0dHJpYnV0ZU5hbWVzcGFjZSA9IG9yaWdpbmFsLmF0dHJpYnV0ZU5hbWVzcGFjZTtcbiAgICByZWNvcmQub2xkVmFsdWUgPSBvcmlnaW5hbC5vbGRWYWx1ZTtcbiAgICByZXR1cm4gcmVjb3JkO1xuICB9XG4gIHZhciBjdXJyZW50UmVjb3JkLCByZWNvcmRXaXRoT2xkVmFsdWU7XG4gIGZ1bmN0aW9uIGdldFJlY29yZCh0eXBlLCB0YXJnZXQpIHtcbiAgICByZXR1cm4gY3VycmVudFJlY29yZCA9IG5ldyBNdXRhdGlvblJlY29yZCh0eXBlLCB0YXJnZXQpO1xuICB9XG4gIGZ1bmN0aW9uIGdldFJlY29yZFdpdGhPbGRWYWx1ZShvbGRWYWx1ZSkge1xuICAgIGlmIChyZWNvcmRXaXRoT2xkVmFsdWUpIHJldHVybiByZWNvcmRXaXRoT2xkVmFsdWU7XG4gICAgcmVjb3JkV2l0aE9sZFZhbHVlID0gY29weU11dGF0aW9uUmVjb3JkKGN1cnJlbnRSZWNvcmQpO1xuICAgIHJlY29yZFdpdGhPbGRWYWx1ZS5vbGRWYWx1ZSA9IG9sZFZhbHVlO1xuICAgIHJldHVybiByZWNvcmRXaXRoT2xkVmFsdWU7XG4gIH1cbiAgZnVuY3Rpb24gY2xlYXJSZWNvcmRzKCkge1xuICAgIGN1cnJlbnRSZWNvcmQgPSByZWNvcmRXaXRoT2xkVmFsdWUgPSB1bmRlZmluZWQ7XG4gIH1cbiAgZnVuY3Rpb24gcmVjb3JkUmVwcmVzZW50c0N1cnJlbnRNdXRhdGlvbihyZWNvcmQpIHtcbiAgICByZXR1cm4gcmVjb3JkID09PSByZWNvcmRXaXRoT2xkVmFsdWUgfHwgcmVjb3JkID09PSBjdXJyZW50UmVjb3JkO1xuICB9XG4gIGZ1bmN0aW9uIHNlbGVjdFJlY29yZChsYXN0UmVjb3JkLCBuZXdSZWNvcmQpIHtcbiAgICBpZiAobGFzdFJlY29yZCA9PT0gbmV3UmVjb3JkKSByZXR1cm4gbGFzdFJlY29yZDtcbiAgICBpZiAocmVjb3JkV2l0aE9sZFZhbHVlICYmIHJlY29yZFJlcHJlc2VudHNDdXJyZW50TXV0YXRpb24obGFzdFJlY29yZCkpIHJldHVybiByZWNvcmRXaXRoT2xkVmFsdWU7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgZnVuY3Rpb24gUmVnaXN0cmF0aW9uKG9ic2VydmVyLCB0YXJnZXQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLm9ic2VydmVyID0gb2JzZXJ2ZXI7XG4gICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcbiAgICB0aGlzLnRyYW5zaWVudE9ic2VydmVkTm9kZXMgPSBbXTtcbiAgfVxuICBSZWdpc3RyYXRpb24ucHJvdG90eXBlID0ge1xuICAgIGVucXVldWU6IGZ1bmN0aW9uKHJlY29yZCkge1xuICAgICAgdmFyIHJlY29yZHMgPSB0aGlzLm9ic2VydmVyLnJlY29yZHNfO1xuICAgICAgdmFyIGxlbmd0aCA9IHJlY29yZHMubGVuZ3RoO1xuICAgICAgaWYgKHJlY29yZHMubGVuZ3RoID4gMCkge1xuICAgICAgICB2YXIgbGFzdFJlY29yZCA9IHJlY29yZHNbbGVuZ3RoIC0gMV07XG4gICAgICAgIHZhciByZWNvcmRUb1JlcGxhY2VMYXN0ID0gc2VsZWN0UmVjb3JkKGxhc3RSZWNvcmQsIHJlY29yZCk7XG4gICAgICAgIGlmIChyZWNvcmRUb1JlcGxhY2VMYXN0KSB7XG4gICAgICAgICAgcmVjb3Jkc1tsZW5ndGggLSAxXSA9IHJlY29yZFRvUmVwbGFjZUxhc3Q7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzY2hlZHVsZUNhbGxiYWNrKHRoaXMub2JzZXJ2ZXIpO1xuICAgICAgfVxuICAgICAgcmVjb3Jkc1tsZW5ndGhdID0gcmVjb3JkO1xuICAgIH0sXG4gICAgYWRkTGlzdGVuZXJzOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuYWRkTGlzdGVuZXJzXyh0aGlzLnRhcmdldCk7XG4gICAgfSxcbiAgICBhZGRMaXN0ZW5lcnNfOiBmdW5jdGlvbihub2RlKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgIGlmIChvcHRpb25zLmF0dHJpYnV0ZXMpIG5vZGUuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUF0dHJNb2RpZmllZFwiLCB0aGlzLCB0cnVlKTtcbiAgICAgIGlmIChvcHRpb25zLmNoYXJhY3RlckRhdGEpIG5vZGUuYWRkRXZlbnRMaXN0ZW5lcihcIkRPTUNoYXJhY3RlckRhdGFNb2RpZmllZFwiLCB0aGlzLCB0cnVlKTtcbiAgICAgIGlmIChvcHRpb25zLmNoaWxkTGlzdCkgbm9kZS5hZGRFdmVudExpc3RlbmVyKFwiRE9NTm9kZUluc2VydGVkXCIsIHRoaXMsIHRydWUpO1xuICAgICAgaWYgKG9wdGlvbnMuY2hpbGRMaXN0IHx8IG9wdGlvbnMuc3VidHJlZSkgbm9kZS5hZGRFdmVudExpc3RlbmVyKFwiRE9NTm9kZVJlbW92ZWRcIiwgdGhpcywgdHJ1ZSk7XG4gICAgfSxcbiAgICByZW1vdmVMaXN0ZW5lcnM6IGZ1bmN0aW9uKCkge1xuICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcnNfKHRoaXMudGFyZ2V0KTtcbiAgICB9LFxuICAgIHJlbW92ZUxpc3RlbmVyc186IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuICAgICAgaWYgKG9wdGlvbnMuYXR0cmlidXRlcykgbm9kZS5yZW1vdmVFdmVudExpc3RlbmVyKFwiRE9NQXR0ck1vZGlmaWVkXCIsIHRoaXMsIHRydWUpO1xuICAgICAgaWYgKG9wdGlvbnMuY2hhcmFjdGVyRGF0YSkgbm9kZS5yZW1vdmVFdmVudExpc3RlbmVyKFwiRE9NQ2hhcmFjdGVyRGF0YU1vZGlmaWVkXCIsIHRoaXMsIHRydWUpO1xuICAgICAgaWYgKG9wdGlvbnMuY2hpbGRMaXN0KSBub2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJET01Ob2RlSW5zZXJ0ZWRcIiwgdGhpcywgdHJ1ZSk7XG4gICAgICBpZiAob3B0aW9ucy5jaGlsZExpc3QgfHwgb3B0aW9ucy5zdWJ0cmVlKSBub2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJET01Ob2RlUmVtb3ZlZFwiLCB0aGlzLCB0cnVlKTtcbiAgICB9LFxuICAgIGFkZFRyYW5zaWVudE9ic2VydmVyOiBmdW5jdGlvbihub2RlKSB7XG4gICAgICBpZiAobm9kZSA9PT0gdGhpcy50YXJnZXQpIHJldHVybjtcbiAgICAgIHRoaXMuYWRkTGlzdGVuZXJzXyhub2RlKTtcbiAgICAgIHRoaXMudHJhbnNpZW50T2JzZXJ2ZWROb2Rlcy5wdXNoKG5vZGUpO1xuICAgICAgdmFyIHJlZ2lzdHJhdGlvbnMgPSByZWdpc3RyYXRpb25zVGFibGUuZ2V0KG5vZGUpO1xuICAgICAgaWYgKCFyZWdpc3RyYXRpb25zKSByZWdpc3RyYXRpb25zVGFibGUuc2V0KG5vZGUsIHJlZ2lzdHJhdGlvbnMgPSBbXSk7XG4gICAgICByZWdpc3RyYXRpb25zLnB1c2godGhpcyk7XG4gICAgfSxcbiAgICByZW1vdmVUcmFuc2llbnRPYnNlcnZlcnM6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHRyYW5zaWVudE9ic2VydmVkTm9kZXMgPSB0aGlzLnRyYW5zaWVudE9ic2VydmVkTm9kZXM7XG4gICAgICB0aGlzLnRyYW5zaWVudE9ic2VydmVkTm9kZXMgPSBbXTtcbiAgICAgIHRyYW5zaWVudE9ic2VydmVkTm9kZXMuZm9yRWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXJzXyhub2RlKTtcbiAgICAgICAgdmFyIHJlZ2lzdHJhdGlvbnMgPSByZWdpc3RyYXRpb25zVGFibGUuZ2V0KG5vZGUpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlZ2lzdHJhdGlvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAocmVnaXN0cmF0aW9uc1tpXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgcmVnaXN0cmF0aW9ucy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0sIHRoaXMpO1xuICAgIH0sXG4gICAgaGFuZGxlRXZlbnQ6IGZ1bmN0aW9uKGUpIHtcbiAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICBzd2l0Y2ggKGUudHlwZSkge1xuICAgICAgIGNhc2UgXCJET01BdHRyTW9kaWZpZWRcIjpcbiAgICAgICAgdmFyIG5hbWUgPSBlLmF0dHJOYW1lO1xuICAgICAgICB2YXIgbmFtZXNwYWNlID0gZS5yZWxhdGVkTm9kZS5uYW1lc3BhY2VVUkk7XG4gICAgICAgIHZhciB0YXJnZXQgPSBlLnRhcmdldDtcbiAgICAgICAgdmFyIHJlY29yZCA9IG5ldyBnZXRSZWNvcmQoXCJhdHRyaWJ1dGVzXCIsIHRhcmdldCk7XG4gICAgICAgIHJlY29yZC5hdHRyaWJ1dGVOYW1lID0gbmFtZTtcbiAgICAgICAgcmVjb3JkLmF0dHJpYnV0ZU5hbWVzcGFjZSA9IG5hbWVzcGFjZTtcbiAgICAgICAgdmFyIG9sZFZhbHVlID0gZS5hdHRyQ2hhbmdlID09PSBNdXRhdGlvbkV2ZW50LkFERElUSU9OID8gbnVsbCA6IGUucHJldlZhbHVlO1xuICAgICAgICBmb3JFYWNoQW5jZXN0b3JBbmRPYnNlcnZlckVucXVldWVSZWNvcmQodGFyZ2V0LCBmdW5jdGlvbihvcHRpb25zKSB7XG4gICAgICAgICAgaWYgKCFvcHRpb25zLmF0dHJpYnV0ZXMpIHJldHVybjtcbiAgICAgICAgICBpZiAob3B0aW9ucy5hdHRyaWJ1dGVGaWx0ZXIgJiYgb3B0aW9ucy5hdHRyaWJ1dGVGaWx0ZXIubGVuZ3RoICYmIG9wdGlvbnMuYXR0cmlidXRlRmlsdGVyLmluZGV4T2YobmFtZSkgPT09IC0xICYmIG9wdGlvbnMuYXR0cmlidXRlRmlsdGVyLmluZGV4T2YobmFtZXNwYWNlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKG9wdGlvbnMuYXR0cmlidXRlT2xkVmFsdWUpIHJldHVybiBnZXRSZWNvcmRXaXRoT2xkVmFsdWUob2xkVmFsdWUpO1xuICAgICAgICAgIHJldHVybiByZWNvcmQ7XG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcblxuICAgICAgIGNhc2UgXCJET01DaGFyYWN0ZXJEYXRhTW9kaWZpZWRcIjpcbiAgICAgICAgdmFyIHRhcmdldCA9IGUudGFyZ2V0O1xuICAgICAgICB2YXIgcmVjb3JkID0gZ2V0UmVjb3JkKFwiY2hhcmFjdGVyRGF0YVwiLCB0YXJnZXQpO1xuICAgICAgICB2YXIgb2xkVmFsdWUgPSBlLnByZXZWYWx1ZTtcbiAgICAgICAgZm9yRWFjaEFuY2VzdG9yQW5kT2JzZXJ2ZXJFbnF1ZXVlUmVjb3JkKHRhcmdldCwgZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICAgIGlmICghb3B0aW9ucy5jaGFyYWN0ZXJEYXRhKSByZXR1cm47XG4gICAgICAgICAgaWYgKG9wdGlvbnMuY2hhcmFjdGVyRGF0YU9sZFZhbHVlKSByZXR1cm4gZ2V0UmVjb3JkV2l0aE9sZFZhbHVlKG9sZFZhbHVlKTtcbiAgICAgICAgICByZXR1cm4gcmVjb3JkO1xuICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgICBjYXNlIFwiRE9NTm9kZVJlbW92ZWRcIjpcbiAgICAgICAgdGhpcy5hZGRUcmFuc2llbnRPYnNlcnZlcihlLnRhcmdldCk7XG5cbiAgICAgICBjYXNlIFwiRE9NTm9kZUluc2VydGVkXCI6XG4gICAgICAgIHZhciBjaGFuZ2VkTm9kZSA9IGUudGFyZ2V0O1xuICAgICAgICB2YXIgYWRkZWROb2RlcywgcmVtb3ZlZE5vZGVzO1xuICAgICAgICBpZiAoZS50eXBlID09PSBcIkRPTU5vZGVJbnNlcnRlZFwiKSB7XG4gICAgICAgICAgYWRkZWROb2RlcyA9IFsgY2hhbmdlZE5vZGUgXTtcbiAgICAgICAgICByZW1vdmVkTm9kZXMgPSBbXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhZGRlZE5vZGVzID0gW107XG4gICAgICAgICAgcmVtb3ZlZE5vZGVzID0gWyBjaGFuZ2VkTm9kZSBdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBwcmV2aW91c1NpYmxpbmcgPSBjaGFuZ2VkTm9kZS5wcmV2aW91c1NpYmxpbmc7XG4gICAgICAgIHZhciBuZXh0U2libGluZyA9IGNoYW5nZWROb2RlLm5leHRTaWJsaW5nO1xuICAgICAgICB2YXIgcmVjb3JkID0gZ2V0UmVjb3JkKFwiY2hpbGRMaXN0XCIsIGUudGFyZ2V0LnBhcmVudE5vZGUpO1xuICAgICAgICByZWNvcmQuYWRkZWROb2RlcyA9IGFkZGVkTm9kZXM7XG4gICAgICAgIHJlY29yZC5yZW1vdmVkTm9kZXMgPSByZW1vdmVkTm9kZXM7XG4gICAgICAgIHJlY29yZC5wcmV2aW91c1NpYmxpbmcgPSBwcmV2aW91c1NpYmxpbmc7XG4gICAgICAgIHJlY29yZC5uZXh0U2libGluZyA9IG5leHRTaWJsaW5nO1xuICAgICAgICBmb3JFYWNoQW5jZXN0b3JBbmRPYnNlcnZlckVucXVldWVSZWNvcmQoZS5yZWxhdGVkTm9kZSwgZnVuY3Rpb24ob3B0aW9ucykge1xuICAgICAgICAgIGlmICghb3B0aW9ucy5jaGlsZExpc3QpIHJldHVybjtcbiAgICAgICAgICByZXR1cm4gcmVjb3JkO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGNsZWFyUmVjb3JkcygpO1xuICAgIH1cbiAgfTtcbiAgZ2xvYmFsLkpzTXV0YXRpb25PYnNlcnZlciA9IEpzTXV0YXRpb25PYnNlcnZlcjtcbiAgaWYgKCFnbG9iYWwuTXV0YXRpb25PYnNlcnZlcikge1xuICAgIGdsb2JhbC5NdXRhdGlvbk9ic2VydmVyID0gSnNNdXRhdGlvbk9ic2VydmVyO1xuICAgIEpzTXV0YXRpb25PYnNlcnZlci5faXNQb2x5ZmlsbGVkID0gdHJ1ZTtcbiAgfVxufSkoc2VsZik7XG4iLCIvKlxuQ29weXJpZ2h0IChjKSAyMDEyIEJhcm5lc2FuZG5vYmxlLmNvbSwgbGxjLCBEb25hdm9uIFdlc3QsIGFuZCBEb21lbmljIERlbmljb2xhXG5cblBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZ1xuYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG5cIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbndpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbmRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0b1xucGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvXG50aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG5cblRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG5pbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cblxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCxcbkVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkRcbk5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkVcbkxJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT05cbk9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTlxuV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbiovXG4oZnVuY3Rpb24gKGdsb2JhbCwgdW5kZWZpbmVkKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICBpZiAoZ2xvYmFsLnNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIG5leHRIYW5kbGUgPSAxOyAvLyBTcGVjIHNheXMgZ3JlYXRlciB0aGFuIHplcm9cbiAgICB2YXIgdGFza3NCeUhhbmRsZSA9IHt9O1xuICAgIHZhciBjdXJyZW50bHlSdW5uaW5nQVRhc2sgPSBmYWxzZTtcbiAgICB2YXIgZG9jID0gZ2xvYmFsLmRvY3VtZW50O1xuICAgIHZhciBzZXRJbW1lZGlhdGU7XG5cbiAgICBmdW5jdGlvbiBhZGRGcm9tU2V0SW1tZWRpYXRlQXJndW1lbnRzKGFyZ3MpIHtcbiAgICAgICAgdGFza3NCeUhhbmRsZVtuZXh0SGFuZGxlXSA9IHBhcnRpYWxseUFwcGxpZWQuYXBwbHkodW5kZWZpbmVkLCBhcmdzKTtcbiAgICAgICAgcmV0dXJuIG5leHRIYW5kbGUrKztcbiAgICB9XG5cbiAgICAvLyBUaGlzIGZ1bmN0aW9uIGFjY2VwdHMgdGhlIHNhbWUgYXJndW1lbnRzIGFzIHNldEltbWVkaWF0ZSwgYnV0XG4gICAgLy8gcmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgcmVxdWlyZXMgbm8gYXJndW1lbnRzLlxuICAgIGZ1bmN0aW9uIHBhcnRpYWxseUFwcGxpZWQoaGFuZGxlcikge1xuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBoYW5kbGVyID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICBoYW5kbGVyLmFwcGx5KHVuZGVmaW5lZCwgYXJncyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIChuZXcgRnVuY3Rpb24oXCJcIiArIGhhbmRsZXIpKSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJ1bklmUHJlc2VudChoYW5kbGUpIHtcbiAgICAgICAgLy8gRnJvbSB0aGUgc3BlYzogXCJXYWl0IHVudGlsIGFueSBpbnZvY2F0aW9ucyBvZiB0aGlzIGFsZ29yaXRobSBzdGFydGVkIGJlZm9yZSB0aGlzIG9uZSBoYXZlIGNvbXBsZXRlZC5cIlxuICAgICAgICAvLyBTbyBpZiB3ZSdyZSBjdXJyZW50bHkgcnVubmluZyBhIHRhc2ssIHdlJ2xsIG5lZWQgdG8gZGVsYXkgdGhpcyBpbnZvY2F0aW9uLlxuICAgICAgICBpZiAoY3VycmVudGx5UnVubmluZ0FUYXNrKSB7XG4gICAgICAgICAgICAvLyBEZWxheSBieSBkb2luZyBhIHNldFRpbWVvdXQuIHNldEltbWVkaWF0ZSB3YXMgdHJpZWQgaW5zdGVhZCwgYnV0IGluIEZpcmVmb3ggNyBpdCBnZW5lcmF0ZWQgYVxuICAgICAgICAgICAgLy8gXCJ0b28gbXVjaCByZWN1cnNpb25cIiBlcnJvci5cbiAgICAgICAgICAgIHNldFRpbWVvdXQocGFydGlhbGx5QXBwbGllZChydW5JZlByZXNlbnQsIGhhbmRsZSksIDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIHRhc2sgPSB0YXNrc0J5SGFuZGxlW2hhbmRsZV07XG4gICAgICAgICAgICBpZiAodGFzaykge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRseVJ1bm5pbmdBVGFzayA9IHRydWU7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgdGFzaygpO1xuICAgICAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFySW1tZWRpYXRlKGhhbmRsZSk7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRseVJ1bm5pbmdBVGFzayA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNsZWFySW1tZWRpYXRlKGhhbmRsZSkge1xuICAgICAgICBkZWxldGUgdGFza3NCeUhhbmRsZVtoYW5kbGVdO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxOZXh0VGlja0ltcGxlbWVudGF0aW9uKCkge1xuICAgICAgICBzZXRJbW1lZGlhdGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBoYW5kbGUgPSBhZGRGcm9tU2V0SW1tZWRpYXRlQXJndW1lbnRzKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICBwcm9jZXNzLm5leHRUaWNrKHBhcnRpYWxseUFwcGxpZWQocnVuSWZQcmVzZW50LCBoYW5kbGUpKTtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2FuVXNlUG9zdE1lc3NhZ2UoKSB7XG4gICAgICAgIC8vIFRoZSB0ZXN0IGFnYWluc3QgYGltcG9ydFNjcmlwdHNgIHByZXZlbnRzIHRoaXMgaW1wbGVtZW50YXRpb24gZnJvbSBiZWluZyBpbnN0YWxsZWQgaW5zaWRlIGEgd2ViIHdvcmtlcixcbiAgICAgICAgLy8gd2hlcmUgYGdsb2JhbC5wb3N0TWVzc2FnZWAgbWVhbnMgc29tZXRoaW5nIGNvbXBsZXRlbHkgZGlmZmVyZW50IGFuZCBjYW4ndCBiZSB1c2VkIGZvciB0aGlzIHB1cnBvc2UuXG4gICAgICAgIGlmIChnbG9iYWwucG9zdE1lc3NhZ2UgJiYgIWdsb2JhbC5pbXBvcnRTY3JpcHRzKSB7XG4gICAgICAgICAgICB2YXIgcG9zdE1lc3NhZ2VJc0FzeW5jaHJvbm91cyA9IHRydWU7XG4gICAgICAgICAgICB2YXIgb2xkT25NZXNzYWdlID0gZ2xvYmFsLm9ubWVzc2FnZTtcbiAgICAgICAgICAgIGdsb2JhbC5vbm1lc3NhZ2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZUlzQXN5bmNocm9ub3VzID0gZmFsc2U7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZ2xvYmFsLnBvc3RNZXNzYWdlKFwiXCIsIFwiKlwiKTtcbiAgICAgICAgICAgIGdsb2JhbC5vbm1lc3NhZ2UgPSBvbGRPbk1lc3NhZ2U7XG4gICAgICAgICAgICByZXR1cm4gcG9zdE1lc3NhZ2VJc0FzeW5jaHJvbm91cztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxQb3N0TWVzc2FnZUltcGxlbWVudGF0aW9uKCkge1xuICAgICAgICAvLyBJbnN0YWxscyBhbiBldmVudCBoYW5kbGVyIG9uIGBnbG9iYWxgIGZvciB0aGUgYG1lc3NhZ2VgIGV2ZW50OiBzZWVcbiAgICAgICAgLy8gKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9ET00vd2luZG93LnBvc3RNZXNzYWdlXG4gICAgICAgIC8vICogaHR0cDovL3d3dy53aGF0d2cub3JnL3NwZWNzL3dlYi1hcHBzL2N1cnJlbnQtd29yay9tdWx0aXBhZ2UvY29tbXMuaHRtbCNjcm9zc0RvY3VtZW50TWVzc2FnZXNcblxuICAgICAgICB2YXIgbWVzc2FnZVByZWZpeCA9IFwic2V0SW1tZWRpYXRlJFwiICsgTWF0aC5yYW5kb20oKSArIFwiJFwiO1xuICAgICAgICB2YXIgb25HbG9iYWxNZXNzYWdlID0gZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC5zb3VyY2UgPT09IGdsb2JhbCAmJlxuICAgICAgICAgICAgICAgIHR5cGVvZiBldmVudC5kYXRhID09PSBcInN0cmluZ1wiICYmXG4gICAgICAgICAgICAgICAgZXZlbnQuZGF0YS5pbmRleE9mKG1lc3NhZ2VQcmVmaXgpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcnVuSWZQcmVzZW50KCtldmVudC5kYXRhLnNsaWNlKG1lc3NhZ2VQcmVmaXgubGVuZ3RoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGdsb2JhbC5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgICAgICAgICBnbG9iYWwuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgb25HbG9iYWxNZXNzYWdlLCBmYWxzZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbG9iYWwuYXR0YWNoRXZlbnQoXCJvbm1lc3NhZ2VcIiwgb25HbG9iYWxNZXNzYWdlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldEltbWVkaWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZSA9IGFkZEZyb21TZXRJbW1lZGlhdGVBcmd1bWVudHMoYXJndW1lbnRzKTtcbiAgICAgICAgICAgIGdsb2JhbC5wb3N0TWVzc2FnZShtZXNzYWdlUHJlZml4ICsgaGFuZGxlLCBcIipcIik7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxNZXNzYWdlQ2hhbm5lbEltcGxlbWVudGF0aW9uKCkge1xuICAgICAgICB2YXIgY2hhbm5lbCA9IG5ldyBNZXNzYWdlQ2hhbm5lbCgpO1xuICAgICAgICBjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgaGFuZGxlID0gZXZlbnQuZGF0YTtcbiAgICAgICAgICAgIHJ1bklmUHJlc2VudChoYW5kbGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNldEltbWVkaWF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZSA9IGFkZEZyb21TZXRJbW1lZGlhdGVBcmd1bWVudHMoYXJndW1lbnRzKTtcbiAgICAgICAgICAgIGNoYW5uZWwucG9ydDIucG9zdE1lc3NhZ2UoaGFuZGxlKTtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbFJlYWR5U3RhdGVDaGFuZ2VJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgdmFyIGh0bWwgPSBkb2MuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgICBzZXRJbW1lZGlhdGUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciBoYW5kbGUgPSBhZGRGcm9tU2V0SW1tZWRpYXRlQXJndW1lbnRzKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAvLyBDcmVhdGUgYSA8c2NyaXB0PiBlbGVtZW50OyBpdHMgcmVhZHlzdGF0ZWNoYW5nZSBldmVudCB3aWxsIGJlIGZpcmVkIGFzeW5jaHJvbm91c2x5IG9uY2UgaXQgaXMgaW5zZXJ0ZWRcbiAgICAgICAgICAgIC8vIGludG8gdGhlIGRvY3VtZW50LiBEbyBzbywgdGh1cyBxdWV1aW5nIHVwIHRoZSB0YXNrLiBSZW1lbWJlciB0byBjbGVhbiB1cCBvbmNlIGl0J3MgYmVlbiBjYWxsZWQuXG4gICAgICAgICAgICB2YXIgc2NyaXB0ID0gZG9jLmNyZWF0ZUVsZW1lbnQoXCJzY3JpcHRcIik7XG4gICAgICAgICAgICBzY3JpcHQub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJ1bklmUHJlc2VudChoYW5kbGUpO1xuICAgICAgICAgICAgICAgIHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBudWxsO1xuICAgICAgICAgICAgICAgIGh0bWwucmVtb3ZlQ2hpbGQoc2NyaXB0KTtcbiAgICAgICAgICAgICAgICBzY3JpcHQgPSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGh0bWwuYXBwZW5kQ2hpbGQoc2NyaXB0KTtcbiAgICAgICAgICAgIHJldHVybiBoYW5kbGU7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbFNldFRpbWVvdXRJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgc2V0SW1tZWRpYXRlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICB2YXIgaGFuZGxlID0gYWRkRnJvbVNldEltbWVkaWF0ZUFyZ3VtZW50cyhhcmd1bWVudHMpO1xuICAgICAgICAgICAgc2V0VGltZW91dChwYXJ0aWFsbHlBcHBsaWVkKHJ1bklmUHJlc2VudCwgaGFuZGxlKSwgMCk7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIElmIHN1cHBvcnRlZCwgd2Ugc2hvdWxkIGF0dGFjaCB0byB0aGUgcHJvdG90eXBlIG9mIGdsb2JhbCwgc2luY2UgdGhhdCBpcyB3aGVyZSBzZXRUaW1lb3V0IGV0IGFsLiBsaXZlLlxuICAgIHZhciBhdHRhY2hUbyA9IE9iamVjdC5nZXRQcm90b3R5cGVPZiAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YoZ2xvYmFsKTtcbiAgICBhdHRhY2hUbyA9IGF0dGFjaFRvICYmIGF0dGFjaFRvLnNldFRpbWVvdXQgPyBhdHRhY2hUbyA6IGdsb2JhbDtcblxuICAgIC8vIERvbid0IGdldCBmb29sZWQgYnkgZS5nLiBicm93c2VyaWZ5IGVudmlyb25tZW50cy5cbiAgICBpZiAoe30udG9TdHJpbmcuY2FsbChnbG9iYWwucHJvY2VzcykgPT09IFwiW29iamVjdCBwcm9jZXNzXVwiKSB7XG4gICAgICAgIC8vIEZvciBOb2RlLmpzIGJlZm9yZSAwLjlcbiAgICAgICAgaW5zdGFsbE5leHRUaWNrSW1wbGVtZW50YXRpb24oKTtcblxuICAgIH0gZWxzZSBpZiAoY2FuVXNlUG9zdE1lc3NhZ2UoKSkge1xuICAgICAgICAvLyBGb3Igbm9uLUlFMTAgbW9kZXJuIGJyb3dzZXJzXG4gICAgICAgIGluc3RhbGxQb3N0TWVzc2FnZUltcGxlbWVudGF0aW9uKCk7XG5cbiAgICB9IGVsc2UgaWYgKGdsb2JhbC5NZXNzYWdlQ2hhbm5lbCkge1xuICAgICAgICAvLyBGb3Igd2ViIHdvcmtlcnMsIHdoZXJlIHN1cHBvcnRlZFxuICAgICAgICBpbnN0YWxsTWVzc2FnZUNoYW5uZWxJbXBsZW1lbnRhdGlvbigpO1xuXG4gICAgfSBlbHNlIGlmIChkb2MgJiYgXCJvbnJlYWR5c3RhdGVjaGFuZ2VcIiBpbiBkb2MuY3JlYXRlRWxlbWVudChcInNjcmlwdFwiKSkge1xuICAgICAgICAvLyBGb3IgSUUgNuKAkzhcbiAgICAgICAgaW5zdGFsbFJlYWR5U3RhdGVDaGFuZ2VJbXBsZW1lbnRhdGlvbigpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRm9yIG9sZGVyIGJyb3dzZXJzXG4gICAgICAgIGluc3RhbGxTZXRUaW1lb3V0SW1wbGVtZW50YXRpb24oKTtcbiAgICB9XG5cbiAgICBhdHRhY2hUby5zZXRJbW1lZGlhdGUgPSBzZXRJbW1lZGlhdGU7XG4gICAgYXR0YWNoVG8uY2xlYXJJbW1lZGlhdGUgPSBjbGVhckltbWVkaWF0ZTtcbn0oc2VsZikpO1xuIiwiLy8gQ2F1dGlvbjpcbi8vIERvIG5vdCByZXBsYWNlIHRoaXMgaW1wb3J0IHN0YXRlbWVudCB3aXRoIGNvZGVzLlxuLy9cbi8vIElmIHlvdSByZXBsYWNlIHRoaXMgaW1wb3J0IHN0YXRlbWVudCB3aXRoIGNvZGVzLFxuLy8gdGhlIGNvZGVzIHdpbGwgYmUgZXhlY3V0ZWQgYWZ0ZXIgdGhlIGZvbGxvd2luZyBwb2x5ZmlsbHMgYXJlIGltcG9ydGVkXG4vLyBiZWNhdXNlIGltcG9ydCBzdGF0ZW1lbnRzIGFyZSBob2lzdGVkIGR1cmluZyBjb21waWxhdGlvbi5cbmltcG9ydCAnLi9wb2x5ZmlsbC1zd2l0Y2hlcyc7XG5cbi8vIFBvbHlmaWxsIEVDTUFTY3JpcHQgc3RhbmRhcmQgZmVhdHVyZXMgd2l0aCBnbG9iYWwgbmFtZXNwYWNlIHBvbGx1dGlvblxuaW1wb3J0ICdjb3JlLWpzL2ZuL29iamVjdC9zZXQtcHJvdG90eXBlLW9mJztcbmltcG9ydCAnY29yZS1qcy9mbi9zZXQnO1xuaW1wb3J0ICdjb3JlLWpzL2ZuL21hcCc7XG5pbXBvcnQgJ2NvcmUtanMvZm4vd2Vhay1tYXAnO1xuaW1wb3J0ICdjb3JlLWpzL2ZuL2FycmF5L2Zyb20nO1xuXG4vLyBQb2x5ZmlsbCBDdXN0b20gRWxlbWVudHMgdjEgd2l0aCBnbG9iYWwgbmFtZXNwYWNlIHBvbGx1dGlvblxuaW1wb3J0ICdAb25zZW51aS9jdXN0b20tZWxlbWVudHMvc3JjL2N1c3RvbS1lbGVtZW50cyc7XG5cbi8vIFBvbHlmaWxsIE11dGF0aW9uT2JzZXJ2ZXIgd2l0aCBnbG9iYWwgbmFtZXNwYWNlIHBvbGx1dGlvblxuaW1wb3J0ICcuL011dGF0aW9uT2JzZXJ2ZXJAMC43LjIyL011dGF0aW9uT2JzZXJ2ZXIuanMnO1xuXG4vLyBQb2x5ZmlsbCBzZXRJbW1lZGlhdGUgd2l0aCBnbG9iYWwgbmFtZXNwYWNlIHBvbGx1dGlvblxuaW1wb3J0ICcuL3NldEltbWVkaWF0ZUAxLjAuMittb2Qvc2V0SW1tZWRpYXRlLmpzJztcbiIsIihmdW5jdGlvbigpIHtcbiAgdmFyIERFRkFVTFRfVklFV1BPUlQgPSAnd2lkdGg9ZGV2aWNlLXdpZHRoLGluaXRpYWwtc2NhbGU9MSxtYXhpbXVtLXNjYWxlPTEsbWluaW11bS1zY2FsZT0xLHVzZXItc2NhbGFibGU9bm8nO1xuXG4gIHZhciBWaWV3cG9ydCA9IHsgXG4gICAgZW5zdXJlVmlld3BvcnRFbGVtZW50OiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB2aWV3cG9ydEVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdtZXRhW25hbWU9dmlld3BvcnRdJyk7XG5cbiAgICAgIGlmICghdmlld3BvcnRFbGVtZW50KSB7XG4gICAgICAgIHZpZXdwb3J0RWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ21ldGEnKTtcbiAgICAgICAgdmlld3BvcnRFbGVtZW50Lm5hbWUgPSAndmlld3BvcnQnO1xuICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHZpZXdwb3J0RWxlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB2aWV3cG9ydEVsZW1lbnQ7XG4gICAgfSxcblxuICAgIHNldHVwOiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB2aWV3cG9ydEVsZW1lbnQgPSBWaWV3cG9ydC5lbnN1cmVWaWV3cG9ydEVsZW1lbnQoKTtcblxuICAgICAgaWYgKCF2aWV3cG9ydEVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXZpZXdwb3J0RWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2NvbnRlbnQnKSkge1xuICAgICAgICB2aWV3cG9ydEVsZW1lbnQuc2V0QXR0cmlidXRlKCdjb250ZW50JywgREVGQVVMVF9WSUVXUE9SVCk7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIHdpbmRvdy5WaWV3cG9ydCA9IFZpZXdwb3J0O1xufSkoKTtcbiIsImltcG9ydCB7IEZhc3RDbGljayB9IGZyb20gJ0BvbnNlbnVpL2Zhc3RjbGljayc7XG5pbXBvcnQgJy4vb25zL3BsYXRmb3JtJzsgLy8gVGhpcyBmaWxlIG11c3QgYmUgbG9hZGVkIGJlZm9yZSBDdXN0b20gRWxlbWVudHMgcG9seWZpbGxzLlxuaW1wb3J0ICcuL3BvbHlmaWxscy9pbmRleC5qcyc7XG5pbXBvcnQgJy4vdmVuZG9yL2luZGV4LmpzJztcbmltcG9ydCAnLi9vbnMvbWljcm9ldmVudC5qcyc7XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIHNldHVwKG9ucykge1xuICBpZiAod2luZG93Ll9vbnNMb2FkZWQpIHtcbiAgICBvbnMuX3V0aWwud2FybignT25zZW4gVUkgaXMgbG9hZGVkIG1vcmUgdGhhbiBvbmNlLicpO1xuICB9XG4gIHdpbmRvdy5fb25zTG9hZGVkID0gdHJ1ZTtcblxuICAvLyBmYXN0Y2xpY2tcbiAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCAoKSA9PiB7XG4gICAgb25zLmZhc3RDbGljayA9IEZhc3RDbGljay5hdHRhY2goZG9jdW1lbnQuYm9keSk7XG5cbiAgICBjb25zdCBzdXBwb3J0VG91Y2hBY3Rpb24gPSAndG91Y2gtYWN0aW9uJyBpbiBkb2N1bWVudC5ib2R5LnN0eWxlO1xuXG4gICAgb25zLnBsYXRmb3JtLl9ydW5PbkFjdHVhbFBsYXRmb3JtKCgpID0+IHtcbiAgICAgIGlmIChvbnMucGxhdGZvcm0uaXNBbmRyb2lkKCkpIHtcbiAgICAgICAgLy8gSW4gQW5kcm9pZDQuNCssIGNvcnJlY3Qgdmlld3BvcnQgc2V0dGluZ3MgY2FuIHJlbW92ZSBjbGljayBkZWxheS5cbiAgICAgICAgLy8gU28gZGlzYWJsZSBGYXN0Q2xpY2sgb24gQW5kcm9pZC5cbiAgICAgICAgb25zLmZhc3RDbGljay5kZXN0cm95KCk7XG4gICAgICB9IGVsc2UgaWYgKG9ucy5wbGF0Zm9ybS5pc0lPUygpKSB7XG4gICAgICAgIGlmIChzdXBwb3J0VG91Y2hBY3Rpb24gJiYgKG9ucy5wbGF0Zm9ybS5pc0lPU1NhZmFyaSgpIHx8IG9ucy5wbGF0Zm9ybS5pc1dLV2ViVmlldygpKSkge1xuICAgICAgICAgIC8vIElmICd0b3VjaC1hY3Rpb24nIHN1cHBvcnRlZCBpbiBpT1MgU2FmYXJpIG9yIFdLV2ViVmlldywgZGlzYWJsZSBGYXN0Q2xpY2suXG4gICAgICAgICAgb25zLmZhc3RDbGljay5kZXN0cm95KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gRG8gbm90aGluZy4gJ3RvdWNoLWFjdGlvbjogbWFuaXB1bGF0aW9uJyBoYXMgbm8gZWZmZWN0IG9uIFVJV2ViVmlldy5cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9LCBmYWxzZSk7XG5cbiAgb25zLnJlYWR5KGZ1bmN0aW9uKCkge1xuICAgIG9ucy5lbmFibGVEZXZpY2VCYWNrQnV0dG9uSGFuZGxlcigpO1xuICAgIG9ucy5fZGVmYXVsdERldmljZUJhY2tCdXR0b25IYW5kbGVyID0gb25zLl9pbnRlcm5hbC5kYmJEaXNwYXRjaGVyLmNyZWF0ZUhhbmRsZXIod2luZG93LmRvY3VtZW50LmJvZHksICgpID0+IHtcbiAgICAgIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChuYXZpZ2F0b3IsICdhcHAnKSkge1xuICAgICAgICBuYXZpZ2F0b3IuYXBwLmV4aXRBcHAoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybignQ291bGQgbm90IGNsb3NlIHRoZSBhcHAuIElzIFxcJ2NvcmRvdmEuanNcXCcgaW5jbHVkZWQ/XFxuRXJyb3I6IFxcJ3dpbmRvdy5uYXZpZ2F0b3IuYXBwXFwnIGlzIHVuZGVmaW5lZC4nKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBkb2N1bWVudC5ib2R5Ll9nZXN0dXJlRGV0ZWN0b3IgPSBuZXcgb25zLkdlc3R1cmVEZXRlY3Rvcihkb2N1bWVudC5ib2R5LCB7IHBhc3NpdmU6IHRydWUgfSk7XG5cbiAgICAvLyBTaW11bGF0ZSBEZXZpY2UgQmFjayBCdXR0b24gb24gRVNDIHByZXNzXG4gICAgaWYgKCFvbnMucGxhdGZvcm0uaXNXZWJWaWV3KCkpIHtcbiAgICAgIGRvY3VtZW50LmJvZHkuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgIGlmIChldmVudC5rZXlDb2RlID09PSAyNykge1xuICAgICAgICAgIG9ucy5maXJlRGV2aWNlQmFja0J1dHRvbkV2ZW50KCk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8gc2V0dXAgbG9hZGluZyBwbGFjZWhvbGRlclxuICAgIG9ucy5fc2V0dXBMb2FkaW5nUGxhY2VIb2xkZXJzKCk7XG4gIH0pO1xuXG4gIC8vIHZpZXdwb3J0LmpzXG4gIFZpZXdwb3J0LnNldHVwKCk7XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5mdW5jdGlvbiBnZXRFbGVtZW50Q2xhc3MoKSB7XG4gIGlmICh0eXBlb2YgSFRNTEVsZW1lbnQgIT09ICdmdW5jdGlvbicpIHsgLy8gY2FzZSBvZiBTYWZhcmlcbiAgICBjb25zdCBCYXNlRWxlbWVudCA9ICgpID0+IHt9O1xuICAgIEJhc2VFbGVtZW50LnByb3RvdHlwZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIHJldHVybiBCYXNlRWxlbWVudDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gSFRNTEVsZW1lbnQ7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQmFzZUVsZW1lbnQgZXh0ZW5kcyBnZXRFbGVtZW50Q2xhc3MoKSB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy10ZW1wbGF0ZVxuICogQGNhdGVnb3J5IHV0aWxcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgRGVmaW5lIGEgc2VwYXJhdGUgSFRNTCBmcmFnbWVudCBhbmQgdXNlIGFzIGEgdGVtcGxhdGUuIFRoZXNlIHRlbXBsYXRlcyBjYW4gYmUgbG9hZGVkIGFzIHBhZ2VzIGluIGA8b25zLW5hdmlnYXRvcj5gLCBgPG9ucy10YWJiYXI+YCBhbmQgYDxvbnMtc3BsaXR0ZXI+YC4gVGhleSBjYW4gYWxzbyBiZSB1c2VkIHRvIGdlbmVyYXRlIGRpYWxvZ3MuIFNpbmNlIE9uc2VuIFVJIDIuNC4wLCB0aGUgbmF0aXZlIGA8dGVtcGxhdGU+YCBlbGVtZW50IGNhbiBiZSB1c2VkIGluc3RlYWQgb2YgYDxvbnMtdGVtcGxhdGU+YCBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlIGFuZCBmZWF0dXJlcy4gYDxvbnMtdGVtcGxhdGU+YCBpcyBzdGlsbCBzdXBwb3J0ZWQgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg4bjg7Pjg5fjg6zjg7zjg4jjgajjgZfjgabkvb/nlKjjgZnjgovjgZ/jgoHjga5IVE1M44OV44Op44Kw44Oh44Oz44OI44KS5a6a576p44GX44G+44GZ44CC44GT44Gu6KaB57Sg44GnSFRNTOOCkuWuo+iogOOBmeOCi+OBqOOAgWlk5bGe5oCn44Gr5oyH5a6a44GX44Gf5ZCN5YmN44KScGFnZeOBrlVSTOOBqOOBl+OBpm9ucy1uYXZpZ2F0b3Ljgarjganjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgYvjgonlj4LnhafjgafjgY3jgb7jgZnjgIJbL2phXVxuICogQHNlZWFsc28gb25zLW5hdmlnYXRvclxuICogICBbZW5dVGhlIGA8b25zLW5hdmlnYXRvcj5gIGNvbXBvbmVudCBlbmFibGVzIHN0YWNrIGJhc2VkIG5hdmlnYXRpb24uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtdGFiYmFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtdGFiYmFyPmAgY29tcG9uZW50IGlzIHVzZWQgdG8gYWRkIHRhYiBuYXZpZ2F0aW9uLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXNwbGl0dGVyXG4gKiAgIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXI+YCBjb21wb25lbnQgY2FuIGJlIHVzZWQgdG8gY3JlYXRlIGEgZHJhZ2dhYmxlIG1lbnUgb3IgY29sdW1uIGJhc2VkIGxheW91dC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXRlbXBsYXRlIGlkPVwiZm9vYmFyLmh0bWxcIj5cbiAqICAgPG9ucy1wYWdlPlxuICogICAgIFBhZ2UgY29udGVudFxuICogICA8L29ucy1wYWdlPlxuICogPC9vbnMtdGVtcGxhdGU+XG4gKlxuICogPG9ucy1uYXZpZ2F0b3IgcGFnZT1cImZvb2Jhci5odG1sXCI+PC9vbnMtbmF2aWdhdG9yPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUZW1wbGF0ZUVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB0ZW1wbGF0ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UZW1wbGF0ZSBjb250ZW50LiBUaGlzIHByb3BlcnR5IGNhbiBub3QgYmUgdXNlZCB3aXRoIEFuZ3VsYXJKUyBiaW5kaW5ncy5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLnRlbXBsYXRlID0gdGhpcy5pbm5lckhUTUw7XG5cbiAgICB3aGlsZSAodGhpcy5maXJzdENoaWxkKSB7XG4gICAgICB0aGlzLnJlbW92ZUNoaWxkKHRoaXMuZmlyc3RDaGlsZCk7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgaWYgKHRoaXMucGFyZW50Tm9kZSkgeyAvLyBOb3RlOiB0aGlzLnBhcmVudE5vZGUgaXMgbm90IHNldCBpbiBzb21lIENFMC9DRTEgcG9seWZpbGxzLlxuICAgICAgLy8gU2hvdyB3YXJuaW5nIHdoZW4gdGhlIG9ucy10ZW1wbGF0ZSBpcyBub3QgbG9jYXRlZCBqdXN0IHVuZGVyIGRvY3VtZW50LmJvZHlcbiAgICAgIGlmICh0aGlzLnBhcmVudE5vZGUgIT09IGRvY3VtZW50LmJvZHkpIHsgLy8gaWYgdGhlIHBhcmVudCBpcyBub3QgZG9jdW1lbnQuYm9keVxuICAgICAgICB1dGlsLndhcm4oYG9ucy10ZW1wbGF0ZSAoaWQgPSAke3RoaXMuZ2V0QXR0cmlidXRlKCdpZCcpfSkgbXVzdCBiZSBsb2NhdGVkIGp1c3QgdW5kZXIgZG9jdW1lbnQuYm9keSR7IHRoaXMucGFyZW50Tm9kZS5vdXRlckhUTUwgPyBgOlxcblxcbiR7dGhpcy5wYXJlbnROb2RlLm91dGVySFRNTH1gIDogJy4nIH1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgZXZlbnQgPSBuZXcgQ3VzdG9tRXZlbnQoJ190ZW1wbGF0ZWxvYWRlZCcsIHtidWJibGVzOiB0cnVlLCBjYW5jZWxhYmxlOiB0cnVlfSk7XG4gICAgZXZlbnQudGVtcGxhdGUgPSB0aGlzLnRlbXBsYXRlO1xuICAgIGV2ZW50LnRlbXBsYXRlSWQgPSB0aGlzLmdldEF0dHJpYnV0ZSgnaWQnKTtcblxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gIH1cbn1cblxub25zRWxlbWVudHMuVGVtcGxhdGUgPSBUZW1wbGF0ZUVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy10ZW1wbGF0ZScsIFRlbXBsYXRlRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCBvcmllbnRhdGlvbiBmcm9tICcuLi9vbnMvb3JpZW50YXRpb24nO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uL29ucy9wbGF0Zm9ybSc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtaWZcbiAqIEBjYXRlZ29yeSBjb25kaXRpb25hbFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2lmXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIENvbmRpdGlvbmFsbHkgZGlzcGxheSBjb250ZW50IGRlcGVuZGluZyBvbiB0aGUgcGxhdGZvcm0sIGRldmljZSBvcmllbnRhdGlvbiBvciBib3RoLlxuICpcbiAqICAgICBTb21ldGltZXMgaXQgaXMgdXNlZnVsIHRvIGNvbmRpdGlvbmFsbHkgaGlkZSBvciBzaG93IGNlcnRhaW4gY29tcG9uZW50cyBiYXNlZCBvbiBwbGF0Zm9ybS4gV2hlbiBydW5uaW5nIG9uIGlPUyB0aGUgYDxvbnMtaWY+YCBlbGVtZW50IGNhbiBiZSB1c2VkIHRvIGhpZGUgdGhlIGA8b25zLWZhYj5gIGVsZW1lbnQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNjcm9zcy1wbGF0Zm9ybS1zdHlsaW5nLWF1dG9zdHlsaW5nIFtlbl1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9lbl1bamFdSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1wYWdlPlxuICogICA8b25zLWlmIG9yaWVudGF0aW9uPVwibGFuZHNjYXBlXCI+XG4gKiAgICAgTGFuZHNjYXBlIHZpZXchXG4gKiAgIDwvb25zLWlmPlxuICogICA8b25zLWlmIHBsYXRmb3JtPVwiYW5kcm9pZFwiPlxuICogICAgIFRoaXMgaXMgQW5kcm9pZC5cbiAqICAgPC9vbnMtaWY+XG4gKiAgIDxvbnMtaWYgcGxhdGZvcm09XCJpb3Mgb3RoZXJcIj5cbiAqICAgICBUaGlzIGlzIG5vdCBBbmRyb2lkLlxuICogICA8L29ucy1pZj5cbiAqIDwvb25zLXBhZ2U+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIElmRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBwbGF0Zm9ybVxuICAgKiBAaW5pdG9ubHlcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BhY2Utc2VwYXJhdGVkIHBsYXRmb3JtIG5hbWVzLiBQb3NzaWJsZSB2YWx1ZXMgYXJlIGBcImlvc1wiYCwgYFwiYW5kcm9pZFwiYCwgYFwid2luZG93c1wiYCBhbmQgYFwib3RoZXJcImAuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBvcmllbnRhdGlvblxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1FaXRoZXIgYFwicG9ydHJhaXRcImAgb3IgYFwibGFuZHNjYXBlXCJgLlsvZW5dXG4gICAqICBbamFdcG9ydHJhaXTjgoLjgZfjgY/jga9sYW5kc2NhcGXjgpLmjIflrprjgZfjgb7jgZlbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIGlmIChwbGF0Zm9ybS5fZ2V0U2VsZWN0ZWRQbGF0Zm9ybSgpICE9PSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3BsYXRmb3JtVXBkYXRlKCk7XG4gICAgICB9IGVsc2UgaWYgKCF0aGlzLl9pc0FsbG93ZWRQbGF0Zm9ybSgpKSB7XG4gICAgICAgIHdoaWxlICh0aGlzLmNoaWxkTm9kZXNbMF0pIHtcbiAgICAgICAgICB0aGlzLmNoaWxkTm9kZXNbMF0ucmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcGxhdGZvcm1VcGRhdGUoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMuX29uT3JpZW50YXRpb25DaGFuZ2UoKTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIG9yaWVudGF0aW9uLm9uKCdjaGFuZ2UnLCB0aGlzLl9vbk9yaWVudGF0aW9uQ2hhbmdlLmJpbmQodGhpcykpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnb3JpZW50YXRpb24nXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lKSB7XG4gICAgaWYgKG5hbWUgPT09ICdvcmllbnRhdGlvbicpIHtcbiAgICAgIHRoaXMuX29uT3JpZW50YXRpb25DaGFuZ2UoKTtcbiAgICB9XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBvcmllbnRhdGlvbi5vZmYoJ2NoYW5nZScsIHRoaXMuX29uT3JpZW50YXRpb25DaGFuZ2UpO1xuICB9XG5cbiAgX3BsYXRmb3JtVXBkYXRlKCkge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9IHRoaXMuX2lzQWxsb3dlZFBsYXRmb3JtKCkgPyAnJyA6ICdub25lJztcbiAgfVxuXG4gIF9pc0FsbG93ZWRQbGF0Zm9ybSgpIHtcbiAgICByZXR1cm4gIXRoaXMuZ2V0QXR0cmlidXRlKCdwbGF0Zm9ybScpIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdwbGF0Zm9ybScpLnNwbGl0KC9cXHMrLykuaW5kZXhPZihwbGF0Zm9ybS5nZXRNb2JpbGVPUygpKSA+PSAwO1xuICB9XG5cbiAgX29uT3JpZW50YXRpb25DaGFuZ2UoKSB7XG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdvcmllbnRhdGlvbicpICYmIHRoaXMuX2lzQWxsb3dlZFBsYXRmb3JtKCkpIHtcbiAgICAgIGNvbnN0IGNvbmRpdGlvbmFsT3JpZW50YXRpb24gPSB0aGlzLmdldEF0dHJpYnV0ZSgnb3JpZW50YXRpb24nKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgY29uc3QgY3VycmVudE9yaWVudGF0aW9uID0gb3JpZW50YXRpb24uaXNQb3J0cmFpdCgpID8gJ3BvcnRyYWl0JyA6ICdsYW5kc2NhcGUnO1xuXG4gICAgICB0aGlzLnN0eWxlLmRpc3BsYXkgPSAoY29uZGl0aW9uYWxPcmllbnRhdGlvbiA9PT0gY3VycmVudE9yaWVudGF0aW9uKSA/ICcnIDogJ25vbmUnO1xuICAgIH1cbiAgfVxufVxuXG5vbnNFbGVtZW50cy5JZiA9IElmRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWlmJywgSWZFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4vdXRpbCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhc2VBbmltYXRvciB7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnRpbWluZ1xuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kdXJhdGlvblxuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kZWxheVxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy50aW1pbmcgPSBvcHRpb25zLnRpbWluZyB8fCAnbGluZWFyJztcbiAgICB0aGlzLmR1cmF0aW9uID0gb3B0aW9ucy5kdXJhdGlvbiB8fCAwO1xuICAgIHRoaXMuZGVsYXkgPSBvcHRpb25zLmRlbGF5IHx8IDA7XG5cbiAgICB0aGlzLmRlZiA9IHtcbiAgICAgIHRpbWluZzogdGhpcy50aW1pbmcsXG4gICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgIGRlbGF5OiB0aGlzLmRlbGF5XG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBleHRlbmQocHJvcGVydGllcyA9IHt9KSB7XG4gICAgY29uc3QgZXh0ZW5kZWRBbmltYXRvciA9IHRoaXM7XG4gICAgY29uc3QgbmV3QW5pbWF0b3IgPSBmdW5jdGlvbigpIHtcbiAgICAgIGV4dGVuZGVkQW5pbWF0b3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHV0aWwuZXh0ZW5kKHRoaXMsIHByb3BlcnRpZXMpO1xuICAgIH07XG5cbiAgICBuZXdBbmltYXRvci5wcm90b3R5cGUgPSB0aGlzLnByb3RvdHlwZTtcbiAgICByZXR1cm4gbmV3QW5pbWF0b3I7XG4gIH1cbn1cblxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuLy8gVGhpcyBvYmplY3Qgc2hvdWxkIG5vdCBiZSBleHBvc2VkIHRvIHVzZXJzLiBQbGVhc2Uga2VlcCB0aGlzIHByaXZhdGUuXG5jb25zdCBpUGhvbmVYUGF0Y2ggPSB7fTtcblxuaVBob25lWFBhdGNoLmlzSVBob25lWFBvcnRyYWl0UGF0Y2hBY3RpdmUgPSAoKSA9PiB7XG4gIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZ2V0QXR0cmlidXRlKCdvbnNmbGFnLWlwaG9uZXgtcG9ydHJhaXQnKSAhPSBudWxsICYmIHdpbmRvdy5pbm5lcldpZHRoIDwgd2luZG93LmlubmVySGVpZ2h0O1xufVxuXG5pUGhvbmVYUGF0Y2guaXNJUGhvbmVYTGFuZHNjYXBlUGF0Y2hBY3RpdmUgPSAoKSA9PiB7XG4gIC8vIElmIHdpZHRoID09PSBoZWlnaHQsIHRyZWF0IGl0IGFzIGxhbmRzY2FwZVxuICByZXR1cm4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmdldEF0dHJpYnV0ZSgnb25zZmxhZy1pcGhvbmV4LWxhbmRzY2FwZScpICE9IG51bGwgJiYgd2luZG93LmlubmVyV2lkdGggPj0gd2luZG93LmlubmVySGVpZ2h0O1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHNhZmUgYXJlYSBsZW5ndGhzIGJhc2VkIG9uIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBzYWZlIGFyZWFzLlxuICovXG5pUGhvbmVYUGF0Y2guZ2V0U2FmZUFyZWFMZW5ndGhzID0gKCkgPT4ge1xuICBsZXQgc2FmZUFyZWFMZW5ndGhzO1xuICBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWFBvcnRyYWl0UGF0Y2hBY3RpdmUoKSkge1xuICAgIHNhZmVBcmVhTGVuZ3RocyA9IHtcbiAgICAgIHRvcDogNDQsXG4gICAgICByaWdodDogMCxcbiAgICAgIGJvdHRvbTogMzQsXG4gICAgICBsZWZ0OiAwXG4gICAgfTtcbiAgfSBlbHNlIGlmIChpUGhvbmVYUGF0Y2guaXNJUGhvbmVYTGFuZHNjYXBlUGF0Y2hBY3RpdmUoKSkge1xuICAgIHNhZmVBcmVhTGVuZ3RocyA9IHtcbiAgICAgIHRvcDogMCxcbiAgICAgIHJpZ2h0OiA0NCxcbiAgICAgIGJvdHRvbTogMjEsXG4gICAgICBsZWZ0OiA0NFxuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgc2FmZUFyZWFMZW5ndGhzID0ge1xuICAgICAgdG9wOiAwLFxuICAgICAgcmlnaHQ6IDAsXG4gICAgICBib3R0b206IDAsXG4gICAgICBsZWZ0OiAwXG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBzYWZlQXJlYUxlbmd0aHM7XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgc2FmZSBhcmVhIHJlY3QgYmFzZWQgb24gdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIHNhZmUgYXJlYXMuXG4gKi9cbmlQaG9uZVhQYXRjaC5nZXRTYWZlQXJlYURPTVJlY3QgPSAoKSA9PiB7XG4gIGxldCBzYWZlQXJlYVJlY3Q7XG4gIGlmIChpUGhvbmVYUGF0Y2guaXNJUGhvbmVYUG9ydHJhaXRQYXRjaEFjdGl2ZSgpKSB7XG4gICAgc2FmZUFyZWFSZWN0ID0ge1xuICAgICAgeDogMCxcbiAgICAgIHk6IDQ0LCAvKiAwICsgNDQgKHRvcCBzYWZlIGFyZWEpICovXG4gICAgICB3aWR0aDogd2luZG93LmlubmVyV2lkdGgsXG4gICAgICBoZWlnaHQ6IHdpbmRvdy5pbm5lckhlaWdodCAtIDc4IC8qIGhlaWdodCAtIDQ0ICh0b3Agc2FmZSBhcmVhKSAtIDM0IChib3R0b20gc2FmZSBhcmVhKSAqL1xuICAgIH07XG4gIH0gZWxzZSBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWExhbmRzY2FwZVBhdGNoQWN0aXZlKCkpIHtcbiAgICBzYWZlQXJlYVJlY3QgPSB7XG4gICAgICB4OiA0NCwgLyogMCArIDQ0IChsZWZ0IHNhZmUgYXJlYSkgKi9cbiAgICAgIHk6IDAsXG4gICAgICB3aWR0aDogd2luZG93LmlubmVyV2lkdGggLSA4OCwgLyogd2lkdGggLSA0NCAobGVmdCBzYWZlIGFyZWEpIC0gMzQgKHJpZ2h0IHNhZmUgYXJlYSkgKi9cbiAgICAgIGhlaWdodDogd2luZG93LmlubmVySGVpZ2h0IC0gMjEgLyogaGVpZ2h0IC0gMjEgKGJvdHRvbSBzYWZlIGFyZWEpICovXG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICBzYWZlQXJlYVJlY3QgPSB7XG4gICAgICB4OiAwLFxuICAgICAgeTogMCxcbiAgICAgIHdpZHRoOiB3aW5kb3cuaW5uZXJXaWR0aCxcbiAgICAgIGhlaWdodDogd2luZG93LmlubmVySGVpZ2h0XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uc2FmZUFyZWFSZWN0LFxuICAgIGxlZnQ6IHNhZmVBcmVhUmVjdC54LFxuICAgIHRvcDogc2FmZUFyZWFSZWN0LnksXG4gICAgcmlnaHQ6IHNhZmVBcmVhUmVjdC54ICsgc2FmZUFyZWFSZWN0LndpZHRoLFxuICAgIGJvdHRvbTogc2FmZUFyZWFSZWN0LnkgKyBzYWZlQXJlYVJlY3QuaGVpZ2h0XG4gIH07XG59XG5cbmV4cG9ydCBkZWZhdWx0IGlQaG9uZVhQYXRjaDtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5pbXBvcnQgQmFzZUFuaW1hdG9yIGZyb20gJy4uLy4uL29ucy9iYXNlLWFuaW1hdG9yJ1xuaW1wb3J0IGlQaG9uZVhQYXRjaCBmcm9tICcuLi8uLi9vbnMvaXBob25leC1wYXRjaCc7XG5cbmV4cG9ydCBjbGFzcyBBY3Rpb25TaGVldEFuaW1hdG9yIGV4dGVuZHMgQmFzZUFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2xpbmVhcicsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjJ9ID0ge30pIHtcbiAgICBzdXBlcih7IHRpbWluZywgZGVsYXksIGR1cmF0aW9uIH0pXG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGRvbmVcbiAgICovXG4gIHNob3coZGlhbG9nLCBkb25lKSB7XG4gICAgZG9uZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBoaWRlKGRpYWxvZywgZG9uZSkge1xuICAgIGRvbmUoKTtcbiAgfVxufVxuXG4vKipcbiAqIEFuZHJvaWQgc3R5bGUgYW5pbWF0b3IgZm9yIEFjdGlvbiBTaGVldC5cbiAqL1xuZXhwb3J0IGNsYXNzIE1EQWN0aW9uU2hlZXRBbmltYXRvciBleHRlbmRzIEFjdGlvblNoZWV0QW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHsgdGltaW5nID0gJ2Vhc2UnLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC40IH0gPSB7fSkge1xuICAgIHN1cGVyKHt0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbn0pO1xuXG4gICAgdGhpcy5tYXNrVGltaW5nID0gJ2xpbmVhcic7XG4gICAgdGhpcy5tYXNrRHVyYXRpb24gPSAwLjI7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaylcbiAgICAgICAgLnF1ZXVlKHsgb3BhY2l0eTogMCB9KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoeyBvcGFjaXR5OiAxLjAgfSwge1xuICAgICAgICAgIGR1cmF0aW9uOiB0aGlzLm1hc2tEdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6IHRoaXMubWFza1RpbWluZ1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fc2hlZXQsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDAsIDgwJSwgMClgLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScsIG9wYWNpdHk6IDEgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2spXG4gICAgICAgIC5xdWV1ZSh7IG9wYWNpdHk6IDEgfSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHsgb3BhY2l0eTogMCB9LCB7XG4gICAgICAgICAgZHVyYXRpb246IHRoaXMubWFza0R1cmF0aW9uLFxuICAgICAgICAgIHRpbWluZzogdGhpcy5tYXNrVGltaW5nXG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9zaGVldCwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiAxIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCA4MCUsIDApYCwgb3BhY2l0eTogMCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBpT1Mgc3R5bGUgYW5pbWF0b3IgZm9yIGRpYWxvZy5cbiAqL1xuZXhwb3J0IGNsYXNzIElPU0FjdGlvblNoZWV0QW5pbWF0b3IgZXh0ZW5kcyBBY3Rpb25TaGVldEFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7IHRpbWluZyA9ICdlYXNlJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMyB9ID0ge30pIHtcbiAgICBzdXBlcih7dGltaW5nLCBkZWxheSwgZHVyYXRpb259KTtcblxuICAgIHRoaXMubWFza1RpbWluZyA9ICdsaW5lYXInO1xuICAgIHRoaXMubWFza0R1cmF0aW9uID0gMC4yO1xuICAgIGlmIChpUGhvbmVYUGF0Y2guaXNJUGhvbmVYUG9ydHJhaXRQYXRjaEFjdGl2ZSgpKSB7XG4gICAgICB0aGlzLmxpZnRBbW91bnQgPSAnY2FsYygxMDAlICsgNDhweCknO1xuICAgIH0gZWxzZSBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWExhbmRzY2FwZVBhdGNoQWN0aXZlKCkpIHtcbiAgICAgIHRoaXMubGlmdEFtb3VudCA9ICdjYWxjKDEwMCUgKyAzM3B4KSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubGlmdEFtb3VudCA9IGRvY3VtZW50LmJvZHkuY2xpZW50SGVpZ2h0IC8gMi4wIC0gMSArICdweCc7IC8vIGF2b2lkIEZvcmNlZCBTeW5jaHJvbm91cyBMYXlvdXRcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaylcbiAgICAgIC5xdWV1ZSh7IG9wYWNpdHk6IDAgfSlcbiAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAucXVldWUoeyBvcGFjaXR5OiAxIH0sIHtcbiAgICAgICAgZHVyYXRpb246IHRoaXMubWFza0R1cmF0aW9uLFxuICAgICAgICB0aW1pbmc6IHRoaXMubWFza1RpbWluZ1xuICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX3NoZWV0LCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAke3RoaXMubGlmdEFtb3VudH0sIDApYCB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBoaWRlKGRpYWxvZywgY2FsbGJhY2spIHtcbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrKVxuICAgICAgLnF1ZXVlKHsgb3BhY2l0eTogMSB9KVxuICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgIC5xdWV1ZSh7IG9wYWNpdHk6IDAgfSwge1xuICAgICAgICBkdXJhdGlvbjogdGhpcy5tYXNrRHVyYXRpb24sXG4gICAgICAgIHRpbWluZzogdGhpcy5tYXNrVGltaW5nXG4gICAgICB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fc2hlZXQsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJyB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoMCwgJHt0aGlzLmxpZnRBbW91bnR9LCAwKWAgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCBEb29yTG9jayBmcm9tICcuLi8uLi9vbnMvZG9vcmxvY2snO1xuaW1wb3J0IGRldmljZUJhY2tCdXR0b25EaXNwYXRjaGVyIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9kZXZpY2UtYmFjay1idXR0b24tZGlzcGF0Y2hlcic7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQmFzZURpYWxvZ0VsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgdXRpbC50aHJvd01lbWJlcigpO1xuICB9XG5cbiAgX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICB1dGlsLnRocm93TWVtYmVyKCk7XG4gIH1cblxuICBfdG9nZ2xlU3R5bGUoc2hvdWxkU2hvdykge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9IHNob3VsZFNob3cgPyAnYmxvY2snIDogJ25vbmUnO1xuICB9XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBCYXNlRGlhbG9nRWxlbWVudCkge1xuICAgICAgdXRpbC50aHJvd0Fic3RyYWN0KCk7XG4gICAgfVxuXG4gICAgdGhpcy5fdmlzaWJsZSA9IGZhbHNlO1xuICAgIHRoaXMuX2Rvb3JMb2NrID0gbmV3IERvb3JMb2NrKCk7XG4gICAgdGhpcy5fY2FuY2VsID0gdGhpcy5fY2FuY2VsLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fc2VsZkNhbWVsTmFtZSA9IHV0aWwuY2FtZWxpemUodGhpcy50YWdOYW1lLnNsaWNlKDQpKTtcbiAgICB0aGlzLl9kZWZhdWx0REJCID0gZSA9PiB0aGlzLmNhbmNlbGFibGUgPyB0aGlzLl9jYW5jZWwoKSA6IGUuY2FsbFBhcmVudEhhbmRsZXIoKTtcbiAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSB0aGlzLl91cGRhdGVBbmltYXRvckZhY3RvcnkoKTtcbiAgfVxuXG4gIGdldCBvbkRldmljZUJhY2tCdXR0b24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyO1xuICB9XG5cbiAgc2V0IG9uRGV2aWNlQmFja0J1dHRvbihjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLl9iYWNrQnV0dG9uSGFuZGxlcikge1xuICAgICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyID0gZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIuY3JlYXRlSGFuZGxlcih0aGlzLCBjYWxsYmFjayk7XG4gIH1cblxuICBfY2FuY2VsKCkge1xuICAgIGlmICh0aGlzLmNhbmNlbGFibGUgJiYgIXRoaXMuX3J1bm5pbmcpIHtcbiAgICAgIHRoaXMuX3J1bm5pbmcgPSB0cnVlO1xuICAgICAgdGhpcy5oaWRlKClcbiAgICAgICAgLnRoZW4oXG4gICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fcnVubmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdkaWFsb2ctY2FuY2VsJyk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICAoKSA9PiB0aGlzLl9ydW5uaW5nID0gZmFsc2VcbiAgICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBzaG93KC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gdGhpcy5fc2V0VmlzaWJsZSh0cnVlLCAuLi5hcmdzKTtcbiAgfVxuXG4gIGhpZGUoLi4uYXJncykge1xuICAgIHJldHVybiB0aGlzLl9zZXRWaXNpYmxlKGZhbHNlLCAuLi5hcmdzKTtcbiAgfVxuXG4gIHRvZ2dsZSguLi5hcmdzKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NldFZpc2libGUoIXRoaXMudmlzaWJsZSwgLi4uYXJncyk7XG4gIH1cblxuICBfc2V0VmlzaWJsZShzaG91bGRTaG93LCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBhY3Rpb24gPSBzaG91bGRTaG93ID8gJ3Nob3cnIDogJ2hpZGUnO1xuXG4gICAgb3B0aW9ucyA9IHsgLi4ub3B0aW9ucyB9O1xuICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyA9IHV0aWwuZXh0ZW5kKFxuICAgICAgb3B0aW9ucy5hbmltYXRpb25PcHRpb25zIHx8IHt9LFxuICAgICAgQW5pbWF0b3JGYWN0b3J5LnBhcnNlQW5pbWF0aW9uT3B0aW9uc1N0cmluZyh0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKSlcbiAgICApO1xuXG4gICAgbGV0IGNhbmNlbGVkID0gZmFsc2U7XG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsIGBwcmUke2FjdGlvbn1gLCB7IC8vIHByZXNob3cgcHJlaGlkZVxuICAgICAgW3RoaXMuX3NlbGZDYW1lbE5hbWVdOiB0aGlzLFxuICAgICAgY2FuY2VsOiAoKSA9PiBjYW5jZWxlZCA9IHRydWVcbiAgICB9KTtcblxuICAgIGlmIChjYW5jZWxlZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGBDYW5jZWxlZCBpbiBwcmUke2FjdGlvbn0gZXZlbnQuYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5fZG9vckxvY2sud2FpdFVubG9jaygoKSA9PiB7XG4gICAgICAgIGNvbnN0IHVubG9jayA9IHRoaXMuX2Rvb3JMb2NrLmxvY2soKTtcbiAgICAgICAgY29uc3QgYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRvckZhY3RvcnkubmV3QW5pbWF0b3Iob3B0aW9ucyk7XG5cbiAgICAgICAgc2hvdWxkU2hvdyAmJiB0aGlzLl90b2dnbGVTdHlsZSh0cnVlLCBvcHRpb25zKTtcbiAgICAgICAgdGhpcy5fdmlzaWJsZSA9IHNob3VsZFNob3c7XG4gICAgICAgIHV0aWwuaW9zUGFnZVNjcm9sbEZpeChzaG91bGRTaG93KTtcblxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgIGFuaW1hdG9yW2FjdGlvbl0odGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgIXNob3VsZFNob3cgJiYgdGhpcy5fdG9nZ2xlU3R5bGUoZmFsc2UsIG9wdGlvbnMpO1xuXG4gICAgICAgICAgICB1bmxvY2soKTtcblxuICAgICAgICAgICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ18nICsgYWN0aW9uKTtcbiAgICAgICAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncG9zdCcgKyBhY3Rpb24sIHtbdGhpcy5fc2VsZkNhbWVsTmFtZV06IHRoaXN9KTsgLy8gcG9zdHNob3cgcG9zdGhpZGVcblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuY2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgICAgICBvcHRpb25zLmNhbGxiYWNrKHRoaXMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXNvbHZlKHRoaXMpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgdmlzaWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fdmlzaWJsZTtcbiAgfVxuXG4gIHNldCBkaXNhYmxlZCh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnZGlzYWJsZWQnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICB9XG5cbiAgc2V0IGNhbmNlbGFibGUodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2NhbmNlbGFibGUnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgY2FuY2VsYWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2NhbmNlbGFibGUnKTtcbiAgfVxuXG4gIF91cGRhdGVNYXNrKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5fbWFzayAmJiB0aGlzLmdldEF0dHJpYnV0ZSgnbWFzay1jb2xvcicpKSB7XG4gICAgICAgIHRoaXMuX21hc2suc3R5bGUuYmFja2dyb3VuZENvbG9yID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ21hc2stY29sb3InKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICh0eXBlb2YgdGhpcy5fZGVmYXVsdERCQiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhpcy5vbkRldmljZUJhY2tCdXR0b24gPSB0aGlzLl9kZWZhdWx0REJCLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIGlmICh0aGlzLl9tYXNrKSB7XG4gICAgICAgIHRoaXMuX21hc2suYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9jYW5jZWwsIGZhbHNlKTtcbiAgICAgICAgdXRpbC5pb3NNYXNrU2Nyb2xsRml4KHRoaXMuX21hc2ssIHRydWUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgaWYgKHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyKSB7XG4gICAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlci5kZXN0cm95KCk7XG4gICAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlciA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX21hc2spIHtcbiAgICAgIHRoaXMuX21hc2sucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9jYW5jZWwsIGZhbHNlKTtcbiAgICAgIHV0aWwuaW9zTWFza1Njcm9sbEZpeCh0aGlzLl9tYXNrLCBmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnYW5pbWF0aW9uJywgJ21hc2stY29sb3InXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdtb2RpZmllcic6XG4gICAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCB0aGlzLl9zY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2FuaW1hdGlvbic6XG4gICAgICAgIHRoaXMuX2FuaW1hdG9yRmFjdG9yeSA9IHRoaXMuX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21hc2stY29sb3InOlxuICAgICAgICB0aGlzLl91cGRhdGVNYXNrKCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBnZXQgZXZlbnRzKCkge1xuICAgIHJldHVybiBbJ3ByZXNob3cnLCAncG9zdHNob3cnLCAncHJlaGlkZScsICdwb3N0aGlkZScsICdkaWFsb2ctY2FuY2VsJ107XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi8uLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi8uLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgeyBBY3Rpb25TaGVldEFuaW1hdG9yLCBJT1NBY3Rpb25TaGVldEFuaW1hdG9yLCBNREFjdGlvblNoZWV0QW5pbWF0b3IgfSBmcm9tICcuL2FuaW1hdG9yJztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuLi8uLi9vbnMvcGxhdGZvcm0nO1xuaW1wb3J0IEJhc2VEaWFsb2dFbGVtZW50IGZyb20gJy4uL2Jhc2UvYmFzZS1kaWFsb2cnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5hY3Rpb24tc2hlZXQnOiAnYWN0aW9uLXNoZWV0LS0qJyxcbiAgJy5hY3Rpb24tc2hlZXQtbWFzayc6ICdhY3Rpb24tc2hlZXQtbWFzay0tKicsXG4gICcuYWN0aW9uLXNoZWV0LXRpdGxlJzogJ2FjdGlvbi1zaGVldC10aXRsZS0tKidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdkZWZhdWx0JzogKCkgPT4gcGxhdGZvcm0uaXNBbmRyb2lkKCkgPyBNREFjdGlvblNoZWV0QW5pbWF0b3IgOiBJT1NBY3Rpb25TaGVldEFuaW1hdG9yLFxuICAnbm9uZSc6IEFjdGlvblNoZWV0QW5pbWF0b3Jcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWFjdGlvbi1zaGVldFxuICogQGNhdGVnb3J5IGRpYWxvZ1xuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBBY3Rpb24vYm90dG9tIHNoZWV0IHRoYXQgaXMgZGlzcGxheWVkIG9uIHRvcCBvZiBjdXJyZW50IHNjcmVlbi5cbiAqXG4gKiAgICAgVGhpcyBlbGVtZW50IGNhbiBlaXRoZXIgYmUgYXR0YWNoZWQgZGlyZWN0bHkgdG8gdGhlIGA8Ym9keT5gIG9yIGR5bmFtaWNhbGx5IGNyZWF0ZWQgZnJvbSBhIHRlbXBsYXRlIHVzaW5nIHRoZSBgb25zLmNyZWF0ZUVsZW1lbnQodGVtcGxhdGUsIHsgYXBwZW5kOiB0cnVlIH0pYCB1dGlsaXR5IGZ1bmN0aW9uIGFuZCB0aGUgYDx0ZW1wbGF0ZT5gIHRhZy5cbiAqXG4gKiAgICAgVGhlIGFjdGlvbiBzaGVldCBpcyB1c2VmdWwgZm9yIGRpc3BsYXlpbmcgYSBsaXN0IG9mIG9wdGlvbnMgYW5kIGFza2luZyB0aGUgdXNlciB0byBtYWtlIGEgZGVjaXNpb24uIEEgYG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uYCBpcyBwcm92aWRlZCBmb3IgdGhpcyBwdXJwb3NlLCBhbHRob3VnaCBpdCBjYW4gY29udGFpbiBhbnkgdHlwZSBvZiBjb250ZW50LlxuICpcbiAqICAgICBJdCB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgZGlzcGxheWVkIGFzIE1hdGVyaWFsIERlc2lnbiAoYm90dG9tIHNoZWV0KSB3aGVuIHJ1bm5pbmcgb24gYW4gQW5kcm9pZCBkZXZpY2UuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1cbiAqICAgICDjgqLjgq/jgrfjg6fjg7Pjgrfjg7zjg4jjgIHjgoLjgZfjgY/jga/jg5zjg4jjg6Djgrfjg7zjg4jjgpLnj77lnKjjga7jgrnjgq/jg6rjg7zjg7PkuIrjgavooajnpLrjgZfjgb7jgZnjgIJcbiAqXG4gKiAgICAg44GT44Gu6KaB57Sg44Gv44CBYDxib2R5PmDopoHntKDjgavnm7TmjqXjgqLjgr/jg4Pjg4HjgZXjgozjgovjgYvjgIHjgoLjgZfjgY/jga9gb25zLmNyZWF0ZUVsZW1lbnQodGVtcGxhdGUsIHsgYXBwZW5kOiB0cnVlIH0pYOOBqGA8dGVtcGxhdGU+YOOCv+OCsOOCkuS9v+OBo+OBpuODhuODs+ODl+ODrOODvOODiOOBi+OCieWLleeahOOBq+eUn+aIkOOBleOCjOOBvuOBmeOAglxuICpcbiAqICAgICDjgqLjgq/jgrfjg6fjg7Pjgrfjg7zjg4jjga/jgIHpgbjmip7ogqLjga7jg6rjgrnjg4jjgpLooajnpLrjgZfjgabjg6bjg7zjgrbjg7zjgavlsIvjga3jgovjga7jgavkvr/liKnjgafjgZnjgIJgb25zLWFjdGlvbi1zaGVldC1idXR0b25g44Gv44CB44GT44Gu6KaB57Sg44Gu5Lit44Gr572u44GP44Gf44KB44Gr5o+Q5L6b44GV44KM44Gm44GE44G+44GZ44GM44CB44Gd44KM5Lul5aSW44Gr44KC5LuW44Gu44Gp44Gu44KI44GG44Gq6KaB57Sg44KS5ZCr44KA44GT44Go44GM44Gn44GN44G+44GZ44CCXG4gKlxuICogICAgIEFuZHJvaWTjg4fjg5DjgqTjgrnjgaflrp/ooYzjgZXjgozjgovjgajjgY3jgavjga/jgIHoh6rli5XnmoTjgavjg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Mo44Oc44OI44Og44K344O844OIKeOBqOOBl+OBpuihqOekuuOBleOCjOOBvuOBmeOAglxuICogICBbL2phXVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1EaXNwbGF5IGEgTWF0ZXJpYWwgRGVzaWduIGJvdHRvbSBzaGVldC5bL2VuXVxuICogICBbamFd44Oe44OG44Oq44Ki44Or44OH44K244Kk44Oz44Gu44Oc44OI44Og44K344O844OI44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL3JlZmVyZW5jZS9hY3Rpb24tc2hlZXRcbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjbW9kaWZpZXJzIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQHNlZWFsc28gb25zLXBvcG92ZXJcbiAqICAgW2VuXWA8b25zLXBvcG92ZXI+YCBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLXBvcG92ZXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLW1vZGFsXG4gKiAgIFtlbl1gPG9ucy1tb2RhbD5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbW9kYWzjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtYWN0aW9uLXNoZWV0IGlkPVwic2hlZXRcIj5cbiAqICAgPG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uPkxhYmVsPC9vbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbj5cbiAqICAgPG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uPkxhYmVsPC9vbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbj5cbiAqIDwvb25zLWFjdGlvbi1zaGVldD5cbiAqXG4gKiA8c2NyaXB0PlxuICogICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2hlZXQnKS5zaG93KCk7XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQWN0aW9uU2hlZXRFbGVtZW50IGV4dGVuZHMgQmFzZURpYWxvZ0VsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlc2hvd1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBhY3Rpb24gc2hlZXQgaXMgZGlzcGxheWVkLlsvZW5dXG4gICAqIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzooajnpLrjgZXjgozjgovnm7TliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuYWN0aW9uU2hlZXRcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dRXhlY3V0ZSB0aGlzIGZ1bmN0aW9uIHRvIHN0b3AgdGhlIGFjdGlvbiBzaGVldCBmcm9tIGJlaW5nIHNob3duLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWun+ihjOOBmeOCi+OBqOOAgeODgOOCpOOCouODreOCsOOBruihqOekuuOBjOOCreODo+ODs+OCu+ODq+OBleOCjOOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdHNob3dcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBhY3Rpb24gc2hlZXQgaXMgZGlzcGxheWVkLlsvZW5dXG4gICAqIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzooajnpLrjgZXjgozjgZ/nm7TlvozjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuYWN0aW9uU2hlZXRcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHByZWhpZGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgYWN0aW9uIHNoZWV0IGlzIGhpZGRlbi5bL2VuXVxuICAgKiBbamFd44OA44Kk44Ki44Ot44Kw44GM6Zqg44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmFjdGlvblNoZWV0XG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdGhpcyBmdW5jdGlvbiB0byBzdG9wIHRoZSBhY3Rpb24gc2hlZXQgZnJvbSBiZWluZyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44GT44Gu6Zai5pWw44KS5a6f6KGM44GZ44KL44Go44CB44OA44Kk44Ki44Ot44Kw44Gu6Z2e6KGo56S644GM44Kt44Oj44Oz44K744Or44GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0aGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIGFjdGlvbiBzaGVldCBpcyBoaWRkZW4uWy9lbl1cbiAgICogW2phXeODgOOCpOOCouODreOCsOOBjOmaoOOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5hY3Rpb25TaGVldFxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHRpdGxlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXU9wdGlvbmFsIHRpdGxlIG9mIHRoZSBhY3Rpb24gc2hlZXQuIEEgbmV3IGVsZW1lbnQgd2lsbCBiZSBjcmVhdGVkIGNvbnRhaW5pbmcgdGhpcyBzdHJpbmcuWy9lbl1cbiAgICogIFtqYV3jgqLjgq/jgrfjg6fjg7Pjgrfjg7zjg4jjga7jgr/jgqTjg4jjg6vjgpLmjIflrprjgZfjgb7jgZnjgILjgZPjgZPjgafmjIflrprjgZfjgZ/mloflrZfliJfjgpLlkKvjgoDmlrDjgZfjgYTopoHntKDjgYzkvZzmiJDjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgYWN0aW9uIHNoZWV0LlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY2FuY2VsYWJsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGFjdGlvbiBzaGVldCBjYW4gYmUgY2xvc2VkIGJ5IHRhcHBpbmcgdGhlIGJhY2tncm91bmQgb3IgYnkgcHJlc3NpbmcgdGhlIGJhY2sgYnV0dG9uIG9uIEFuZHJvaWQgZGV2aWNlcy5bL2VuXVxuICAgKiAgW2phXeOBk+OBruWxnuaAp+OBjOioreWumuOBleOCjOOCi+OBqOOAgeOCouOCr+OCt+ODp+ODs+OCt+ODvOODiOOBruiDjOaZr+OChEFuZHJvaWTjg4fjg5DjgqTjgrnjga7jg5Djg4Pjgq/jg5zjgr/jg7PjgpLmjqjjgZnjgZPjgajjgafjgqLjgq/jgrfjg6fjg7Pjgrfjg7zjg4jjgYzplonjgZjjgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGFjdGlvbiBzaGVldCBpcyBkaXNhYmxlZC5bL2VuXVxuICAgKiAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeODgOOCpOOCouODreOCsOOBr2Rpc2FibGVk54q25oWL44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFuaW1hdGlvbiB1c2VkIHdoZW4gc2hvd2luZyBhbmQgaGlkaW5nIHRoZSBhY3Rpb24gc2hlZXQuIENhbiBiZSBlaXRoZXIgYFwibm9uZVwiYCBvciBgXCJkZWZhdWx0XCJgLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GZ44KL6Zqb44Gu44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJub25lXCLjgoLjgZfjgY/jga9cImRlZmF1bHRcIuOCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvbi1vcHRpb25zXG4gICAqIEB0eXBlIHtFeHByZXNzaW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgdGltaW5nLCBkZWxheeOCkuOCquODluOCuOOCp+OCr+ODiOODquODhuODqeODq+OBp+aMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1hc2stY29sb3JcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgcmdiYSgwLCAwLCAwLCAwLjIpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUNvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kIG1hc2suIERlZmF1bHQgaXMgYFwicmdiYSgwLCAwLCAwLCAwLjIpXCJgLlsvZW5dXG4gICAqICBbamFd6IOM5pmv44Gu44Oe44K544Kv44Gu6Imy44KS5oyH5a6a44GX44G+44GZ44CCXCJyZ2JhKDAsIDAsIDAsIDAuMilcIuOBjOODh+ODleOCqeODq+ODiOWApOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcbiAgfVxuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiBzY2hlbWU7XG4gIH1cblxuICBnZXQgX21hc2soKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcuYWN0aW9uLXNoZWV0LW1hc2snKTtcbiAgfVxuXG4gIGdldCBfc2hlZXQoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcuYWN0aW9uLXNoZWV0Jyk7XG4gIH1cblxuICBnZXQgX3RpdGxlKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJy5hY3Rpb24tc2hlZXQtdGl0bGUnKTtcbiAgfVxuXG4gIF91cGRhdGVBbmltYXRvckZhY3RvcnkoKSB7XG4gICAgcmV0dXJuIG5ldyBBbmltYXRvckZhY3Rvcnkoe1xuICAgICAgYW5pbWF0b3JzOiBfYW5pbWF0b3JEaWN0LFxuICAgICAgYmFzZUNsYXNzOiBBY3Rpb25TaGVldEFuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ0FjdGlvblNoZWV0QW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpXG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICB0aGlzLnN0eWxlLnpJbmRleCA9IDEwMDAxO1xuXG4gICAgLyogRXhwZWN0ZWQgcmVzdWx0OlxuICAgICAqICAgPG9ucy1hY3Rpb24tc2hlZXQ+XG4gICAgICogICAgIDxkaXYgY2xhc3M9XCJhY3Rpb24tc2hlZXQtbWFza1wiPjwvZGl2PlxuICAgICAqICAgICA8ZGl2IGNsYXNzPVwiYWN0aW9uLXNoZWV0XCI+XG4gICAgICogICAgICAgPGRpdiBjbGFzcz1cImFjdGlvbi1zaGVldC10aXRsZT48L2Rpdj5cbiAgICAgKiAgICAgICAuLi5cbiAgICAgKiAgICAgPC9kaXY+XG4gICAgICogICA8L29ucy1hY3Rpb24tc2hlZXQ+XG4gICAgICovXG5cbiAgICBpZiAoIXRoaXMuX3NoZWV0KSB7XG4gICAgICBjb25zdCBzaGVldCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgc2hlZXQuY2xhc3NMaXN0LmFkZCgnYWN0aW9uLXNoZWV0Jyk7XG5cbiAgICAgIHdoaWxlICh0aGlzLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgc2hlZXQuYXBwZW5kQ2hpbGQodGhpcy5maXJzdENoaWxkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZChzaGVldCk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLl90aXRsZSAmJiB0aGlzLmhhc0F0dHJpYnV0ZSgndGl0bGUnKSkge1xuICAgICAgY29uc3QgdGl0bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIHRpdGxlLmlubmVySFRNTCA9IHRoaXMuZ2V0QXR0cmlidXRlKCd0aXRsZScpO1xuICAgICAgdGl0bGUuY2xhc3NMaXN0LmFkZCgnYWN0aW9uLXNoZWV0LXRpdGxlJyk7XG4gICAgICB0aGlzLl9zaGVldC5pbnNlcnRCZWZvcmUodGl0bGUsIHRoaXMuX3NoZWV0LmZpcnN0Q2hpbGQpO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fbWFzaykge1xuICAgICAgY29uc3QgbWFzayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgbWFzay5jbGFzc0xpc3QuYWRkKCdhY3Rpb24tc2hlZXQtbWFzaycpO1xuICAgICAgdGhpcy5pbnNlcnRCZWZvcmUobWFzaywgdGhpcy5maXJzdENoaWxkKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zaGVldC5zdHlsZS56SW5kZXggPSAyMDAwMTtcbiAgICB0aGlzLl9tYXNrLnN0eWxlLnpJbmRleCA9IDIwMDAwO1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCB0aGlzLl9zY2hlbWUpO1xuICB9XG5cbiAgX3VwZGF0ZVRpdGxlKCkge1xuICAgIGlmICh0aGlzLl90aXRsZSkge1xuICAgICAgdGhpcy5fdGl0bGUuaW5uZXJIVE1MID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3RpdGxlJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2hvd1xuICAgKiBAc2lnbmF0dXJlIHNob3coW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJub25lXCJgIGFuZCBgXCJzbGlkZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIiwgXCJzbGlkZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gIFsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1UaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBhZnRlciB0aGUgYWN0aW9uIHNoZWV0IGhhcyBiZWVuIHJldmVhbGVkLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOBjOihqOekuuOBleOCjOe1guOCj+OBo+OBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNob3cgdGhlIGFjdGlvbiBzaGVldC5bL2VuXVxuICAgKiAgW2phXeODgOOCpOOCouODreOCsOOCkumWi+OBjeOBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IFJlc29sdmVzIHRvIHRoZSBkaXNwbGF5ZWQgZWxlbWVudC5cbiAgICovXG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZVxuICAgKiBAc2lnbmF0dXJlIGhpZGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJub25lXCJgIGFuZCBgXCJzbGlkZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIiwgXCJzbGlkZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb25zIGlzIGNhbGxlZCBhZnRlciB0aGUgYWN0aW9uIHNoZWV0IGhhcyBiZWVuIGhpZGRlbi5bL2VuXVxuICAgKiAgIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzpmqDjgozjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSGlkZSB0aGUgYWN0aW9uIHNoZWV0LlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOCkumWieOBmOOBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBoaWRkZW4gZWxlbWVudFsvZW5dXG4gICAqICAgW2phXemaoOOCjOOBn+imgee0oOOCkuino+axuuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBhY3Rpb24gc2hlZXQgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd6KaB57Sg44GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGFjdGlvbiBzaGVldCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBjYW5jZWxhYmxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgYWN0aW9uIHNoZWV0IGlzIGNhbmNlbGFibGUgb3Igbm90LiBBIGNhbmNlbGFibGUgYWN0aW9uIHNoZWV0IGNhbiBiZSBjbG9zZWQgYnkgdGFwcGluZyB0aGUgYmFja2dyb3VuZCBvciBieSBwcmVzc2luZyB0aGUgYmFjayBidXR0b24gb24gQW5kcm9pZCBkZXZpY2VzLlsvZW5dXG4gICAqICAgW2phXeOCouOCr+OCt+ODp+ODs+OCt+ODvOODiOOBjOOCreODo+ODs+OCu+ODq+WPr+iDveOBi+OBqeOBhuOBi+OCkuioreWumuOBl+OBvuOBmeOAguOCreODo+ODs+OCu+ODq+WPr+iDveOBquOCouOCr+OCt+ODp+ODs+OCt+ODvOODiOOBr+OAgeiDjOaZr+OCkuOCv+ODg+ODl+OBl+OBn+OCikFuZHJvaWTjg4fjg5DjgqTjgrnjga7jg5Djg4Pjgq/jg5zjgr/jg7PjgpLmjqjjgZnjgZPjgajjgafplonjgZjjgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWy4uLnN1cGVyLm9ic2VydmVkQXR0cmlidXRlcywgJ3RpdGxlJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChuYW1lID09PSAndGl0bGUnKSB7XG4gICAgICB0aGlzLl91cGRhdGVUaXRsZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdXBlci5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7QWN0aW9uU2hlZXRBbmltYXRvcn0gQW5pbWF0b3JcbiAgICovXG4gIHN0YXRpYyByZWdpc3RlckFuaW1hdG9yKG5hbWUsIEFuaW1hdG9yKSB7XG4gICAgaWYgKCEoQW5pbWF0b3IucHJvdG90eXBlIGluc3RhbmNlb2YgQWN0aW9uU2hlZXRBbmltYXRvcikpIHtcbiAgICAgIHV0aWwudGhyb3dBbmltYXRvcignQWN0aW9uU2hlZXQnKTtcbiAgICB9XG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG5cbiAgc3RhdGljIGdldCBhbmltYXRvcnMoKSB7XG4gICAgcmV0dXJuIF9hbmltYXRvckRpY3Q7XG4gIH1cblxuICBzdGF0aWMgZ2V0IEFjdGlvblNoZWV0QW5pbWF0b3IoKSB7XG4gICAgcmV0dXJuIEFjdGlvblNoZWV0QW5pbWF0b3I7XG4gIH1cbn1cblxub25zRWxlbWVudHMuQWN0aW9uU2hlZXQgPSBBY3Rpb25TaGVldEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1hY3Rpb24tc2hlZXQnLCBBY3Rpb25TaGVldEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uLy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uLy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UtZWxlbWVudCc7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhc2VCdXR0b25FbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHV0aWwudGhyb3dNZW1iZXIoKTtcbiAgfVxuXG4gIGdldCBfZGVmYXVsdENsYXNzTmFtZSgpIHtcbiAgICB1dGlsLnRocm93TWVtYmVyKCk7XG4gIH1cblxuICBnZXQgX3JpcHBsZU9wdCgpIHtcbiAgICByZXR1cm4gW3RoaXNdO1xuICB9XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBCYXNlQnV0dG9uRWxlbWVudCkge1xuICAgICAgdXRpbC50aHJvd0Fic3RyYWN0KCk7XG4gICAgfVxuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2NvbXBpbGUoKSk7XG4gIH1cblxuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgfVxuXG4gIGdldCBfaWNvbigpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJ29ucy1pY29uJyk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuY2xhc3NMaXN0LmFkZCh0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lKTtcblxuICAgIGlmICghdGhpcy5faWNvbiAmJiB0aGlzLmhhc0F0dHJpYnV0ZSgnaWNvbicpKSB7XG4gICAgICB1dGlsLmNoZWNrTWlzc2luZ0ltcG9ydCgnSWNvbicpO1xuICAgICAgY29uc3QgaWNvbiA9IHV0aWwuY3JlYXRlRWxlbWVudChgPG9ucy1pY29uIGljb249XCIke3RoaXMuZ2V0QXR0cmlidXRlKCdpY29uJyl9XCI+PC9vbnMtaWNvbj5gKTtcbiAgICAgIGljb24uY2xhc3NMaXN0LmFkZCh0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lLnJlcGxhY2UoJ2J1dHRvbicsICdpY29uJykpO1xuICAgICAgdGhpcy5pbnNlcnRCZWZvcmUoaWNvbiwgdGhpcy5maXJzdENoaWxkKTtcbiAgICB9XG5cbiAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgdGhpcy5fc2NoZW1lKTtcbiAgfVxuXG4gIF91cGRhdGVJY29uKCkge1xuICAgIGlmICh0aGlzLl9pY29uKSB7XG4gICAgICB0aGlzLl9pY29uLnNldEF0dHJpYnV0ZSgnaWNvbicsIHRoaXMuZ2V0QXR0cmlidXRlKCdpY29uJykpO1xuICAgIH1cbiAgfVxuXG4gIF91cGRhdGVSaXBwbGUoKSB7XG4gICAgdGhpcy5fcmlwcGxlT3B0ICYmIHV0aWwudXBkYXRlUmlwcGxlKC4uLnRoaXMuX3JpcHBsZU9wdCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdjbGFzcycsICdpY29uJywgJ3JpcHBsZSddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ2NsYXNzJzpcbiAgICAgICAgdXRpbC5yZXN0b3JlQ2xhc3ModGhpcywgdGhpcy5fZGVmYXVsdENsYXNzTmFtZSwgdGhpcy5fc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdtb2RpZmllcic6XG4gICAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCB0aGlzLl9zY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2ljb24nOlxuICAgICAgICB0aGlzLl91cGRhdGVJY29uKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncmlwcGxlJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuY29udGFpbnModGhpcy5fZGVmYXVsdENsYXNzTmFtZSkgJiYgdGhpcy5fdXBkYXRlUmlwcGxlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUJ1dHRvbkVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtYnV0dG9uJztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtYWN0aW9uLXNoZWV0LWJ1dHRvblxuICogQGNhdGVnb3J5IGRpYWxvZ1xuICogQG1vZGlmaWVyIGRlc3RydWN0aXZlXG4gKiAgIFtlbl1TaG93cyBhIFwiZGVzdHJ1Y3RpdmVcIiBidXR0b24gKG9ubHkgZm9yIGlPUykuWy9lbl1cbiAqICAgW2phXVwiZGVzdHJ1Y3RpdmVcIuOBquODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmShpT1Pjgafjga7jgb/mnInlirkp44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dQ29tcG9uZW50IHRoYXQgcmVwcmVzZW50IGVhY2ggYnV0dG9uIG9mIHRoZSBhY3Rpb24gc2hlZXQuWy9lbl1cbiAqICAgW2phXeOCouOCr+OCt+ODp+ODs+OCt+ODvOODiOOBq+ihqOekuuOBleOCjOOCi+WQhOODnOOCv+ODs+OCkuihqOePvuOBmeOCi+OCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAglsvamFdXG4gKiBAc2VlYWxzbyBvbnMtYWN0aW9uLXNoZWV0XG4gKiAgIFtlbl1UaGUgYDxvbnMtYWN0aW9uLXNoZWV0PmAgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1hY3Rpb24tc2hlZXTjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWxpc3QtaXRlbVxuICogICBbZW5dVGhlIGA8b25zLWxpc3QtaXRlbT5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdC1pdGVt44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1pY29uXG4gKiAgIFtlbl1UaGUgYDxvbnMtaWNvbj5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtaWNvbuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvYWN0aW9uLXNoZWV0XG4gKiBAZ3VpZGUgYXBwc2l6ZS5odG1sI3JlbW92aW5nLWljb24tcGFja3MgW2VuXVJlbW92aW5nIGljb24gcGFja3MuWy9lbl1bamFdWy9qYV1cbiAqIEBndWlkZSBmYXEuaHRtbCNob3ctY2FuLWktdXNlLWN1c3RvbS1pY29uLXBhY2tzIFtlbl1BZGRpbmcgY3VzdG9tIGljb24gcGFja3MuWy9lbl1bamFdWy9qYV1cbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogICBbZW5dRGlzcGxheSBhIE1hdGVyaWFsIERlc2lnbiBhY3Rpb24gc2hlZXQgYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV3jg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Pjga7jgqLjgq/jgrfjg6fjg7Pjgrfjg7zjg4jnlKjjga7jg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtYWN0aW9uLXNoZWV0IGlkPVwic2hlZXRcIj5cbiAqICAgPG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uPkxhYmVsPC9vbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbj5cbiAqICAgPG9ucy1hY3Rpb24tc2hlZXQtYnV0dG9uPkxhYmVsPC9vbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbj5cbiAqIDwvb25zLWFjdGlvbi1zaGVldD5cbiAqXG4gKiA8c2NyaXB0PlxuICogICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2hlZXQnKS5zaG93KCk7XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQWN0aW9uU2hlZXRCdXR0b25FbGVtZW50IGV4dGVuZHMgQmFzZUJ1dHRvbkVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGljb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dQ3JlYXRlcyBhbiBgb25zLWljb25gIGNvbXBvbmVudCB3aXRoIHRoaXMgc3RyaW5nLiBPbmx5IHZpc2libGUgb24gQW5kcm9pZC4gQ2hlY2sgW1NlZSBhbHNvXSgjc2VlYWxzbykgc2VjdGlvbiBmb3IgbW9yZSBpbmZvcm1hdGlvbi5bL2VuXVxuICAgKiAgW2phXWBvbnMtaWNvbmDjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgpLmgqrmgKfjgZfjgb7jgZnjgIJBbmRyb2lk44Gn44Gu44G/6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBhY3Rpb24gc2hlZXQgYnV0dG9uLlsvZW5dXG4gICAqICAgW2phXeOCouOCr+OCt+ODp+ODs+OCt+ODvOODiOODnOOCv+ODs+OBruimi+OBn+ebruOCkuioreWumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiB7XG4gICAgICAnJzogJ2FjdGlvbi1zaGVldC1idXR0b24tLSonLFxuICAgICAgJy5hY3Rpb24tc2hlZXQtaWNvbic6ICdhY3Rpb24tc2hlZXQtaWNvbi0tKidcbiAgICB9O1xuICB9XG5cbiAgZ2V0IF9kZWZhdWx0Q2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnYWN0aW9uLXNoZWV0LWJ1dHRvbic7XG4gIH1cblxuICBnZXQgX3JpcHBsZU9wdCgpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLkFjdGlvblNoZWV0QnV0dG9uID0gQWN0aW9uU2hlZXRCdXR0b25FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbicsIEFjdGlvblNoZWV0QnV0dG9uRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IEJhc2VBbmltYXRvciBmcm9tICcuLi8uLi9vbnMvYmFzZS1hbmltYXRvcic7XG5cbmV4cG9ydCBjbGFzcyBBbGVydERpYWxvZ0FuaW1hdG9yIGV4dGVuZHMgQmFzZUFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2xpbmVhcicsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjJ9ID0ge30pIHtcbiAgICBzdXBlcih7IHRpbWluZywgZGVsYXksIGR1cmF0aW9uIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBzaG93KGRpYWxvZywgZG9uZSkge1xuICAgIGRvbmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgaGlkZShkaWFsb2csIGRvbmUpIHtcbiAgICBkb25lKCk7XG4gIH1cbn1cblxuLyoqXG4gKiBBbmRyb2lkIHN0eWxlIGFuaW1hdG9yIGZvciBhbGVydCBkaWFsb2cuXG4gKi9cbmV4cG9ydCBjbGFzcyBBbmRyb2lkQWxlcnREaWFsb2dBbmltYXRvciBleHRlbmRzIEFsZXJ0RGlhbG9nQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjQsIDEpJywgZHVyYXRpb24gPSAwLjIsIGRlbGF5ID0gMH0gPSB7fSkge1xuICAgIHN1cGVyKHtkdXJhdGlvbiwgdGltaW5nLCBkZWxheX0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHNob3coZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAwIH0sIHsgb3BhY2l0eTogMSB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKSBzY2FsZTNkKC45LCAuOSwgMSknLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKSBzY2FsZTNkKDEsIDEsIDEpJywgb3BhY2l0eTogMSB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgaGlkZShkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2ssIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdCh7IG9wYWNpdHk6IDEgfSwgeyBvcGFjaXR5OiAwIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9kaWFsb2csIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIC01MCUsIDApIHNjYWxlM2QoMSwgMSwgMSknLCBvcGFjaXR5OiAxIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKSBzY2FsZTNkKC45LCAuOSwgMSknLCBvcGFjaXR5OiAwIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIGlPUyBzdHlsZSBhbmltYXRvciBmb3IgYWxlcnQgZGlhbG9nLlxuICovXG5leHBvcnQgY2xhc3MgSU9TQWxlcnREaWFsb2dBbmltYXRvciBleHRlbmRzIEFsZXJ0RGlhbG9nQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjQsIDEpJywgZHVyYXRpb24gPSAwLjIsIGRlbGF5ID0gMH0gPSB7fSkge1xuICAgIHN1cGVyKHtkdXJhdGlvbiwgdGltaW5nLCBkZWxheX0pO1xuICB9XG5cbiAgLypcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2ssIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdCh7IG9wYWNpdHk6IDAgfSwgeyBvcGFjaXR5OiAxIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9kaWFsb2csIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIC01MCUsIDApIHNjYWxlM2QoMS4zLCAxLjMsIDEpJywgb3BhY2l0eTogMCB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTUwJSwgMCkgc2NhbGUzZCgxLCAxLCAxKScsIG9wYWNpdHk6IDEgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogMCB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogMCB9KVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uLy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uLy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCB7IEFsZXJ0RGlhbG9nQW5pbWF0b3IsIElPU0FsZXJ0RGlhbG9nQW5pbWF0b3IsIEFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIH0gZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRGlhbG9nRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZGlhbG9nJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcuYWxlcnQtZGlhbG9nJzogJ2FsZXJ0LWRpYWxvZy0tKicsXG4gICcuYWxlcnQtZGlhbG9nLWNvbnRhaW5lcic6ICdhbGVydC1kaWFsb2ctY29udGFpbmVyLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctdGl0bGUnOiAnYWxlcnQtZGlhbG9nLXRpdGxlLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctY29udGVudCc6ICdhbGVydC1kaWFsb2ctY29udGVudC0tKicsXG4gICcuYWxlcnQtZGlhbG9nLWZvb3Rlcic6ICdhbGVydC1kaWFsb2ctZm9vdGVyLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctZm9vdGVyLS1yb3dmb290ZXInOiAnYWxlcnQtZGlhbG9nLWZvb3Rlci0tcm93Zm9vdGVyLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctYnV0dG9uLS1yb3dmb290ZXInOiAnYWxlcnQtZGlhbG9nLWJ1dHRvbi0tcm93Zm9vdGVyLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctYnV0dG9uLS1wcmltYWwnOiAnYWxlcnQtZGlhbG9nLWJ1dHRvbi0tcHJpbWFsLS0qJyxcbiAgJy5hbGVydC1kaWFsb2ctYnV0dG9uJzogJ2FsZXJ0LWRpYWxvZy1idXR0b24tLSonLFxuICAnb25zLWFsZXJ0LWRpYWxvZy1idXR0b24nOiAnYWxlcnQtZGlhbG9nLWJ1dHRvbi0tKicsXG4gICcuYWxlcnQtZGlhbG9nLW1hc2snOiAnYWxlcnQtZGlhbG9nLW1hc2stLSonLFxuICAnLnRleHQtaW5wdXQnOiAndGV4dC1pbnB1dC0tKidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdub25lJzogQWxlcnREaWFsb2dBbmltYXRvcixcbiAgJ2RlZmF1bHQnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IEFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIDogSU9TQWxlcnREaWFsb2dBbmltYXRvcixcbiAgJ2ZhZGUnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IEFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIDogSU9TQWxlcnREaWFsb2dBbmltYXRvclxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtYWxlcnQtZGlhbG9nXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIEFsZXJ0IGRpYWxvZyB0aGF0IGlzIGRpc3BsYXllZCBvbiB0b3Agb2YgdGhlIGN1cnJlbnQgc2NyZWVuLiBVc2VmdWwgZm9yIGRpc3BsYXlpbmcgcXVlc3Rpb25zLCB3YXJuaW5ncyBvciBlcnJvciBtZXNzYWdlcyB0byB0aGUgdXNlci4gVGhlIHRpdGxlLCBjb250ZW50IGFuZCBidXR0b25zIGNhbiBiZSBlYXNpbHkgY3VzdG9taXplZCBhbmQgaXQgd2lsbCBhdXRvbWF0aWNhbGx5IHN3aXRjaCBzdHlsZSBiYXNlZCBvbiB0aGUgcGxhdGZvcm0uXG4gKlxuICogICAgIFRvIHVzZSB0aGUgZWxlbWVudCBpdCBjYW4gZWl0aGVyIGJlIGF0dGFjaGVkIGRpcmVjdGx5IHRvIHRoZSBgPGJvZHk+YCBlbGVtZW50IG9yIGR5bmFtaWNhbGx5IGNyZWF0ZWQgZnJvbSBhIHRlbXBsYXRlIHVzaW5nIHRoZSBgb25zLmNyZWF0ZUFsZXJ0RGlhbG9nKHRlbXBsYXRlKWAgdXRpbGl0eSBmdW5jdGlvbiBhbmQgdGhlIGA8dGVtcGxhdGU+YCB0YWcuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1cbiAqICAgICDnj77lnKjjga7jgrnjgq/jg6rjg7zjg7Pjga7kuIrjgavooajnpLrjgZnjgovjgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjgafjgZnjgILjg6bjg7zjgrbjgavlr77jgZnjgovllY/jgYTjgYvjgZHjgIHorablkYrjgIHjgqjjg6njg7zjg6Hjg4Pjgrvjg7zjgrjjgpLooajnpLrjgZnjgovjga7jgavliKnnlKjjgafjgY3jgb7jgZnjgILjgr/jgqTjg4jjg6vjgoTjgrPjg7Pjg4bjg7Pjg4TjgoTjg5zjgr/jg7Pjga/nsKHljZjjgavjgqvjgrnjgr/jg57jgqTjgrrjgafjgY3jgIHlrp/ooYzjgZfjgabjgYTjgovjg5fjg6njg4Pjg4jjg5Xjgqnjg7zjg6DjgavkvbXjgZvjgabjgrnjgr/jgqTjg6vjgYzoh6rli5XnmoTjgavliIfjgormm7/jgo/jgorjgb7jgZnjgIJcbiAqICAgWy9qYV1cbiAqIEBjb2RlcGVuIFF3d3h5cFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2FsZXJ0LWRpYWxvZ1xuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gc3R5bGVbL2VuXVxuICogICBbamFd44Oe44OG44Oq44Ki44Or44OH44K244Kk44Oz44Gu44K544K/44Kk44OrWy9qYV1cbiAqIEBtb2RpZmllciByb3dmb290ZXJcbiAqICAgW2VuXUhvcml6b250YWxseSBhbGlnbnMgdGhlIGZvb3RlciBidXR0b25zLlsvZW5dXG4gKiAgIFtqYV3jg5Xjg4Pjgr/jg7zjga7opIfmlbDjga7jg5zjgr/jg7PjgpLmsLTlubPjgavphY3nva5bL2phXVxuICogQHNlZWFsc28gb25zLWRpYWxvZ1xuICogICBbZW5db25zLWRpYWxvZyBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWRpYWxvZ+OCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcG9wb3ZlclxuICogICBbZW5db25zLXBvcG92ZXIgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1kaWFsb2fjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLm5vdGlmaWNhdGlvblxuICogICBbZW5dVXNpbmcgb25zLm5vdGlmaWNhdGlvbiB1dGlsaXR5IGZ1bmN0aW9ucy5bL2VuXVxuICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GZ44KL44Gr44Gv44CBb25zLm5vdGlmaWNhdGlvbuOCquODluOCuOOCp+OCr+ODiOOBruODoeOCveODg+ODieOCkuS9v+OBhuOBk+OBqOOCguOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1hbGVydC1kaWFsb2cgaWQ9XCJhbGVydC1kaWFsb2dcIj5cbiAqICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy10aXRsZVwiPldhcm5pbmchPC9kaXY+XG4gKiAgIDxkaXYgY2xhc3M9XCJhbGVydC1kaWFsb2ctY29udGVudFwiPlxuICogICAgIEFuIGVycm9yIGhhcyBvY2N1cnJlZCFcbiAqICAgPC9kaXY+XG4gKiAgIDxkaXYgY2xhc3M9XCJhbGVydC1kaWFsb2ctZm9vdGVyXCI+XG4gKiAgICAgPGJ1dHRvbiBpZD1cImFsZXJ0LWRpYWxvZy1idXR0b25cIiBjbGFzcz1cImFsZXJ0LWRpYWxvZy1idXR0b25cIj5PSzwvYnV0dG9uPlxuICogICA8L2Rpdj5cbiAqIDwvb25zLWFsZXJ0LWRpYWxvZz5cbiAqIDxzY3JpcHQ+XG4gKiAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhbGVydC1kaWFsb2cnKS5zaG93KCk7XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQWxlcnREaWFsb2dFbGVtZW50IGV4dGVuZHMgQmFzZURpYWxvZ0VsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlc2hvd1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBiZWZvcmUgdGhlIGFsZXJ0IGRpYWxvZyBpcyBkaXNwbGF5ZWQuWy9lbl1cbiAgICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44GM6KGo56S644GV44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmFsZXJ0RGlhbG9nXG4gICAqICAgW2VuXUFsZXJ0IGRpYWxvZyBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdG8gc3RvcCB0aGUgZGlhbG9nIGZyb20gc2hvd2luZy5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7plqLmlbDjgpLlrp/ooYzjgZnjgovjgajjgIHjgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga7ooajnpLrjgpLmraLjgoHjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBhbGVydCBkaWFsb2cgaXMgZGlzcGxheWVkLlsvZW5dXG4gICAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBjOihqOekuuOBleOCjOOBn+ebtOW+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5hbGVydERpYWxvZ1xuICAgKiAgIFtlbl1BbGVydCBkaWFsb2cgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlaGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBiZWZvcmUgdGhlIGFsZXJ0IGRpYWxvZyBpcyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44GM6Zqg44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmFsZXJ0RGlhbG9nXG4gICAqICAgW2VuXUFsZXJ0IGRpYWxvZyBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Ki44Op44O844OI44OA44Kk44Ki44Ot44Kw44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdG8gc3RvcCB0aGUgZGlhbG9nIGZyb20gaGlkaW5nLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWun+ihjOOBmeOCi+OBqOOAgeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBjOmWieOBmOOCiOOBhuOBqOOBmeOCi+OBruOCkuatouOCgeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGhpZGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBhbGVydCBkaWFsb2cgaXMgaGlkZGVuLlsvZW5dXG4gICAqIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjgYzpmqDjgozjgZ/lvozjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuYWxlcnREaWFsb2dcbiAgICogICBbZW5dQWxlcnQgZGlhbG9nIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg6njg7zjg4jjg4DjgqTjgqLjg63jgrDjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgZGlhbG9nLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44Gu6KaL44Gf55uu44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY2FuY2VsYWJsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGRpYWxvZyBjYW4gYmUgY2xvc2VkIGJ5IHRhcHBpbmcgdGhlIGJhY2tncm91bmQgb3IgYnkgcHJlc3NpbmcgdGhlIGJhY2sgYnV0dG9uIG9uIEFuZHJvaWQgZGV2aWNlcy5bL2VuXVxuICAgKiAgW2phXeOBk+OBruWxnuaAp+OCkuioreWumuOBmeOCi+OBqOOAgeODgOOCpOOCouODreOCsOOBruiDjOaZr+OCkuOCv+ODg+ODl+OBl+OBn+OCikFuZHJvaWTjg4fjg5DjgqTjgrnjga7jg5Djg4Pjgq/jg5zjgr/jg7PjgpLmirzjgZnjgajjg4DjgqTjgqLjg63jgrDjgYzplonjgZjjgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGRpYWxvZyBpcyBkaXNhYmxlZC5bL2VuXVxuICAgKiAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeOCouODqeODvOODiOODgOOCpOOCouODreOCsOOBr2Rpc2FibGVk54q25oWL44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFuaW1hdGlvbiB1c2VkIHdoZW4gc2hvd2luZyBhbmQgaGlkaW5nIHRoZSBkaWFsb2cuIENhbiBiZSBlaXRoZXIgYFwibm9uZVwiYCBvciBgXCJkZWZhdWx0XCJgLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GZ44KL6Zqb44Gu44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44Gn44GvXCJub25lXCLjgYtcImRlZmF1bHRcIuOBjOaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvbi1vcHRpb25zXG4gICAqIEB0eXBlIHtFeHByZXNzaW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgdGltaW5nLCBkZWxheeOCkuOCquODluOCuOOCp+OCr+ODiOODquODhuODqeODq+OBp+aMh+WumuOBl+OBvuOBmeOAguS+i++8mntkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbWFzay1jb2xvclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCByZ2JhKDAsIDAsIDAsIDAuMilcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dQ29sb3Igb2YgdGhlIGJhY2tncm91bmQgbWFzay4gRGVmYXVsdCBpcyBcInJnYmEoMCwgMCwgMCwgMC4yKVwiLlsvZW5dXG4gICAqICBbamFd6IOM5pmv44Gu44Oe44K544Kv44Gu6Imy44KS5oyH5a6a44GX44G+44GZ44CCXCJyZ2JhKDAsIDAsIDAsIDAuMilcIuOBjOODh+ODleOCqeODq+ODiOWApOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcbiAgfVxuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiBzY2hlbWU7XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7RWxlbWVudH1cbiAgICovXG4gIGdldCBfbWFzaygpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5hbGVydC1kaWFsb2ctbWFzaycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0VsZW1lbnR9XG4gICAqL1xuICBnZXQgX2RpYWxvZygpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5hbGVydC1kaWFsb2cnKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0VsZW1lbnR9XG4gICAqL1xuICBnZXQgX3RpdGxlRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcy5fZGlhbG9nLmNoaWxkcmVuWzBdLCAnLmFsZXJ0LWRpYWxvZy10aXRsZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0VsZW1lbnR9XG4gICAqL1xuICBnZXQgX2NvbnRlbnRFbGVtZW50KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLl9kaWFsb2cuY2hpbGRyZW5bMF0sICcuYWxlcnQtZGlhbG9nLWNvbnRlbnQnKTtcbiAgfVxuXG4gIF91cGRhdGVBbmltYXRvckZhY3RvcnkoKSB7XG4gICAgcmV0dXJuIG5ldyBBbmltYXRvckZhY3Rvcnkoe1xuICAgICAgYW5pbWF0b3JzOiBfYW5pbWF0b3JEaWN0LFxuICAgICAgYmFzZUNsYXNzOiBBbGVydERpYWxvZ0FuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ0FsZXJ0RGlhbG9nQW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpXG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICB0aGlzLnN0eWxlLnpJbmRleCA9IDEwMDAxO1xuXG4gICAgLyoqXG4gICAgICogRXhwZWN0ZWQgcmVzdWx0IGFmdGVyIGNvbXBpbGU6XG4gICAgICpcbiAgICAgKiA8b25zLWFsZXJ0LWRpYWxvZyBzdHlsZT1cIm5vbmVcIj5cbiAgICAgKiAgIDxkaXYgY2xhc3M9XCJhbGVydC1kaWFsb2ctbWFza1wiPjwvZGl2PlxuICAgICAqICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZ1wiPlxuICAgICAqICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLWNvbnRhaW5lclwiPi4uLjwvZGl2PlxuICAgICAqICAgPC9kaXY+XG4gICAgICogPC9vbnMtYWxlcnQtZGlhbG9nPlxuICAgICAqL1xuXG4gICAgY29uc3QgY29udGVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKTtcblxuICAgIGlmICghdGhpcy5fbWFzayAmJiAhdGhpcy5fZGlhbG9nKSB7XG4gICAgICB3aGlsZSAodGhpcy5maXJzdENoaWxkKSB7XG4gICAgICAgIGNvbnRlbnQuYXBwZW5kQ2hpbGQodGhpcy5maXJzdENoaWxkKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX21hc2spIHtcbiAgICAgIGNvbnN0IG1hc2sgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIG1hc2suY2xhc3NMaXN0LmFkZCgnYWxlcnQtZGlhbG9nLW1hc2snKTtcbiAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKG1hc2ssIHRoaXMuY2hpbGRyZW5bMF0pO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fZGlhbG9nKSB7XG4gICAgICBjb25zdCBkaWFsb2cgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGRpYWxvZy5jbGFzc0xpc3QuYWRkKCdhbGVydC1kaWFsb2cnKTtcbiAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKGRpYWxvZywgbnVsbCk7XG4gICAgfVxuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLl9kaWFsb2csICcuYWxlcnQtZGlhbG9nLWNvbnRhaW5lcicpKSB7XG4gICAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGNvbnRhaW5lci5jbGFzc0xpc3QuYWRkKCdhbGVydC1kaWFsb2ctY29udGFpbmVyJyk7XG4gICAgICB0aGlzLl9kaWFsb2cuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcbiAgICB9XG5cbiAgICB0aGlzLl9kaWFsb2cuY2hpbGRyZW5bMF0uYXBwZW5kQ2hpbGQoY29udGVudCk7XG5cbiAgICB0aGlzLl9kaWFsb2cuc3R5bGUuekluZGV4ID0gMjAwMDE7XG4gICAgdGhpcy5fbWFzay5zdHlsZS56SW5kZXggPSAyMDAwMDtcblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgdGhpcy5fc2NoZW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGNhbmNlbGFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBkaWFsb2cgaXMgY2FuY2VsYWJsZSBvciBub3QuIEEgY2FuY2VsYWJsZSBkaWFsb2cgY2FuIGJlIGNsb3NlZCBieSB0YXBwaW5nIHRoZSBiYWNrZ3JvdW5kIG9yIGJ5IHByZXNzaW5nIHRoZSBiYWNrIGJ1dHRvbiBvbiBBbmRyb2lkIGRldmljZXMuWy9lbl1cbiAgICogICBbamFd44Gd44Gu44OA44Kk44Ki44Ot44Kw44GM44Kt44Oj44Oz44K744Or5Y+v6IO944GL44Gp44GG44GL44KS6KGo44GX44G+44GZ44CC44Kt44Oj44Oz44K744Or5Y+v6IO944Gq44OA44Kk44Ki44Ot44Kw44Gv44CB6IOM5pmv44KS44K/44OD44OX44GZ44KL44GLQW5kcm9pZOODh+ODkOOCpOOCueOBruODkOODg+OCr+ODnOOCv+ODs+OCkuaKvOOBmeOBk+OBqOOBp+mWieOBmOOCi+OBk+OBqOOBjOWHuuadpeOCi+OCiOOBhuOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgYW5pbWF0aW9ucyBhcmUgYFwiZmFkZVwiYCBhbmQgYFwibm9uZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgILmjIflrprjgafjgY3jgovjga7jga/jgIFcImZhZGVcIiwgXCJub25lXCLjga7jgYTjgZrjgozjgYvjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gPGNvZGU+e2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfTwvY29kZT4gWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUZ1bmN0aW9uIHRvIGV4ZWN1dGUgYWZ0ZXIgdGhlIGRpYWxvZyBoYXMgYmVlbiByZXZlYWxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzooajnpLrjgZXjgozntYLjgo/jgaPjgZ/mmYLjgavlkbzjgbPlh7rjgZXjgozjgovjgrPjg7zjg6vjg5Djg4Pjgq/jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgYWxlcnQgZGlhbG9nLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXUEgYFByb21pc2VgIG9iamVjdCB0aGF0IHJlc29sdmVzIHRvIHRoZSBkaXNwbGF5ZWQgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV3ooajnpLrjgZXjgozjgovopoHntKDjgpLop6PmsbrjgZnjgotgUHJvbWlzZWDjgqrjg5bjgrjjgqfjgq/jg4jjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZShbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcImZhZGVcImAgYW5kIGBcIm5vbmVcImAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJmYWRlXCIsIFwibm9uZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuICA8Y29kZT57ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9PC9jb2RlPlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiA8Y29kZT57ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9PC9jb2RlPiBbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dRnVuY3Rpb24gdG8gZXhlY3V0ZSBhZnRlciB0aGUgZGlhbG9nIGhhcyBiZWVuIGhpZGRlbi5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jg4DjgqTjgqLjg63jgrDjgYzplonjgZjjgZ/mmYLjgavlkbzjgbPlh7rjgZXjgozjgovjgrPjg7zjg6vjg5Djg4Pjgq/jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSGlkZSB0aGUgYWxlcnQgZGlhbG9nLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOCkumWieOBmOOBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBoaWRkZW4gZWxlbWVudFsvZW5dXG4gICAqICAgW2phXemaoOOCjOOBn+imgee0oOOCkuino+axuuOBmeOCi2BQcm9taXNlYOOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBkaWFsb2cgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd6KaB57Sg44GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7RGlhbG9nQW5pbWF0b3J9IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIEFsZXJ0RGlhbG9nQW5pbWF0b3IpKSB7XG4gICAgICB1dGlsLnRocm93QW5pbWF0b3IoJ0FsZXJ0RGlhbG9nJyk7XG4gICAgfVxuICAgIF9hbmltYXRvckRpY3RbbmFtZV0gPSBBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgYW5pbWF0b3JzKCkge1xuICAgIHJldHVybiBfYW5pbWF0b3JEaWN0O1xuICB9XG5cbiAgc3RhdGljIGdldCBBbGVydERpYWxvZ0FuaW1hdG9yKCkge1xuICAgIHJldHVybiBBbGVydERpYWxvZ0FuaW1hdG9yO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLkFsZXJ0RGlhbG9nID0gQWxlcnREaWFsb2dFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtYWxlcnQtZGlhbG9nJywgQWxlcnREaWFsb2dFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IEJhc2VCdXR0b25FbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWJ1dHRvbic7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWFsZXJ0LWRpYWxvZy1idXR0b25cbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogICBbZW5dTWF0ZXJpYWwgRGVzaWduIGFsZXJ0LWRpYWxvZyBidXR0b24uWy9lbl1cbiAqICAgW2phXeODnuODhuODquOCouODq+ODh+OCtuOCpOODs+OBruODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLWFsZXJ0LWRpYWxvZ1xuICogICBbZW5dVGhlIGA8b25zLWFsZXJ0LWRpYWxvZz5gIGNvbXBvbmVudCBkaXNwbGF5cyBhIGFsZXJ0IGRpYWxvZy5bL2VuXVxuICogICBbamFdb25zLWFsZXJ0LWRpYWxvZ+OCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogIDxvbnMtYWxlcnQtZGlhbG9nPlxuICogICAgPGRpdiBjbGFzcz1cImFsZXJ0LWRpYWxvZy10aXRsZVwiPldhcm5pbmchPC9kaXY+XG4gKiAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLWNvbnRlbnRcIj5cbiAqICAgICAgQW4gZXJyb3IgaGFzIG9jY3VycmVkIVxuICogICAgPC9kaXY+XG4gKiAgICA8ZGl2IGNsYXNzPVwiYWxlcnQtZGlhbG9nLWZvb3RlclwiPlxuICogICAgICA8YWxlcnQtZGlhbG9nLWJ1dHRvbiBvbmNsaWNrPVwiYXBwLmNsb3NlKClcIj5DYW5jZWw8L2FsZXJ0LWRpYWxvZy1idXR0b24+XG4gKiAgICAgIDxhbGVydC1kaWFsb2ctYnV0dG9uIGNsYXNzPVwiYWxlcnQtZGlhbG9nLWJ1dHRvblwiIG9uY2xpY2s9XCJhcHAuY2xvc2UoKVwiPk9LPC9hbGVydC1kaWFsb2ctYnV0dG9uPlxuICogICAgPC9kaXY+XG4gKiAgPC9vbnMtYWxlcnQtZGlhbG9nPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBBbGVydERpYWxvZ0J1dHRvbkVsZW1lbnQgZXh0ZW5kcyBCYXNlQnV0dG9uRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBidXR0b24uWy9lbl1cbiAgICogICBbamFd44Oc44K/44Oz44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgYnV0dG9uIHNob3VsZCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg5zjgr/jg7PjgpLnhKHlirnljJbjgZnjgovloLTlkIjjga/mjIflrprjgZfjgabjgY/jgaDjgZXjgYTjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHsgJyc6ICdhbGVydC1kaWFsb2ctYnV0dG9uLS0qJyB9O1xuICB9XG5cbiAgZ2V0IF9kZWZhdWx0Q2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnYWxlcnQtZGlhbG9nLWJ1dHRvbic7XG4gIH1cblxuICBnZXQgX3JpcHBsZU9wdCgpIHtcbiAgICByZXR1cm4gW3RoaXMsIHVuZGVmaW5lZCwgeyAnbW9kaWZpZXInOiAnbGlnaHQtZ3JheScgfV07XG4gIH1cbn1cblxub25zRWxlbWVudHMuQWxlcnREaWFsb2dCdXR0b24gPSBBbGVydERpYWxvZ0J1dHRvbkVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1hbGVydC1kaWFsb2ctYnV0dG9uJywgQWxlcnREaWFsb2dCdXR0b25FbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgaW9zQmFja0J1dHRvbkljb24gZnJvbSAnLi4vLi4vaW1hZ2VzL2lvcy1iYWNrLWJ1dHRvbi1pY29uLnN2Zyc7XG5pbXBvcnQgbWRCYWNrQnV0dG9uSWNvbiBmcm9tICcuLi8uLi9pbWFnZXMvbWQtYmFjay1idXR0b24taWNvbi5zdmcnO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ2JhY2stYnV0dG9uJztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ2JhY2stYnV0dG9uLS0qJyxcbiAgJy5iYWNrLWJ1dHRvbl9faWNvbic6ICdiYWNrLWJ1dHRvbi0tKl9faWNvbicsXG4gICcuYmFjay1idXR0b25fX2xhYmVsJzogJ2JhY2stYnV0dG9uLS0qX19sYWJlbCdcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWJhY2stYnV0dG9uXG4gKiBAY2F0ZWdvcnkgbmF2aWdhdGlvblxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBCYWNrIGJ1dHRvbiBjb21wb25lbnQgZm9yIGA8b25zLXRvb2xiYXI+YC4gUHV0IGl0IGluIHRoZSBsZWZ0IHBhcnQgb2YgdGhlIGA8b25zLXRvb2xiYXI+YC5cbiAqXG4gKiAgICAgSXQgd2lsbCBmaW5kIHRoZSBwYXJlbnQgYDxvbnMtbmF2aWdhdG9yPmAgZWxlbWVudCBhbmQgcG9wIGEgcGFnZSB3aGVuIGNsaWNrZWQuIFRoaXMgYmVoYXZpb3IgY2FuIGJlIG92ZXJyaWRlbiBieSBzcGVjaWZ5aW5nIHRoZSBgb25DbGlja2AgcHJvcGVydHkuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4gYUhtR0xcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9iYWNrLWJ1dHRvblxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gc3R5bGVbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy10b29sYmFyXG4gKiAgIFtlbl1vbnMtdG9vbGJhciBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLXRvb2xiYXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLW5hdmlnYXRvclxuICogICBbZW5db25zLW5hdmlnYXRvciBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLW5hdmlnYXRvcuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy10b29sYmFyPlxuICogICA8ZGl2IGNsYXNzPVwibGVmdFwiPlxuICogICAgIDxvbnMtYmFjay1idXR0b24+QmFjazwvb25zLWJhY2stYnV0dG9uPlxuICogICA8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlxuICogICAgIFRpdGxlXG4gKiAgIDxkaXY+XG4gKiA8L29ucy10b29sYmFyPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhY2tCdXR0b25FbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgYmFjayBidXR0b24uWy9lbl1cbiAgICogIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjga7opovjgZ/nm67jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX29wdGlvbnMgPSB7fTtcbiAgICB0aGlzLl9ib3VuZE9uQ2xpY2sgPSB0aGlzLl9vbkNsaWNrLmJpbmQodGhpcyk7XG4gIH1cblxuICBfdXBkYXRlSWNvbihpY29uID0gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5iYWNrLWJ1dHRvbl9faWNvbicpKSB7XG4gICAgaWNvbi5pbm5lckhUTUwgPSBhdXRvU3R5bGUuZ2V0UGxhdGZvcm0odGhpcykgPT09ICdhbmRyb2lkJyB8fCB1dGlsLmhhc01vZGlmaWVyKHRoaXMsICdtYXRlcmlhbCcpID8gbWRCYWNrQnV0dG9uSWNvbiA6IGlvc0JhY2tCdXR0b25JY29uO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHRoaXMsICcuYmFjay1idXR0b25fX2xhYmVsJykpIHtcbiAgICAgIGNvbnN0IGxhYmVsID0gdXRpbC5jcmVhdGUoJ3NwYW4uYmFjay1idXR0b25fX2xhYmVsJyk7XG5cbiAgICAgIHdoaWxlICh0aGlzLmNoaWxkTm9kZXNbMF0pIHtcbiAgICAgICAgbGFiZWwuYXBwZW5kQ2hpbGQodGhpcy5jaGlsZE5vZGVzWzBdKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQobGFiZWwpO1xuICAgIH1cblxuICAgIGlmICghdXRpbC5maW5kQ2hpbGQodGhpcywgJy5iYWNrLWJ1dHRvbl9faWNvbicpKSB7XG4gICAgICBjb25zdCBpY29uID0gdXRpbC5jcmVhdGUoJ3NwYW4uYmFjay1idXR0b25fX2ljb24nKTtcbiAgICAgIHRoaXMuX3VwZGF0ZUljb24oaWNvbik7XG5cbiAgICAgIHRoaXMuaW5zZXJ0QmVmb3JlKGljb24sIHRoaXMuY2hpbGRyZW5bMF0pO1xuICAgIH1cblxuICAgIHV0aWwudXBkYXRlUmlwcGxlKHRoaXMsIHVuZGVmaW5lZCwge2NlbnRlcjogJycsICdzaXplJzogJ2NvbnRhaW4nLCAnYmFja2dyb3VuZCc6ICd0cmFuc3BhcmVudCd9KTtcblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb3B0aW9uc1xuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dT3B0aW9ucyBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zLmFuaW1hdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBcInNsaWRlXCIsIFwibGlmdFwiLCBcImZhZGVcIiBhbmQgXCJub25lXCIuXG4gICAqICAgICBUaGVzZSBhcmUgcGxhdGZvcm0gYmFzZWQgYW5pbWF0aW9ucy4gRm9yIGZpeGVkIGFuaW1hdGlvbnMsIGFkZCBcIi1pb3NcIiBvciBcIi1tZFwiXG4gICAqICAgICBzdWZmaXggdG8gdGhlIGFuaW1hdGlvbiBuYW1lLiBFLmcuIFwibGlmdC1pb3NcIiwgXCJsaWZ0LW1kXCIuIERlZmF1bHRzIHZhbHVlcyBhcmUgXCJzbGlkZS1pb3NcIiBhbmQgXCJmYWRlLW1kXCIuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuICBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWBbL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb3B0aW9ucy5jYWxsYmFja1xuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiB0aGUgdHJhbnNpdGlvbiBoYXMgZW5kZWQuWy9lbl1cbiAgICogICBbamFd44GT44Gu44Oh44K944OD44OJ44Gr44KI44KL55S76Z2i6YG356e744GM57WC5LqG44GX44Gf6Zqb44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IG9wdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX29wdGlvbnM7XG4gIH1cblxuICBzZXQgb3B0aW9ucyhvYmplY3QpIHtcbiAgICB0aGlzLl9vcHRpb25zID0gb2JqZWN0O1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkNsaWNrXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVVzZWQgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgYmFjayBidXR0b24gYmVoYXZpb3IuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIF9vbkNsaWNrKCkge1xuICAgIGlmICh0aGlzLm9uQ2xpY2spIHtcbiAgICAgIHRoaXMub25DbGljay5hcHBseSh0aGlzKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBjb25zdCBuYXZpZ2F0b3IgPSB1dGlsLmZpbmRQYXJlbnQodGhpcywgJ29ucy1uYXZpZ2F0b3InKTtcbiAgICAgIGlmIChuYXZpZ2F0b3IpIHtcbiAgICAgICAgbmF2aWdhdG9yLnBvcFBhZ2UodGhpcy5vcHRpb25zKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fYm91bmRPbkNsaWNrLCBmYWxzZSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdjbGFzcyddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ2NsYXNzJzpcbiAgICAgICAgdXRpbC5yZXN0b3JlQ2xhc3ModGhpcywgZGVmYXVsdENsYXNzTmFtZSwgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ21vZGlmaWVyJzoge1xuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKSAmJiB0aGlzLl91cGRhdGVJY29uKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9ib3VuZE9uQ2xpY2ssIGZhbHNlKTtcbiAgfVxuXG4gIHNob3coKSB7XG4gICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJ2lubGluZS1ibG9jayc7XG4gIH1cblxuICBoaWRlKCkge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5CYWNrQnV0dG9uID0gQmFja0J1dHRvbkVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1iYWNrLWJ1dHRvbicsIEJhY2tCdXR0b25FbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ2JvdHRvbS1iYXInO1xuY29uc3Qgc2NoZW1lID0geycnOiAnYm90dG9tLWJhci0tKid9O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1ib3R0b20tdG9vbGJhclxuICogQGNhdGVnb3J5IHBhZ2VcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dVG9vbGJhciBjb21wb25lbnQgdGhhdCBpcyBwb3NpdGlvbmVkIGF0IHRoZSBib3R0b20gb2YgdGhlIHBhZ2UuIFNpbmNlIGJvdHRvbSB0b29sYmFycyBhcmUgdmVyeSB2ZXJzYXRpbGUgZWxlbWVudHMsIGBvbnMtYm90dG9tLXRvb2xiYXJgIGRvZXMgbm90IHByb3ZpZGUgYW55IHNwZWNpZmljIGxheW91dCBzeW50YXggZm9yIGl0cyBjaGlsZHJlbi4gTW9kaWZpZXJzIG9yIGN1c3RvbSBDU1MgbXVzdCBiZSB1c2VkLlsvZW5dXG4gKiAgIFtqYV3jg5rjg7zjgrjkuIvpg6jjgavphY3nva7jgZXjgozjgovjg4Tjg7zjg6vjg5Djg7znlKjjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgafjgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIHRyYW5zcGFyZW50XG4gKiAgIFtlbl1NYWtlIHRoZSB0b29sYmFyIHRyYW5zcGFyZW50LlsvZW5dXG4gKiAgIFtqYV3jg4Tjg7zjg6vjg5Djg7zjga7og4zmma/jgpLpgI/mmI7jgavjgZfjgabooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIGFsaWduZWRcbiAqICAgW2VuXVZlcnRpY2FsbHkgYWxpZ25zIGl0cyBjaGlsZHJlbiBhbmQgYXBwbGllcyBmbGV4Ym94IGZvciBibG9jayBlbGVtZW50cy4gYGp1c3RpZnktY29udGVudGAgQ1NTIHJ1bGUgY2FuIGJlIHVzZWQgdG8gY2hhbmdlIGhvcml6b250YWwgYWxpZ24uWy9lbl1cbiAqICAgW2phXeODhOODvOODq+ODkOODvOOBruiDjOaZr+OCkumAj+aYjuOBq+OBl+OBpuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAc2VlYWxzbyBvbnMtdG9vbGJhciBbZW5db25zLXRvb2xiYXIgY29tcG9uZW50Wy9lbl1bamFdb25zLXRvb2xiYXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtYm90dG9tLXRvb2xiYXI+XG4gKiAgIENvbnRlbnRcbiAqIDwvb25zLWJvdHRvbS10b29sYmFyPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCb3R0b21Ub29sYmFyRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSB0b29sYmFyLlsvZW5dXG4gICAqICAgW2phXeODhOODvOODq+ODkOODvOOBruimi+OBn+ebruOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbn1cblxub25zRWxlbWVudHMuQm90dG9tVG9vbGJhciA9IEJvdHRvbVRvb2xiYXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtYm90dG9tLXRvb2xiYXInLCBCb3R0b21Ub29sYmFyRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCBCYXNlQnV0dG9uRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1idXR0b24nO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1idXR0b25cbiAqIEBjYXRlZ29yeSBmb3JtXG4gKiBAbW9kaWZpZXIgb3V0bGluZVxuICogICBbZW5dQnV0dG9uIHdpdGggb3V0bGluZSBhbmQgdHJhbnNwYXJlbnQgYmFja2dyb3VuZFsvZW5dXG4gKiAgIFtqYV3jgqLjgqbjg4jjg6njgqTjg7PjgpLmjIHjgaPjgZ/jg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIGxpZ2h0XG4gKiAgIFtlbl1CdXR0b24gdGhhdCBkb2Vzbid0IHN0YW5kIG91dC5bL2VuXVxuICogICBbamFd55uu56uL44Gf44Gq44GE44Oc44K/44Oz44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBxdWlldFxuICogICBbZW5dQnV0dG9uIHdpdGggbm8gb3V0bGluZSBhbmQgb3IgYmFja2dyb3VuZC4uWy9lbl1cbiAqICAgW2phXeaeoOe3muOChOiDjOaZr+OBjOeEoeOBhOaWh+Wtl+OBoOOBkeOBruODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAbW9kaWZpZXIgY3RhXG4gKiAgIFtlbl1CdXR0b24gdGhhdCByZWFsbHkgc3RhbmRzIG91dC5bL2VuXVxuICogICBbamFd55uu56uL44Gk44Oc44K/44Oz44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBsYXJnZVxuICogICBbZW5dTGFyZ2UgYnV0dG9uIHRoYXQgY292ZXJzIHRoZSB3aWR0aCBvZiB0aGUgc2NyZWVuLlsvZW5dXG4gKiAgIFtqYV3mqKrjgYTjgaPjgbHjgYTjgavluoPjgYzjgovlpKfjgY3jgarjg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIGxhcmdlLS1xdWlldFxuICogICBbZW5dTGFyZ2UgcXVpZXQgYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV3mqKrjgYTjgaPjgbHjgYTjgavluoPjgYzjgotxdWlldOODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAbW9kaWZpZXIgbGFyZ2UtLWN0YVxuICogICBbZW5dTGFyZ2UgY2FsbCB0byBhY3Rpb24gYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV3mqKrjgYTjgaPjgbHjgYTjgavluoPjgYzjgotjdGHjg5zjgr/jg7PjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gYnV0dG9uWy9lbl1cbiAqICAgW2phXeODnuODhuODquOCouODq+ODh+OCtuOCpOODs+OBruODnOOCv+ODs1svamFdXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWwtLWZsYXRcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiBmbGF0IGJ1dHRvblsvZW5dXG4gKiAgIFtqYV3jg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Pjga7jg5Xjg6njg4Pjg4jjg5zjgr/jg7NbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBCdXR0b24gY29tcG9uZW50LiBJZiB5b3Ugd2FudCB0byBwbGFjZSBhIGJ1dHRvbiBpbiBhIHRvb2xiYXIsIHVzZSBgPG9ucy10b29sYmFyLWJ1dHRvbj5gIG9yIGA8b25zLWJhY2stYnV0dG9uPmAgaW5zdGVhZC5cbiAqXG4gKiAgICAgV2lsbCBhdXRvbWF0aWNhbGx5IGRpc3BsYXkgYXMgYSBNYXRlcmlhbCBEZXNpZ24gYnV0dG9uIHdpdGggYSByaXBwbGUgZWZmZWN0IG9uIEFuZHJvaWQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg5zjgr/jg7PnlKjjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgILjg4Tjg7zjg6vjg5Djg7zjgavjg5zjgr/jg7PjgpLoqK3nva7jgZnjgovloLTlkIjjga/jgIFvbnMtdG9vbGJhci1idXR0b27jgoLjgZfjgY/jga9vbnMtYmFjay1idXR0b27jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgpLkvb/nlKjjgZfjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gaExheXhcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9idXR0b25cbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjbW9kaWZpZXJzIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNjcm9zcy1wbGF0Zm9ybS1zdHlsaW5nLWF1dG9zdHlsaW5nIFtlbl1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9lbl1bamFdSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1idXR0b24gbW9kaWZpZXI9XCJsYXJnZS0tY3RhXCI+XG4gKiAgIFRhcCBNZVxuICogPC9vbnMtYnV0dG9uPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJ1dHRvbkVsZW1lbnQgZXh0ZW5kcyBCYXNlQnV0dG9uRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGJ1dHRvbi5bL2VuXVxuICAgKiAgW2phXeODnOOCv+ODs+OBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHJpcHBsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBkZWZpbmVkLCB0aGUgYnV0dG9uIHdpbGwgaGF2ZSBhIHJpcHBsZSBlZmZlY3QuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSBpZiBidXR0b24gc2hvdWxkIGJlIGRpc2FibGVkLlsvZW5dXG4gICAqICAgW2phXeODnOOCv+ODs+OCkueEoeWKueWMluOBmeOCi+WgtOWQiOOBr+aMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBidXR0b24gaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiB7ICcnOiAnYnV0dG9uLS0qJyB9O1xuICB9XG5cbiAgZ2V0IF9kZWZhdWx0Q2xhc3NOYW1lKCkge1xuICAgIHJldHVybiAnYnV0dG9uJztcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5CdXR0b24gPSBCdXR0b25FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtYnV0dG9uJywgQnV0dG9uRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ2NhcmQnO1xuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ2NhcmQtLSonLFxuICAnLmNhcmRfX3RpdGxlJzogJ2NhcmQtLSpfX3RpdGxlJyxcbiAgJy5jYXJkX19jb250ZW50JzogJ2NhcmQtLSpfX2NvbnRlbnQnXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1jYXJkXG4gKiBAY2F0ZWdvcnkgdmlzdWFsXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXUEgY2FyZCB3aXRoIG1hdGVyaWFsIGRlc2lnbi5bL2VuXVxuICogICBbamFd44Oq44K544OI44Gu5LiK5LiL44Gu44Oc44O844OA44O844GM54Sh44GE44Oq44K544OI44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICBDb21wb25lbnQgdG8gY3JlYXRlIGEgY2FyZCB0aGF0IGRpc3BsYXlzIHNvbWUgaW5mb3JtYXRpb24uXG4gKlxuICogICAgVGhlIGNhcmQgbWF5IGJlIGNvbXBvc2VkIGJ5IGRpdnMgd2l0aCBzcGVjaWFsbHkgcHJlcGFyZWQgY2xhc3NlcyBgdGl0bGVgIGFuZC9vciBgY29udGVudGAuIFlvdSBjYW4gYWxzbyBhZGQgeW91ciBvd24gY29udGVudCBhcyB5b3UgcGxlYXNlLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2NhcmRcbiAqIEBleGFtcGxlXG4gKiA8b25zLWNhcmQ+XG4gKiAgIDxwPlNvbWUgY29udGVudDwvcD5cbiAqIDwvb25zLWNhcmQ+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENhcmRFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgY2FyZC5bL2VuXVxuICAgKiAgIFtqYV3jg6rjgrnjg4jjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGxldCB0aXRsZSwgY29udGVudDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgZWwgPSB0aGlzLmNoaWxkcmVuW2ldO1xuXG4gICAgICBpZiAoZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCd0aXRsZScpKSB7XG4gICAgICAgIGVsLmNsYXNzTGlzdC5hZGQoJ2NhcmRfX3RpdGxlJyk7XG4gICAgICAgIHRpdGxlID0gZWw7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChlbC5jbGFzc0xpc3QuY29udGFpbnMoJ2NvbnRlbnQnKSkge1xuICAgICAgICBlbC5jbGFzc0xpc3QuYWRkKCdjYXJkX19jb250ZW50Jyk7XG4gICAgICAgIGNvbnRlbnQgPSBlbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG59XG5cbm9uc0VsZW1lbnRzLkNhcmQgPSBDYXJkRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWNhcmQnLCBDYXJkRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuY29uc3Qgc2NoZW1lID0geycnOiAnY2Fyb3VzZWwtaXRlbS0tKid9O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1jYXJvdXNlbC1pdGVtXG4gKiBAY2F0ZWdvcnkgY2Fyb3VzZWxcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgQ2Fyb3VzZWwgaXRlbSBjb21wb25lbnQuIFVzZWQgYXMgYSBjaGlsZCBvZiB0aGUgYDxvbnMtY2Fyb3VzZWw+YCBlbGVtZW50LlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIHhiYnpPUVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2Nhcm91c2VsXG4gKiBAc2VlYWxzbyBvbnMtY2Fyb3VzZWxcbiAqICAgW2VuXWA8b25zLWNhcm91c2VsPmAgY29tcG9uZW50c1svZW5dXG4gKiAgIFtqYV08b25zLWNhcm91c2VsPuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1jYXJvdXNlbCBzdHlsZT1cIndpZHRoOiAxMDAlOyBoZWlnaHQ6IDIwMHB4XCI+XG4gKiAgIDxvbnMtY2Fyb3VzZWwtaXRlbT5cbiAqICAgIC4uLlxuICogICA8L29ucy1jYXJvdXNlbC1pdGVtPlxuICogICA8b25zLWNhcm91c2VsLWl0ZW0+XG4gKiAgICAuLi5cbiAqICAgPC9vbnMtY2Fyb3VzZWwtaXRlbT5cbiAqIDwvb25zLWNhcm91c2VsPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDYXJvdXNlbEl0ZW1FbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJ11cbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIHJldHVybiBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICB9XG4gIH1cbn1cblxub25zRWxlbWVudHMuQ2Fyb3VzZWxJdGVtID0gQ2Fyb3VzZWxJdGVtRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWNhcm91c2VsLWl0ZW0nLCBDYXJvdXNlbEl0ZW1FbGVtZW50KTtcbiIsImltcG9ydCB1dGlsIGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uL3BsYXRmb3JtJztcbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vYW5pbWl0JztcbmltcG9ydCBHZXN0dXJlRGV0ZWN0b3IgZnJvbSAnLi4vZ2VzdHVyZS1kZXRlY3Rvcic7XG5cbmNvbnN0IGRpcmVjdGlvbk1hcCA9IHtcbiAgdmVydGljYWw6IHtcbiAgICBheGlzOiAnWScsXG4gICAgc2l6ZTogJ0hlaWdodCcsXG4gICAgZGlyOiBbJ3VwJywgJ2Rvd24nXSxcbiAgICB0M2Q6IFsnMHB4LCAnLCAncHgsIDBweCddXG4gIH0sXG4gIGhvcml6b250YWw6IHtcbiAgICBheGlzOiAnWCcsXG4gICAgc2l6ZTogJ1dpZHRoJyxcbiAgICBkaXI6IFsnbGVmdCcsICdyaWdodCddLFxuICAgIHQzZDogWycnLCAncHgsIDBweCwgMHB4J11cbiAgfVxufTtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3dpcGVyIHtcbiAgY29uc3RydWN0b3IocGFyYW1zKSB7XG4gICAgLy8gUGFyYW1ldGVyc1xuICAgIGNvbnN0IEZBTFNFID0gKCgpID0+IGZhbHNlKTtcbiAgICBgZ2V0SW5pdGlhbEluZGV4IGdldEJ1YmJsZVdpZHRoIGlzVmVydGljYWwgaXNPdmVyU2Nyb2xsYWJsZSBpc0NlbnRlcmVkXG4gICAgaXNBdXRvU2Nyb2xsYWJsZSByZWZyZXNoSG9vayBwcmVDaGFuZ2VIb29rIHBvc3RDaGFuZ2VIb29rIG92ZXJTY3JvbGxIb29rYFxuICAgICAgLnNwbGl0KC9cXHMrLylcbiAgICAgIC5mb3JFYWNoKGtleSA9PiB0aGlzW2tleV0gPSBwYXJhbXNba2V5XSB8fCBGQUxTRSk7XG5cbiAgICB0aGlzLmdldEVsZW1lbnQgPSBwYXJhbXMuZ2V0RWxlbWVudDsgLy8gUmVxdWlyZWRcbiAgICB0aGlzLnNjcm9sbEhvb2sgPSBwYXJhbXMuc2Nyb2xsSG9vazsgLy8gT3B0aW9uYWxcbiAgICB0aGlzLml0ZW1TaXplID0gcGFyYW1zLml0ZW1TaXplIHx8ICcxMDAlJztcblxuICAgIHRoaXMuZ2V0QXV0b1Njcm9sbFJhdGlvID0gKC4uLmFyZ3MpID0+IHtcbiAgICAgIGxldCByYXRpbyA9IHBhcmFtcy5nZXRBdXRvU2Nyb2xsUmF0aW8gJiYgcGFyYW1zLmdldEF1dG9TY3JvbGxSYXRpbyguLi5hcmdzKTtcbiAgICAgIHJhdGlvID0gdHlwZW9mIHJhdGlvID09PSAnbnVtYmVyJyAmJiByYXRpbyA9PT0gcmF0aW8gPyByYXRpbyA6IC41O1xuICAgICAgaWYgKHJhdGlvIDwgMC4wIHx8IHJhdGlvID4gMS4wKSB7XG4gICAgICAgIHV0aWwudGhyb3coJ0ludmFsaWQgYXV0by1zY3JvbGwtcmF0aW8gJyArIHJhdGlvICsgJy4gTXVzdCBiZSBiZXR3ZWVuIDAgYW5kIDEnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByYXRpbztcbiAgICB9O1xuXG4gICAgLy8gUHJldmVudCBjbGlja3Mgb25seSBvbiBkZXNrdG9wXG4gICAgdGhpcy5zaG91bGRCbG9jayA9IHV0aWwuZ2xvYmFscy5hY3R1YWxNb2JpbGVPUyA9PT0gJ290aGVyJztcblxuICAgIC8vIEJpbmQgaGFuZGxlcnNcbiAgICB0aGlzLm9uRHJhZ1N0YXJ0ID0gdGhpcy5vbkRyYWdTdGFydC5iaW5kKHRoaXMpO1xuICAgIHRoaXMub25EcmFnID0gdGhpcy5vbkRyYWcuYmluZCh0aGlzKTtcbiAgICB0aGlzLm9uRHJhZ0VuZCA9IHRoaXMub25EcmFnRW5kLmJpbmQodGhpcyk7XG4gICAgdGhpcy5vblJlc2l6ZSA9IHRoaXMub25SZXNpemUuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX3Nob3VsZEZpeFNjcm9sbCA9IHV0aWwuZ2xvYmFscy5hY3R1YWxNb2JpbGVPUyA9PT0gJ2lvcyc7XG4gIH1cblxuICBpbml0KHsgc3dpcGVhYmxlLCBhdXRvUmVmcmVzaCB9ID0ge30pIHtcbiAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB0aGlzLnRhcmdldCA9IHRoaXMuZ2V0RWxlbWVudCgpLmNoaWxkcmVuWzBdO1xuICAgIHRoaXMuYmxvY2tlciA9IHRoaXMuZ2V0RWxlbWVudCgpLmNoaWxkcmVuWzFdO1xuICAgIGlmICghdGhpcy50YXJnZXQgfHwgIXRoaXMuYmxvY2tlcikge1xuICAgICAgdXRpbC50aHJvdygnRXhwZWN0ZWQgXCJ0YXJnZXRcIiBhbmQgXCJibG9ja2VyXCIgZWxlbWVudHMgdG8gZXhpc3QgYmVmb3JlIGluaXRpYWxpemluZyBTd2lwZXInKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuc2hvdWxkQmxvY2spIHtcbiAgICAgIHRoaXMuYmxvY2tlci5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIH1cblxuICAgIC8vIEFkZCBjbGFzc2VzXG4gICAgdGhpcy5nZXRFbGVtZW50KCkuY2xhc3NMaXN0LmFkZCgnb25zLXN3aXBlcicpO1xuICAgIHRoaXMudGFyZ2V0LmNsYXNzTGlzdC5hZGQoJ29ucy1zd2lwZXItdGFyZ2V0Jyk7XG4gICAgdGhpcy5ibG9ja2VyLmNsYXNzTGlzdC5hZGQoJ29ucy1zd2lwZXItYmxvY2tlcicpO1xuXG4gICAgLy8gU2V0dXAgbGlzdGVuZXJzXG4gICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yID0gbmV3IEdlc3R1cmVEZXRlY3Rvcih0aGlzLmdldEVsZW1lbnQoKSxcbiAgICAgIHsgZHJhZ01pbkRpc3RhbmNlOiAxLCBkcmFnTG9ja1RvQXhpczogdHJ1ZSwgcGFzc2l2ZTogIXRoaXMuX3Nob3VsZEZpeFNjcm9sbCB9XG4gICAgKTtcbiAgICB0aGlzLl9tdXRhdGlvbk9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKCkgPT4gdGhpcy5yZWZyZXNoKCkpO1xuICAgIHRoaXMudXBkYXRlU3dpcGVhYmxlKHN3aXBlYWJsZSk7XG4gICAgdGhpcy51cGRhdGVBdXRvUmVmcmVzaChhdXRvUmVmcmVzaCk7XG5cbiAgICAvLyBTZXR1cCBpbml0aWFsIGxheW91dFxuICAgIHRoaXMuX3Njcm9sbCA9IHRoaXMuX29mZnNldCA9IHRoaXMuX2xhc3RBY3RpdmVJbmRleCA9IDA7XG4gICAgdGhpcy5fdXBkYXRlTGF5b3V0KCk7XG4gICAgdGhpcy5fc2V0dXBJbml0aWFsSW5kZXgoKTtcbiAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGhpcy5pbml0aWFsaXplZCAmJiB0aGlzLl9zZXR1cEluaXRpYWxJbmRleCgpKTtcblxuICAgIC8vIEZpeCByZW5kZXJpbmcgZ2xpdGNoIG9uIEFuZHJvaWQgNC4xXG4gICAgLy8gRml4IGZvciBpZnJhbWVzIHdoZXJlIHRoZSB3aWR0aCBpcyBpbmNvbnNpc3RlbnQgYXQgdGhlIGJlZ2lubmluZ1xuICAgIGlmICh3aW5kb3cgIT09IHdpbmRvdy5wYXJlbnQgfHwgdGhpcy5vZmZzZXRIZWlnaHQgPT09IDApIHtcbiAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gdGhpcy5pbml0aWFsaXplZCAmJiB0aGlzLm9uUmVzaXplKCkpO1xuICAgIH1cbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5pbml0aWFsaXplZCA9IGZhbHNlO1xuICAgIHRoaXMudXBkYXRlU3dpcGVhYmxlKGZhbHNlKTtcbiAgICB0aGlzLnVwZGF0ZUF1dG9SZWZyZXNoKGZhbHNlKTtcblxuICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvciAmJiB0aGlzLl9nZXN0dXJlRGV0ZWN0b3IuZGlzcG9zZSgpO1xuICAgIHRoaXMudGFyZ2V0ID0gdGhpcy5ibG9ja2VyID0gdGhpcy5fZ2VzdHVyZURldGVjdG9yID0gdGhpcy5fbXV0YXRpb25PYnNlcnZlciA9IG51bGw7XG5cbiAgICB0aGlzLnNldHVwUmVzaXplKGZhbHNlKTtcbiAgfVxuXG4gIG9uUmVzaXplKCkge1xuICAgIGNvbnN0IGkgPSB0aGlzLl9zY3JvbGwgLyB0aGlzLnRhcmdldFNpemU7XG4gICAgdGhpcy5fcmVzZXQoKTtcbiAgICB0aGlzLnNldEFjdGl2ZUluZGV4KGkpO1xuICAgIHRoaXMucmVmcmVzaCgpO1xuICB9XG5cbiAgZ2V0IGl0ZW1Db3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy50YXJnZXQuY2hpbGRyZW4ubGVuZ3RoO1xuICB9XG5cbiAgZ2V0IGl0ZW1OdW1TaXplKCkge1xuICAgIGlmICh0eXBlb2YgdGhpcy5faXRlbU51bVNpemUgIT09ICdudW1iZXInIHx8IHRoaXMuX2l0ZW1OdW1TaXplICE9PSB0aGlzLl9pdGVtTnVtU2l6ZSkge1xuICAgICAgdGhpcy5faXRlbU51bVNpemUgPSB0aGlzLl9jYWxjdWxhdGVJdGVtU2l6ZSgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5faXRlbU51bVNpemU7XG4gIH1cblxuICBnZXQgbWF4U2Nyb2xsKCkge1xuICAgIGNvbnN0IG1heCA9IHRoaXMuaXRlbUNvdW50ICogdGhpcy5pdGVtTnVtU2l6ZSAtIHRoaXMudGFyZ2V0U2l6ZTtcbiAgICByZXR1cm4gTWF0aC5jZWlsKG1heCA8IDAgPyAwIDogbWF4KTsgLy8gTmVlZCB0byByZXR1cm4gYW4gaW50ZWdlciB2YWx1ZS5cbiAgfVxuXG4gIF9jYWxjdWxhdGVJdGVtU2l6ZSgpIHtcbiAgICBjb25zdCBtYXRjaGVzID0gdGhpcy5pdGVtU2l6ZS5tYXRjaCgvXihcXGQrKShweHwlKS8pO1xuXG4gICAgaWYgKCFtYXRjaGVzKSB7XG4gICAgICB1dGlsLnRocm93KGBJbnZhbGlkIHN0YXRlOiBzd2lwZXIncyBzaXplIHVuaXQgbXVzdCBiZSAnJScgb3IgJ3B4J2ApO1xuICAgIH1cblxuICAgIGNvbnN0IHZhbHVlID0gcGFyc2VJbnQobWF0Y2hlc1sxXSwgMTApO1xuICAgIHJldHVybiBtYXRjaGVzWzJdID09PSAnJScgPyBNYXRoLnJvdW5kKHZhbHVlIC8gMTAwICogdGhpcy50YXJnZXRTaXplKSA6IHZhbHVlO1xuICB9XG5cbiAgX3NldHVwSW5pdGlhbEluZGV4KCkge1xuICAgIHRoaXMuX3Jlc2V0KCk7XG4gICAgdGhpcy5fbGFzdEFjdGl2ZUluZGV4ID0gTWF0aC5tYXgoTWF0aC5taW4oTnVtYmVyKHRoaXMuZ2V0SW5pdGlhbEluZGV4KCkpLCB0aGlzLml0ZW1Db3VudCksIDApO1xuICAgIHRoaXMuX3Njcm9sbCA9IHRoaXMuX29mZnNldCArIHRoaXMuaXRlbU51bVNpemUgKiB0aGlzLl9sYXN0QWN0aXZlSW5kZXg7XG4gICAgdGhpcy5fc2Nyb2xsVG8odGhpcy5fc2Nyb2xsKTtcbiAgfVxuXG4gIF9zZXRTd2lwaW5nKHRvZ2dsZSkge1xuICAgIHRoaXMudGFyZ2V0LmNsYXNzTGlzdC50b2dnbGUoJ3N3aXBpbmcnLCB0b2dnbGUpOyAvLyBIaWRlcyBldmVyeXRoaW5nIGV4Y2VwdCBzaG93biBwYWdlc1xuICB9XG5cbiAgc2V0QWN0aXZlSW5kZXgoaW5kZXgsIG9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMuX3NldFN3aXBpbmcodHJ1ZSk7XG4gICAgaW5kZXggPSBNYXRoLm1heCgwLCBNYXRoLm1pbihpbmRleCwgdGhpcy5pdGVtQ291bnQgLSAxKSk7XG4gICAgY29uc3Qgc2Nyb2xsID0gTWF0aC5tYXgoMCwgTWF0aC5taW4odGhpcy5tYXhTY3JvbGwsIHRoaXMuX29mZnNldCArIHRoaXMuaXRlbU51bVNpemUgKiBpbmRleCkpO1xuXG4gICAgaWYgKHBsYXRmb3JtLmlzVUlXZWJWaWV3KCkpIHtcbiAgICAgIC8qIERpcnR5IGZpeCBmb3IgIzIyMzEoaHR0cHM6Ly9naXRodWIuY29tL09uc2VuVUkvT25zZW5VSS9pc3N1ZXMvMjIzMSkuIGJlZ2luICovXG4gICAgICBjb25zdCBjb25jYXQgPSBhcnJheU9mQXJyYXkgPT4gQXJyYXkucHJvdG90eXBlLmNvbmNhdC5hcHBseShbXSwgYXJyYXlPZkFycmF5KTtcbiAgICAgIGNvbnN0IGNvbnRlbnRzID0gY29uY2F0KFxuICAgICAgICB1dGlsLmFycmF5RnJvbSh0aGlzLnRhcmdldC5jaGlsZHJlbikubWFwKHBhZ2UgPT4ge1xuICAgICAgICAgIHJldHVybiB1dGlsLmFycmF5RnJvbShwYWdlLmNoaWxkcmVuKVxuICAgICAgICAgICAgLmZpbHRlcihjaGlsZCA9PiBjaGlsZC5jbGFzc0xpc3QuY29udGFpbnMoJ3BhZ2VfX2NvbnRlbnQnKSk7XG4gICAgICAgIH0pXG4gICAgICApO1xuXG4gICAgICBjb25zdCBtYXAgPSBuZXcgTWFwKCk7XG4gICAgICByZXR1cm4gKFxuICAgICAgICBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICBjb250ZW50cy5mb3JFYWNoKGNvbnRlbnQgPT4ge1xuICAgICAgICAgICAgbWFwLnNldChjb250ZW50LCBjb250ZW50LmdldEF0dHJpYnV0ZSgnY2xhc3MnKSk7XG4gICAgICAgICAgICBjb250ZW50LmNsYXNzTGlzdC5hZGQoJ3BhZ2VfX2NvbnRlbnQtLXN1cHByZXNzLWxheWVyLWNyZWF0aW9uJylcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocmVzb2x2ZSk7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKCgpID0+IHRoaXMuX2NoYW5nZVRvKHNjcm9sbCwgb3B0aW9ucykpXG4gICAgICAgIC50aGVuKCgpID0+IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICAgIGNvbnRlbnRzLmZvckVhY2goY29udGVudCA9PiB7XG4gICAgICAgICAgICBjb250ZW50LnNldEF0dHJpYnV0ZSgnY2xhc3MnLCBtYXAuZ2V0KGNvbnRlbnQpKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUocmVzb2x2ZSk7XG4gICAgICAgIH0pKVxuICAgICAgKTtcbiAgICAgIC8qIGVuZCAqL1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5fY2hhbmdlVG8oc2Nyb2xsLCBvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICBnZXRBY3RpdmVJbmRleChzY3JvbGwgPSB0aGlzLl9zY3JvbGwpIHtcbiAgICBzY3JvbGwgLT0gdGhpcy5fb2Zmc2V0O1xuICAgIGNvbnN0IGNvdW50ID0gdGhpcy5pdGVtQ291bnQsXG4gICAgICBzaXplID0gdGhpcy5pdGVtTnVtU2l6ZTtcblxuICAgIGlmICh0aGlzLml0ZW1OdW1TaXplID09PSAwIHx8ICF1dGlsLmlzSW50ZWdlcihzY3JvbGwpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fbGFzdEFjdGl2ZUluZGV4O1xuICAgIH1cblxuICAgIGlmIChzY3JvbGwgPD0gMCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICBpZiAoc2l6ZSAqIGkgPD0gc2Nyb2xsICYmIHNpemUgKiAoaSArIDEpID4gc2Nyb2xsKSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb3VudCAtIDE7XG4gIH1cblxuICBzZXR1cFJlc2l6ZShhZGQpIHtcbiAgICB3aW5kb3dbKGFkZCA/ICdhZGQnIDogJ3JlbW92ZScpICsgJ0V2ZW50TGlzdGVuZXInXSgncmVzaXplJywgdGhpcy5vblJlc2l6ZSwgdHJ1ZSk7XG4gIH1cblxuICBzaG93KCkge1xuICAgIHRoaXMuc2V0dXBSZXNpemUodHJ1ZSk7XG4gICAgdGhpcy5vblJlc2l6ZSgpO1xuICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy50YXJnZXQgJiYgdGhpcy50YXJnZXQuY2xhc3NMaXN0LmFkZCgnYWN0aXZlJyksIDEwMDAvNjApOyAvLyBIaWRlIGVsZW1lbnRzIGFmdGVyIGFuaW1hdGlvbnNcbiAgfVxuXG4gIGhpZGUoKSB7XG4gICAgdGhpcy5zZXR1cFJlc2l6ZShmYWxzZSk7XG4gICAgdGhpcy50YXJnZXQuY2xhc3NMaXN0LnJlbW92ZSgnYWN0aXZlJyk7IC8vIFNob3cgZWxlbWVudHMgYmVmb3JlIGFuaW1hdGlvbnNcbiAgfVxuXG4gIHVwZGF0ZVN3aXBlYWJsZShzaG91bGRVcGRhdGUpIHtcbiAgICBpZiAodGhpcy5fZ2VzdHVyZURldGVjdG9yKSB7XG4gICAgICBjb25zdCBhY3Rpb24gPSBzaG91bGRVcGRhdGUgPyAnb24nIDogJ29mZic7XG4gICAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3JbYWN0aW9uXSgnZHJhZycsIHRoaXMub25EcmFnKTtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvclthY3Rpb25dKCdkcmFnc3RhcnQnLCB0aGlzLm9uRHJhZ1N0YXJ0KTtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvclthY3Rpb25dKCdkcmFnZW5kJywgdGhpcy5vbkRyYWdFbmQpO1xuICAgIH1cbiAgfVxuXG4gIHVwZGF0ZUF1dG9SZWZyZXNoKHNob3VsZFdhdGNoKSB7XG4gICAgaWYgKHRoaXMuX211dGF0aW9uT2JzZXJ2ZXIpIHtcbiAgICAgIHNob3VsZFdhdGNoXG4gICAgICAgID8gdGhpcy5fbXV0YXRpb25PYnNlcnZlci5vYnNlcnZlKHRoaXMudGFyZ2V0LCB7IGNoaWxkTGlzdDogdHJ1ZSB9KVxuICAgICAgICA6IHRoaXMuX211dGF0aW9uT2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuICAgIH1cbiAgfVxuXG4gIHVwZGF0ZUl0ZW1TaXplKG5ld1NpemUpIHtcbiAgICB0aGlzLml0ZW1TaXplID0gbmV3U2l6ZSB8fCAnMTAwJSc7XG4gICAgdGhpcy5yZWZyZXNoKCk7XG4gIH1cblxuICB0b2dnbGVCbG9ja2VyKGJsb2NrKSB7XG4gICAgdGhpcy5ibG9ja2VyLnN0eWxlLnBvaW50ZXJFdmVudHMgPSBibG9jayA/ICdhdXRvJyA6ICdub25lJztcbiAgfVxuXG4gIF9jYW5Db25zdW1lR2VzdHVyZShnZXN0dXJlKSB7XG4gICAgY29uc3QgZCA9IGdlc3R1cmUuZGlyZWN0aW9uO1xuICAgIGNvbnN0IGlzRmlyc3QgPSB0aGlzLl9zY3JvbGwgPT09IDAgJiYgIXRoaXMuaXNPdmVyU2Nyb2xsYWJsZSgpO1xuICAgIGNvbnN0IGlzTGFzdCA9IHRoaXMuX3Njcm9sbCA9PT0gdGhpcy5tYXhTY3JvbGwgJiYgIXRoaXMuaXNPdmVyU2Nyb2xsYWJsZSgpO1xuXG4gICAgcmV0dXJuIHRoaXMuaXNWZXJ0aWNhbCgpXG4gICAgICA/ICgoZCA9PT0gJ2Rvd24nICYmICFpc0ZpcnN0KSB8fCAoZCA9PT0gJ3VwJyAmJiAhaXNMYXN0KSlcbiAgICAgIDogKChkID09PSAncmlnaHQnICYmICFpc0ZpcnN0KSB8fCAoZCA9PT0gJ2xlZnQnICYmICFpc0xhc3QpKTtcbiAgfVxuXG4gIG9uRHJhZ1N0YXJ0KGV2ZW50KSB7XG4gICAgdGhpcy5faWdub3JlRHJhZyA9IGV2ZW50LmNvbnN1bWVkIHx8ICF1dGlsLmlzVmFsaWRHZXN0dXJlKGV2ZW50KTtcblxuICAgIGlmICghdGhpcy5faWdub3JlRHJhZykge1xuICAgICAgY29uc3QgY29uc3VtZSA9IGV2ZW50LmNvbnN1bWU7XG4gICAgICBldmVudC5jb25zdW1lID0gKCkgPT4geyBjb25zdW1lICYmIGNvbnN1bWUoKTsgdGhpcy5faWdub3JlRHJhZyA9IHRydWU7IH07XG5cbiAgICAgIGlmICh0aGlzLl9jYW5Db25zdW1lR2VzdHVyZShldmVudC5nZXN0dXJlKSkge1xuICAgICAgICBjb25zdCBzdGFydFggPSBldmVudC5nZXN0dXJlLmNlbnRlciAmJiBldmVudC5nZXN0dXJlLmNlbnRlci5jbGllbnRYIHx8IDAsXG4gICAgICAgICAgZGlzdEZyb21FZGdlID0gdGhpcy5nZXRCdWJibGVXaWR0aCgpIHx8IDAsXG4gICAgICAgICAgc3RhcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICBjb25zdW1lICYmIGNvbnN1bWUoKTtcbiAgICAgICAgICAgIGV2ZW50LmNvbnN1bWVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuX3N0YXJ0ZWQgPSB0cnVlOyAvLyBBdm9pZCBzdGFydGluZyBkcmFnIGZyb20gb3V0c2lkZVxuICAgICAgICAgICAgdGhpcy5zaG91bGRCbG9jayAmJiB0aGlzLnRvZ2dsZUJsb2NrZXIodHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLl9zZXRTd2lwaW5nKHRydWUpO1xuICAgICAgICAgICAgdXRpbC5pb3NQcmV2ZW50U2Nyb2xsKHRoaXMuX2dlc3R1cmVEZXRlY3Rvcik7XG4gICAgICAgICAgfTtcblxuICAgICAgICAvLyBMZXQgcGFyZW50IGVsZW1lbnRzIGNvbnN1bWUgdGhlIGdlc3R1cmUgb3IgY29uc3VtZSBpdCByaWdodCBhd2F5XG4gICAgICAgIHN0YXJ0WCA8IGRpc3RGcm9tRWRnZSB8fCBzdGFydFggPiAodGhpcy50YXJnZXRTaXplIC0gZGlzdEZyb21FZGdlKVxuICAgICAgICAgID8gc2V0SW1tZWRpYXRlKCgpID0+ICF0aGlzLl9pZ25vcmVEcmFnICYmIHN0YXJ0KCkpXG4gICAgICAgICAgOiBzdGFydCgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG9uRHJhZyhldmVudCkge1xuICAgIGlmICghZXZlbnQuZ2VzdHVyZSB8fCB0aGlzLl9pZ25vcmVEcmFnIHx8ICF0aGlzLl9zdGFydGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fY29udGludWVkID0gdHJ1ZTsgLy8gRml4IGZvciByYW5kb20gJ2RyYWdlbmQnIHdpdGhvdXQgJ2RyYWcnXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICB0aGlzLl9zY3JvbGxUbyh0aGlzLl9zY3JvbGwgLSB0aGlzLl9nZXREZWx0YShldmVudCksIHsgdGhyb3R0bGU6IHRydWUgfSk7XG4gIH1cblxuICBvbkRyYWdFbmQoZXZlbnQpIHtcbiAgICB0aGlzLl9zdGFydGVkID0gZmFsc2U7XG4gICAgaWYgKCFldmVudC5nZXN0dXJlIHx8IHRoaXMuX2lnbm9yZURyYWcgfHwgIXRoaXMuX2NvbnRpbnVlZCkge1xuICAgICAgdGhpcy5faWdub3JlRHJhZyA9IHRydWU7IC8vIG9uRHJhZ0VuZCBtaWdodCBmaXJlIGJlZm9yZSBvbkRyYWdTdGFydCdzIHNldEltbWVkaWF0ZVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX2NvbnRpbnVlZCA9IGZhbHNlO1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgY29uc3Qgc2Nyb2xsID0gdGhpcy5fc2Nyb2xsIC0gdGhpcy5fZ2V0RGVsdGEoZXZlbnQpO1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRTY3JvbGwgPSB0aGlzLl9ub3JtYWxpemVTY3JvbGwoc2Nyb2xsKTtcbiAgICBzY3JvbGwgPT09IG5vcm1hbGl6ZWRTY3JvbGwgPyB0aGlzLl9zdGFydE1vbWVudHVtU2Nyb2xsKHNjcm9sbCwgZXZlbnQpIDogdGhpcy5fa2lsbE92ZXJTY3JvbGwobm9ybWFsaXplZFNjcm9sbCk7XG4gICAgdGhpcy5zaG91bGRCbG9jayAmJiB0aGlzLnRvZ2dsZUJsb2NrZXIoZmFsc2UpO1xuICB9XG5cbiAgX3N0YXJ0TW9tZW50dW1TY3JvbGwoc2Nyb2xsLCBldmVudCkge1xuICAgIGNvbnN0IHZlbG9jaXR5ID0gdGhpcy5fZ2V0VmVsb2NpdHkoZXZlbnQpLFxuICAgICAgbWF0Y2hlc0RpcmVjdGlvbiA9IGV2ZW50Lmdlc3R1cmUuaW50ZXJpbURpcmVjdGlvbiA9PT0gdGhpcy5kTS5kaXJbdGhpcy5fZ2V0RGVsdGEoZXZlbnQpIDwgMCA/IDAgOiAxXTtcblxuICAgIGNvbnN0IG5leHRTY3JvbGwgPSB0aGlzLl9nZXRBdXRvU2Nyb2xsKHNjcm9sbCwgdmVsb2NpdHksIG1hdGNoZXNEaXJlY3Rpb24pO1xuICAgIGxldCBkdXJhdGlvbiA9IE1hdGguYWJzKG5leHRTY3JvbGwgLSBzY3JvbGwpIC8gKHZlbG9jaXR5ICsgMC4wMSkgLyAxMDAwO1xuICAgIGR1cmF0aW9uID0gTWF0aC5taW4oLjI1LCBNYXRoLm1heCguMSwgZHVyYXRpb24pKTtcblxuICAgIHRoaXMuX2NoYW5nZVRvKG5leHRTY3JvbGwsIHsgc3dpcGU6IHRydWUsIGFuaW1hdGlvbk9wdGlvbnM6IHsgZHVyYXRpb24sIHRpbWluZzogJ2N1YmljLWJlemllciguNCwgLjcsIC41LCAxKScgfSB9KTtcbiAgfVxuXG4gIF9raWxsT3ZlclNjcm9sbChzY3JvbGwpIHtcbiAgICB0aGlzLl9zY3JvbGwgPSBzY3JvbGw7XG4gICAgY29uc3QgZGlyZWN0aW9uID0gdGhpcy5kTS5kaXJbTnVtYmVyKHNjcm9sbCA+IDApXTtcbiAgICBjb25zdCBraWxsT3ZlclNjcm9sbCA9ICgpID0+IHRoaXMuX2NoYW5nZVRvKHNjcm9sbCwgeyBhbmltYXRpb25PcHRpb25zOiB7IGR1cmF0aW9uOiAuNCwgdGltaW5nOiAnY3ViaWMtYmV6aWVyKC4xLCAuNCwgLjEsIDEpJyB9IH0pO1xuICAgIHRoaXMub3ZlclNjcm9sbEhvb2soeyBkaXJlY3Rpb24sIGtpbGxPdmVyU2Nyb2xsIH0pIHx8IGtpbGxPdmVyU2Nyb2xsKCk7XG4gIH1cblxuICBfY2hhbmdlVG8oc2Nyb2xsLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCBlID0geyBhY3RpdmVJbmRleDogdGhpcy5nZXRBY3RpdmVJbmRleChzY3JvbGwpLCBsYXN0QWN0aXZlSW5kZXg6IHRoaXMuX2xhc3RBY3RpdmVJbmRleCwgc3dpcGU6IG9wdGlvbnMuc3dpcGUgfHwgZmFsc2UgfTtcbiAgICBjb25zdCBjaGFuZ2UgPSBlLmFjdGl2ZUluZGV4ICE9PSBlLmxhc3RBY3RpdmVJbmRleDtcbiAgICBjb25zdCBjYW5jZWxlZCA9IGNoYW5nZSA/IHRoaXMucHJlQ2hhbmdlSG9vayhlKSA6IGZhbHNlO1xuXG4gICAgdGhpcy5fc2Nyb2xsID0gY2FuY2VsZWQgPyB0aGlzLl9vZmZzZXQgKyBlLmxhc3RBY3RpdmVJbmRleCAqIHRoaXMuaXRlbU51bVNpemUgOiBzY3JvbGw7XG4gICAgdGhpcy5fbGFzdEFjdGl2ZUluZGV4ID0gY2FuY2VsZWQgPyBlLmxhc3RBY3RpdmVJbmRleCA6IGUuYWN0aXZlSW5kZXg7XG5cbiAgICByZXR1cm4gdGhpcy5fc2Nyb2xsVG8odGhpcy5fc2Nyb2xsLCBvcHRpb25zKS50aGVuKCgpID0+IHtcbiAgICAgIGlmIChzY3JvbGwgPT09IHRoaXMuX3Njcm9sbCAmJiAhY2FuY2VsZWQpIHtcbiAgICAgICAgdGhpcy5fc2V0U3dpcGluZyhmYWxzZSk7XG4gICAgICAgIGNoYW5nZSAmJiB0aGlzLnBvc3RDaGFuZ2VIb29rKGUpO1xuICAgICAgfSBlbHNlIGlmIChvcHRpb25zLnJlamVjdCkge1xuICAgICAgICB0aGlzLl9zZXRTd2lwaW5nKGZhbHNlKTtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdDYW5jZWxlZCcpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgX3Njcm9sbFRvKHNjcm9sbCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKG9wdGlvbnMudGhyb3R0bGUpIHtcbiAgICAgIGNvbnN0IHJhdGlvID0gMC4zNTtcbiAgICAgIGlmIChzY3JvbGwgPCAwKSB7XG4gICAgICAgIHNjcm9sbCA9IHRoaXMuaXNPdmVyU2Nyb2xsYWJsZSgpID8gTWF0aC5yb3VuZChzY3JvbGwgKiByYXRpbykgOiAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgbWF4U2Nyb2xsID0gdGhpcy5tYXhTY3JvbGw7XG4gICAgICAgIGlmIChtYXhTY3JvbGwgPCBzY3JvbGwpIHtcbiAgICAgICAgICBzY3JvbGwgPSB0aGlzLmlzT3ZlclNjcm9sbGFibGUoKSA/IG1heFNjcm9sbCArIE1hdGgucm91bmQoKHNjcm9sbCAtIG1heFNjcm9sbCkgKiByYXRpbykgOiBtYXhTY3JvbGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBvcHQgPSBvcHRpb25zLmFuaW1hdGlvbiAgPT09ICdub25lJyA/IHt9IDogb3B0aW9ucy5hbmltYXRpb25PcHRpb25zO1xuICAgIHRoaXMuc2Nyb2xsSG9vayAmJiB0aGlzLml0ZW1OdW1TaXplID4gMCAmJiB0aGlzLnNjcm9sbEhvb2soKHNjcm9sbCAvIHRoaXMuaXRlbU51bVNpemUpLnRvRml4ZWQoMiksIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fSk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PlxuICAgICAgYW5pbWl0KHRoaXMudGFyZ2V0KVxuICAgICAgICAucXVldWUoeyB0cmFuc2Zvcm06IHRoaXMuX2dldFRyYW5zZm9ybShzY3JvbGwpIH0sIG9wdClcbiAgICAgICAgLnBsYXkocmVzb2x2ZSlcbiAgICApO1xuICB9XG5cbiAgX2dldEF1dG9TY3JvbGwoc2Nyb2xsLCB2ZWxvY2l0eSwgbWF0Y2hlc0RpcmVjdGlvbikge1xuICAgIGNvbnN0IG1heCA9IHRoaXMubWF4U2Nyb2xsLFxuICAgICAgb2Zmc2V0ID0gdGhpcy5fb2Zmc2V0LFxuICAgICAgc2l6ZSA9IHRoaXMuaXRlbU51bVNpemU7XG5cbiAgICBpZiAoIXRoaXMuaXNBdXRvU2Nyb2xsYWJsZSgpKSB7XG4gICAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4obWF4LCBzY3JvbGwpKTtcbiAgICB9XG5cbiAgICBsZXQgYXJyID0gW107XG4gICAgZm9yIChsZXQgcyA9IG9mZnNldDsgcyA8IG1heDsgcyArPSBzaXplKSB7XG4gICAgICBhcnIucHVzaChzKTtcbiAgICB9XG4gICAgYXJyLnB1c2gobWF4KTtcblxuICAgIGFyciA9IGFyclxuICAgICAgLnNvcnQoKGxlZnQsIHJpZ2h0KSA9PiBNYXRoLmFicyhsZWZ0IC0gc2Nyb2xsKSAtIE1hdGguYWJzKHJpZ2h0IC0gc2Nyb2xsKSlcbiAgICAgIC5maWx0ZXIoKGl0ZW0sIHBvcykgPT4gIXBvcyB8fCBpdGVtICE9PSBhcnJbcG9zIC0gMV0pO1xuXG4gICAgbGV0IHJlc3VsdCA9IGFyclswXTtcbiAgICBjb25zdCBsYXN0U2Nyb2xsID0gdGhpcy5fbGFzdEFjdGl2ZUluZGV4ICogc2l6ZSArIG9mZnNldDtcbiAgICBjb25zdCBzY3JvbGxSYXRpbyA9IE1hdGguYWJzKHNjcm9sbCAtIGxhc3RTY3JvbGwpIC8gc2l6ZTtcblxuICAgIGlmIChzY3JvbGxSYXRpbyA8PSB0aGlzLmdldEF1dG9TY3JvbGxSYXRpbyhtYXRjaGVzRGlyZWN0aW9uLCB2ZWxvY2l0eSwgc2l6ZSkpIHtcbiAgICAgIHJlc3VsdCA9IGxhc3RTY3JvbGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChzY3JvbGxSYXRpbyA8IDEuMCAmJiBhcnJbMF0gPT09IGxhc3RTY3JvbGwgJiYgYXJyLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgcmVzdWx0ID0gYXJyWzFdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5taW4obWF4LCByZXN1bHQpKTtcbiAgfVxuXG4gIF9yZXNldCgpIHtcbiAgICB0aGlzLl90YXJnZXRTaXplID0gdGhpcy5faXRlbU51bVNpemUgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBfbm9ybWFsaXplU2Nyb2xsKHNjcm9sbCkge1xuICAgIHJldHVybiBNYXRoLm1heCggTWF0aC5taW4oc2Nyb2xsLCB0aGlzLm1heFNjcm9sbCksIDApXG4gIH1cblxuICByZWZyZXNoKCkge1xuICAgIHRoaXMuX3Jlc2V0KCk7XG4gICAgdGhpcy5fdXBkYXRlTGF5b3V0KCk7XG5cbiAgICBpZiAodXRpbC5pc0ludGVnZXIodGhpcy5fc2Nyb2xsKSkge1xuICAgICAgY29uc3Qgc2Nyb2xsID0gdGhpcy5fbm9ybWFsaXplU2Nyb2xsKHRoaXMuX3Njcm9sbCk7XG4gICAgICBzY3JvbGwgIT09IHRoaXMuX3Njcm9sbCA/IHRoaXMuX2tpbGxPdmVyU2Nyb2xsKHNjcm9sbCkgOiB0aGlzLl9jaGFuZ2VUbyhzY3JvbGwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9zZXR1cEluaXRpYWxJbmRleCgpO1xuICAgIH1cblxuICAgIHRoaXMucmVmcmVzaEhvb2soKTtcbiAgfVxuXG4gIGdldCB0YXJnZXRTaXplKCkge1xuICAgIGlmICghdGhpcy5fdGFyZ2V0U2l6ZSkge1xuICAgICAgdGhpcy5fdGFyZ2V0U2l6ZSA9IHRoaXMudGFyZ2V0W2BvZmZzZXQke3RoaXMuZE0uc2l6ZX1gXTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3RhcmdldFNpemU7XG4gIH1cblxuICBfZ2V0RGVsdGEoZXZlbnQpIHtcbiAgICByZXR1cm4gZXZlbnQuZ2VzdHVyZVtgZGVsdGEke3RoaXMuZE0uYXhpc31gXTtcbiAgfVxuXG4gIF9nZXRWZWxvY2l0eShldmVudCkge1xuICAgIHJldHVybiBldmVudC5nZXN0dXJlW2B2ZWxvY2l0eSR7dGhpcy5kTS5heGlzfWBdO1xuICB9XG5cbiAgX2dldFRyYW5zZm9ybShzY3JvbGwpIHtcbiAgICByZXR1cm4gYHRyYW5zbGF0ZTNkKCR7dGhpcy5kTS50M2RbMF19JHstc2Nyb2xsfSR7dGhpcy5kTS50M2RbMV19KWA7XG4gIH1cblxuICBfdXBkYXRlTGF5b3V0KCkge1xuICAgIHRoaXMuZE0gPSBkaXJlY3Rpb25NYXBbdGhpcy5pc1ZlcnRpY2FsKCkgPyAndmVydGljYWwnIDogJ2hvcml6b250YWwnXTtcbiAgICB0aGlzLnRhcmdldC5jbGFzc0xpc3QudG9nZ2xlKCdvbnMtc3dpcGVyLXRhcmdldC0tdmVydGljYWwnLCB0aGlzLmlzVmVydGljYWwoKSk7XG5cbiAgICBmb3IgKGxldCBjID0gdGhpcy50YXJnZXQuY2hpbGRyZW5bMF07IGM7IGMgPSBjLm5leHRFbGVtZW50U2libGluZykge1xuICAgICAgYy5zdHlsZVt0aGlzLmRNLnNpemUudG9Mb3dlckNhc2UoKV0gPSB0aGlzLml0ZW1TaXplO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmlzQ2VudGVyZWQoKSkge1xuICAgICAgdGhpcy5fb2Zmc2V0ID0gKHRoaXMudGFyZ2V0U2l6ZSAtIHRoaXMuaXRlbU51bVNpemUpIC8gLTIgfHwgMDtcbiAgICB9XG4gIH1cbn1cblxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcbmltcG9ydCBTd2lwZXIgZnJvbSAnLi4vb25zL2ludGVybmFsL3N3aXBlcic7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWNhcm91c2VsXG4gKiBAY2F0ZWdvcnkgY2Fyb3VzZWxcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgQ2Fyb3VzZWwgY29tcG9uZW50LiBBIGNhcm91c2VsIGNhbiBiZSB1c2VkIHRvIGRpc3BsYXkgc2V2ZXJhbCBpdGVtcyBpbiB0aGUgc2FtZSBzcGFjZS5cbiAqXG4gKiAgICAgVGhlIGNvbXBvbmVudCBzdXBwb3J0cyBkaXNwbGF5aW5nIGNvbnRlbnQgYm90aCBob3Jpem9udGFsbHkgYW5kIHZlcnRpY2FsbHkuIFRoZSB1c2VyIGNhbiBzY3JvbGwgdGhyb3VnaCB0aGUgaXRlbXMgYnkgZHJhZ2dpbmcgYW5kIGl0IGNhbiBhbHNvIGJlIGNvbnRyb2xsZXIgcHJvZ3JhbW1hdGljYWxseS5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAY29kZXBlbiB4YmJ6T1FcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9jYXJvdXNlbFxuICogQHNlZWFsc28gb25zLWNhcm91c2VsLWl0ZW1cbiAqICAgW2VuXWA8b25zLWNhcm91c2VsLWl0ZW0+YCBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWNhcm91c2VsLWl0ZW3jgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtY2Fyb3VzZWwgc3R5bGU9XCJ3aWR0aDogMTAwJTsgaGVpZ2h0OiAyMDBweFwiPlxuICogICA8b25zLWNhcm91c2VsLWl0ZW0+XG4gKiAgICAuLi5cbiAqICAgPC9vbnMtY2Fyb3VzZWwtaXRlbT5cbiAqICAgPG9ucy1jYXJvdXNlbC1pdGVtPlxuICogICAgLi4uXG4gKiAgIDwvb25zLWNhcm91c2VsLWl0ZW0+XG4gKiA8L29ucy1jYXJvdXNlbD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ2Fyb3VzZWxFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGNoYW5nZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBhZnRlciB0aGUgY3VycmVudCBjYXJvdXNlbCBpdGVtIGhhcyBjaGFuZ2VkLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOihqOekuuOBl+OBpuOBhOOCi+OCq+ODq+ODvOOCu+ODq+OBruimgee0oOOBjOWkieOCj+OBo+OBn+aZguOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmNhcm91c2VsXG4gICAqICAgW2VuXUNhcm91c2VsIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgYznmbrngavjgZfjgZ9DYXJvdXNlbOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBldmVudC5hY3RpdmVJbmRleFxuICAgKiAgIFtlbl1DdXJyZW50IGFjdGl2ZSBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjgqLjgq/jg4bjgqPjg5bjgavjgarjgaPjgabjgYTjgovopoHntKDjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgIJbL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gZXZlbnQubGFzdEFjdGl2ZUluZGV4XG4gICAqICAgW2VuXVByZXZpb3VzIGFjdGl2ZSBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3ku6XliY3jgqLjgq/jg4bjgqPjg5bjgaDjgaPjgZ/opoHntKDjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHJlZnJlc2hcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIGNhcm91c2VsIGhhcyBiZWVuIHJlZnJlc2hlZC5bL2VuXVxuICAgKiAgIFtqYV3jgqvjg6vjg7zjgrvjg6vjgYzmm7TmlrDjgZXjgozjgZ/mmYLjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5jYXJvdXNlbFxuICAgKiAgIFtlbl1DYXJvdXNlbCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44GM55m654Gr44GX44GfQ2Fyb3VzZWzjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IG92ZXJzY3JvbGxcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIGNhcm91c2VsIGhhcyBiZWVuIG92ZXJzY3JvbGxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgqvjg6vjg7zjgrvjg6vjgYzjgqrjg7zjg5Djg7zjgrnjgq/jg63jg7zjg6vjgZfjgZ/mmYLjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5jYXJvdXNlbFxuICAgKiAgIFtlbl1GaXJlZCB3aGVuIHRoZSBjYXJvdXNlbCBoYXMgYmVlbiByZWZyZXNoZWQuWy9lbl1cbiAgICogICBbamFd44Kr44Or44O844K744Or44GM5pu05paw44GV44KM44Gf5pmC44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV2ZW50LmFjdGl2ZUluZGV4XG4gICAqICAgW2VuXUN1cnJlbnQgYWN0aXZlIGluZGV4LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOCouOCr+ODhuOCo+ODluOBq+OBquOBo+OBpuOBhOOCi+imgee0oOOBruOCpOODs+ODh+ODg+OCr+OCueOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudC5kaXJlY3Rpb25cbiAgICogICBbZW5dQ2FuIGJlIG9uZSBvZiBlaXRoZXIgXCJ1cFwiLCBcImRvd25cIiwgXCJsZWZ0XCIgb3IgXCJyaWdodFwiLlsvZW5dXG4gICAqICAgW2phXeOCquODvOODkOODvOOCueOCr+ODreODvOODq+OBleOCjOOBn+aWueWQkeOBjOW+l+OCieOCjOOBvuOBmeOAglwidXBcIiwgXCJkb3duXCIsIFwibGVmdFwiLCBcInJpZ2h0XCLjga7jgYTjgZrjgozjgYvjga7mlrnlkJHjgYzmuKHjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC53YWl0VG9SZXR1cm5cbiAgICogICBbZW5dVGFrZXMgYSA8Y29kZT5Qcm9taXNlPC9jb2RlPiBvYmplY3QgYXMgYW4gYXJndW1lbnQuIFRoZSBjYXJvdXNlbCB3aWxsIG5vdCBzY3JvbGwgYmFjayB1bnRpbCB0aGUgcHJvbWlzZSBoYXMgYmVlbiByZXNvbHZlZCBvciByZWplY3RlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7plqLmlbDjga9Qcm9taXNl44Kq44OW44K444Kn44Kv44OI44KS5byV5pWw44Go44GX44Gm5Y+X44GR5Y+W44KK44G+44GZ44CC5rih44GX44GfUHJvbWlzZeOCquODluOCuOOCp+OCr+ODiOOBjHJlc29sdmXjgZXjgozjgovjgYtyZWplY3TjgZXjgozjgovjgb7jgafjgIHjgqvjg6vjg7zjgrvjg6vjga/jgrnjgq/jg63jg7zjg6vjg5Djg4Pjgq/jgZfjgb7jgZvjgpPjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXJlY3Rpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBkaXJlY3Rpb24gb2YgdGhlIGNhcm91c2VsLiBDYW4gYmUgZWl0aGVyIFwiaG9yaXpvbnRhbFwiIG9yIFwidmVydGljYWxcIi4gRGVmYXVsdCBpcyBcImhvcml6b250YWxcIi5bL2VuXVxuICAgKiAgIFtqYV3jgqvjg6vjg7zjgrvjg6vjga7mlrnlkJHjgpLmjIflrprjgZfjgb7jgZnjgIJcImhvcml6b250YWxcIuOBi1widmVydGljYWxcIuOCkuaMh+WumuOBp+OBjeOBvuOBmeOAglwiaG9yaXpvbnRhbFwi44GM44OH44OV44Kp44Or44OI5YCk44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZnVsbHNjcmVlblxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjYXJvdXNlbCB3aWxsIGNvdmVyIHRoZSB3aG9sZSBzY3JlZW4uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM44GC44KL44Go44CBYWJzb2x1dGXjg53jgrjjgrfjg6fjg7PjgpLkvb/jgaPjgabjgqvjg6vjg7zjgrvjg6vjgYzoh6rli5XnmoTjgavnlLvpnaLjgYTjgaPjgbHjgYTjgavluoPjgYzjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBvdmVyc2Nyb2xsYWJsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjYXJvdXNlbCB3aWxsIGJlIHNjcm9sbGFibGUgb3ZlciB0aGUgZWRnZS4gSXQgd2lsbCBib3VuY2UgYmFjayB3aGVuIHJlbGVhc2VkLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeOCv+ODg+ODgeOChOODieODqeODg+OCsOOBp+err+OBvuOBp+OCueOCr+ODreODvOODq+OBl+OBn+aZguOBq+OAgeODkOOCpuODs+ODieOBmeOCi+OCiOOBhuOBquWKueaenOOBjOW9k+OBn+OCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGNlbnRlcmVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGNhcm91c2VsIHRoZW4gdGhlIHNlbGVjdGVkIGl0ZW0gd2lsbCBiZSBpbiB0aGUgY2VudGVyIG9mIHRoZSBjYXJvdXNlbCBpbnN0ZWFkIG9mIHRoZSBiZWdpbm5pbmcuIFVzZWZ1bCBvbmx5IHdoZW4gdGhlIGl0ZW1zIGFyZSBzbWFsbGVyIHRoYW4gdGhlIGNhcm91c2VsLiBbL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIHpgbjjgpPjgafjgYTjgotvbnMtY2Fyb3VzZWwtaXRlbeOBr+OCq+ODq+ODvOOCu+ODq+OBruecn+OCk+S4reOBuOihjOOBjeOBvuOBmeOAgumgheebruOBjOOCq+ODq+ODvOOCu+ODq+OCiOOCiuOCguWwj+OBleOBhOWgtOWQiOOBq+OBruOBv+OAgeOBk+OCjOOBr+S+v+WIqeOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGl0ZW0td2lkdGhcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgIFtlbl1vbnMtY2Fyb3VzZWwtaXRlbSdzIHdpZHRoLiBPbmx5IHdvcmtzIHdoZW4gdGhlIGRpcmVjdGlvbiBpcyBzZXQgdG8gXCJob3Jpem9udGFsXCIuWy9lbl1cbiAgICogICAgW2phXW9ucy1jYXJvdXNlbC1pdGVt44Gu5bmF44KS5oyH5a6a44GX44G+44GZ44CC44GT44Gu5bGe5oCn44Gv44CBZGlyZWN0aW9u5bGe5oCn44GrXCJob3Jpem9udGFsXCLjgpLmjIflrprjgZfjgZ/mmYLjga7jgb/mnInlirnjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpdGVtLWhlaWdodFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5db25zLWNhcm91c2VsLWl0ZW0ncyBoZWlnaHQuIE9ubHkgd29ya3Mgd2hlbiB0aGUgZGlyZWN0aW9uIGlzIHNldCB0byBcInZlcnRpY2FsXCIuWy9lbl1cbiAgICogICBbamFdb25zLWNhcm91c2VsLWl0ZW3jga7pq5jjgZXjgpLmjIflrprjgZfjgb7jgZnjgILjgZPjga7lsZ7mgKfjga/jgIFkaXJlY3Rpb27lsZ7mgKfjgatcInZlcnRpY2FsXCLjgpLmjIflrprjgZfjgZ/mmYLjga7jgb/mnInlirnjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhdXRvLXNjcm9sbFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjYXJvdXNlbCB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgc2Nyb2xsZWQgdG8gdGhlIGNsb3Nlc3QgaXRlbSBib3JkZXIgd2hlbiByZWxlYXNlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIHkuIDnlarov5HjgYRjYXJvdXNlbC1pdGVt44Gu5aKD55WM44G+44Gn6Ieq5YuV55qE44Gr44K544Kv44Ot44O844Or44GZ44KL44KI44GG44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYXV0by1zY3JvbGwtcmF0aW9cbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgIFtlbl1BIG51bWJlciBiZXR3ZWVuIDAuMCBhbmQgMS4wIHRoYXQgc3BlY2lmaWVzIGhvdyBtdWNoIHRoZSB1c2VyIG11c3QgZHJhZyB0aGUgY2Fyb3VzZWwgaW4gb3JkZXIgZm9yIGl0IHRvIGF1dG8gc2Nyb2xsIHRvIHRoZSBuZXh0IGl0ZW0uWy9lbl1cbiAgICogICAgW2phXTAuMOOBi+OCiTEuMOOBvuOBp+OBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAguOCq+ODq+ODvOOCu+ODq+OBruimgee0oOOCkuOBqeOCjOOBkOOCieOBhOOBruWJsuWQiOOBvuOBp+ODieODqeODg+OCsOOBmeOCi+OBqOasoeOBruimgee0oOOBq+iHquWLleeahOOBq+OCueOCr+ODreODvOODq+OBmeOCi+OBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHN3aXBlYWJsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjYXJvdXNlbCBjYW4gYmUgc2Nyb2xsZWQgYnkgZHJhZyBvciBzd2lwZS5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIHjgqvjg6vjg7zjgrvjg6vjgpLjgrnjg6/jgqTjg5fjgoTjg4njg6njg4PjgrDjgafnp7vli5XjgafjgY3jgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjYXJvdXNlbCBpcyBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIFkcmFn44KEdG91Y2jjgoRzd2lwZeOCkuWPl+OBkeS7mOOBkeOBquOBj+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGluaXRpYWwtaW5kZXhcbiAgICogQGluaXRvbmx5XG4gICAqIEBkZWZhdWx0IDBcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGluZGV4IG9mIHRoZSBvbnMtY2Fyb3VzZWwtaXRlbSB0byBzaG93IGluaXRpYWxseS4gRGVmYXVsdCBpcyAwLlsvZW5dXG4gICAqICAgW2phXeacgOWIneOBq+ihqOekuuOBmeOCi29ucy1jYXJvdXNlbC1pdGVt44KSMOWni+OBvuOCiuOBruOCpOODs+ODh+ODg+OCr+OCueOBp+aMh+WumuOBl+OBvuOBmeOAguODh+ODleOCqeODq+ODiOWApOOBryAwIOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGF1dG8tcmVmcmVzaFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hlbiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGNhcm91c2VsIHdpbGwgYXV0b21hdGljYWxseSByZWZyZXNoIHdoZW4gdGhlIG51bWJlciBvZiBjaGlsZCBub2RlcyBjaGFuZ2UuWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM44GC44KL5pmC44CB5a2Q6KaB57Sg44Gu5pWw44GM5aSJ44KP44KL44Go44Kr44Or44O844K744Or44Gv6Ieq5YuV55qE44Gr5pu05paw44GV44KM44KL44KI44GG44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYFwibm9uZVwiYCB0aGUgdHJhbnNpdGlvbnMgd2lsbCBub3QgYmUgYW5pbWF0ZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIHRpbWluZywgZGVsYXnjgpLjgqrjg5bjgrjjgqfjgq/jg4jjg6rjg4bjg6njg6vjgafmjIflrprjgZfjgb7jgZnjgILkvovvvJp7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGNvbnN0IHRhcmdldCA9IHRoaXMuY2hpbGRyZW5bMF0gJiYgdGhpcy5jaGlsZHJlblswXS50YWdOYW1lICE9PSAnT05TLUNBUk9VU0VMLUlURU0nICYmIHRoaXMuY2hpbGRyZW5bMF0gfHwgZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgaWYgKCF0YXJnZXQucGFyZW50Tm9kZSkge1xuICAgICAgd2hpbGUgKHRoaXMuZmlyc3RDaGlsZCkge1xuICAgICAgICB0YXJnZXQuYXBwZW5kQ2hpbGQodGhpcy5maXJzdENoaWxkKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQodGFyZ2V0KTtcbiAgICB9XG5cbiAgICAhdGhpcy5jaGlsZHJlblsxXSAmJiB0aGlzLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpKTtcblxuICAgIHRoaXMuYXBwZW5kQ2hpbGQgPSB0aGlzLmFwcGVuZENoaWxkLmJpbmQodGFyZ2V0KTtcbiAgICB0aGlzLmluc2VydEJlZm9yZSA9IHRoaXMuaW5zZXJ0QmVmb3JlLmJpbmQodGFyZ2V0KTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICghdGhpcy5fc3dpcGVyKSB7XG4gICAgICB0aGlzLl9zd2lwZXIgPSBuZXcgU3dpcGVyKHtcbiAgICAgICAgZ2V0RWxlbWVudDogKCkgPT4gdGhpcyxcbiAgICAgICAgZ2V0SW5pdGlhbEluZGV4OiAoKSA9PiB0aGlzLmdldEF0dHJpYnV0ZSgnaW5pdGlhbC1pbmRleCcpLFxuICAgICAgICBnZXRBdXRvU2Nyb2xsUmF0aW86ICgpID0+IHRoaXMuYXV0b1Njcm9sbFJhdGlvLFxuICAgICAgICBpc1ZlcnRpY2FsOiAoKSA9PiB0aGlzLnZlcnRpY2FsLFxuICAgICAgICBpc092ZXJTY3JvbGxhYmxlOiAoKSA9PiB0aGlzLm92ZXJzY3JvbGxhYmxlLFxuICAgICAgICBpc0NlbnRlcmVkOiAoKSA9PiB0aGlzLmNlbnRlcmVkLFxuICAgICAgICBpc0F1dG9TY3JvbGxhYmxlOiAoKSA9PiB0aGlzLmF1dG9TY3JvbGwsXG4gICAgICAgIGl0ZW1TaXplOiB0aGlzLml0ZW1TaXplLFxuICAgICAgICBvdmVyU2Nyb2xsSG9vazogdGhpcy5fb25PdmVyU2Nyb2xsLmJpbmQodGhpcyksXG4gICAgICAgIHByZUNoYW5nZUhvb2s6IHRoaXMuX29uQ2hhbmdlLmJpbmQodGhpcywgJ3ByZWNoYW5nZScpLFxuICAgICAgICBwb3N0Q2hhbmdlSG9vazogdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzLCAncG9zdGNoYW5nZScpLFxuICAgICAgICByZWZyZXNoSG9vazogdGhpcy5fb25SZWZyZXNoLmJpbmQodGhpcyksXG4gICAgICAgIHNjcm9sbEhvb2s6ICguLi5hcmdzKSA9PiB0aGlzLl9vblN3aXBlICYmIHRoaXMuX29uU3dpcGUoLi4uYXJncylcbiAgICAgIH0pO1xuXG4gICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fc3dpcGVyLmluaXQoe1xuICAgICAgICBzd2lwZWFibGU6IHRoaXMuaGFzQXR0cmlidXRlKCdzd2lwZWFibGUnKSxcbiAgICAgICAgYXV0b1JlZnJlc2g6IHRoaXMuaGFzQXR0cmlidXRlKCdhdXRvLXJlZnJlc2gnKVxuICAgICAgfSkpO1xuICAgIH1cbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICh0aGlzLl9zd2lwZXIgJiYgdGhpcy5fc3dpcGVyLmluaXRpYWxpemVkKSB7XG4gICAgICB0aGlzLl9zd2lwZXIuZGlzcG9zZSgpO1xuICAgICAgdGhpcy5fc3dpcGVyID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydzd2lwZWFibGUnLCAnYXV0by1yZWZyZXNoJywgJ2RpcmVjdGlvbicsICdpdGVtLWhlaWdodCcsICdpdGVtLXdpZHRoJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmICghdGhpcy5fc3dpcGVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdzd2lwZWFibGUnOlxuICAgICAgICB0aGlzLl9zd2lwZXIudXBkYXRlU3dpcGVhYmxlKHRoaXMuaGFzQXR0cmlidXRlKCdzd2lwZWFibGUnKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnYXV0by1yZWZyZXNoJzpcbiAgICAgICAgdGhpcy5fc3dpcGVyLnVwZGF0ZUF1dG9SZWZyZXNoKHRoaXMuaGFzQXR0cmlidXRlKCdhdXRvLXJlZnJlc2gnKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaXRlbS1oZWlnaHQnOlxuICAgICAgICB0aGlzLnZlcnRpY2FsICYmIHRoaXMuX3N3aXBlci51cGRhdGVJdGVtU2l6ZSh0aGlzLml0ZW1TaXplKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpdGVtLXdpZHRoJzpcbiAgICAgICAgdGhpcy52ZXJ0aWNhbCB8fCB0aGlzLl9zd2lwZXIudXBkYXRlSXRlbVNpemUodGhpcy5pdGVtU2l6ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZGlyZWN0aW9uJzpcbiAgICAgICAgdGhpcy5fc3dpcGVyLnJlZnJlc2goKTtcbiAgICB9XG4gIH1cblxuICBfc2hvdygpIHtcbiAgICB0aGlzLl9zd2lwZXIuc2hvdygpO1xuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgdGhpcy5fc3dpcGVyLmhpZGUoKTtcbiAgfVxuXG4gIF9vbk92ZXJTY3JvbGwoeyBkaXJlY3Rpb24sIGtpbGxPdmVyU2Nyb2xsIH0pIHtcbiAgICBsZXQgd2FpdEZvckFjdGlvbiA9IGZhbHNlO1xuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnb3ZlcnNjcm9sbCcsIHtcbiAgICAgIGNhcm91c2VsOiB0aGlzLFxuICAgICAgYWN0aXZlSW5kZXg6IHRoaXMuZ2V0QWN0aXZlSW5kZXgoKSxcbiAgICAgIGRpcmVjdGlvbixcbiAgICAgIHdhaXRUb1JldHVybjogcHJvbWlzZSA9PiB7XG4gICAgICAgIHdhaXRGb3JBY3Rpb24gPSB0cnVlO1xuICAgICAgICBwcm9taXNlLnRoZW4oa2lsbE92ZXJTY3JvbGwpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHdhaXRGb3JBY3Rpb247XG4gIH1cblxuICBfb25DaGFuZ2UoZXZlbnROYW1lLCB7IGFjdGl2ZUluZGV4LCBsYXN0QWN0aXZlSW5kZXggfSkge1xuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCBldmVudE5hbWUsIHsgY2Fyb3VzZWw6IHRoaXMsIGFjdGl2ZUluZGV4LCBsYXN0QWN0aXZlSW5kZXggfSk7XG4gIH1cblxuICBfb25SZWZyZXNoKCkge1xuICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAncmVmcmVzaCcsIHsgY2Fyb3VzZWw6IHRoaXMgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzZXRBY3RpdmVJbmRleFxuICAgKiBAc2lnbmF0dXJlIHNldEFjdGl2ZUluZGV4KGluZGV4LCBbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpbmRleFxuICAgKiAgIFtlbl1UaGUgaW5kZXggdGhhdCB0aGUgY2Fyb3VzZWwgc2hvdWxkIGJlIHNldCB0by5bL2VuXVxuICAgKiAgIFtqYV1jYXJvdXNlbOimgee0oOOBruOCpOODs+ODh+ODg+OCr+OCueOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dQSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgY2FsbGVkIGFmdGVyIHRoZSBhbmltYXRpb24gaXMgZmluaXNoZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRvIGBcIm5vbmVcImAgdGhlIHRyYW5zaXRpb25zIHdpbGwgbm90IGJlIGFuaW1hdGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1BbiBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB0byBzcGVjaWZ5IGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nIGZ1bmN0aW9uIG9mIHRoZSBhbmltYXRpb24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGluZGV4IG9mIHRoZSBgPG9ucy1jYXJvdXNlbC1pdGVtPmAgdG8gc2hvdy5bL2VuXVxuICAgKiAgIFtqYV3ooajnpLrjgZnjgotvbnMtY2Fyb3VzZWwtaXRlbeOCkmluZGV444Gn5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGNhcm91c2VsIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNldEFjdGl2ZUluZGV4KGluZGV4LCBvcHRpb25zID0ge30pIHtcbiAgICBvcHRpb25zID0ge1xuICAgICAgYW5pbWF0aW9uOiB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uJyksXG4gICAgICBhbmltYXRpb25PcHRpb25zOiB0aGlzLmhhc0F0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKVxuICAgICAgICA/IHV0aWwuYW5pbWF0aW9uT3B0aW9uc1BhcnNlKHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKVxuICAgICAgICA6IHsgZHVyYXRpb246IC4zLCB0aW1pbmc6ICdjdWJpYy1iZXppZXIoLjQsIC43LCAuNSwgMSknIH0sXG4gICAgICAuLi5vcHRpb25zXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLl9zd2lwZXIuc2V0QWN0aXZlSW5kZXgoaW5kZXgsIG9wdGlvbnMpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIG9wdGlvbnMuY2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbiAmJiBvcHRpb25zLmNhbGxiYWNrKHRoaXMpO1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBnZXRBY3RpdmVJbmRleFxuICAgKiBAc2lnbmF0dXJlIGdldEFjdGl2ZUluZGV4KClcbiAgICogQHJldHVybiB7TnVtYmVyfVxuICAgKiAgIFtlbl1UaGUgY3VycmVudCBjYXJvdXNlbCBpdGVtIGluZGV4LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOihqOekuuOBl+OBpuOBhOOCi+OCq+ODq+ODvOOCu+ODq+imgee0oOOBruOCpOODs+ODh+ODg+OCr+OCueOBjOi/lOOBleOCjOOBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1SZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgY3VycmVudGx5IHZpc2libGUgYDxvbnMtY2Fyb3VzZWwtaXRlbT5gLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOihqOekuuOBleOCjOOBpuOBhOOCi29ucy1jYXJvdXNlbC1pdGVt6KaB57Sg44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldEFjdGl2ZUluZGV4KCkge1xuICAgIHJldHVybiB0aGlzLl9zd2lwZXIuZ2V0QWN0aXZlSW5kZXgoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIG5leHRcbiAgICogQHNpZ25hdHVyZSBuZXh0KFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1BIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhZnRlciB0aGUgYW5pbWF0aW9uIGhhcyBmaW5pc2hlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYFwibm9uZVwiYCB0aGUgdHJhbnNpdGlvbnMgd2lsbCBub3QgYmUgYW5pbWF0ZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXUFuIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIHNwZWNpZnkgdGhlIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nIGZ1bmN0aW9uIG9mIHRoZSBhbmltYXRpb24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGNhcm91c2VsIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyBuZXh0IGA8b25zLWNhcm91c2VsLWl0ZW0+YC5bL2VuXVxuICAgKiAgIFtqYV3mrKHjga5vbnMtY2Fyb3VzZWwtaXRlbeOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBuZXh0KG9wdGlvbnMpIHtcbiAgICByZXR1cm4gdGhpcy5zZXRBY3RpdmVJbmRleCh0aGlzLmdldEFjdGl2ZUluZGV4KCkgKyAxLCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHByZXZcbiAgICogQHNpZ25hdHVyZSBwcmV2KFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1BIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhZnRlciB0aGUgYW5pbWF0aW9uIGhhcyBmaW5pc2hlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdG8gYFwibm9uZVwiYCB0aGUgdHJhbnNpdGlvbnMgd2lsbCBub3QgYmUgYW5pbWF0ZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXUFuIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIHNwZWNpZnkgdGhlIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nIGZ1bmN0aW9uIG9mIHRoZSBhbmltYXRpb24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGNhcm91c2VsIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyBwcmV2aW91cyBgPG9ucy1jYXJvdXNlbC1pdGVtPmAuWy9lbl1cbiAgICogICBbamFd5YmN44Gub25zLWNhcm91c2VsLWl0ZW3jgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgcHJldihvcHRpb25zKSB7XG4gICAgcmV0dXJuIHRoaXMuc2V0QWN0aXZlSW5kZXgodGhpcy5nZXRBY3RpdmVJbmRleCgpIC0gMSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBmaXJzdFxuICAgKiBAc2lnbmF0dXJlIGZpcnN0KClcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1BIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhZnRlciB0aGUgYW5pbWF0aW9uIGhhcyBmaW5pc2hlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1JZiB0aGlzIGlzIHNldCB0byBgXCJub25lXCJgLCB0aGUgdHJhbnNpdGlvbnMgd2lsbCBub3QgYmUgYW5pbWF0ZWQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXUFuIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIHRvIHNwZWNpZnkgdGhlIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nIGZ1bmN0aW9uIG9mIHRoZSBhbmltYXRpb24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGNhcm91c2VsIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyBmaXJzdCBgPG9ucy1jYXJvdXNlbC1pdGVtPmAuWy9lbl1cbiAgICogICBbamFd5pyA5Yid44Gub25zLWNhcm91c2VsLWl0ZW3jgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZmlyc3Qob3B0aW9ucykge1xuICAgIHJldHVybiB0aGlzLnNldEFjdGl2ZUluZGV4KDAsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgbGFzdFxuICAgKiBAc2lnbmF0dXJlIGxhc3QoKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIGFmdGVyIHRoZSBhbmltYXRpb24gaGFzIGZpbmlzaGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0byBgXCJub25lXCJgIHRoZSB0cmFuc2l0aW9ucyB3aWxsIG5vdCBiZSBhbmltYXRlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dQW4gb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gc3BlY2lmeSB0aGUgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcgZnVuY3Rpb24gb2YgdGhlIGFuaW1hdGlvbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgY2Fyb3VzZWwgZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVJlc29sdmVzIHRvIHRoZSBjYXJvdXNlbCBlbGVtZW50Wy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgbGFzdCBvbnMtY2Fyb3VzZWwgaXRlbS5bL2VuXVxuICAgKiAgIFtqYV3mnIDlvozjga5vbnMtY2Fyb3VzZWwtaXRlbeOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBsYXN0KG9wdGlvbnMpIHtcbiAgICB0aGlzLnNldEFjdGl2ZUluZGV4KE1hdGgubWF4KHRoaXMuaXRlbUNvdW50IC0gMSwgMCksIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgcmVmcmVzaFxuICAgKiBAc2lnbmF0dXJlIHJlZnJlc2goKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVXBkYXRlIHRoZSBsYXlvdXQgb2YgdGhlIGNhcm91c2VsLiBVc2VkIHdoZW4gYWRkaW5nIGA8b25zLWNhcm91c2VsLWl0ZW1zPmAgZHluYW1pY2FsbHkgb3IgdG8gYXV0b21hdGljYWxseSBhZGp1c3QgdGhlIHNpemUuWy9lbl1cbiAgICogICBbamFd44Os44Kk44Ki44Km44OI44KE5YaF6YOo44Gu54q25oWL44KS5pyA5paw44Gu44KC44Gu44Gr5pu05paw44GX44G+44GZ44CCb25zLWNhcm91c2VsLWl0ZW3jgpLli5XnmoTjgavlopfjgoTjgZfjgZ/jgorjgIFvbnMtY2Fyb3VzZWzjga7lpKfjgY3jgZXjgpLli5XnmoTjgavlpInjgYjjgovpmpvjgavliKnnlKjjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgcmVmcmVzaCgpIHtcbiAgICB0aGlzLl9zd2lwZXIucmVmcmVzaCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBpdGVtQ291bnRcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgbnVtYmVyIG9mIGNhcm91c2VsIGl0ZW1zLlsvZW5dXG4gICAqICAgW2phXeOCq+ODq+ODvOOCu+ODq+imgee0oOOBruaVsOOBp+OBmeOAglsvamFdXG4gICAqL1xuICBnZXQgaXRlbUNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLl9zd2lwZXIuaXRlbUNvdW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBzd2lwZWFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl10cnVlIGlmIHRoZSBjYXJvdXNlbCBpcyBzd2lwZWFibGUuWy9lbl1cbiAgICogICBbamFdc3dpcGVhYmxl44Gn44GC44KM44GwdHJ1ZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgc3dpcGVhYmxlKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnc3dpcGVhYmxlJyk7XG4gIH1cblxuICBzZXQgc3dpcGVhYmxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdzd2lwZWFibGUnLCB2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9uU3dpcGVcbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSG9vayBjYWxsZWQgd2hlbmV2ZXIgdGhlIHVzZXIgc2xpZGVzIHRoZSBjYXJvdXNlbC4gSXQgZ2V0cyBhIGRlY2ltYWwgaW5kZXggYW5kIGFuIGFuaW1hdGlvbk9wdGlvbnMgb2JqZWN0IGFzIGFyZ3VtZW50cy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0IG9uU3dpcGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuX29uU3dpcGU7XG4gIH1cblxuICBzZXQgb25Td2lwZSh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgRnVuY3Rpb24pKSB7XG4gICAgICB1dGlsLnRocm93KGBcIm9uU3dpcGVcIiBtdXN0IGJlIGEgZnVuY3Rpb25gKVxuICAgIH1cbiAgICB0aGlzLl9vblN3aXBlID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGF1dG9TY3JvbGxcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl10cnVlIGlmIGF1dG8gc2Nyb2xsIGlzIGVuYWJsZWQuWy9lbl1cbiAgICogICBbamFd44Kq44O844OI44K544Kv44Ot44O844Or44GM5pyJ5Yq544Gn44GC44KM44GwdHJ1ZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgYXV0b1Njcm9sbCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2F1dG8tc2Nyb2xsJyk7XG4gIH1cblxuICBzZXQgYXV0b1Njcm9sbCh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnYXV0by1zY3JvbGwnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgdmVydGljYWwoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QXR0cmlidXRlKCdkaXJlY3Rpb24nKSA9PT0gJ3ZlcnRpY2FsJztcbiAgfVxuXG4gIGdldCBpdGVtU2l6ZSgpIHtcbiAgICBjb25zdCBpdGVtU2l6ZUF0dHIgPSAodGhpcy5nZXRBdHRyaWJ1dGUoYGl0ZW0tJHt0aGlzLnZlcnRpY2FsID8gJ2hlaWdodCcgOiAnd2lkdGgnfWApIHx8ICcnKS50cmltKCk7XG4gICAgcmV0dXJuIGl0ZW1TaXplQXR0ci5tYXRjaCgvXlxcZCsocHh8JSkkLykgPyBpdGVtU2l6ZUF0dHIgOiAnMTAwJSc7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGF1dG9TY3JvbGxSYXRpb1xuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGN1cnJlbnQgYXV0byBzY3JvbGwgcmF0aW8uIFsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBruOCquODvOODiOOCueOCr+ODreODvOODq+OBrnJhdGlv5YCk44CCWy9qYV1cbiAgICovXG4gIGdldCBhdXRvU2Nyb2xsUmF0aW8oKSB7XG4gICAgcmV0dXJuIHBhcnNlRmxvYXQodGhpcy5nZXRBdHRyaWJ1dGUoJ2F1dG8tc2Nyb2xsLXJhdGlvJykpO1xuICB9XG5cbiAgc2V0IGF1dG9TY3JvbGxSYXRpbyhyYXRpbykge1xuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdhdXRvLXNjcm9sbC1yYXRpbycsIHJhdGlvKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBjYXJvdXNlbCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gIH1cblxuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvdmVyc2Nyb2xsYWJsZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGNhcm91c2VsIGlzIG92ZXJzY3JvbGxhYmxlIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV1vdmVyc2Nyb2xs44Gn44GN44KM44GwdHJ1ZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgb3ZlcnNjcm9sbGFibGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdvdmVyc2Nyb2xsYWJsZScpO1xuICB9XG5cbiAgc2V0IG92ZXJzY3JvbGxhYmxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdvdmVyc2Nyb2xsYWJsZScsIHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2VudGVyZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBjYXJvdXNlbCBpcyBjZW50ZXJlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFdY2VudGVyZWTnirbmhYvjgavjgarjgaPjgabjgYTjgozjgbB0cnVl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldCBjZW50ZXJlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2NlbnRlcmVkJyk7XG4gIH1cblxuICBzZXQgY2VudGVyZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2NlbnRlcmVkJywgdmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBldmVudHMoKSB7XG4gICAgcmV0dXJuIFsncG9zdGNoYW5nZScsICdyZWZyZXNoJywgJ292ZXJzY3JvbGwnXTtcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5DYXJvdXNlbCA9IENhcm91c2VsRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWNhcm91c2VsJywgQ2Fyb3VzZWxFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHN0eWxlciBmcm9tICcuLi9vbnMvc3R5bGVyJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtY29sXG4gKiBAY2F0ZWdvcnkgZ3JpZFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1SZXByZXNlbnRzIGEgY29sdW1uIGluIHRoZSBncmlkIHN5c3RlbS4gVXNlIHdpdGggYDxvbnMtcm93PmAgdG8gbGF5b3V0IGNvbXBvbmVudHMuWy9lbl1cbiAqICAgW2phXeOCsOODquODg+ODieOCt+OCueODhuODoOOBq+OBpuWIl+OCkuWumue+qeOBl+OBvuOBmeOAgm9ucy1yb3fjgajjgajjgoLjgavkvb/nlKjjgZfjgIHjgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jg6zjgqTjgqLjgqbjg4jjgavliKnnlKjjgZfjgb7jgZnjgIJbL2phXVxuICogQG5vdGVcbiAqICAgW2VuXUZvciBBbmRyb2lkIDQuMyBhbmQgZWFybGllciwgYW5kIGlPUzYgYW5kIGVhcmxpZXIsIHdoZW4gdXNpbmcgbWl4ZWQgYWxpZ25tZW50IHdpdGggb25zLXJvdyBhbmQgb25zLWNvbHVtbiwgdGhleSBtYXkgbm90IGJlIGRpc3BsYXllZCBjb3JyZWN0bHkuIFlvdSBjYW4gdXNlIG9ubHkgb25lIGFsaWdubWVudC5bL2VuXVxuICogICBbamFdQW5kcm9pZCA0LjPku6XliY3jgIHjgoLjgZfjgY/jga9pT1MgNuS7peWJjeOBrk9T44Gu5aC05ZCI44CBb25zLXJvd+OBqG9ucy1jb2x1bW7jgpLntYTjgb/lkIjjgo/jgZvjgZ/loLTlkIjjgavmj4/nlLvjgYzltKnjgozjgovloLTlkIjjgYzjgYLjgorjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gR2d1akMge3dpZGV9XG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sIFtlbl1MYXlvdXRpbmcgZ3VpZGVbL2VuXVtqYV3jg6zjgqTjgqLjgqbjg4jmqZ/og71bL2phXVxuICogQHNlZWFsc28gb25zLXJvd1xuICogICBbZW5dVGhlIGA8b25zLXJvdz5gIGNvbXBvbmVudCBpcyB0aGUgcGFyZW50IG9mIGA8b25zLWNvbD5gLlsvZW5dXG4gKiAgIFtqYV1vbnMtcm9344Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXJvdz5cbiAqICAgPG9ucy1jb2wgd2lkdGg9XCI1MHB4XCI+PG9ucy1pY29uIGljb249XCJmYS10d2l0dGVyXCI+PC9vbnMtaWNvbj48L29ucy1jb2w+XG4gKiAgIDxvbnMtY29sPlRleHQ8L29ucy1jb2w+XG4gKiA8L29ucy1yb3c+XG4gKi9cblxuLyoqXG4gKiBAYXR0cmlidXRlIHZlcnRpY2FsLWFsaWduXG4gKiBAdHlwZSB7U3RyaW5nfVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1WZXJ0aWNhbCBhbGlnbm1lbnQgb2YgdGhlIGNvbHVtbi4gVmFsaWQgdmFsdWVzIGFyZSBcInRvcFwiLCBcImNlbnRlclwiLCBhbmQgXCJib3R0b21cIi5bL2VuXVxuICogICBbamFd57im44Gu6YWN572u44KS5oyH5a6a44GZ44KL44CCXCJ0b3BcIiwgXCJjZW50ZXJcIiwgXCJib3R0b21cIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gKi9cblxuLyoqXG4gKiBAYXR0cmlidXRlIHdpZHRoXG4gKiBAdHlwZSB7U3RyaW5nfVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1UaGUgd2lkdGggb2YgdGhlIGNvbHVtbi4gVmFsaWQgdmFsdWVzIGFyZSBjc3Mgd2lkdGggdmFsdWVzIChcIjEwJVwiLCBcIjUwcHhcIikuWy9lbl1cbiAqICAgW2phXeOCq+ODqeODoOOBruaoquW5heOCkuaMh+WumuOBmeOCi+OAguODkeODvOOCu+ODs+ODiOOCguOBl+OBj+OBr+ODlOOCr+OCu+ODq+OBp+aMh+WumuOBl+OBvuOBme+8iDEwJeOChDUwcHjvvInjgIJbL2phXVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDb2xFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodGhpcy5nZXRBdHRyaWJ1dGUoJ3dpZHRoJykpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVdpZHRoKCk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnd2lkdGgnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICd3aWR0aCcpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVdpZHRoKCk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZVdpZHRoKCkge1xuICAgIGxldCB3aWR0aCA9IHRoaXMuZ2V0QXR0cmlidXRlKCd3aWR0aCcpO1xuICAgIGlmICghd2lkdGgpIHtcbiAgICAgIHN0eWxlci5jbGVhcih0aGlzLCAnZmxleCBtYXhXaWR0aCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aWR0aCA9IHdpZHRoLnRyaW0oKS5tYXRjaCgvXlxcZCskLykgPyB3aWR0aCArICclJyA6IHdpZHRoO1xuXG4gICAgICBzdHlsZXIodGhpcywge1xuICAgICAgICBmbGV4OiAnMCAwICcgKyB3aWR0aCxcbiAgICAgICAgbWF4V2lkdGg6IHdpZHRoXG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cblxub25zRWxlbWVudHMuQ29sID0gQ29sRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWNvbCcsIENvbEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcbmltcG9ydCBCYXNlQW5pbWF0b3IgZnJvbSAnLi4vLi4vb25zL2Jhc2UtYW5pbWF0b3InXG5cbmV4cG9ydCBjbGFzcyBEaWFsb2dBbmltYXRvciBleHRlbmRzIEJhc2VBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdsaW5lYXInLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4yfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBzaG93KGRpYWxvZywgZG9uZSkge1xuICAgIGRvbmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgaGlkZShkaWFsb2csIGRvbmUpIHtcbiAgICBkb25lKCk7XG4gIH1cbn1cblxuLyoqXG4gKiBBbmRyb2lkIHN0eWxlIGFuaW1hdG9yIGZvciBkaWFsb2cuXG4gKi9cbmV4cG9ydCBjbGFzcyBBbmRyb2lkRGlhbG9nQW5pbWF0b3IgZXh0ZW5kcyBEaWFsb2dBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdlYXNlLWluLW91dCcsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjN9ID0ge30pIHtcbiAgICBzdXBlcih7dGltaW5nLCBkZWxheSwgZHVyYXRpb259KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KGRpYWxvZywgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMCB9LCB7IG9wYWNpdHk6IDEgfSksXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX2RpYWxvZywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTYwJSwgMCknLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKScsIG9wYWNpdHk6IDEgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogMCB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKScsIG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC01MCUsIC02MCUsIDApJywgb3BhY2l0eTogMCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBpT1Mgc3R5bGUgYW5pbWF0b3IgZm9yIGRpYWxvZy5cbiAqL1xuZXhwb3J0IGNsYXNzIElPU0RpYWxvZ0FuaW1hdG9yIGV4dGVuZHMgRGlhbG9nQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnZWFzZS1pbi1vdXQnLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4yfSA9IHt9KSB7XG4gICAgc3VwZXIoe3RpbWluZywgZGVsYXksIGR1cmF0aW9ufSk7XG5cbiAgICB0aGlzLmJvZHlIZWlnaHQgPSBkb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodDsgLy8gYXZvaWQgRm9yY2VkIFN5bmNocm9ub3VzIExheW91dFxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHNob3coZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAwIH0sIHsgb3BhY2l0eTogMSB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgtNTAlLCAke3RoaXMuYm9keUhlaWdodCAvIDIuMCAtIDF9cHgsIDApYCB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTUwJSwgMCknIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGlhbG9nXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBoaWRlKGRpYWxvZywgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fbWFzaywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMSB9LCB7IG9wYWNpdHk6IDAgfSksXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX2RpYWxvZywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoLTUwJSwgLTUwJSwgMCknIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgtNTAlLCAke3RoaXMuYm9keUhlaWdodCAvIDIuMCAtIDF9cHgsIDApYCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBTbGlkZSBhbmltYXRvciBmb3IgZGlhbG9nLlxuICovXG5leHBvcnQgY2xhc3MgU2xpZGVEaWFsb2dBbmltYXRvciBleHRlbmRzIERpYWxvZ0FuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2N1YmljLWJlemllciguMSwgLjcsIC40LCAxKScsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjJ9ID0ge30pIHtcbiAgICBzdXBlcih7dGltaW5nLCBkZWxheSwgZHVyYXRpb259KTtcblxuICAgIHRoaXMuYm9keUhlaWdodCA9IGRvY3VtZW50LmJvZHkuY2xpZW50SGVpZ2h0OyAvLyBhdm9pZCBGb3JjZWQgU3luY2hyb25vdXMgTGF5b3V0XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGRpYWxvZ1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhkaWFsb2csIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdChkaWFsb2cuX21hc2ssIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdCh7IG9wYWNpdHk6IDAgfSwgeyBvcGFjaXR5OiAxIH0pLFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9kaWFsb2csIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAvLyBGSVhNRTogVGhpcyBzaG91bGQgYXZvaWQgRm9yY2VkIFN5bmNocm9ub3VzIExheW91dC4gT3RoZXJ3aXNlLCBmYWRlIGFuaW1hdGlvbiBvZiBtYXNrIHdpbGwgYmUgYnJva2VuLlxuICAgICAgICAgIHsgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoLTUwJSwgJHstICh0aGlzLmJvZHlIZWlnaHQgLyAyLjApICsgMSAtIGRpYWxvZy5fZGlhbG9nLmNsaWVudEhlaWdodH1weCwgMClgIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKScgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkaWFsb2dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUoZGlhbG9nLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZGlhbG9nLl9tYXNrLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogMCB9KSxcblxuICAgICAgYW5pbWl0KGRpYWxvZy5fZGlhbG9nLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNTAlLCAtNTAlLCAwKScgfSxcbiAgICAgICAgICAvLyBGSVhNRTogVGhpcyBzaG91bGQgYXZvaWQgRm9yY2VkIFN5bmNocm9ub3VzIExheW91dC4gT3RoZXJ3aXNlLCBmYWRlIGFuaW1hdGlvbiBvZiBtYXNrIHdpbGwgYmUgYnJva2VuLlxuICAgICAgICAgIHsgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoLTUwJSwgJHstICh0aGlzLmJvZHlIZWlnaHQgLyAyLjApICsgMSAtIGRpYWxvZy5fZGlhbG9nLmNsaWVudEhlaWdodH1weCwgMClgIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uLy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uLy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCB7IERpYWxvZ0FuaW1hdG9yLCBJT1NEaWFsb2dBbmltYXRvciwgQW5kcm9pZERpYWxvZ0FuaW1hdG9yLCBTbGlkZURpYWxvZ0FuaW1hdG9yIH0gZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRGlhbG9nRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZGlhbG9nJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcuZGlhbG9nJzogJ2RpYWxvZy0tKicsXG4gICcuZGlhbG9nLWNvbnRhaW5lcic6ICdkaWFsb2ctY29udGFpbmVyLS0qJyxcbiAgJy5kaWFsb2ctbWFzayc6ICdkaWFsb2ctbWFzay0tKidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdkZWZhdWx0JzogKCkgPT4gcGxhdGZvcm0uaXNBbmRyb2lkKCkgPyBBbmRyb2lkRGlhbG9nQW5pbWF0b3IgOiBJT1NEaWFsb2dBbmltYXRvcixcbiAgJ3NsaWRlJzogU2xpZGVEaWFsb2dBbmltYXRvcixcbiAgJ25vbmUnOiBEaWFsb2dBbmltYXRvclxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtZGlhbG9nXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIERpYWxvZyB0aGF0IGlzIGRpc3BsYXllZCBvbiB0b3Agb2YgY3VycmVudCBzY3JlZW4uIEFzIG9wcG9zZWQgdG8gdGhlIGA8b25zLWFsZXJ0LWRpYWxvZz5gIGVsZW1lbnQsIHRoaXMgY29tcG9uZW50IGNhbiBjb250YWluIGFueSBraW5kIG9mIGNvbnRlbnQuXG4gKlxuICogICAgIFRvIHVzZSB0aGUgZWxlbWVudCBpdCBjYW4gZWl0aGVyIGJlIGF0dGFjaGVkIGRpcmVjdGx5IHRvIHRoZSBgPGJvZHk+YCBlbGVtZW50IG9yIGR5bmFtaWNhbGx5IGNyZWF0ZWQgZnJvbSBhIHRlbXBsYXRlIHVzaW5nIHRoZSBgb25zLmNyZWF0ZURpYWxvZyh0ZW1wbGF0ZSlgIHV0aWxpdHkgZnVuY3Rpb24gYW5kIHRoZSBgPHRlbXBsYXRlPmAgdGFnLlxuICpcbiAqICAgICBUaGUgZGlhbG9nIGlzIHVzZWZ1bCBmb3IgZGlzcGxheWluZyBtZW51cywgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiBvciB0byBhc2sgdGhlIHVzZXIgdG8gbWFrZSBhIGRlY2lzaW9uLlxuICpcbiAqICAgICBJdCB3aWxsIGF1dG9tYXRpY2FsbHkgYmUgZGlzcGxheWVkIGFzIE1hdGVyaWFsIERlc2lnbiB3aGVuIHJ1bm5pbmcgb24gYW4gQW5kcm9pZCBkZXZpY2UuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1EaXNwbGF5IGEgTWF0ZXJpYWwgRGVzaWduIGRpYWxvZy5bL2VuXVxuICogICBbamFd44Oe44OG44Oq44Ki44Or44OH44K244Kk44Oz44Gu44OA44Kk44Ki44Ot44Kw44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIHp4eGFHYVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2RpYWxvZ1xuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNtb2RpZmllcnMgW2VuXU1vcmUgZGV0YWlscyBhYm91dCB0aGUgYG1vZGlmaWVyYCBhdHRyaWJ1dGVbL2VuXVtqYV1tb2RpZmllcuWxnuaAp+OBruS9v+OBhOaWuVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtYWxlcnQtZGlhbG9nXG4gKiAgIFtlbl1gPG9ucy1hbGVydC1kaWFsb2c+YCBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWFsZXJ0LWRpYWxvZ+OCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcG9wb3ZlclxuICogICBbZW5dYDxvbnMtcG9wb3Zlcj5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtcG9wb3ZlcuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtbW9kYWxcbiAqICAgW2VuXWA8b25zLW1vZGFsPmAgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1tb2RhbOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1kaWFsb2cgaWQ9XCJkaWFsb2dcIj5cbiAqICAgPHA+VGhpcyBpcyBhIGRpYWxvZyE8L3A+XG4gKiA8L29ucy1kaWFsb2c+XG4gKlxuICogPHNjcmlwdD5cbiAqICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RpYWxvZycpLnNob3coKTtcbiAqIDwvc2NyaXB0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBEaWFsb2dFbGVtZW50IGV4dGVuZHMgQmFzZURpYWxvZ0VsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlc2hvd1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBkaWFsb2cgaXMgZGlzcGxheWVkLlsvZW5dXG4gICAqIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzooajnpLrjgZXjgozjgovnm7TliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuZGlhbG9nXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdGhpcyBmdW5jdGlvbiB0byBzdG9wIHRoZSBkaWFsb2cgZnJvbSBiZWluZyBzaG93bi5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7plqLmlbDjgpLlrp/ooYzjgZnjgovjgajjgIHjg4DjgqTjgqLjg63jgrDjga7ooajnpLrjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBbZW5dRmlyZWQganVzdCBhZnRlciB0aGUgZGlhbG9nIGlzIGRpc3BsYXllZC5bL2VuXVxuICAgKiBbamFd44OA44Kk44Ki44Ot44Kw44GM6KGo56S644GV44KM44Gf55u05b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmRpYWxvZ1xuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlaGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBkaWFsb2cgaXMgaGlkZGVuLlsvZW5dXG4gICAqIFtqYV3jg4DjgqTjgqLjg63jgrDjgYzpmqDjgozjgovnm7TliY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuZGlhbG9nXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdGhpcyBmdW5jdGlvbiB0byBzdG9wIHRoZSBkaWFsb2cgZnJvbSBiZWluZyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44GT44Gu6Zai5pWw44KS5a6f6KGM44GZ44KL44Go44CB44OA44Kk44Ki44Ot44Kw44Gu6Z2e6KGo56S644GM44Kt44Oj44Oz44K744Or44GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0aGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIGRpYWxvZyBpcyBoaWRkZW4uWy9lbl1cbiAgICogW2phXeODgOOCpOOCouODreOCsOOBjOmaoOOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5kaWFsb2dcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgZGlhbG9nLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY2FuY2VsYWJsZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIGRpYWxvZyBjYW4gYmUgY2xvc2VkIGJ5IHRhcHBpbmcgdGhlIGJhY2tncm91bmQgb3IgYnkgcHJlc3NpbmcgdGhlIGJhY2sgYnV0dG9uIG9uIEFuZHJvaWQgZGV2aWNlcy5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0aGUgZGlhbG9nIGlzIGRpc2FibGVkLlsvZW5dXG4gICAqICBbamFd44GT44Gu5bGe5oCn44GM44GC44KL5pmC44CB44OA44Kk44Ki44Ot44Kw44GvZGlzYWJsZWTnirbmhYvjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgZGVmYXVsdFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYW5pbWF0aW9uIHVzZWQgd2hlbiBzaG93aW5nIGFuZCBoaWRpbmcgdGhlIGRpYWxvZy4gQ2FuIGJlIGVpdGhlciBgXCJub25lXCJgIG9yIGBcImRlZmF1bHRcImAuWy9lbl1cbiAgICogIFtqYV3jg4DjgqTjgqLjg63jgrDjgpLooajnpLrjgZnjgovpmpvjga7jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIuOCguOBl+OBj+OBr1wiZGVmYXVsdFwi44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCB0aW1pbmcsIGRlbGF544KS44Kq44OW44K444Kn44Kv44OI44Oq44OG44Op44Or44Gn5oyH5a6a44GX44G+44GZ44CCZS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAxLCB0aW1pbmc6ICdlYXNlLWluJ31gWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbWFzay1jb2xvclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCByZ2JhKDAsIDAsIDAsIDAuMilcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dQ29sb3Igb2YgdGhlIGJhY2tncm91bmQgbWFzay4gRGVmYXVsdCBpcyBgXCJyZ2JhKDAsIDAsIDAsIDAuMilcImAuWy9lbl1cbiAgICogIFtqYV3og4zmma/jga7jg57jgrnjgq/jga7oibLjgpLmjIflrprjgZfjgb7jgZnjgIJcInJnYmEoMCwgMCwgMCwgMC4yKVwi44GM44OH44OV44Kp44Or44OI5YCk44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuICB9XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHNjaGVtZTtcbiAgfVxuXG4gIGdldCBfbWFzaygpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5kaWFsb2ctbWFzaycpO1xuICB9XG5cbiAgZ2V0IF9kaWFsb2coKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcuZGlhbG9nJyk7XG4gIH1cblxuICBfdXBkYXRlQW5pbWF0b3JGYWN0b3J5KCkge1xuICAgIHJldHVybiBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogRGlhbG9nQW5pbWF0b3IsXG4gICAgICBiYXNlQ2xhc3NOYW1lOiAnRGlhbG9nQW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpXG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICB0aGlzLnN0eWxlLnpJbmRleCA9IDEwMDAxO1xuXG4gICAgLyogRXhwZWN0ZWQgcmVzdWx0OlxuICAgICAqICAgPG9ucy1kaWFsb2c+XG4gICAgICogICAgIDxkaXYgY2xhc3M9XCJkaWFsb2ctbWFza1wiPjwvZGl2PlxuICAgICAqICAgICA8ZGl2IGNsYXNzPVwiZGlhbG9nXCI+XG4gICAgICogICAgICAgPGRpdiBjbGFzcz1cImRpYWxvZy1jb250YWluZXJcIj4uLi48L2Rpdj5cbiAgICAgKiAgICAgPC9kaXY+XG4gICAgICogICA8L29ucy1kaWFsb2c+XG4gICAgICovXG5cbiAgICBpZiAoIXRoaXMuX2RpYWxvZykge1xuICAgICAgY29uc3QgZGlhbG9nID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICBkaWFsb2cuY2xhc3NMaXN0LmFkZCgnZGlhbG9nJyk7XG5cbiAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoJ2RpYWxvZy1jb250YWluZXInKTtcbiAgICAgIHdoaWxlICh0aGlzLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuZmlyc3RDaGlsZCk7XG4gICAgICB9XG4gICAgICBkaWFsb2cuYXBwZW5kQ2hpbGQoY29udGFpbmVyKTtcblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZChkaWFsb2cpO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fbWFzaykge1xuICAgICAgY29uc3QgbWFzayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgbWFzay5jbGFzc0xpc3QuYWRkKCdkaWFsb2ctbWFzaycpO1xuICAgICAgdGhpcy5pbnNlcnRCZWZvcmUobWFzaywgdGhpcy5maXJzdENoaWxkKTtcbiAgICB9XG5cbiAgICB0aGlzLl9kaWFsb2cuc3R5bGUuekluZGV4ID0gMjAwMDE7XG4gICAgdGhpcy5fbWFzay5zdHlsZS56SW5kZXggPSAyMDAwMDtcblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdzdGF0dXMtYmFyLWZpbGwnLCAnJyk7XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHRoaXMuX3NjaGVtZSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9uRGV2aWNlQmFja0J1dHRvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQmFjay1idXR0b24gaGFuZGxlci5bL2VuXVxuICAgKiAgIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjg4/jg7Pjg4njg6njgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCBzaG93XG4gICAqIEBzaWduYXR1cmUgc2hvdyhbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcIm5vbmVcImAgYW5kIGBcInNsaWRlXCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwiLCBcInNsaWRlXCLjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAgWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGFmdGVyIHRoZSBkaWFsb2cgaGFzIGJlZW4gcmV2ZWFsZWQuWy9lbl1cbiAgICogICBbamFd44OA44Kk44Ki44Ot44Kw44GM6KGo56S644GV44KM57WC44KP44Gj44Gf5b6M44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU2hvdyB0aGUgZGlhbG9nLlsvZW5dXG4gICAqICBbamFd44OA44Kk44Ki44Ot44Kw44KS6ZaL44GN44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX0gUmVzb2x2ZXMgdG8gdGhlIGRpc3BsYXllZCBlbGVtZW50LlxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZShbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcIm5vbmVcImAgYW5kIGBcInNsaWRlXCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwiLCBcInNsaWRlXCLjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWBbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dVGhpcyBmdW5jdGlvbnMgaXMgY2FsbGVkIGFmdGVyIHRoZSBkaWFsb2cgaGFzIGJlZW4gaGlkZGVuLlsvZW5dXG4gICAqICAgW2phXeODgOOCpOOCouODreOCsOOBjOmaoOOCjOOBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1IaWRlIHRoZSBkaWFsb2cuWy9lbl1cbiAgICogICBbamFd44OA44Kk44Ki44Ot44Kw44KS6ZaJ44GY44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGhpZGRlbiBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2aXNpYmxlXG4gICAqIEByZWFkb25seVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGRpYWxvZyBpcyB2aXNpYmxlIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3opoHntKDjgYzopovjgYjjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZGlhbG9nIGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGNhbmNlbGFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBkaWFsb2cgaXMgY2FuY2VsYWJsZSBvciBub3QuIEEgY2FuY2VsYWJsZSBkaWFsb2cgY2FuIGJlIGNsb3NlZCBieSB0YXBwaW5nIHRoZSBiYWNrZ3JvdW5kIG9yIGJ5IHByZXNzaW5nIHRoZSBiYWNrIGJ1dHRvbiBvbiBBbmRyb2lkIGRldmljZXMuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7RGlhbG9nQW5pbWF0b3J9IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIERpYWxvZ0FuaW1hdG9yKSkge1xuICAgICAgdXRpbC50aHJvd0FuaW1hdG9yKCdEaWFsb2cnKTtcbiAgICB9XG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG5cbiAgc3RhdGljIGdldCBhbmltYXRvcnMoKSB7XG4gICAgcmV0dXJuIF9hbmltYXRvckRpY3Q7XG4gIH1cblxuICBzdGF0aWMgZ2V0IERpYWxvZ0FuaW1hdG9yKCkge1xuICAgIHJldHVybiBEaWFsb2dBbmltYXRvcjtcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5EaWFsb2cgPSBEaWFsb2dFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtZGlhbG9nJywgRGlhbG9nRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgc3R5bGVyIGZyb20gJy4uL29ucy9zdHlsZXInO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IGRlZmF1bHRDbGFzc05hbWUgPSAnZmFiJztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ2ZhYi0tKicsXG4gICcuZmFiX19pY29uJzogJ2ZhYi0tKl9faWNvbidcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWZhYlxuICogQGNhdGVnb3J5IGZvcm1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgVGhlIEZsb2F0aW5nIGFjdGlvbiBidXR0b24gaXMgYSBjaXJjdWxhciBidXR0b24gZGVmaW5lZCBpbiB0aGUgW01hdGVyaWFsIERlc2lnbiBzcGVjaWZpY2F0aW9uXShodHRwczovL3d3dy5nb29nbGUuY29tL2Rlc2lnbi9zcGVjL2NvbXBvbmVudHMvYnV0dG9ucy1mbG9hdGluZy1hY3Rpb24tYnV0dG9uLmh0bWwpLiBUaGV5IGFyZSBvZnRlbiB1c2VkIHRvIHByb21vdGUgdGhlIHByaW1hcnkgYWN0aW9uIG9mIHRoZSBhcHAuXG4gKlxuICogICAgIEl0IGNhbiBiZSBkaXNwbGF5ZWQgZWl0aGVyIGFzIGFuIGlubGluZSBlbGVtZW50IG9yIGluIG9uZSBvZiB0aGUgY29ybmVycy4gTm9ybWFsbHkgaXQgd2lsbCBiZSBwb3NpdGlvbmVkIGluIHRoZSBsb3dlciByaWdodCBjb3JuZXIgb2YgdGhlIHNjcmVlbi5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvZmFiXG4gKiBAbW9kaWZpZXIgbWluaVxuICogICBbZW5dTWFrZXMgdGhlIGBvbnMtZmFiYCBzbWFsbGVyLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNjcm9zcy1wbGF0Zm9ybS1zdHlsaW5nLWF1dG9zdHlsaW5nIFtlbl1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9lbl1bamFdSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svamFdXG4gKiBAc2VlYWxzbyBvbnMtc3BlZWQtZGlhbFxuICogICBbZW5dVGhlIGA8b25zLXNwZWVkLWRpYWw+YCBjb21wb25lbnQgaXMgYSBGbG9hdGluZyBhY3Rpb24gYnV0dG9uIHRoYXQgZGlzcGxheXMgYSBtZW51IHdoZW4gdGFwcGVkLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBGYWJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBidXR0b24uWy9lbl1cbiAgICogIFtqYV3jg5zjgr/jg7Pjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSByaXBwbGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgZGVmaW5lZCwgdGhlIGJ1dHRvbiB3aWxsIGhhdmUgYSByaXBwbGUgZWZmZWN0IHdoZW4gdGFwcGVkLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgcG9zaXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIHBvc2l0aW9uIG9mIHRoZSBidXR0b24uIFNob3VsZCBiZSBhIHN0cmluZyBsaWtlIGBcImJvdHRvbSByaWdodFwiYCBvciBgXCJ0b3AgbGVmdFwiYC4gSWYgdGhpcyBhdHRyaWJ1dGUgaXMgbm90IGRlZmluZWQgaXQgd2lsbCBiZSBkaXNwbGF5ZWQgYXMgYW4gaW5saW5lIGVsZW1lbnQuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSBpZiBidXR0b24gc2hvdWxkIGJlIGRpc2FibGVkLlsvZW5dXG4gICAqICAgW2phXeODnOOCv+ODs+OCkueEoeWKueWMluOBmeOCi+WgtOWQiOOBr+aMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICAvLyBUaGUgZm9sbG93aW5nIHN0YXRlbWVudHMgY2FuIGJlIGV4ZWN1dGVkIGJlZm9yZSBjb250ZW50UmVhZHlcbiAgICAvLyBzaW5jZSB0aGVzZSBkbyBub3QgYWNjZXNzIHRoZSBjaGlsZHJlblxuICAgIHRoaXMuX2hpZGUoKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHRoaXMsICcuZmFiX19pY29uJykpIHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgICBjb250ZW50LmNsYXNzTGlzdC5hZGQoJ2ZhYl9faWNvbicpO1xuXG4gICAgICB1dGlsLmFycmF5RnJvbSh0aGlzLmNoaWxkTm9kZXMpLmZvckVhY2goZWxlbWVudCA9PiB7XG4gICAgICAgIGlmICghZWxlbWVudC50YWdOYW1lIHx8IGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpICE9PSAnb25zLXJpcHBsZScpIHtcbiAgICAgICAgICBjb250ZW50LmFwcGVuZENoaWxkKGVsZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQoY29udGVudCk7XG4gICAgfVxuXG4gICAgdGhpcy5fdXBkYXRlUmlwcGxlKCk7XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG5cbiAgICB0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgc2V0SW1tZWRpYXRlKCgpID0+IHRoaXMuX3Nob3coKSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdyaXBwbGUnLCAncG9zaXRpb24nLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdyaXBwbGUnOlxuICAgICAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdwb3NpdGlvbic6XG4gICAgICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIF9zaG93KCkge1xuICAgIGlmICghdGhpcy5fbWFudWFsbHlIaWRkZW4pIHsgLy8gaWYgdXNlciBoYXMgbm90IGNhbGxlZCBvbnMtZmFiLmhpZGUoKVxuICAgICAgdGhpcy5fdG9nZ2xlKHRydWUpO1xuICAgIH1cbiAgfVxuXG4gIF9oaWRlKCkge1xuICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLl90b2dnbGUoZmFsc2UpKTtcbiAgfVxuXG4gIF91cGRhdGVSaXBwbGUoKSB7XG4gICAgdXRpbC51cGRhdGVSaXBwbGUodGhpcyk7XG4gIH1cblxuICBfdXBkYXRlUG9zaXRpb24oKSB7XG4gICAgY29uc3QgcG9zaXRpb24gPSB0aGlzLmdldEF0dHJpYnV0ZSgncG9zaXRpb24nKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5yZW1vdmUoXG4gICAgICAnZmFiLS10b3BfX2xlZnQnLFxuICAgICAgJ2ZhYi0tYm90dG9tX19yaWdodCcsXG4gICAgICAnZmFiLS1ib3R0b21fX2xlZnQnLFxuICAgICAgJ2ZhYi0tdG9wX19yaWdodCcsXG4gICAgICAnZmFiLS10b3BfX2NlbnRlcicsXG4gICAgICAnZmFiLS1ib3R0b21fX2NlbnRlcicpO1xuICAgIHN3aXRjaCAocG9zaXRpb24pIHtcbiAgICAgIGNhc2UgJ3RvcCByaWdodCc6XG4gICAgICBjYXNlICdyaWdodCB0b3AnOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tdG9wX19yaWdodCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3RvcCBsZWZ0JzpcbiAgICAgIGNhc2UgJ2xlZnQgdG9wJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLXRvcF9fbGVmdCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbSByaWdodCc6XG4gICAgICBjYXNlICdyaWdodCBib3R0b20nOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tYm90dG9tX19yaWdodCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2JvdHRvbSBsZWZ0JzpcbiAgICAgIGNhc2UgJ2xlZnQgYm90dG9tJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLWJvdHRvbV9fbGVmdCcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2NlbnRlciB0b3AnOlxuICAgICAgY2FzZSAndG9wIGNlbnRlcic6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS10b3BfX2NlbnRlcicpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2NlbnRlciBib3R0b20nOlxuICAgICAgY2FzZSAnYm90dG9tIGNlbnRlcic6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS1ib3R0b21fX2NlbnRlcicpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU2hvdyB0aGUgZmxvYXRpbmcgYWN0aW9uIGJ1dHRvbi5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuICBzaG93KCkge1xuICAgIHRoaXMudG9nZ2xlKHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZVxuICAgKiBAc2lnbmF0dXJlIGhpZGUoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1IaWRlIHRoZSBmbG9hdGluZyBhY3Rpb24gYnV0dG9uLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG4gIGhpZGUoKSB7XG4gICAgdGhpcy50b2dnbGUoZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgdG9nZ2xlXG4gICAqIEBzaWduYXR1cmUgdG9nZ2xlKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRvZ2dsZSB0aGUgdmlzaWJpbGl0eSBvZiB0aGUgYnV0dG9uLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICB0b2dnbGUoYWN0aW9uID0gIXRoaXMudmlzaWJsZSkge1xuICAgIHRoaXMuX21hbnVhbGx5SGlkZGVuID0gIWFjdGlvbjtcbiAgICB0aGlzLl90b2dnbGUoYWN0aW9uKTtcbiAgfVxuXG4gIF90b2dnbGUoYWN0aW9uID0gIXRoaXMudmlzaWJsZSkge1xuICAgIGNvbnN0IGlzQm90dG9tID0gKHRoaXMuZ2V0QXR0cmlidXRlKCdwb3NpdGlvbicpIHx8ICcnKS5pbmRleE9mKCdib3R0b20nKSA+PSAwO1xuICAgIGNvbnN0IHRyYW5zbGF0ZSA9IGlzQm90dG9tID8gYHRyYW5zbGF0ZTNkKDBweCwgLSR7dXRpbC5nbG9iYWxzLmZhYk9mZnNldCB8fCAwfXB4LCAwcHgpYCA6ICcnO1xuXG4gICAgc3R5bGVyKHRoaXMsIHsgdHJhbnNmb3JtOiBgJHt0cmFuc2xhdGV9IHNjYWxlKCR7TnVtYmVyKGFjdGlvbil9KWAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIHNldCBkaXNhYmxlZCh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnZGlzYWJsZWQnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2aXNpYmxlXG4gICAqIEByZWFkb25seVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd6KaB57Sg44GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIGdldCB2aXNpYmxlKCkge1xuICAgIHJldHVybiB0aGlzLnN0eWxlLnRyYW5zZm9ybS5pbmRleE9mKCdzY2FsZSgwKScpID09PSAtMSAmJiB0aGlzLnN0eWxlLmRpc3BsYXkgIT09ICdub25lJztcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5GYWIgPSBGYWJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtZmFiJywgRmFiRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBHZXN0dXJlRGV0ZWN0b3IgZnJvbSAnLi4vb25zL2dlc3R1cmUtZGV0ZWN0b3InO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1nZXN0dXJlLWRldGVjdG9yXG4gKiBAY2F0ZWdvcnkgZ2VzdHVyZVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBDb21wb25lbnQgdG8gZGV0ZWN0IGZpbmdlciBnZXN0dXJlcyB3aXRoaW4gdGhlIHdyYXBwZWQgZWxlbWVudC4gRm9sbG93aW5nIGdlc3R1cmVzIGFyZSBzdXBwb3J0ZWQ6XG4gKiAgICAgLSBEcmFnIGdlc3R1cmVzOiBgZHJhZ2AsIGBkcmFnbGVmdGAsIGBkcmFncmlnaHRgLCBgZHJhZ3VwYCwgYGRyYWdkb3duYFxuICogICAgIC0gSG9sZCBnZXN0dXJlczogYGhvbGRgLCBgcmVsZWFzZWBcbiAqICAgICAtIFN3aXBlIGdlc3R1cmVzOiBgc3dpcGVgLCBgc3dpcGVsZWZ0YCwgYHN3aXBlcmlnaHRgLCBgc3dpcGV1cGAsIGBzd2lwZWRvd25gXG4gKiAgICAgLSBUYXAgZ2VzdHVyZXM6IGB0YXBgLCBgZG91YmxldGFwYFxuICogICAgIC0gUGluY2ggZ2VzdHVyZXM6IGBwaW5jaGAsIGBwaW5jaGluYCwgYHBpbmNob3V0YFxuICogICAgIC0gT3RoZXIgZ2VzdHVyZXM6IGB0b3VjaGAsIGB0cmFuc2Zvcm1gLCBgcm90YXRlYFxuICogICBbL2VuXVxuICogICBbamFd6KaB57Sg5YaF44Gu44K444Kn44K544OB44Oj44O85pON5L2c44KS5qSc55+l44GX44G+44GZ44CC6Kmz44GX44GP44Gv44Ks44Kk44OJ44KS5Y+C54Wn44GX44Gm44GP44Gg44GV44GE44CCWy9qYV1cbiAqIEBndWlkZSBmZWF0dXJlcy5odG1sI2dlc3R1cmUtZGV0ZWN0aW9uXG4gKiAgIFtlbl1EZXRlY3RpbmcgZmluZ2VyIGdlc3R1cmVzWy9lbl1cbiAqICAgW2phXeOCuOOCp+OCueODgeODo+ODvOaTjeS9nOOBruaknOefpVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1nZXN0dXJlLWRldGVjdG9yPlxuICogICA8ZGl2IGlkPVwiZGV0ZWN0LWFyZWFcIiBzdHlsZT1cIndpZHRoOiAxMDBweDsgaGVpZ2h0OiAxMDBweDtcIj5cbiAqICAgICBTd2lwZSBIZXJlXG4gKiAgIDwvZGl2PlxuICogPC9vbnMtZ2VzdHVyZS1kZXRlY3Rvcj5cbiAqXG4gKiA8c2NyaXB0PlxuICogICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdzd2lwZWxlZnQnLCBmdW5jdGlvbihldmVudCkge1xuICogICAgIGlmIChldmVudC50YXJnZXQubWF0Y2hlcygnI2RldGVjdC1hcmVhJykpIHtcbiAqICAgICAgIGNvbnNvbGUubG9nKCdTd2lwZSBsZWZ0IGlzIGRldGVjdGVkLicpO1xuICogICAgIH1cbiAqICAgfSk7XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR2VzdHVyZURldGVjdG9yRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvciA9IG5ldyBHZXN0dXJlRGV0ZWN0b3IodGhpcywgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLkdlc3R1cmVEZXRlY3RvciA9IEdlc3R1cmVEZXRlY3RvckVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1nZXN0dXJlLWRldGVjdG9yJywgR2VzdHVyZURldGVjdG9yRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxubGV0IGF1dG9QcmVmaXggPSAnZmEnOyAvLyBGSVhNRTogVG8gYmUgcmVtb3ZlZCBpbiB2M1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1pY29uXG4gKiBAY2F0ZWdvcnkgdmlzdWFsXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIERpc3BsYXlzIGFuIGljb24uIFRoZSBmb2xsb3dpbmcgaWNvbiBzdWl0ZXMgYXJlIGF2YWlsYWJsZTpcbiAqXG4gKiAgICAgKiBbRm9udCBBd2Vzb21lXShodHRwczovL2ZvcnRhd2Vzb21lLmdpdGh1Yi5pby9Gb250LUF3ZXNvbWUvKVxuICogICAgICogW0lvbmljb25zXShodHRwOi8vaW9uaWNvbnMuY29tLylcbiAqICAgICAqIFtNYXRlcmlhbCBEZXNpZ24gSWNvbmljIEZvbnRdKGh0dHA6Ly96YXZvbG9rbG9tLmdpdGh1Yi5pby9tYXRlcmlhbC1kZXNpZ24taWNvbmljLWZvbnQvKVxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIHhBaHZnXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvaWNvblxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNjcm9zcy1wbGF0Zm9ybS1zdHlsaW5nLWF1dG9zdHlsaW5nIFtlbl1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9lbl1bamFdWy9qYV1cbiAqIEBndWlkZSBhcHBzaXplLmh0bWwjcmVtb3ZpbmctaWNvbi1wYWNrcyBbZW5dUmVtb3ZpbmcgaWNvbiBwYWNrcy5bL2VuXVtqYV1bL2phXVxuICogQGd1aWRlIGZhcS5odG1sI2hvdy1jYW4taS11c2UtY3VzdG9tLWljb24tcGFja3MgW2VuXUFkZGluZyBjdXN0b20gaWNvbiBwYWNrcy5bL2VuXVtqYV1bL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtaWNvblxuICogICBpY29uPVwibWQtY2FyXCJcbiAqICAgc2l6ZT1cIjIwcHhcIlxuICogICBzdHlsZT1cImNvbG9yOiByZWRcIj5cbiAqIDwvb25zLWljb24+XG4gKlxuICogPG9ucy1idXR0b24+XG4gKiAgIDxvbnMtaWNvbiBpY29uPVwibWQtY2FyXCI+PC9vbnMtaWNvbj5cbiAqICAgQ2FyXG4gKiA8L29ucy1idXR0b24+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEljb25FbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGljb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhlIGljb24gbmFtZS4gYFwibWQtXCJgIHByZWZpeCBmb3IgTWF0ZXJpYWwgSWNvbnMsIGBcImZhLVwiYCBmb3IgRm9udCBBd2Vzb21lIGFuZCBgXCJpb24tXCJgIHByZWZpeCBmb3IgSW9uaWNvbnMuXG4gICAqXG4gICAqICAgICBTZWUgYWxsIGF2YWlsYWJsZSBpY29ucyBvbiB0aGUgZWxlbWVudCBkZXNjcmlwdGlvbiAoYXQgdGhlIHRvcCkuXG4gICAqXG4gICAqICAgICBJY29ucyBjYW4gYWxzbyBiZSBzdHlsZWQgYmFzZWQgb24gbW9kaWZpZXIgcHJlc2VuY2UuIEFkZCBjb21tYS1zZXBhcmF0ZWQgaWNvbnMgd2l0aCBgXCJtb2RpZmllck5hbWU6XCJgIHByZWZpeC5cbiAgICpcbiAgICogICAgIFRoZSBjb2RlIGA8b25zLWljb24gaWNvbj1cImlvbi1lZGl0LCBtYXRlcmlhbDptZC1lZGl0XCI+PC9vbnMtaWNvbj5gIHdpbGwgZGlzcGxheSBgXCJtZC1lZGl0XCJgIGZvciBNYXRlcmlhbCBEZXNpZ24gYW5kIGBcImlvbi1lZGl0XCJgIGFzIHRoZSBkZWZhdWx0IGljb24uXG4gICAqXG4gICAqICAgICBgZmEtYCBwcmVmaXggaXMgYWRkZWQgYXV0b21hdGljYWxseSBpZiBub25lIGlzIHByb3ZpZGVkLiBDaGVjayBbU2VlIGFsc29dKCNzZWVhbHNvKSBzZWN0aW9uIGZvciBtb3JlIGluZm9ybWF0aW9uLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNpemVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhlIHNpemVzIG9mIHRoZSBpY29uLiBWYWxpZCB2YWx1ZXMgYXJlIGxnLCAyeCwgM3gsIDR4LCA1eCwgb3IgaW4gdGhlIHNpemUgaW4gcGl4ZWxzLlxuICAgKiAgICAgSWNvbnMgY2FuIGFsc28gYmUgc3R5bGVkIGJhc2VkIG9uIG1vZGlmaWVyIHByZXNlbmNlLiBBZGQgY29tbWEtc2VwYXJhdGVkIGljb25zIHdpdGggYFwibW9kaWZpZXJOYW1lOlwiYCBwcmVmaXguXG4gICAqXG4gICAqICAgICBUaGUgY29kZTpcbiAgICpcbiAgICogICAgIGBgYFxuICAgKiAgICAgPG9ucy1pY29uXG4gICAqICAgICAgIGljb249XCJpb24tZWRpdFwiXG4gICAqICAgICAgIHNpemU9XCIzMnB4LCBtYXRlcmlhbDoyNHB4XCI+XG4gICAqICAgICA8L29ucy1pY29uPlxuICAgKiAgICAgYGBgXG4gICAqXG4gICAqICAgICB3aWxsIHJlbmRlciBhcyBhIGAyNHB4YCBpY29uIGlmIHRoZSBgXCJtYXRlcmlhbFwiYCBtb2RpZmllciBpcyBwcmVzZW50IGFuZCBgMzJweGAgb3RoZXJ3aXNlLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHJvdGF0ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dTnVtYmVyIG9mIGRlZ3JlZXMgdG8gcm90YXRlIHRoZSBpY29uLiBWYWxpZCB2YWx1ZXMgYXJlIDkwLCAxODAgYW5kIDI3MC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjgqTjgrPjg7PjgpLlm57ou6LjgZfjgabooajnpLrjgZfjgb7jgZnjgII5MCwgMTgwLCAyNzDjgYvjgonmjIflrprjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBmaXhlZC13aWR0aFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dV2hlbiB1c2VkIGluIGEgbGlzdCwgeW91IHdhbnQgdGhlIGljb25zIHRvIGhhdmUgdGhlIHNhbWUgd2lkdGggc28gdGhhdCB0aGV5IGFsaWduIHZlcnRpY2FsbHkgYnkgZGVmaW5pbmcgdGhpcyBhdHRyaWJ1dGUuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBzcGluXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHdoZXRoZXIgdGhlIGljb24gc2hvdWxkIGJlIHNwaW5uaW5nLlsvZW5dXG4gICAqICAgW2phXeOCouOCpOOCs+ODs+OCkuWbnui7ouOBmeOCi+OBi+OBqeOBhuOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnaWNvbicsICdzaXplJywgJ21vZGlmaWVyJywgJ2NsYXNzJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHRoaXMuX2NsZWFuQ2xhc3NBdHRyaWJ1dGUobmFtZSA9PT0gJ2ljb24nID8gbGFzdCA6IHRoaXMuZ2V0QXR0cmlidXRlKCdpY29uJyksIG5hbWUgPT09ICdtb2RpZmllcicgPyBsYXN0IDogdW5kZWZpbmVkKTtcbiAgICB0aGlzLl91cGRhdGUoKTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuICAgIHRoaXMuX3VwZGF0ZSgpO1xuICB9XG5cbiAgX3VwZGF0ZSgpIHtcbiAgICBjb25zdCB7Y2xhc3NMaXN0LCBzdHlsZX0gPSB0aGlzLl9idWlsZENsYXNzQW5kU3R5bGUodGhpcy5fcGFyc2VBdHRyKCdpY29uJyksIHRoaXMuX3BhcnNlQXR0cignc2l6ZScpKTtcbiAgICB1dGlsLmV4dGVuZCh0aGlzLnN0eWxlLCBzdHlsZSk7XG5cbiAgICBjbGFzc0xpc3QuZm9yRWFjaChjbGFzc05hbWUgPT4gdGhpcy5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSkpO1xuICB9XG5cbiAgX3BhcnNlQXR0cihhdHRyTmFtZSwgbW9kaWZpZXIgPSB0aGlzLmdldEF0dHJpYnV0ZSgnbW9kaWZpZXInKSB8fCAnJykge1xuICAgIGNvbnN0IGF0dHIgPSB0aGlzLmdldEF0dHJpYnV0ZShhdHRyTmFtZSkgfHwgYXR0ck5hbWUgfHwgJydcbiAgICBjb25zdCBwYXJ0cyA9IGF0dHIuc3BsaXQoL1xccyosXFxzKi8pO1xuICAgIGNvbnN0IGRlZiA9IHBhcnRzWzBdO1xuICAgIGxldCBtZCA9IHBhcnRzWzFdO1xuICAgIG1kID0gKG1kIHx8ICcnKS5zcGxpdCgvXFxzKjpcXHMqLyk7XG5cbiAgICByZXR1cm4gKG1vZGlmaWVyICYmIChSZWdFeHAoYChefFxcXFxzKykke21kWzBdfSgkfFxcXFxzKylgLCAnaScpLnRlc3QobW9kaWZpZXIpKSA/IG1kWzFdIDogZGVmKSB8fCAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdW5uZWVkZWQgY2xhc3MgdmFsdWUuXG4gICAqL1xuICBfY2xlYW5DbGFzc0F0dHJpYnV0ZShsYXN0SWNvbiwgbGFzdE1vZGlmaWVyKSB7XG4gICAgY29uc3QgeyBjbGFzc05hbWUsIHByZWZpeCB9ID0gdGhpcy5fcHJlZml4SWNvbih0aGlzLl9wYXJzZUF0dHIobGFzdEljb24sIGxhc3RNb2RpZmllcikpO1xuICAgIGNvbnN0IGN1c3RvbVByZWZpeFJFID0gY2xhc3NOYW1lICE9PSBwcmVmaXggPyBgfCR7cHJlZml4fSR8JHtwcmVmaXh9LWAgOiBgfCR7Y2xhc3NOYW1lfSRgIHx8ICcnO1xuICAgIGNvbnN0IHJlID0gbmV3IFJlZ0V4cChgXihmYSR8ZmEtfGlvbi18em1kaSR8em1kaS18b25zLWljb24tLSR7Y3VzdG9tUHJlZml4UkV9KWApO1xuXG4gICAgdXRpbC5hcnJheUZyb20odGhpcy5jbGFzc0xpc3QpXG4gICAgICAuZmlsdGVyKGNsYXNzTmFtZSA9PiByZS50ZXN0KGNsYXNzTmFtZSkpXG4gICAgICAuZm9yRWFjaChjbGFzc05hbWUgPT4gdGhpcy5jbGFzc0xpc3QucmVtb3ZlKGNsYXNzTmFtZSkpO1xuICB9XG5cbiAgX3ByZWZpeEljb24oaWNvbk5hbWUpIHtcbiAgICBjb25zdCBjbGFzc05hbWUgPSBhdXRvUHJlZml4ICsgKGF1dG9QcmVmaXggPyAnLScgOiAnJykgKyBpY29uTmFtZTtcbiAgICByZXR1cm4geyBjbGFzc05hbWUsIHByZWZpeDogY2xhc3NOYW1lLnNwbGl0KCctJylbMF0gfTtcbiAgfVxuXG4gIF9idWlsZENsYXNzQW5kU3R5bGUoaWNvbk5hbWUsIHNpemUpIHtcbiAgICBjb25zdCBjbGFzc0xpc3QgPSBbJ29ucy1pY29uJ107XG4gICAgY29uc3Qgc3R5bGUgPSB7fTtcblxuICAgIC8vIEljb25cbiAgICBpZiAoaWNvbk5hbWUuaW5kZXhPZignaW9uLScpID09PSAwKSB7XG4gICAgICBjbGFzc0xpc3QucHVzaChpY29uTmFtZSk7XG4gICAgICBjbGFzc0xpc3QucHVzaCgnb25zLWljb24tLWlvbicpO1xuICAgIH0gZWxzZSBpZiAoaWNvbk5hbWUuaW5kZXhPZignZmEtJykgPT09IDApIHtcbiAgICAgIGNsYXNzTGlzdC5wdXNoKGljb25OYW1lKTtcbiAgICAgIC8vIGRlZmF1bHQgaWNvbiBzdHlsZSB0byBGb250IEF3ZXNvbWUgU29saWQgaWYgaWNvbiBzdHlsZSBpcyBub3Qgc3BlY2lmaWVkIGFscmVhZHlcbiAgICAgIGlmICghKHRoaXMuY2xhc3NMaXN0LmNvbnRhaW5zKCdmYXInKSB8fCB0aGlzLmNsYXNzTGlzdC5jb250YWlucygnZmFiJykgfHwgdGhpcy5jbGFzc0xpc3QuY29udGFpbnMoJ2ZhbCcpKSkge1xuICAgICAgICBjbGFzc0xpc3QucHVzaCgnZmEnKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGljb25OYW1lLmluZGV4T2YoJ21kLScpID09PSAwKSAge1xuICAgICAgY2xhc3NMaXN0LnB1c2goJ3ptZGknKTtcbiAgICAgIGNsYXNzTGlzdC5wdXNoKCd6bWRpLScgKyBpY29uTmFtZS5zcGxpdCgvLSguKyk/LylbMV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB7IGNsYXNzTmFtZSwgcHJlZml4IH0gPSB0aGlzLl9wcmVmaXhJY29uKGljb25OYW1lKTtcbiAgICAgIHByZWZpeCAmJiBjbGFzc0xpc3QucHVzaChwcmVmaXgpO1xuICAgICAgY2xhc3NOYW1lICYmIGNsYXNzTGlzdC5wdXNoKGNsYXNzTmFtZSk7XG4gICAgfVxuXG4gICAgLy8gU2l6ZVxuICAgIGlmIChzaXplLm1hdGNoKC9eWzEtNV14fGxnJC8pKSB7XG4gICAgICBjbGFzc0xpc3QucHVzaCgnb25zLWljb24tLScgKyBzaXplKTtcbiAgICAgIHRoaXMuc3R5bGUucmVtb3ZlUHJvcGVydHkoJ2ZvbnQtc2l6ZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHlsZS5mb250U2l6ZSA9IHNpemU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNsYXNzTGlzdDogY2xhc3NMaXN0LFxuICAgICAgc3R5bGU6IHN0eWxlXG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBzZXRBdXRvUHJlZml4KHByZWZpeCkge1xuICAgIGF1dG9QcmVmaXggPSBwcmVmaXggPyAodHlwZW9mIHByZWZpeCA9PT0gJ3N0cmluZycgJiYgcHJlZml4IHx8ICdmYScpIDogJyc7XG4gIH1cbn1cblxub25zRWxlbWVudHMuSWNvbiA9IEljb25FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtaWNvbicsIEljb25FbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uL3V0aWwnO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uL3BsYXRmb3JtJztcblxuZXhwb3J0IGNsYXNzIExhenlSZXBlYXREZWxlZ2F0ZSB7XG5cbiAgY29uc3RydWN0b3IodXNlckRlbGVnYXRlLCB0ZW1wbGF0ZUVsZW1lbnQgPSBudWxsKSB7XG4gICAgaWYgKHR5cGVvZiB1c2VyRGVsZWdhdGUgIT09ICdvYmplY3QnIHx8IHVzZXJEZWxlZ2F0ZSA9PT0gbnVsbCkge1xuICAgICAgdXRpbC50aHJvdygnXCJkZWxlZ2F0ZVwiIHBhcmFtZXRlciBtdXN0IGJlIGFuIG9iamVjdCcpO1xuICAgIH1cbiAgICB0aGlzLl91c2VyRGVsZWdhdGUgPSB1c2VyRGVsZWdhdGU7XG5cbiAgICBpZiAoISh0ZW1wbGF0ZUVsZW1lbnQgaW5zdGFuY2VvZiBFbGVtZW50KSAmJiB0ZW1wbGF0ZUVsZW1lbnQgIT09IG51bGwpIHtcbiAgICAgIHV0aWwudGhyb3coJ1widGVtcGxhdGVFbGVtZW50XCIgcGFyYW1ldGVyIG11c3QgYmUgYW4gaW5zdGFuY2Ugb2YgRWxlbWVudCBvciBudWxsJyk7XG4gICAgfVxuICAgIHRoaXMuX3RlbXBsYXRlRWxlbWVudCA9IHRlbXBsYXRlRWxlbWVudDtcbiAgfVxuXG4gIGdldCBpdGVtSGVpZ2h0KCkge1xuICAgIHJldHVybiB0aGlzLl91c2VyRGVsZWdhdGUuaXRlbUhlaWdodDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtCb29sZWFufVxuICAgKi9cbiAgaGFzUmVuZGVyRnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX3VzZXJEZWxlZ2F0ZS5fcmVuZGVyIGluc3RhbmNlb2YgRnVuY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7dm9pZH1cbiAgICovXG4gIF9yZW5kZXIoKSB7XG4gICAgdGhpcy5fdXNlckRlbGVnYXRlLl9yZW5kZXIuYXBwbHkodGhpcy5fdXNlckRlbGVnYXRlLCBhcmd1bWVudHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpbmRleFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lIEEgZnVuY3Rpb24gdGhhdCB0YWtlIGl0ZW0gb2JqZWN0IGFzIHBhcmFtZXRlci5cbiAgICovXG4gIGxvYWRJdGVtRWxlbWVudChpbmRleCwgZG9uZSkge1xuICAgIGlmICh0aGlzLl91c2VyRGVsZWdhdGUubG9hZEl0ZW1FbGVtZW50IGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHRoaXMuX3VzZXJEZWxlZ2F0ZS5sb2FkSXRlbUVsZW1lbnQoaW5kZXgsIGRvbmUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fdXNlckRlbGVnYXRlLmNyZWF0ZUl0ZW1Db250ZW50KGluZGV4LCB0aGlzLl90ZW1wbGF0ZUVsZW1lbnQpO1xuICAgICAgaWYgKCEoZWxlbWVudCBpbnN0YW5jZW9mIEVsZW1lbnQpKSB7XG4gICAgICAgIHV0aWwudGhyb3coJ1wiY3JlYXRlSXRlbUNvbnRlbnRcIiBtdXN0IHJldHVybiBhbiBpbnN0YW5jZSBvZiBFbGVtZW50Jyk7XG4gICAgICB9XG5cbiAgICAgIGRvbmUoe2VsZW1lbnR9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHJldHVybiB7TnVtYmVyfVxuICAgKi9cbiAgY291bnRJdGVtcygpIHtcbiAgICBjb25zdCBjb3VudCA9IHRoaXMuX3VzZXJEZWxlZ2F0ZS5jb3VudEl0ZW1zKCk7XG4gICAgaWYgKHR5cGVvZiBjb3VudCAhPT0gJ251bWJlcicpIHtcbiAgICAgIHV0aWwudGhyb3coJ1wiY291bnRJdGVtc1wiIG11c3QgcmV0dXJuIGEgbnVtYmVyJyk7XG4gICAgfVxuICAgIHJldHVybiBjb3VudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW1cbiAgICogQHBhcmFtIHtFbGVtZW50fSBpdGVtLmVsZW1lbnRcbiAgICovXG4gIHVwZGF0ZUl0ZW0oaW5kZXgsIGl0ZW0pIHtcbiAgICBpZiAodGhpcy5fdXNlckRlbGVnYXRlLnVwZGF0ZUl0ZW1Db250ZW50IGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHRoaXMuX3VzZXJEZWxlZ2F0ZS51cGRhdGVJdGVtQ29udGVudChpbmRleCwgaXRlbSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge051bWJlcn1cbiAgICovXG4gIGNhbGN1bGF0ZUl0ZW1IZWlnaHQoaW5kZXgpIHtcbiAgICBpZiAodGhpcy5fdXNlckRlbGVnYXRlLmNhbGN1bGF0ZUl0ZW1IZWlnaHQgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5fdXNlckRlbGVnYXRlLmNhbGN1bGF0ZUl0ZW1IZWlnaHQoaW5kZXgpO1xuXG4gICAgICBpZiAodHlwZW9mIGhlaWdodCAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgdXRpbC50aHJvdygnXCJjYWxjdWxhdGVJdGVtSGVpZ2h0XCIgbXVzdCByZXR1cm4gYSBudW1iZXInKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGhlaWdodDtcbiAgICB9XG5cbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtPYmplY3R9IGl0ZW1cbiAgICovXG4gIGRlc3Ryb3lJdGVtKGluZGV4LCBpdGVtKSB7XG4gICAgaWYgKHRoaXMuX3VzZXJEZWxlZ2F0ZS5kZXN0cm95SXRlbSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICB0aGlzLl91c2VyRGVsZWdhdGUuZGVzdHJveUl0ZW0oaW5kZXgsIGl0ZW0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgZGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5fdXNlckRlbGVnYXRlLmRlc3Ryb3kgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgdGhpcy5fdXNlckRlbGVnYXRlLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLl91c2VyRGVsZWdhdGUgPSB0aGlzLl90ZW1wbGF0ZUVsZW1lbnQgPSBudWxsO1xuICB9XG59XG5cbi8qKlxuICogVGhpcyBjbGFzcyBwcm92aWRlIGNvcmUgZnVuY3Rpb25zIGZvciBvbnMtbGF6eS1yZXBlYXQuXG4gKi9cbmV4cG9ydCBjbGFzcyBMYXp5UmVwZWF0UHJvdmlkZXIge1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IHdyYXBwZXJFbGVtZW50XG4gICAqIEBwYXJhbSB7TGF6eVJlcGVhdERlbGVnYXRlfSBkZWxlZ2F0ZVxuICAgKi9cbiAgY29uc3RydWN0b3Iod3JhcHBlckVsZW1lbnQsIGRlbGVnYXRlKSB7XG4gICAgaWYgKCEoZGVsZWdhdGUgaW5zdGFuY2VvZiBMYXp5UmVwZWF0RGVsZWdhdGUpKSB7XG4gICAgICB1dGlsLnRocm93KCdcImRlbGVnYXRlXCIgcGFyYW1ldGVyIG11c3QgYmUgYW4gaW5zdGFuY2Ugb2YgTGF6eVJlcGVhdERlbGVnYXRlJyk7XG4gICAgfVxuXG4gICAgdGhpcy5fd3JhcHBlckVsZW1lbnQgPSB3cmFwcGVyRWxlbWVudDtcbiAgICB0aGlzLl9kZWxlZ2F0ZSA9IGRlbGVnYXRlO1xuICAgIHRoaXMuX2luc2VydEluZGV4ID0gKHRoaXMuX3dyYXBwZXJFbGVtZW50LmNoaWxkcmVuWzBdICYmIHRoaXMuX3dyYXBwZXJFbGVtZW50LmNoaWxkcmVuWzBdLnRhZ05hbWUgPT09ICdPTlMtTEFaWS1SRVBFQVQnKSA/IDEgOiAwO1xuXG4gICAgaWYgKHdyYXBwZXJFbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ29ucy1saXN0Jykge1xuICAgICAgd3JhcHBlckVsZW1lbnQuY2xhc3NMaXN0LmFkZCgnbGF6eS1saXN0Jyk7XG4gICAgfVxuXG4gICAgdGhpcy5fcGFnZUNvbnRlbnQgPSB0aGlzLl9maW5kUGFnZUNvbnRlbnRFbGVtZW50KHdyYXBwZXJFbGVtZW50KTtcblxuICAgIGlmICghdGhpcy5fcGFnZUNvbnRlbnQpIHtcbiAgICAgIHV0aWwudGhyb3coJ0xhenlSZXBlYXQgbXVzdCBiZSBkZXNjZW5kYW50IG9mIGEgUGFnZSBlbGVtZW50Jyk7XG4gICAgfVxuXG4gICAgdGhpcy5sYXN0U2Nyb2xsVG9wID0gdGhpcy5fcGFnZUNvbnRlbnQuc2Nyb2xsVG9wO1xuICAgIHRoaXMucGFkZGluZyA9IDA7XG4gICAgdGhpcy5fdG9wUG9zaXRpb25zID0gWzBdO1xuICAgIHRoaXMuX3JlbmRlcmVkSXRlbXMgPSB7fTtcblxuICAgIGlmICghdGhpcy5fZGVsZWdhdGUuaXRlbUhlaWdodCAmJiAhdGhpcy5fZGVsZWdhdGUuY2FsY3VsYXRlSXRlbUhlaWdodCgwKSkge1xuICAgICAgdGhpcy5fdW5rbm93bkl0ZW1IZWlnaHQgPSB0cnVlO1xuICAgIH1cblxuICAgIHRoaXMuX2FkZEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgdGhpcy5fb25DaGFuZ2UoKTtcbiAgfVxuXG4gIGdldCBwYWRkaW5nKCkge1xuICAgIHJldHVybiBwYXJzZUludCh0aGlzLl93cmFwcGVyRWxlbWVudC5zdHlsZS5wYWRkaW5nVG9wLCAxMCk7XG4gIH1cblxuICBzZXQgcGFkZGluZyhuZXdWYWx1ZSkge1xuICAgIHRoaXMuX3dyYXBwZXJFbGVtZW50LnN0eWxlLnBhZGRpbmdUb3AgPSBuZXdWYWx1ZSArICdweCc7XG4gIH1cblxuICBfZmluZFBhZ2VDb250ZW50RWxlbWVudCh3cmFwcGVyRWxlbWVudCkge1xuICAgIGNvbnN0IHBhZ2VDb250ZW50ID0gdXRpbC5maW5kUGFyZW50KHdyYXBwZXJFbGVtZW50LCAnLnBhZ2VfX2NvbnRlbnQnKTtcblxuICAgIGlmIChwYWdlQ29udGVudCkge1xuICAgICAgcmV0dXJuIHBhZ2VDb250ZW50O1xuICAgIH1cblxuICAgIGNvbnN0IHBhZ2UgPSB1dGlsLmZpbmRQYXJlbnQod3JhcHBlckVsZW1lbnQsICdvbnMtcGFnZScpO1xuICAgIGlmIChwYWdlKSB7XG4gICAgICBjb25zdCBjb250ZW50ID0gdXRpbC5maW5kQ2hpbGQocGFnZSwgJy5jb250ZW50Jyk7XG4gICAgICBpZiAoY29udGVudCkge1xuICAgICAgICByZXR1cm4gY29udGVudDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIF9jaGVja0l0ZW1IZWlnaHQoY2FsbGJhY2spIHtcbiAgICB0aGlzLl9kZWxlZ2F0ZS5sb2FkSXRlbUVsZW1lbnQoMCwgaXRlbSA9PiB7XG4gICAgICBpZiAoIXRoaXMuX3Vua25vd25JdGVtSGVpZ2h0KSB7XG4gICAgICAgIHV0aWwudGhyb3coJ0ludmFsaWQgc3RhdGUnKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fd3JhcHBlckVsZW1lbnQuYXBwZW5kQ2hpbGQoaXRlbS5lbGVtZW50KTtcblxuICAgICAgY29uc3QgZG9uZSA9ICgpID0+IHtcbiAgICAgICAgdGhpcy5fZGVsZWdhdGUuZGVzdHJveUl0ZW0oMCwgaXRlbSk7XG4gICAgICAgIGl0ZW0uZWxlbWVudCAmJiBpdGVtLmVsZW1lbnQucmVtb3ZlKCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLl91bmtub3duSXRlbUhlaWdodDtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuX2l0ZW1IZWlnaHQgPSBpdGVtLmVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuXG4gICAgICBpZiAodGhpcy5faXRlbUhlaWdodCA+IDApIHtcbiAgICAgICAgZG9uZSgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIHJldHJ5IHRvIG1lYXN1cmUgb2Zmc2V0IGhlaWdodFxuICAgICAgLy8gZGlydHkgZml4IGZvciBhbmd1bGFyMiBkaXJlY3RpdmVcbiAgICAgIHRoaXMuX3dyYXBwZXJFbGVtZW50LnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJztcbiAgICAgIGl0ZW0uZWxlbWVudC5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7XG5cbiAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuX2l0ZW1IZWlnaHQgPSBpdGVtLmVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuICAgICAgICBpZiAodGhpcy5faXRlbUhlaWdodCA9PSAwKSB7XG4gICAgICAgICAgdXRpbC50aHJvdygnSW52YWxpZCBzdGF0ZTogXCJpdGVtSGVpZ2h0XCIgbXVzdCBiZSBncmVhdGVyIHRoYW4gemVybycpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3dyYXBwZXJFbGVtZW50LnN0eWxlLnZpc2liaWxpdHkgPSAnJztcbiAgICAgICAgZG9uZSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgc3RhdGljSXRlbUhlaWdodCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZGVsZWdhdGUuaXRlbUhlaWdodCB8fCB0aGlzLl9pdGVtSGVpZ2h0O1xuICB9XG4gIF9jb3VudEl0ZW1zKCkge1xuICAgIHJldHVybiB0aGlzLl9kZWxlZ2F0ZS5jb3VudEl0ZW1zKCk7XG4gIH1cblxuICBfZ2V0SXRlbUhlaWdodChpKSB7XG4gICAgLy8gSXRlbSBpcyByZW5kZXJlZFxuICAgIGlmICh0aGlzLl9yZW5kZXJlZEl0ZW1zLmhhc093blByb3BlcnR5KGkpKSB7XG4gICAgICBpZiAoIXRoaXMuX3JlbmRlcmVkSXRlbXNbaV0uaGFzT3duUHJvcGVydHkoJ2hlaWdodCcpKSB7XG4gICAgICAgIHRoaXMuX3JlbmRlcmVkSXRlbXNbaV0uaGVpZ2h0ID0gdGhpcy5fcmVuZGVyZWRJdGVtc1tpXS5lbGVtZW50Lm9mZnNldEhlaWdodDtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLl9yZW5kZXJlZEl0ZW1zW2ldLmhlaWdodDtcbiAgICB9XG5cbiAgICAvLyBJdGVtIGlzIG5vdCByZW5kZXJlZCwgc2Nyb2xsIHVwXG4gICAgaWYgKHRoaXMuX3RvcFBvc2l0aW9uc1tpICsgMV0gJiYgdGhpcy5fdG9wUG9zaXRpb25zW2ldKSB7XG4gICAgICByZXR1cm4gdGhpcy5fdG9wUG9zaXRpb25zW2kgKyAxXSAtIHRoaXMuX3RvcFBvc2l0aW9uc1tpXTtcbiAgICB9XG4gICAgLy8gSXRlbSBpcyBub3QgcmVuZGVyZWQsIHNjcm9sbCBkb3duXG4gICAgcmV0dXJuIHRoaXMuc3RhdGljSXRlbUhlaWdodCB8fCB0aGlzLl9kZWxlZ2F0ZS5jYWxjdWxhdGVJdGVtSGVpZ2h0KGkpO1xuICB9XG5cbiAgX2NhbGN1bGF0ZVJlbmRlcmVkSGVpZ2h0KCkge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLl9yZW5kZXJlZEl0ZW1zKS5yZWR1Y2UoKGEsIGIpID0+IGEgKyB0aGlzLl9nZXRJdGVtSGVpZ2h0KCsoYikpLCAwKVxuICB9XG5cbiAgX29uQ2hhbmdlKCkge1xuICAgIHRoaXMuX3JlbmRlcigpO1xuICB9XG5cbiAgX2xhc3RJdGVtUmVuZGVyZWQoKSB7XG4gICAgcmV0dXJuIE1hdGgubWF4KC4uLk9iamVjdC5rZXlzKHRoaXMuX3JlbmRlcmVkSXRlbXMpKTtcbiAgfVxuXG4gIF9maXJzdEl0ZW1SZW5kZXJlZCgpIHtcbiAgICByZXR1cm4gTWF0aC5taW4oLi4uT2JqZWN0LmtleXModGhpcy5fcmVuZGVyZWRJdGVtcykpO1xuICB9XG5cbiAgcmVmcmVzaCgpIHtcbiAgICBjb25zdCBmb3JjZVJlbmRlciA9IHsgZm9yY2VTY3JvbGxEb3duOiB0cnVlIH07XG4gICAgY29uc3QgZmlyc3RJdGVtSW5kZXggPSB0aGlzLl9maXJzdEl0ZW1SZW5kZXJlZCgpO1xuXG4gICAgaWYgKHV0aWwuaXNJbnRlZ2VyKGZpcnN0SXRlbUluZGV4KSkge1xuICAgICAgdGhpcy5fd3JhcHBlckVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gdGhpcy5fdG9wUG9zaXRpb25zW2ZpcnN0SXRlbUluZGV4XSArIHRoaXMuX2NhbGN1bGF0ZVJlbmRlcmVkSGVpZ2h0KCkgKyAncHgnO1xuICAgICAgdGhpcy5wYWRkaW5nID0gdGhpcy5fdG9wUG9zaXRpb25zW2ZpcnN0SXRlbUluZGV4XTtcbiAgICAgIGZvcmNlUmVuZGVyLmZvcmNlRmlyc3RJbmRleCA9IGZpcnN0SXRlbUluZGV4O1xuICAgIH1cblxuICAgIHRoaXMuX3JlbW92ZUFsbEVsZW1lbnRzKCk7XG4gICAgdGhpcy5fcmVuZGVyKGZvcmNlUmVuZGVyKTtcbiAgICB0aGlzLl93cmFwcGVyRWxlbWVudC5zdHlsZS5oZWlnaHQgPSAnaW5oZXJpdCc7XG4gIH1cblxuICBfcmVuZGVyKHtmb3JjZVNjcm9sbERvd24gPSBmYWxzZSwgZm9yY2VGaXJzdEluZGV4LCBmb3JjZUxhc3RJbmRleH0gPSB7fSkge1xuICAgIGlmICh0aGlzLl91bmtub3duSXRlbUhlaWdodCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2NoZWNrSXRlbUhlaWdodCh0aGlzLl9yZW5kZXIuYmluZCh0aGlzLCBhcmd1bWVudHNbMF0pKTtcbiAgICB9XG5cbiAgICBjb25zdCBpc1Njcm9sbFVwID0gIWZvcmNlU2Nyb2xsRG93biAmJiB0aGlzLmxhc3RTY3JvbGxUb3AgPiB0aGlzLl9wYWdlQ29udGVudC5zY3JvbGxUb3A7XG4gICAgdGhpcy5sYXN0U2Nyb2xsVG9wID0gdGhpcy5fcGFnZUNvbnRlbnQuc2Nyb2xsVG9wO1xuICAgIGNvbnN0IGtlZXAgPSB7fTtcblxuICAgIGNvbnN0IG9mZnNldCA9IHRoaXMuX3dyYXBwZXJFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcDtcbiAgICBjb25zdCBsaW1pdCA9IDQgKiB3aW5kb3cuaW5uZXJIZWlnaHQgLSBvZmZzZXQ7XG4gICAgY29uc3QgY291bnQgPSB0aGlzLl9jb3VudEl0ZW1zKCk7XG5cbiAgICBjb25zdCBpdGVtcyA9IFtdO1xuICAgIGNvbnN0IHN0YXJ0ID0gZm9yY2VGaXJzdEluZGV4IHx8IE1hdGgubWF4KDAsIHRoaXMuX2NhbGN1bGF0ZVN0YXJ0SW5kZXgob2Zmc2V0KSAtIDMwKTsgLy8gUmVjYWxjdWxhdGUgZm9yIDAgb3IgdW5kZWZpbmVkXG4gICAgbGV0IGkgPSBzdGFydDtcblxuICAgIGZvciAobGV0IHRvcCA9IHRoaXMuX3RvcFBvc2l0aW9uc1tpXTsgaSA8IGNvdW50ICYmIHRvcCA8IGxpbWl0OyBpKyspIHtcbiAgICAgIGlmIChpID49IHRoaXMuX3RvcFBvc2l0aW9ucy5sZW5ndGgpIHsgLy8gcGVyZiBvcHRpbWl6YXRpb25cbiAgICAgICAgdGhpcy5fdG9wUG9zaXRpb25zLmxlbmd0aCArPSAxMDA7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3RvcFBvc2l0aW9uc1tpXSA9IHRvcDtcbiAgICAgIHRvcCArPSB0aGlzLl9nZXRJdGVtSGVpZ2h0KGkpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9kZWxlZ2F0ZS5oYXNSZW5kZXJGdW5jdGlvbiAmJiB0aGlzLl9kZWxlZ2F0ZS5oYXNSZW5kZXJGdW5jdGlvbigpKSB7XG4gICAgICByZXR1cm4gdGhpcy5fZGVsZWdhdGUuX3JlbmRlcihzdGFydCwgaSwgKCkgPT4ge1xuICAgICAgICB0aGlzLnBhZGRpbmcgPSB0aGlzLl90b3BQb3NpdGlvbnNbc3RhcnRdO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKGlzU2Nyb2xsVXApIHtcbiAgICAgIGZvciAobGV0IGogPSBpIC0gMTsgaiA+PSBzdGFydDsgai0tKSB7XG4gICAgICAgIGtlZXBbal0gPSB0cnVlO1xuICAgICAgICB0aGlzLl9yZW5kZXJFbGVtZW50KGosIGlzU2Nyb2xsVXApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBsYXN0SW5kZXggPSBmb3JjZUxhc3RJbmRleCB8fCBNYXRoLm1heChpIC0gMSwgLi4uT2JqZWN0LmtleXModGhpcy5fcmVuZGVyZWRJdGVtcykpOyAvLyBSZWNhbGN1bGF0ZSBmb3IgMCBvciB1bmRlZmluZWRcbiAgICAgIGZvciAobGV0IGogPSBzdGFydDsgaiA8PSBsYXN0SW5kZXg7IGorKykge1xuICAgICAgICBrZWVwW2pdID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5fcmVuZGVyRWxlbWVudChqLCBpc1Njcm9sbFVwKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBPYmplY3Qua2V5cyh0aGlzLl9yZW5kZXJlZEl0ZW1zKS5mb3JFYWNoKGtleSA9PiBrZWVwW2tleV0gfHwgdGhpcy5fcmVtb3ZlRWxlbWVudChrZXksIGlzU2Nyb2xsVXApKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtCb29sZWFufSBpc1Njcm9sbFVwXG4gICAqL1xuICBfcmVuZGVyRWxlbWVudChpbmRleCwgaXNTY3JvbGxVcCkge1xuICAgIGNvbnN0IGl0ZW0gPSB0aGlzLl9yZW5kZXJlZEl0ZW1zW2luZGV4XTtcbiAgICBpZiAoaXRlbSkge1xuICAgICAgdGhpcy5fZGVsZWdhdGUudXBkYXRlSXRlbShpbmRleCwgaXRlbSk7IC8vIHVwZGF0ZSBpZiBpdCBleGlzdHNcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9kZWxlZ2F0ZS5sb2FkSXRlbUVsZW1lbnQoaW5kZXgsIGl0ZW0gPT4ge1xuICAgICAgaWYgKGlzU2Nyb2xsVXApIHtcbiAgICAgICAgdGhpcy5fd3JhcHBlckVsZW1lbnQuaW5zZXJ0QmVmb3JlKGl0ZW0uZWxlbWVudCwgdGhpcy5fd3JhcHBlckVsZW1lbnQuY2hpbGRyZW5bdGhpcy5faW5zZXJ0SW5kZXhdKVxuICAgICAgICB0aGlzLnBhZGRpbmcgPSB0aGlzLl90b3BQb3NpdGlvbnNbaW5kZXhdO1xuICAgICAgICBpdGVtLmhlaWdodCA9IHRoaXMuX3RvcFBvc2l0aW9uc1tpbmRleCArIDFdIC0gdGhpcy5fdG9wUG9zaXRpb25zW2luZGV4XTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3dyYXBwZXJFbGVtZW50LmFwcGVuZENoaWxkKGl0ZW0uZWxlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3JlbmRlcmVkSXRlbXNbaW5kZXhdID0gaXRlbTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogQHBhcmFtIHtCb29sZWFufSBpc1Njcm9sbFVwXG4gICAqL1xuICBfcmVtb3ZlRWxlbWVudChpbmRleCwgaXNTY3JvbGxVcCA9IHRydWUpIHtcbiAgICBpbmRleCA9ICsoaW5kZXgpO1xuICAgIGNvbnN0IGl0ZW0gPSB0aGlzLl9yZW5kZXJlZEl0ZW1zW2luZGV4XTtcbiAgICB0aGlzLl9kZWxlZ2F0ZS5kZXN0cm95SXRlbShpbmRleCwgaXRlbSk7XG5cbiAgICBpZiAoaXNTY3JvbGxVcCkge1xuICAgICAgdGhpcy5fdG9wUG9zaXRpb25zW2luZGV4ICsgMV0gPSB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucGFkZGluZyA9IHRoaXMucGFkZGluZyArIHRoaXMuX2dldEl0ZW1IZWlnaHQoaW5kZXgpO1xuICAgIH1cblxuICAgIGlmIChpdGVtLmVsZW1lbnQucGFyZW50RWxlbWVudCkge1xuICAgICAgaXRlbS5lbGVtZW50LnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQoaXRlbS5lbGVtZW50KTtcbiAgICB9XG5cbiAgICBkZWxldGUgdGhpcy5fcmVuZGVyZWRJdGVtc1tpbmRleF07XG4gIH1cblxuICBfcmVtb3ZlQWxsRWxlbWVudHMoKSB7XG4gICAgT2JqZWN0LmtleXModGhpcy5fcmVuZGVyZWRJdGVtcykuZm9yRWFjaChrZXkgPT4gdGhpcy5fcmVtb3ZlRWxlbWVudChrZXkpKTtcbiAgfVxuXG4gIF9yZWNhbGN1bGF0ZVRvcFBvc2l0aW9ucyhzdGFydCwgZW5kKSB7XG4gICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDw9IGVuZDsgaSsrKSB7XG4gICAgICB0aGlzLl90b3BQb3NpdGlvbnNbaSArIDFdID0gdGhpcy5fdG9wUG9zaXRpb25zW2ldICsgdGhpcy5fZ2V0SXRlbUhlaWdodChpKTtcbiAgICB9XG4gIH1cblxuICBfY2FsY3VsYXRlU3RhcnRJbmRleChjdXJyZW50KSB7XG4gICAgY29uc3QgZmlyc3RJdGVtSW5kZXggPSB0aGlzLl9maXJzdEl0ZW1SZW5kZXJlZCgpO1xuICAgIGNvbnN0IGxhc3RJdGVtSW5kZXggPSB0aGlzLl9sYXN0SXRlbVJlbmRlcmVkKCk7XG5cbiAgICAvLyBGaXggZm9yIFNhZmFyaSBzY3JvbGwgYW5kIEFuZ3VsYXIgMlxuICAgIHRoaXMuX3JlY2FsY3VsYXRlVG9wUG9zaXRpb25zKGZpcnN0SXRlbUluZGV4LCBsYXN0SXRlbUluZGV4KTtcblxuICAgIGxldCBzdGFydCA9IDA7XG4gICAgbGV0IGVuZCA9IHRoaXMuX2NvdW50SXRlbXMoKSAtIDE7XG5cbiAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBpbmRleCBhdCB0b3Agb2Ygc2NyZWVuIHNvIHdlIGNhbiBzcGVlZCB1cCByZW5kZXJpbmcuXG4gICAgZm9yICg7Oykge1xuICAgICAgY29uc3QgbWlkZGxlID0gTWF0aC5mbG9vcigoc3RhcnQgKyBlbmQpIC8gMik7XG4gICAgICBjb25zdCB2YWx1ZSA9IGN1cnJlbnQgKyB0aGlzLl90b3BQb3NpdGlvbnNbbWlkZGxlXTtcblxuICAgICAgaWYgKGVuZCA8IHN0YXJ0KSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfSBlbHNlIGlmICh2YWx1ZSA8PSAwICYmIHZhbHVlICsgdGhpcy5fZ2V0SXRlbUhlaWdodChtaWRkbGUpID4gMCkge1xuICAgICAgICByZXR1cm4gbWlkZGxlO1xuICAgICAgfSBlbHNlIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPj0gMCkge1xuICAgICAgICBlbmQgPSBtaWRkbGUgLSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RhcnQgPSBtaWRkbGUgKyAxO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF9kZWJvdW5jZShmdW5jLCB3YWl0LCBpbW1lZGlhdGUpIHtcbiAgICBsZXQgdGltZW91dDtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBjb25zdCBjYWxsTm93ID0gaW1tZWRpYXRlICYmICF0aW1lb3V0O1xuICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgaWYgKGNhbGxOb3cpIHtcbiAgICAgICAgZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfSwgd2FpdCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIF9kb3VibGVGaXJlT25Ub3VjaGVuZCgpIHtcbiAgICB0aGlzLl9yZW5kZXIoKTtcbiAgICB0aGlzLl9kZWJvdW5jZSh0aGlzLl9yZW5kZXIuYmluZCh0aGlzKSwgMTAwKTtcbiAgfVxuXG4gIF9hZGRFdmVudExpc3RlbmVycygpIHtcbiAgICB1dGlsLmJpbmRMaXN0ZW5lcnModGhpcywgWydfb25DaGFuZ2UnLCAnX2RvdWJsZUZpcmVPblRvdWNoZW5kJ10pO1xuXG4gICAgaWYgKHBsYXRmb3JtLmlzSU9TKCkpIHtcbiAgICAgIHRoaXMuX2JvdW5kT25DaGFuZ2UgPSB0aGlzLl9kZWJvdW5jZSh0aGlzLl9ib3VuZE9uQ2hhbmdlLCAzMCk7XG4gICAgfVxuXG4gICAgdGhpcy5fcGFnZUNvbnRlbnQuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG5cbiAgICBpZiAocGxhdGZvcm0uaXNJT1MoKSkge1xuICAgICAgdXRpbC5hZGRFdmVudExpc3RlbmVyKHRoaXMuX3BhZ2VDb250ZW50LCAndG91Y2htb3ZlJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgeyBjYXB0dXJlOiB0cnVlLCBwYXNzaXZlOiB0cnVlIH0pO1xuICAgICAgdGhpcy5fcGFnZUNvbnRlbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9ib3VuZERvdWJsZUZpcmVPblRvdWNoZW5kLCB0cnVlKTtcbiAgICB9XG5cbiAgICB3aW5kb3cuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG4gIH1cblxuICBfcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgdGhpcy5fcGFnZUNvbnRlbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG5cbiAgICBpZiAocGxhdGZvcm0uaXNJT1MoKSkge1xuICAgICAgdXRpbC5yZW1vdmVFdmVudExpc3RlbmVyKHRoaXMuX3BhZ2VDb250ZW50LCAndG91Y2htb3ZlJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgeyBjYXB0dXJlOiB0cnVlLCBwYXNzaXZlOiB0cnVlIH0pO1xuICAgICAgdGhpcy5fcGFnZUNvbnRlbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9ib3VuZERvdWJsZUZpcmVPblRvdWNoZW5kLCB0cnVlKTtcbiAgICB9XG5cbiAgICB3aW5kb3cuZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgdHJ1ZSk7XG4gIH1cblxuICBkZXN0cm95KCkge1xuICAgIHRoaXMuX3JlbW92ZUFsbEVsZW1lbnRzKCk7XG4gICAgdGhpcy5fZGVsZWdhdGUuZGVzdHJveSgpO1xuICAgIHRoaXMuX3BhcmVudEVsZW1lbnQgPSB0aGlzLl9kZWxlZ2F0ZSA9IHRoaXMuX3JlbmRlcmVkSXRlbXMgPSBudWxsO1xuICAgIHRoaXMuX3JlbW92ZUV2ZW50TGlzdGVuZXJzKCk7XG4gIH1cbn1cblxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgeyBMYXp5UmVwZWF0RGVsZWdhdGUsIExhenlSZXBlYXRQcm92aWRlciB9IGZyb20gJy4uL29ucy9pbnRlcm5hbC9sYXp5LXJlcGVhdCc7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWxhenktcmVwZWF0XG4gKiBAY2F0ZWdvcnkgbGlzdFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBVc2luZyB0aGlzIGNvbXBvbmVudCBhIGxpc3Qgd2l0aCBtaWxsaW9ucyBvZiBpdGVtcyBjYW4gYmUgcmVuZGVyZWQgd2l0aG91dCBhIGRyb3AgaW4gcGVyZm9ybWFuY2UuXG4gKiAgICAgSXQgZG9lcyB0aGF0IGJ5IFwibGF6aWx5XCIgbG9hZGluZyBlbGVtZW50cyBpbnRvIHRoZSBET00gd2hlbiB0aGV5IGNvbWUgaW50byB2aWV3IGFuZFxuICogICAgIHJlbW92aW5nIGl0ZW1zIGZyb20gdGhlIERPTSB3aGVuIHRoZXkgYXJlIG5vdCB2aXNpYmxlLlxuICogICBbL2VuXVxuICogICBbamFdXG4gKiAgICAg44GT44Gu44Kz44Oz44Od44O844ON44Oz44OI5YaF44Gn5o+P55S744GV44KM44KL44Ki44Kk44OG44Og44GuRE9N6KaB57Sg44Gu6Kqt44G/6L6844G/44Gv44CB55S76Z2i44Gr6KaL44GI44Gd44GG44Gr44Gq44Gj44Gf5pmC44G+44Gn6Ieq5YuV55qE44Gr6YGF5bu244GV44KM44CBXG4gKiAgICAg55S76Z2i44GL44KJ6KaL44GI44Gq44GP44Gq44Gj44Gf5aC05ZCI44Gr44Gv44Gd44Gu6KaB57Sg44Gv5YuV55qE44Gr44Ki44Oz44Ot44O844OJ44GV44KM44G+44GZ44CCXG4gKiAgICAg44GT44Gu44Kz44Oz44Od44O844ON44Oz44OI44KS5L2/44GG44GT44Go44Gn44CB44OR44OV44Kp44O844Oe44Oz44K544KS5Yqj5YyW44GV44Gb44KL44GT44Go54Sh44GX44Gr5beo5aSn44Gq5pWw44Gu6KaB57Sg44KS5o+P55S744Gn44GN44G+44GZ44CCXG4gKiAgIFsvamFdXG4gKiBAY29kZXBlbiBRd3JHQm1cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9sYXp5LXJlcGVhdFxuICogQHNlZWFsc28gb25zLWxpc3RcbiAqICAgW2VuXVRoZSBgPG9ucy1saXN0PmAgZWxlbWVudCBpcyB1c2VkIHRvIHJlbmRlciBhIGxpc3QuWy9lbl1cbiAqICAgW2phXWA8b25zLWxpc3Q+YOimgee0oOOBr+ODquOCueODiOOCkuaPj+eUu+OBmeOCi+OBruOBq+S9v+OCj+OCjOOBvuOBmeOAglsvamFdXG4gKiBAZXhhbXBsZVxuICogPHNjcmlwdD5cbiAqICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBmdW5jdGlvbigpIHtcbiAqICAgICB2YXIgbGF6eVJlcGVhdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNsaXN0Jyk7XG4gKiAgICAgbGF6eVJlcGVhdC5kZWxlZ2F0ZSA9IHtcbiAqICAgICAgY3JlYXRlSXRlbUNvbnRlbnQ6IGZ1bmN0aW9uKGksIHRlbXBsYXRlKSB7XG4gKiAgICAgICAgdmFyIGRvbSA9IHRlbXBsYXRlLmNsb25lTm9kZSh0cnVlKTtcbiAqICAgICAgICBkb20uaW5uZXJUZXh0ID0gaTtcbiAqXG4gKiAgICAgICAgcmV0dXJuIGRvbTtcbiAqICAgICAgfSxcbiAqICAgICAgY291bnRJdGVtczogZnVuY3Rpb24oKSB7XG4gKiAgICAgICAgcmV0dXJuIDEwMDAwMDAwO1xuICogICAgICB9LFxuICogICAgICBkZXN0cm95SXRlbTogZnVuY3Rpb24oaW5kZXgsIGl0ZW0pIHtcbiAqICAgICAgICBjb25zb2xlLmxvZygnRGVzdHJveWVkIGl0ZW0gd2l0aCBpbmRleDogJyArIGluZGV4KTtcbiAqICAgICAgfVxuICogICAgIH07XG4gKiAgIH0pO1xuICogPC9zY3JpcHQ+XG4gKlxuICogPG9ucy1saXN0IGlkPVwibGlzdFwiPlxuICogICA8b25zLWxhenktcmVwZWF0PlxuICogICAgIDxvbnMtbGlzdC1pdGVtPjwvb25zLWxpc3QtaXRlbT5cbiAqICAgPC9vbnMtbGF6eS1yZXBlYXQ+XG4gKiA8L29ucy1saXN0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMYXp5UmVwZWF0RWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICAvLyBub3QgdmVyeSBnb29kIGlkZWEgYW5kIGFsc28gbm90IGRvY3VtZW50ZWRcbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ2RlbGVnYXRlJykpIHtcbiAgICAgIHRoaXMuZGVsZWdhdGUgPSB3aW5kb3dbdGhpcy5nZXRBdHRyaWJ1dGUoJ2RlbGVnYXRlJyldO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGVsZWdhdGVcbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSBhIGRlbGVnYXRlIG9iamVjdCB0byBsb2FkIGFuZCB1bmxvYWQgaXRlbSBlbGVtZW50cy5bL2VuXVxuICAgKiAgW2phXeimgee0oOOBruODreODvOODieOAgeOCouODs+ODreODvOODieOBquOBqeOBruWHpueQhuOCkuWnlOitsuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGVsZWdhdGUuY3JlYXRlSXRlbUNvbnRlbnRcbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dXG4gICAqICAgICBUaGlzIGZ1bmN0aW9uIHNob3VsZCByZXR1cm4gYSBgSFRNTEVsZW1lbnRgLlxuICAgKlxuICAgKiAgICAgVG8gaGVscCByZW5kZXJpbmcgdGhlIGVsZW1lbnQsIHRoZSBjdXJyZW50IGluZGV4IGFuZCBhIHRlbXBsYXRlIGlzIHN1cHBsaWVkIGFzIGFyZ3VtZW50cy4gVGhlIHRlbXBsYXRlIGlzIHRoZSBpbml0aWFsIGNvbnRlbnQgb2YgdGhlIGA8b25zLWxhenktcmVwZWF0PmAgZWxlbWVudC5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1cbiAgICogICAgIOOBk+OBrumWouaVsOOBr2BIVE1MRWxlbWVudGDjgpLov5TjgZfjgabjgY/jgaDjgZXjgYTjgIJcbiAgICogICAgIOimgee0oOOCkueUn+aIkOOBl+OChOOBmeOBj+OBmeOCi+OBn+OCgeOBq+OAgeePvuWcqOOBruOCouOCpOODhuODoOOBruOCpOODs+ODh+ODg+OCr+OCueOBqOODhuODs+ODl+ODrOODvOODiOOBjOW8leaVsOOBq+a4oeOBleOCjOOBvuOBmeOAglxuICAgKiAgICAg44GT44Gu44OG44Oz44OX44Os44O844OI44Gv44CBYDxvbnMtbGF6eS1yZXBlYXQ+YOimgee0oOOBruOCs+ODs+ODhuODs+ODhOOBjOa4oeOBleOCjOOBvuOBmeOAglxuICAgKiAgIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGVsZWdhdGUuY291bnRJdGVtc1xuICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TaG91bGQgcmV0dXJuIHRoZSBudW1iZXIgb2YgaXRlbXMgaW4gdGhlIGxpc3QuWy9lbl1cbiAgICogICBbamFd44Oq44K544OI5YaF44Gu44Ki44Kk44OG44Og5pWw44KS6L+U44GX44Gm44GP44Gg44GV44GE44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkZWxlZ2F0ZS5jYWxjdWxhdGVJdGVtSGVpZ2h0XG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgU2hvdWxkIHJldHVybiB0aGUgaGVpZ2h0IG9mIGFuIGl0ZW0uIFRoZSBpbmRleCBpcyBwcm92aWRlZCBhcyBhbiBhcmd1bWVudC5cbiAgICpcbiAgICogICAgIFRoaXMgaXMgaW1wb3J0YW50IHdoZW4gcmVuZGVyaW5nIGxpc3RzIHdoZXJlIHRoZSBpdGVtcyBoYXZlIGRpZmZlcmVudCBoZWlnaHQuXG4gICAqXG4gICAqICAgICBUaGUgZnVuY3Rpb24gaXMgb3B0aW9uYWwgYW5kIGlmIGl0IGlzbid0IHByZXNlbnQgdGhlIGhlaWdodCBvZiB0aGUgZmlyc3QgaXRlbSB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgY2FsY3VsYXRlZCBhbmQgdXNlZCBmb3IgYWxsIG90aGVyIGl0ZW1zLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVxuICAgKiAgICAg44Ki44Kk44OG44Og44Gu6auY44GVKOODlOOCr+OCu+ODqynjgpLov5TjgZfjgabjgY/jgaDjgZXjgYTjgILjgqLjgqTjg4bjg6Djga7jgqTjg7Pjg4fjg4Pjgq/jgrnlgKTjga/lvJXmlbDjgafmuKHjgZXjgozjgb7jgZnjgIJcbiAgICogICAgIOOBk+OBrumWouaVsOOBr+OAgeOBneOCjOOBnuOCjOOBruOCouOCpOODoOOBjOmBleOBo+OBn+mrmOOBleOCkuaMgeOBpOODquOCueODiOOCkuODrOODs+ODgOODquODs+OCsOOBmeOCi+mam+OBq+mHjeimgeOBp+OBmeOAglxuICAgKiAgICAg44GT44Gu6Zai5pWw44Gv44Kq44OX44K344On44OK44Or44Gn44GZ44CC44KC44GX44GT44Gu6Zai5pWw44GM54Sh44GE5aC05ZCI44Gr44Gv44CBXG4gICAqICAgICDmnIDliJ3jga7jgqLjgqTjg4bjg6Djga7pq5jjgZXjgYzku5bjga7jgZnjgbnjgabjga7jgqLjgqTjg4bjg6Djga7pq5jjgZXjgajjgZfjgabliKnnlKjjgZXjgozjgb7jgZnjgIJcbiAgICogICBbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRlbGVnYXRlLmRlc3Ryb3lJdGVtXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhpcyBmdW5jdGlvbiBpcyB1c2VkIGNhbGxlZCB3aGVuIGFuIGl0ZW0gaXMgcmVtb3ZlZCBmcm9tIHRoZSBET00uIFRoZSBpbmRleCBhbmQgRE9NIGVsZW1lbnQgaXMgcHJvdmlkZWQgYXMgYXJndW1lbnRzLlxuICAgKlxuICAgKiAgICAgVGhlIGZ1bmN0aW9uIGlzIG9wdGlvbmFsIGJ1dCBtYXkgYmUgaW1wb3J0YW50IGluIG9yZGVyIHRvIGF2b2lkIG1lbW9yeSBsZWFrcy5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1cbiAgICogICAgIOOBk+OBrumWouaVsOOBr+OAgeOBguOCi+OCouOCpOODhuODoOOBjERPTeODhOODquODvOOBi+OCiemZpOOBi+OCjOOBn+aZguOBq+WRvOOBs+WHuuOBleOCjOOBvuOBmeOAglxuICAgKiAgICAg44Ki44Kk44OG44Og44Gu44Kk44Oz44OH44OD44Kv44K55YCk44GoRE9N6KaB57Sg44GM5byV5pWw44Go44GX44Gm5rih44GV44KM44G+44GZ44CCXG4gICAqICAgICDjgZPjga7plqLmlbDjga/jgqrjg5fjgrfjg6fjg4rjg6vjgafjgZnjgYzjgIHlkITjgqLjgqTjg4bjg6Djga7lvozlh6bnkIbjgYzlv4XopoHjgarloLTlkIjjgavjga/jg6Hjg6Ljg6rjg7zjg6rjg7zjgq/jgpLpgb/jgZHjgovjgZ/jgoHjgavph43opoHjgafjgZnjgIJcbiAgICogICBbL2phXVxuICAgKi9cblxuICBzZXQgZGVsZWdhdGUodXNlckRlbGVnYXRlKSB7XG4gICAgdGhpcy5fbGF6eVJlcGVhdFByb3ZpZGVyICYmIHRoaXMuX2xhenlSZXBlYXRQcm92aWRlci5kZXN0cm95KCk7XG5cbiAgICBpZiAoIXRoaXMuX3RlbXBsYXRlRWxlbWVudCAmJiB0aGlzLmNoaWxkcmVuWzBdKSB7XG4gICAgICB0aGlzLl90ZW1wbGF0ZUVsZW1lbnQgPSB0aGlzLnJlbW92ZUNoaWxkKHRoaXMuY2hpbGRyZW5bMF0pO1xuICAgIH1cblxuICAgIGNvbnN0IGRlbGVnYXRlID0gbmV3IExhenlSZXBlYXREZWxlZ2F0ZSh1c2VyRGVsZWdhdGUsIHRoaXMuX3RlbXBsYXRlRWxlbWVudCB8fCBudWxsKTtcbiAgICB0aGlzLl9sYXp5UmVwZWF0UHJvdmlkZXIgPSBuZXcgTGF6eVJlcGVhdFByb3ZpZGVyKHRoaXMucGFyZW50RWxlbWVudCwgZGVsZWdhdGUpO1xuICB9XG5cbiAgZ2V0IGRlbGVnYXRlKCkge1xuICAgIHV0aWwudGhyb3coJ05vIGRlbGVnYXRlIGdldHRlcicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgcmVmcmVzaFxuICAgKiBAc2lnbmF0dXJlIHJlZnJlc2goKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmVmcmVzaCB0aGUgbGlzdC4gVXNlIHRoaXMgbWV0aG9kIHdoZW4gdGhlIGRhdGEgaGFzIGNoYW5nZWQuWy9lbl1cbiAgICogICBbamFd44Oq44K544OI44KS5pu05paw44GX44G+44GZ44CC44KC44GX44OH44O844K/44GM5aSJ44KP44Gj44Gf5aC05ZCI44Gr44Gv44GT44Gu44Oh44K944OD44OJ44KS5L2/44Gj44Gm44GP44Gg44GV44GE44CCWy9qYV1cbiAgICovXG4gIHJlZnJlc2goKSB7XG4gICAgdGhpcy5fbGF6eVJlcGVhdFByb3ZpZGVyICYmIHRoaXMuX2xhenlSZXBlYXRQcm92aWRlci5yZWZyZXNoKCk7XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge31cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBpZiAodGhpcy5fbGF6eVJlcGVhdFByb3ZpZGVyKSB7XG4gICAgICB0aGlzLl9sYXp5UmVwZWF0UHJvdmlkZXIuZGVzdHJveSgpO1xuICAgICAgdGhpcy5fbGF6eVJlcGVhdFByb3ZpZGVyID0gbnVsbDtcbiAgICB9XG4gIH1cblxufVxuXG5pbnRlcm5hbC5MYXp5UmVwZWF0RGVsZWdhdGUgPSBMYXp5UmVwZWF0RGVsZWdhdGU7XG5pbnRlcm5hbC5MYXp5UmVwZWF0UHJvdmlkZXIgPSBMYXp5UmVwZWF0UHJvdmlkZXI7XG5cbm9uc0VsZW1lbnRzLkxhenlSZXBlYXQgPSBMYXp5UmVwZWF0RWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWxhenktcmVwZWF0JywgTGF6eVJlcGVhdEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5cbmNvbnN0IGRlZmF1bHRDbGFzc05hbWUgPSAnbGlzdC1oZWFkZXInO1xuY29uc3Qgc2NoZW1lID0geycnOiAnbGlzdC1oZWFkZXItLSonfTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtbGlzdC1oZWFkZXJcbiAqIEBjYXRlZ29yeSBsaXN0XG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUhlYWRlciBlbGVtZW50IGZvciBsaXN0IGl0ZW1zLiBNdXN0IGJlIHB1dCBpbnNpZGUgdGhlIGA8b25zLWxpc3Q+YCBjb21wb25lbnQuWy9lbl1cbiAqICAgW2phXeODquOCueODiOimgee0oOOBq+S9v+eUqOOBmeOCi+ODmOODg+ODgOODvOeUqOOCs+ODs+ODneODvOODjeODs+ODiOOAgm9ucy1saXN044Go5YWx44Gr5L2/55So44GX44G+44GZ44CCWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1saXN0XG4gKiAgIFtlbl1UaGUgYDxvbnMtbGlzdD5gIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtbGlzdC1pdGVtXG4gKiAgIFtlbl1UaGUgYDxvbnMtbGlzdC1pdGVtPmAgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1saXN0LWl0ZW3jgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGNvZGVwZW4geXhjQ3RcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9saXN0XG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXURpc3BsYXkgYSBNYXRlcmlhbCBEZXNpZ24gbGlzdCBoZWFkZXIuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1saXN0PlxuICogICA8b25zLWxpc3QtaGVhZGVyPkhlYWRlciBUZXh0PC9vbnMtbGlzdC1oZWFkZXI+XG4gKiAgIDxvbnMtbGlzdC1pdGVtPkl0ZW08L29ucy1saXN0LWl0ZW0+XG4gKiAgIDxvbnMtbGlzdC1pdGVtPkl0ZW08L29ucy1saXN0LWl0ZW0+XG4gKiA8L29ucy1saXN0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMaXN0SGVhZGVyRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGxpc3QgaGVhZGVyLlsvZW5dXG4gICAqICAgW2phXeODmOODg+ODgOODvOOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9jb21waWxlKCk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG59XG5cbm9uc0VsZW1lbnRzLkxpc3RIZWFkZXIgPSBMaXN0SGVhZGVyRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLWxpc3QtaGVhZGVyJywgTGlzdEhlYWRlckVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5cbmNvbnN0IGRlZmF1bHRDbGFzc05hbWUgPSAnbGlzdC10aXRsZSc7XG5jb25zdCBzY2hlbWUgPSB7Jyc6ICdsaXN0LXRpdGxlLS0qJ307XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWxpc3QtdGl0bGVcbiAqIEBjYXRlZ29yeSBsaXN0XG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVJlcHJlc2VudHMgYSBsaXN0IHRpdGxlLlsvZW5dXG4gKiAgIFtqYV3jg6rjgrnjg4jjga7jgr/jgqTjg4jjg6vjgpLooajnj77jgZfjgb7jgZnjgIJbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtbGlzdC10aXRsZT5MaXN0IFRpdGxlPC9vbnMtbGlzdC10aXRsZT5cbiAqIDxvbnMtbGlzdD5cbiAqICAgPG9ucy1saXN0LWl0ZW0+SXRlbTwvb25zLWxpc3QtaXRlbT5cbiAqIDwvb25zLWxpc3Q+XG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXURpc3BsYXkgYSBNYXRlcmlhbCBEZXNpZ24gbGlzdCB0aXRsZS5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqL1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMaXN0VGl0bGVFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9jb21waWxlKCk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG59XG5cbm9uc0VsZW1lbnRzLkxpc3RUaXRsZSA9IExpc3RUaXRsZUVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1saXN0LXRpdGxlJywgTGlzdFRpdGxlRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxOCBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcbmltcG9ydCBCYXNlQW5pbWF0b3IgZnJvbSAnLi4vLi4vb25zL2Jhc2UtYW5pbWF0b3InXG5cbmV4cG9ydCBjbGFzcyBMaXN0SXRlbUFuaW1hdG9yIGV4dGVuZHMgQmFzZUFuaW1hdG9yIHtcbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdsaW5lYXInLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4yfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcbiAgfVxuXG4gIHNob3dFeHBhbnNpb24obGlzdEl0ZW0sIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIGhpZGVFeHBhbnNpb24obGlzdEl0ZW0sIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgU2xpZGVMaXN0SXRlbUFuaW1hdG9yIGV4dGVuZHMgTGlzdEl0ZW1BbmltYXRvciB7XG5cbiAgc2hvd0V4cGFuc2lvbihsaXN0SXRlbSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLl9hbmltYXRlRXhwYW5zaW9uKGxpc3RJdGVtLCB0cnVlLCBjYWxsYmFjayk7XG4gIH1cblxuICBoaWRlRXhwYW5zaW9uKGxpc3RJdGVtLCBjYWxsYmFjaykge1xuICAgIHRoaXMuX2FuaW1hdGVFeHBhbnNpb24obGlzdEl0ZW0sIGZhbHNlLCBjYWxsYmFjayk7XG4gIH1cblxuICBfYW5pbWF0ZUV4cGFuc2lvbihsaXN0SXRlbSwgc2hvdWxkT3BlbiwgY2FsbGJhY2spIHtcbiAgICAvLyBUbyBhbmltYXRlIHRoZSBvcGVuaW5nIG9mIHRoZSBleHBhbnNpb24gcGFuZWwgY29ycmVjdGx5LCB3ZSBuZWVkIHRvIGtub3cgaXRzXG4gICAgLy8gaGVpZ2h0LiBUbyBjYWxjdWxhdGUgdGhpcywgd2Ugc2V0IGl0cyBoZWlnaHQgdG8gYXV0bywgYW5kIHRoZW4gZ2V0IHRoZSBjb21wdXRlZFxuICAgIC8vIGhlaWdodCBhbmQgcGFkZGluZy4gT25jZSB0aGlzIGlzIGRvbmUsIHdlIHNldCB0aGUgaGVpZ2h0IGJhY2sgdG8gaXRzIG9yaWdpbmFsIHZhbHVlLlxuICAgIGNvbnN0IG9sZEhlaWdodCA9IGxpc3RJdGVtLmV4cGFuZGFibGVDb250ZW50LnN0eWxlLmhlaWdodDtcbiAgICBjb25zdCBvbGREaXNwbGF5ID0gbGlzdEl0ZW0uZXhwYW5kYWJsZUNvbnRlbnQuc3R5bGUuZGlzcGxheTtcbiAgICBsaXN0SXRlbS5leHBhbmRhYmxlQ29udGVudC5zdHlsZS5oZWlnaHQgPSAnYXV0byc7XG4gICAgbGlzdEl0ZW0uZXhwYW5kYWJsZUNvbnRlbnQuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgY29uc3QgY29tcHV0ZWRTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGxpc3RJdGVtLmV4cGFuZGFibGVDb250ZW50KTtcblxuICAgIGNvbnN0IGV4cGFuc2lvbk9wZW5UcmFuc2l0aW9uID0gW1xuICAgICAgeyBoZWlnaHQ6IDAsIHBhZGRpbmdUb3A6IDAsIHBhZGRpbmdCb3R0b206IDAgfSxcbiAgICAgIHtcbiAgICAgICAgaGVpZ2h0OiBjb21wdXRlZFN0eWxlLmhlaWdodCxcbiAgICAgICAgcGFkZGluZ1RvcDogY29tcHV0ZWRTdHlsZS5wYWRkaW5nVG9wLFxuICAgICAgICBwYWRkaW5nQm90dG9tOiBjb21wdXRlZFN0eWxlLnBhZGRpbmdCb3R0b20sXG4gICAgICB9XG4gICAgXTtcbiAgICBjb25zdCBpY29uT3BlblRyYW5zaXRpb24gPSBbe3RyYW5zZm9ybTogJ3JvdGF0ZSg0NWRlZyknfSwge3RyYW5zZm9ybTogJ3JvdGF0ZSgyMjVkZWcpJ31dO1xuXG4gICAgLy8gTm93IHRoYXQgd2UgaGF2ZSB0aGUgdmFsdWVzIHdlIG5lZWQsIHJlc2V0IHRoZSBoZWlnaHQgYmFjayB0byBpdHMgb3JpZ2luYWwgc3RhdGVcbiAgICBsaXN0SXRlbS5leHBhbmRhYmxlQ29udGVudC5zdHlsZS5oZWlnaHQgPSBvbGRIZWlnaHQ7XG5cbiAgICBhbmltaXQobGlzdEl0ZW0uZXhwYW5kYWJsZUNvbnRlbnQsIHsgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sIHByb3BlcnR5OiAnaGVpZ2h0IHBhZGRpbmctdG9wIHBhZGRpbmctYm90dG9tJyB9KVxuICAgICAgLmRlZmF1bHQoLi4uKHNob3VsZE9wZW4gPyBleHBhbnNpb25PcGVuVHJhbnNpdGlvbiA6IGV4cGFuc2lvbk9wZW5UcmFuc2l0aW9uLnJldmVyc2UoKSkpXG4gICAgICAucGxheSgoKSA9PiB7XG4gICAgICAgIGxpc3RJdGVtLmV4cGFuZGFibGVDb250ZW50LnN0eWxlLmRpc3BsYXkgPSBvbGREaXNwbGF5O1xuICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgfSk7XG5cbiAgICBpZiAobGlzdEl0ZW0uZXhwYW5kQ2hldnJvbikge1xuICAgICAgYW5pbWl0KGxpc3RJdGVtLmV4cGFuZENoZXZyb24sIHsgZHVyYXRpb246IHRoaXMuZHVyYXRpb24sIHByb3BlcnR5OiAndHJhbnNmb3JtJyB9KVxuICAgICAgICAuZGVmYXVsdCguLi4oc2hvdWxkT3BlbiA/IGljb25PcGVuVHJhbnNpdGlvbiA6IGljb25PcGVuVHJhbnNpdGlvbi5yZXZlcnNlKCkpKVxuICAgICAgICAucGxheSgpO1xuICAgIH1cbiAgfVxuXG59IiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uLy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IHN0eWxlciBmcm9tICcuLi8uLi9vbnMvc3R5bGVyJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBBbmltYXRvckZhY3RvcnkgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnknO1xuaW1wb3J0IHsgTGlzdEl0ZW1BbmltYXRvciwgU2xpZGVMaXN0SXRlbUFuaW1hdG9yIH0gZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IGRlZmF1bHRDbGFzc05hbWUgPSAnbGlzdC1pdGVtJztcbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5saXN0LWl0ZW0nOiAnbGlzdC1pdGVtLS0qJyxcbiAgJy5saXN0LWl0ZW1fX2xlZnQnOiAnbGlzdC1pdGVtLS0qX19sZWZ0JyxcbiAgJy5saXN0LWl0ZW1fX2NlbnRlcic6ICdsaXN0LWl0ZW0tLSpfX2NlbnRlcicsXG4gICcubGlzdC1pdGVtX19yaWdodCc6ICdsaXN0LWl0ZW0tLSpfX3JpZ2h0JyxcbiAgJy5saXN0LWl0ZW1fX2xhYmVsJzogJ2xpc3QtaXRlbS0tKl9fbGFiZWwnLFxuICAnLmxpc3QtaXRlbV9fdGl0bGUnOiAnbGlzdC1pdGVtLS0qX190aXRsZScsXG4gICcubGlzdC1pdGVtX19zdWJ0aXRsZSc6ICdsaXN0LWl0ZW0tLSpfX3N1YnRpdGxlJyxcbiAgJy5saXN0LWl0ZW1fX3RodW1ibmFpbCc6ICdsaXN0LWl0ZW0tLSpfX3RodW1ibmFpbCcsXG4gICcubGlzdC1pdGVtX19pY29uJzogJ2xpc3QtaXRlbS0tKl9faWNvbidcbn07XG5cbmNvbnN0IF9hbmltYXRvckRpY3QgPSB7XG4gICdkZWZhdWx0JzogU2xpZGVMaXN0SXRlbUFuaW1hdG9yLFxuICAnbm9uZSc6IExpc3RJdGVtQW5pbWF0b3Jcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLWxpc3QtaXRlbVxuICogQGNhdGVnb3J5IGxpc3RcbiAqIEBtb2RpZmllciB0YXBwYWJsZVxuICogICBbZW5dTWFrZSB0aGUgbGlzdCBpdGVtIGNoYW5nZSBhcHBlYXJhbmNlIHdoZW4gaXQncyB0YXBwZWQuIE9uIGlPUyBpdCBpcyBiZXR0ZXIgdG8gdXNlIHRoZSBcInRhcHBhYmxlXCIgYW5kIFwidGFwLWJhY2tncm91bmQtY29sb3JcIiBhdHRyaWJ1dGUgZm9yIGJldHRlciBiZWhhdmlvciB3aGVuIHNjcm9sbGluZy5bL2VuXVxuICogICBbamFd44K/44OD44OX44KE44Kv44Oq44OD44Kv44GX44Gf5pmC44Gr5Yq55p6c44GM6KGo56S644GV44KM44KL44KI44GG44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBjaGV2cm9uXG4gKiAgIFtlbl1EaXNwbGF5IGEgY2hldnJvbiBhdCB0aGUgcmlnaHQgZW5kIG9mIHRoZSBsaXN0IGl0ZW0gYW5kIG1ha2UgaXQgY2hhbmdlIGFwcGVhcmFuY2Ugd2hlbiB0YXBwZWQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAbW9kaWZpZXIgbG9uZ2RpdmlkZXJcbiAqICAgW2VuXURpc3BsYXlzIGEgbG9uZyBob3Jpem9udGFsIGRpdmlkZXIgYmV0d2VlbiBpdGVtcy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciBub2RpdmlkZXJcbiAqICAgW2VuXVJlbW92ZXMgdGhlIGRpdmlkZXIgYmV0d2VlbiBsaXN0IGl0ZW1zLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1EaXNwbGF5IGEgTWF0ZXJpYWwgRGVzaWduIGxpc3QgaXRlbS5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgQ29tcG9uZW50IHRoYXQgcmVwcmVzZW50cyBlYWNoIGl0ZW0gaW4gYSBsaXN0LiBUaGUgbGlzdCBpdGVtIGlzIGNvbXBvc2VkIG9mIGZvdXIgcGFydHMgdGhhdCBhcmUgcmVwcmVzZW50ZWQgd2l0aCB0aGUgYGxlZnRgLCBgY2VudGVyYCwgYHJpZ2h0YCBhbmQgYGV4cGFuZGFibGUtY29udGVudGAgY2xhc3Nlcy4gVGhlc2UgY2xhc3NlcyBjYW4gYmUgdXNlZCB0byBlbnN1cmUgdGhhdCB0aGUgY29udGVudCBvZiB0aGUgbGlzdCBpdGVtcyBpcyBwcm9wZXJseSBhbGlnbmVkLlxuICpcbiAqICAgICBgYGBcbiAqICAgICA8b25zLWxpc3QtaXRlbT5cbiAqICAgICAgIDxkaXYgY2xhc3M9XCJsZWZ0XCI+TGVmdDwvZGl2PlxuICogICAgICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPkNlbnRlcjwvZGl2PlxuICogICAgICAgPGRpdiBjbGFzcz1cInJpZ2h0XCI+UmlnaHQ8L2Rpdj5cbiAqICAgICAgIDxkaXYgY2xhc3M9XCJleHBhbmRhYmxlLWNvbnRlbnRcIj5FeHBhbmRhYmxlIGNvbnRlbnQ8L2Rpdj5cbiAqICAgICA8L29ucy1saXN0LWl0ZW0+XG4gKiAgICAgYGBgXG4gKlxuICogICAgIFRoZXJlIGFyZSBhbHNvIGEgbnVtYmVyIG9mIGNsYXNzZXMgKHByZWZpeGVkIHdpdGggYGxpc3QtaXRlbV9fKmApIHRoYXQgaGVscCB3aGVuIHB1dHRpbmcgdGhpbmdzIGxpa2UgaWNvbnMgYW5kIHRodW1ibmFpbHMgaW50byB0aGUgbGlzdCBpdGVtcy5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtbGlzdFxuICogICBbZW5db25zLWxpc3QgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1saXN044Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1saXN0LWhlYWRlclxuICogICBbZW5db25zLWxpc3QtaGVhZGVyIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdC1oZWFkZXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGNvZGVwZW4geXhjQ3RcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9saXN0XG4gKiBAZXhhbXBsZVxuICogPG9ucy1saXN0LWl0ZW0+XG4gKiAgIDxkaXYgY2xhc3M9XCJsZWZ0XCI+XG4gKiAgICAgPG9ucy1pY29uIGljb249XCJtZC1mYWNlXCIgY2xhc3M9XCJsaXN0LWl0ZW1fX2ljb25cIj48L29ucy1pY29uPlxuICogICA8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlxuICogICAgIDxkaXYgY2xhc3M9XCJsaXN0LWl0ZW1fX3RpdGxlXCI+VGl0bGU8L2Rpdj5cbiAqICAgICA8ZGl2IGNsYXNzPVwibGlzdC1pdGVtX19zdWJ0aXRsZVwiPlN1YnRpdGxlPC9kaXY+XG4gKiAgIDwvZGl2PlxuICogICA8ZGl2IGNsYXNzPVwicmlnaHRcIj5cbiAqICAgICA8b25zLXN3aXRjaD48L29ucy1zd2l0Y2g+XG4gKiAgIDwvZGl2PlxuICogPC9vbnMtbGlzdC1pdGVtPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMaXN0SXRlbUVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBsaXN0IGl0ZW0uWy9lbl1cbiAgICogICBbamFd5ZCE6KaB57Sg44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbG9jay1vbi1kcmFnXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1QcmV2ZW50IHZlcnRpY2FsIHNjcm9sbGluZyB3aGVuIHRoZSB1c2VyIGRyYWdzIGhvcml6b250YWxseS5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovjgajjgIHjg6bjg7zjgrbjg7zjgYzjgZPjga7opoHntKDjgpLmqKrmlrnlkJHjgavjg4njg6njg4PjgrDjgZfjgabjgYTjgovmmYLjgavjgIHnuKbmlrnlkJHjga7jgrnjgq/jg63jg7zjg6vjgYzotbfjgY3jgarjgYTjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB0YXBwYWJsZVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXU1ha2VzIHRoZSBlbGVtZW50IHJlYWN0IHRvIHRhcHMuIGBwcmV2ZW50LXRhcGAgYXR0cmlidXRlIGNhbiBiZSBhZGRlZCB0byBjaGlsZCBlbGVtZW50cyBsaWtlIGJ1dHRvbnMgb3IgaW5wdXRzIHRvIHByZXZlbnQgdGhpcyBlZmZlY3QuIGBvbnMtKmAgZWxlbWVudHMgYXJlIGlnbm9yZWQgYnkgZGVmYXVsdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB0YXAtYmFja2dyb3VuZC1jb2xvclxuICAgKiBAdHlwZSB7Q29sb3J9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl0gQ2hhbmdlcyB0aGUgYmFja2dyb3VuZCBjb2xvciB3aGVuIHRhcHBlZC4gRm9yIHRoaXMgdG8gd29yaywgdGhlIGF0dHJpYnV0ZSBcInRhcHBhYmxlXCIgbmVlZHMgdG8gYmUgc2V0LiBUaGUgZGVmYXVsdCBjb2xvciBpcyBcIiNkOWQ5ZDlcIi4gSXQgd2lsbCBkaXNwbGF5IGFzIGEgcmlwcGxlIGVmZmVjdCBvbiBBbmRyb2lkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGV4cGFuZGFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1NYWtlcyB0aGUgZWxlbWVudCBhYmxlIHRvIGJlIGV4cGFuZGVkIHRvIHJldmVhbCBleHRyYSBjb250ZW50LiBGb3IgdGhpcyB0byB3b3JrLCB0aGUgZXhwYW5kYWJsZSBjb250ZW50IG11c3QgYmUgZGVmaW5lZCBpbiBgZGl2LmV4cGFuZGFibGUtY29udGVudGAuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFuaW1hdGlvbiB1c2VkIHdoZW4gc2hvd2luZyBhbmQgaGlkaW5nIHRoZSBleHBhbmRhYmxlIGNvbnRlbnQuIENhbiBiZSBlaXRoZXIgYFwiZGVmYXVsdFwiYCBvciBgXCJub25lXCJgLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX2FuaW1hdG9yRmFjdG9yeSA9IHRoaXMuX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpO1xuICAgIHRoaXMudG9nZ2xlRXhwYW5zaW9uID0gdGhpcy50b2dnbGVFeHBhbnNpb24uYmluZCh0aGlzKTtcblxuICAgIC8vIEVsZW1lbnRzIGlnbm9yZWQgd2hlbiB0YXBwaW5nXG4gICAgY29uc3QgcmUgPSAvXm9ucy0oPyFjb2wkfHJvdyR8aWYkKS9pO1xuICAgIHRoaXMuX3Nob3VsZElnbm9yZVRhcCA9IGUgPT4gZS5oYXNBdHRyaWJ1dGUoJ3ByZXZlbnQtdGFwJykgfHwgcmUudGVzdChlLnRhZ05hbWUpO1xuXG4gICAgLy8gc2hvdyBhbmQgaGlkZSBmdW5jdGlvbnMgZm9yIFZ1ZSBoaWRhYmxlIG1peGluXG4gICAgdGhpcy5zaG93ID0gdGhpcy5zaG93RXhwYW5zaW9uO1xuICAgIHRoaXMuaGlkZSA9IHRoaXMuaGlkZUV4cGFuc2lvbjtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ29tcGlsZXMgdGhlIGxpc3QgaXRlbS5cbiAgICpcbiAgICogVmFyaW91cyBlbGVtZW50cyBhcmUgYWxsb3dlZCBpbiB0aGUgYm9keSBvZiBhIGxpc3QgaXRlbTpcbiAgICpcbiAgICogIC0gZGl2LmxlZnQsIGRpdi5yaWdodCwgYW5kIGRpdi5jZW50ZXIgYXJlIGFsbG93ZWQgYXMgZGlyZWN0IGNoaWxkcmVuXG4gICAqICAtIGlmIGRpdi5jZW50ZXIgaXMgbm90IGRlZmluZWQsIGFueXRoaW5nIHRoYXQgaXNuJ3QgZGl2LmxlZnQsIGRpdi5yaWdodCBvciBkaXYuZXhwYW5kYWJsZS1jb250ZW50IHdpbGwgYmUgcHV0IGluIGEgZGl2LmNlbnRlclxuICAgKiAgLSBpZiBkaXYuY2VudGVyIGlzIGRlZmluZWQsIGFueXRoaW5nIHRoYXQgaXNuJ3QgZGl2LmxlZnQsIGRpdi5yaWdodCBvciBkaXYuZXhwYW5kYWJsZS1jb250ZW50IHdpbGwgYmUgaWdub3JlZFxuICAgKiAgLSBpZiBsaXN0IGl0ZW0gaGFzIGV4cGFuZGFibGUgYXR0cmlidXRlOlxuICAgKiAgICAgIC0gZGl2LmV4cGFuZGFibGUtY29udGVudCBpcyBhbGxvd2VkIGFzIGEgZGlyZWN0IGNoaWxkXG4gICAqICAgICAgLSBkaXYudG9wIGlzIGFsbG93ZWQgYXMgZGlyZWN0IGNoaWxkXG4gICAqICAgICAgLSBpZiBkaXYudG9wIGlzIGRlZmluZWQsIGFueXRoaW5nIHRoYXQgaXNuJ3QgZGl2LmV4cGFuZGFibGUtY29udGVudCBzaG91bGQgYmUgaW5zaWRlIGRpdi50b3AgLSBhbnl0aGluZyBlbHNlIHdpbGwgYmUgaWdub3JlZFxuICAgKiAgICAgIC0gaWYgZGl2LnJpZ2h0IGlzIG5vdCBkZWZpbmVkLCBhIGRpdi5yaWdodCB3aWxsIGJlIGNyZWF0ZWQgd2l0aCBhIGRyb3AtZG93biBjaGV2cm9uXG4gICAqXG4gICAqIFNlZSB0aGUgdGVzdHMgZm9yIGV4YW1wbGVzLlxuICAgKi9cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuXG4gICAgbGV0IHRvcCwgZXhwYW5kYWJsZUNvbnRlbnQ7XG4gICAgbGV0IHRvcENvbnRlbnQgPSBbXTtcbiAgICBBcnJheS5mcm9tKHRoaXMuY2hpbGROb2RlcykuZm9yRWFjaChub2RlID0+IHtcbiAgICAgIGlmIChub2RlLm5vZGVUeXBlICE9PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xuICAgICAgICB0b3BDb250ZW50LnB1c2gobm9kZSk7XG4gICAgICB9IGVsc2UgaWYgKG5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCd0b3AnKSkge1xuICAgICAgICB0b3AgPSBub2RlO1xuICAgICAgfSBlbHNlIGlmIChub2RlLmNsYXNzTGlzdC5jb250YWlucygnZXhwYW5kYWJsZS1jb250ZW50JykpIHtcbiAgICAgICAgZXhwYW5kYWJsZUNvbnRlbnQgPSBub2RlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdG9wQ29udGVudC5wdXNoKG5vZGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAobm9kZS5ub2RlTmFtZSAhPT0gJ09OUy1SSVBQTEUnKSB7XG4gICAgICAgIG5vZGUucmVtb3ZlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdG9wQ29udGVudCA9IHRvcCA/IEFycmF5LmZyb20odG9wLmNoaWxkTm9kZXMpIDogdG9wQ29udGVudDtcblxuICAgIGxldCBsZWZ0LCByaWdodCwgY2VudGVyO1xuICAgIGNvbnN0IGNlbnRlckNvbnRlbnQgPSBbXTtcbiAgICB0b3BDb250ZW50LmZvckVhY2gobm9kZSA9PiB7XG4gICAgICBpZiAobm9kZS5ub2RlVHlwZSAhPT0gTm9kZS5FTEVNRU5UX05PREUpIHtcbiAgICAgICAgY2VudGVyQ29udGVudC5wdXNoKG5vZGUpO1xuICAgICAgfSBlbHNlIGlmIChub2RlLmNsYXNzTGlzdC5jb250YWlucygnbGVmdCcpKSB7XG4gICAgICAgIGxlZnQgPSBub2RlO1xuICAgICAgfSBlbHNlIGlmIChub2RlLmNsYXNzTGlzdC5jb250YWlucygncmlnaHQnKSkge1xuICAgICAgICByaWdodCA9IG5vZGU7XG4gICAgICB9IGVsc2UgaWYgKG5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCdjZW50ZXInKSkge1xuICAgICAgICBjZW50ZXIgPSBub2RlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2VudGVyQ29udGVudC5wdXNoKG5vZGUpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdleHBhbmRhYmxlJykpIHtcbiAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnbGlzdC1pdGVtLS1leHBhbmRhYmxlJyk7XG5cbiAgICAgIGlmICghdG9wKSB7XG4gICAgICAgIHRvcCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICB0b3AuY2xhc3NMaXN0LmFkZCgndG9wJyk7XG4gICAgICB9XG4gICAgICB0b3AuY2xhc3NMaXN0LmFkZCgnbGlzdC1pdGVtX190b3AnKTtcbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQodG9wKTtcbiAgICAgIHRoaXMuX3RvcCA9IHRvcDtcblxuICAgICAgaWYgKGV4cGFuZGFibGVDb250ZW50KSB7XG4gICAgICAgIGV4cGFuZGFibGVDb250ZW50LmNsYXNzTGlzdC5hZGQoJ2xpc3QtaXRlbV9fZXhwYW5kYWJsZS1jb250ZW50Jyk7XG4gICAgICAgIHRoaXMuYXBwZW5kQ2hpbGQoZXhwYW5kYWJsZUNvbnRlbnQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXJpZ2h0KSB7XG4gICAgICAgIHJpZ2h0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIHJpZ2h0LmNsYXNzTGlzdC5hZGQoJ2xpc3QtaXRlbV9fcmlnaHQnLCAncmlnaHQnKTtcblxuICAgICAgICAvLyBXZSBjYW5ub3QgdXNlIGEgcHNldWRvLWVsZW1lbnQgZm9yIHRoaXMgY2hldnJvbiwgYXMgd2UgY2Fubm90IGFuaW1hdGUgaXQgdXNpbmdcbiAgICAgICAgLy8gSlMuIFNvLCB3ZSBtYWtlIGEgY2hldnJvbiBzcGFuIGluc3RlYWQuXG4gICAgICAgIGNvbnN0IGNoZXZyb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzcGFuJyk7XG4gICAgICAgIGNoZXZyb24uY2xhc3NMaXN0LmFkZCgnbGlzdC1pdGVtX19leHBhbmQtY2hldnJvbicpO1xuICAgICAgICByaWdodC5hcHBlbmRDaGlsZChjaGV2cm9uKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdG9wID0gdGhpcztcbiAgICB9XG5cbiAgICBpZiAoIWNlbnRlcikge1xuICAgICAgY2VudGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICBjZW50ZXIuY2xhc3NMaXN0LmFkZCgnY2VudGVyJyk7XG4gICAgICBjZW50ZXJDb250ZW50LmZvckVhY2gobm9kZSA9PiBjZW50ZXIuYXBwZW5kQ2hpbGQobm9kZSkpO1xuICAgIH1cbiAgICBjZW50ZXIuY2xhc3NMaXN0LmFkZCgnbGlzdC1pdGVtX19jZW50ZXInKTtcbiAgICB0b3AuYXBwZW5kQ2hpbGQoY2VudGVyKTtcblxuICAgIGlmIChsZWZ0KSB7XG4gICAgICBsZWZ0LmNsYXNzTGlzdC5hZGQoJ2xpc3QtaXRlbV9fbGVmdCcpO1xuICAgICAgdG9wLmFwcGVuZENoaWxkKGxlZnQpO1xuICAgIH1cbiAgICBpZiAocmlnaHQpIHtcbiAgICAgIHJpZ2h0LmNsYXNzTGlzdC5hZGQoJ2xpc3QtaXRlbV9fcmlnaHQnKTtcbiAgICAgIHRvcC5hcHBlbmRDaGlsZChyaWdodCk7XG4gICAgfVxuXG4gICAgdXRpbC51cGRhdGVSaXBwbGUodGhpcyk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2hvd0V4cGFuc2lvblxuICAgKiBAc2lnbmF0dXJlIHNob3dFeHBhbnNpb24oKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgZXhwYW5kYWJsZSBjb250ZW50IGlmIHRoZSBlbGVtZW50IGlzIGV4cGFuZGFibGUuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNob3dFeHBhbnNpb24oKSB7XG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdleHBhbmRhYmxlJykgJiYgIXRoaXMuX2V4cGFuZGluZykge1xuICAgICAgdGhpcy5leHBhbmRlZCA9IHRydWU7XG4gICAgICB0aGlzLl9leHBhbmRpbmcgPSB0cnVlO1xuXG4gICAgICBjb25zdCBhbmltYXRvciA9IHRoaXMuX2FuaW1hdG9yRmFjdG9yeS5uZXdBbmltYXRvcigpO1xuICAgICAgYW5pbWF0b3Iuc2hvd0V4cGFuc2lvbih0aGlzLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZXhwYW5kZWQnKTtcbiAgICAgICAgdGhpcy5fZXhwYW5kaW5nID0gZmFsc2U7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlRXhwYW5zaW9uXG4gICAqIEBzaWduYXR1cmUgaGlkZUV4cGFuc2lvbigpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1IaWRlIHRoZSBleHBhbmRhYmxlIGNvbnRlbnQgaWYgdGhlIGVsZW1lbnQgZXhwYW5kYWJsZS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgaGlkZUV4cGFuc2lvbigpIHtcbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ2V4cGFuZGFibGUnKSAmJiAhdGhpcy5fZXhwYW5kaW5nKSB7XG4gICAgICB0aGlzLmV4cGFuZGVkID0gZmFsc2U7XG4gICAgICB0aGlzLl9leHBhbmRpbmcgPSB0cnVlO1xuXG4gICAgICBjb25zdCBhbmltYXRvciA9IHRoaXMuX2FuaW1hdG9yRmFjdG9yeS5uZXdBbmltYXRvcigpO1xuICAgICAgYW5pbWF0b3IuaGlkZUV4cGFuc2lvbih0aGlzLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LnJlbW92ZSgnZXhwYW5kZWQnKTtcbiAgICAgICAgdGhpcy5fZXhwYW5kaW5nID0gZmFsc2U7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICB0b2dnbGVFeHBhbnNpb24oKSB7XG4gICAgdGhpcy5jbGFzc0xpc3QuY29udGFpbnMoJ2V4cGFuZGVkJykgPyB0aGlzLmhpZGVFeHBhbnNpb24oKSA6IHRoaXMuc2hvd0V4cGFuc2lvbigpO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnQoJ2V4cGFuc2lvbicpKTtcbiAgfVxuXG4gIF91cGRhdGVBbmltYXRvckZhY3RvcnkoKSB7XG4gICAgcmV0dXJuIG5ldyBBbmltYXRvckZhY3Rvcnkoe1xuICAgICAgYW5pbWF0b3JzOiBfYW5pbWF0b3JEaWN0LFxuICAgICAgYmFzZUNsYXNzOiBMaXN0SXRlbUFuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ0xpc3RJdGVtQW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpIHx8ICdkZWZhdWx0J1xuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnY2xhc3MnLCAncmlwcGxlJywgJ2FuaW1hdGlvbiddO1xuICB9XG5cbiAgZ2V0IGV4cGFuZGFibGVDb250ZW50KCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJy5saXN0LWl0ZW1fX2V4cGFuZGFibGUtY29udGVudCcpO1xuICB9XG5cbiAgZ2V0IGV4cGFuZENoZXZyb24oKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3RvcignLmxpc3QtaXRlbV9fZXhwYW5kLWNoZXZyb24nKTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdyaXBwbGUnOlxuICAgICAgICB1dGlsLnVwZGF0ZVJpcHBsZSh0aGlzKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdhbmltYXRpb24nOlxuICAgICAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSB0aGlzLl91cGRhdGVBbmltYXRvckZhY3RvcnkoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX3NldHVwTGlzdGVuZXJzKHRydWUpO1xuICAgICAgdGhpcy5fb3JpZ2luYWxCYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLnN0eWxlLmJhY2tncm91bmRDb2xvcjtcbiAgICAgIHRoaXMudGFwcGVkID0gZmFsc2U7XG4gICAgfSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9zZXR1cExpc3RlbmVycyhmYWxzZSk7XG4gIH1cblxuICBfc2V0dXBMaXN0ZW5lcnMoYWRkKSB7XG4gICAgY29uc3QgYWN0aW9uID0gKGFkZCA/ICdhZGQnIDogJ3JlbW92ZScpICsgJ0V2ZW50TGlzdGVuZXInO1xuICAgIHV0aWxbYWN0aW9uXSh0aGlzLCAndG91Y2hzdGFydCcsIHRoaXMuX29uVG91Y2gsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcbiAgICB1dGlsW2FjdGlvbl0odGhpcywgJ3RvdWNobW92ZScsIHRoaXMuX29uUmVsZWFzZSwgeyBwYXNzaXZlOiB0cnVlIH0pO1xuICAgIHRoaXNbYWN0aW9uXSgndG91Y2hjYW5jZWwnLCB0aGlzLl9vblJlbGVhc2UpO1xuICAgIHRoaXNbYWN0aW9uXSgndG91Y2hlbmQnLCB0aGlzLl9vblJlbGVhc2UpO1xuICAgIHRoaXNbYWN0aW9uXSgndG91Y2hsZWF2ZScsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgdGhpc1thY3Rpb25dKCdkcmFnJywgdGhpcy5fb25EcmFnKTtcbiAgICB0aGlzW2FjdGlvbl0oJ21vdXNlZG93bicsIHRoaXMuX29uVG91Y2gpO1xuICAgIHRoaXNbYWN0aW9uXSgnbW91c2V1cCcsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgdGhpc1thY3Rpb25dKCdtb3VzZW91dCcsIHRoaXMuX29uUmVsZWFzZSk7XG5cbiAgICBpZiAodGhpcy5fdG9wKSB7XG4gICAgICB0aGlzLl90b3BbYWN0aW9uXSgnY2xpY2snLCB0aGlzLnRvZ2dsZUV4cGFuc2lvbik7XG4gICAgfVxuICB9XG5cbiAgX29uRHJhZyhldmVudCkge1xuICAgIGNvbnN0IGdlc3R1cmUgPSBldmVudC5nZXN0dXJlO1xuICAgIC8vIFByZXZlbnQgdmVydGljYWwgc2Nyb2xsaW5nIGlmIHRoZSB1c2VycyBwYW5zIGxlZnQgb3IgcmlnaHQuXG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdsb2NrLW9uLWRyYWcnKSAmJiBbJ2xlZnQnLCAncmlnaHQnXS5pbmRleE9mKGdlc3R1cmUuZGlyZWN0aW9uKSA+IC0xKSB7XG4gICAgICBnZXN0dXJlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuICB9XG5cbiAgX29uVG91Y2goZSkge1xuICAgIGlmICh0aGlzLnRhcHBlZCB8fFxuICAgICAgKHRoaXMgIT09IGUudGFyZ2V0ICYmICh0aGlzLl9zaG91bGRJZ25vcmVUYXAoZS50YXJnZXQpIHx8IHV0aWwuZmluZFBhcmVudChlLnRhcmdldCwgdGhpcy5fc2hvdWxkSWdub3JlVGFwLCBwID0+IHAgPT09IHRoaXMpKSlcbiAgICApIHtcbiAgICAgIHJldHVybjsgLy8gSWdub3JlIHRhcFxuICAgIH1cblxuICAgIHRoaXMudGFwcGVkID0gdHJ1ZTtcbiAgICBjb25zdCB0b3VjaFN0eWxlID0geyB0cmFuc2l0aW9uOiAnYmFja2dyb3VuZC1jb2xvciAwLjBzIGxpbmVhciAwLjAycywgYm94LXNoYWRvdyAwLjBzIGxpbmVhciAwLjAycycgfTtcblxuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgndGFwcGFibGUnKSkge1xuICAgICAgaWYgKHRoaXMuc3R5bGUuYmFja2dyb3VuZENvbG9yKSB7XG4gICAgICAgIHRoaXMuX29yaWdpbmFsQmFja2dyb3VuZENvbG9yID0gdGhpcy5zdHlsZS5iYWNrZ3JvdW5kQ29sb3I7XG4gICAgICB9XG5cbiAgICAgIHRvdWNoU3R5bGUuYmFja2dyb3VuZENvbG9yID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3RhcC1iYWNrZ3JvdW5kLWNvbG9yJykgfHwgJyNkOWQ5ZDknO1xuICAgICAgdG91Y2hTdHlsZS5ib3hTaGFkb3cgPSBgMHB4IC0xcHggMHB4IDBweCAke3RvdWNoU3R5bGUuYmFja2dyb3VuZENvbG9yfWA7XG4gICAgfVxuXG4gICAgc3R5bGVyKHRoaXMsIHRvdWNoU3R5bGUpO1xuICB9XG5cbiAgX29uUmVsZWFzZSgpIHtcbiAgICB0aGlzLnRhcHBlZCA9IGZhbHNlO1xuICAgIHRoaXMuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gdGhpcy5fb3JpZ2luYWxCYWNrZ3JvdW5kQ29sb3IgfHwgJyc7XG4gICAgc3R5bGVyLmNsZWFyKHRoaXMsICd0cmFuc2l0aW9uIGJveFNoYWRvdycpO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLkxpc3RJdGVtID0gTGlzdEl0ZW1FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtbGlzdC1pdGVtJywgTGlzdEl0ZW1FbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ2xpc3QnO1xuY29uc3Qgc2NoZW1lID0geycnOiAnbGlzdC0tKid9O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1saXN0XG4gKiBAY2F0ZWdvcnkgbGlzdFxuICogQG1vZGlmaWVyIGluc2V0XG4gKiAgIFtlbl1JbnNldCBsaXN0IHRoYXQgZG9lc24ndCBjb3ZlciB0aGUgd2hvbGUgd2lkdGggb2YgdGhlIHBhcmVudC5bL2VuXVxuICogICBbamFd6Kaq6KaB57Sg44Gu55S76Z2i44GE44Gj44Gx44GE44Gr5bqD44GM44KJ44Gq44GE44Oq44K544OI44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBub2JvcmRlclxuICogICBbZW5dQSBsaXN0IHdpdGggbm8gYm9yZGVycyBhdCB0aGUgdG9wIGFuZCBib3R0b20uWy9lbl1cbiAqICAgW2phXeODquOCueODiOOBruS4iuS4i+OBruODnOODvOODgOODvOOBjOeEoeOBhOODquOCueODiOOCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUNvbXBvbmVudCB0byBkZWZpbmUgYSBsaXN0LCBhbmQgdGhlIGNvbnRhaW5lciBmb3Igb25zLWxpc3QtaXRlbShzKS5bL2VuXVxuICogICBbamFd44Oq44K544OI44KS6KGo54++44GZ44KL44Gf44KB44Gu44Kz44Oz44Od44O844ON44Oz44OI44CCb25zLWxpc3QtaXRlbeOBruOCs+ODs+ODhuODiuOBqOOBl+OBpuS9v+eUqOOBl+OBvuOBmeOAglsvamFdXG4gKiBAc2VlYWxzbyBvbnMtbGlzdC1pdGVtXG4gKiAgIFtlbl1vbnMtbGlzdC1pdGVtIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdC1pdGVt44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1saXN0LWhlYWRlclxuICogICBbZW5db25zLWxpc3QtaGVhZGVyIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtbGlzdC1oZWFkZXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWxhenktcmVwZWF0XG4gKiAgIFtlbl1vbnMtbGF6eS1yZXBlYXQgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1sYXp5LXJlcGVhdOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAY29kZXBlbiB5eGNDdFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2xpc3RcbiAqIEBleGFtcGxlXG4gKiA8b25zLWxpc3Q+XG4gKiAgIDxvbnMtbGlzdC1oZWFkZXI+SGVhZGVyIFRleHQ8L29ucy1saXN0LWhlYWRlcj5cbiAqICAgPG9ucy1saXN0LWl0ZW0+SXRlbTwvb25zLWxpc3QtaXRlbT5cbiAqICAgPG9ucy1saXN0LWl0ZW0+SXRlbTwvb25zLWxpc3QtaXRlbT5cbiAqIDwvb25zLWxpc3Q+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExpc3RFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgYXBwZWFyYW5jZSBvZiB0aGUgbGlzdC5bL2VuXVxuICAgKiAgIFtqYV3jg6rjgrnjg4jjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fY29tcGlsZSgpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ2NsYXNzJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICB1dGlsLnJlc3RvcmVDbGFzcyh0aGlzLCBkZWZhdWx0Q2xhc3NOYW1lLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21vZGlmaWVyJzpcbiAgICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxufVxuXG5vbnNFbGVtZW50cy5MaXN0ID0gTGlzdEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1saXN0JywgTGlzdEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uLy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3QgSU5QVVRfQVRUUklCVVRFUyA9IFtcbiAgJ2F1dG9jYXBpdGFsaXplJyxcbiAgJ2F1dG9jb21wbGV0ZScsXG4gICdhdXRvY29ycmVjdCcsXG4gICdhdXRvZm9jdXMnLFxuICAnZGlzYWJsZWQnLFxuICAnaW5wdXRtb2RlJyxcbiAgJ21heCcsXG4gICdtYXhsZW5ndGgnLFxuICAnbWluJyxcbiAgJ21pbmxlbmd0aCcsXG4gICduYW1lJyxcbiAgJ3BhdHRlcm4nLFxuICAncGxhY2Vob2xkZXInLFxuICAncmVhZG9ubHknLFxuICAncmVxdWlyZWQnLFxuICAnc2l6ZScsXG4gICdzdGVwJyxcbiAgJ3ZhbGlkYXRvcicsXG4gICd2YWx1ZSdcbl07XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJhc2VJbnB1dEVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgX3VwZGF0ZSgpIHt9IC8vIE9wdGlvbmFsbHkgaW1wbGVtZW50ZWRcblxuICBnZXQgX3NjaGVtZSgpIHtcbiAgICB1dGlsLnRocm93TWVtYmVyKCk7XG4gIH1cblxuICBnZXQgX3RlbXBsYXRlKCkge1xuICAgIHV0aWwudGhyb3dNZW1iZXIoKTtcbiAgfVxuXG4gIGdldCB0eXBlKCkge1xuICAgIHV0aWwudGhyb3dNZW1iZXIoKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gQmFzZUlucHV0RWxlbWVudCkge1xuICAgICAgdXRpbC50aHJvd0Fic3RyYWN0KCk7XG4gICAgfVxuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2NvbXBpbGUoKSk7XG4gICAgdGhpcy5fYm91bmREZWxlZ2F0ZUV2ZW50ID0gdGhpcy5fZGVsZWdhdGVFdmVudC5iaW5kKHRoaXMpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5fZGVmYXVsdENsYXNzTmFtZSAmJiB0aGlzLmNsYXNzTGlzdC5hZGQodGhpcy5fZGVmYXVsdENsYXNzTmFtZSk7XG5cbiAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggIT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmFwcGVuZENoaWxkKHV0aWwuY3JlYXRlRnJhZ21lbnQodGhpcy5fdGVtcGxhdGUpKTtcblxuICAgIHRoaXMuX3NldElucHV0SWQoKTtcblxuICAgIHRoaXMuX3VwZGF0ZUJvdW5kQXR0cmlidXRlcygpO1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCB0aGlzLl9zY2hlbWUpO1xuICB9XG5cbiAgX3VwZGF0ZUJvdW5kQXR0cmlidXRlcygpIHtcbiAgICBJTlBVVF9BVFRSSUJVVEVTLmZvckVhY2goYXR0ciA9PiB7XG4gICAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoYXR0cikpIHtcbiAgICAgICAgdGhpcy5faW5wdXQuc2V0QXR0cmlidXRlKGF0dHIsIHRoaXMuZ2V0QXR0cmlidXRlKGF0dHIpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUF0dHJpYnV0ZShhdHRyKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMuX3VwZGF0ZSgpO1xuICB9XG5cbiAgX2RlbGVnYXRlRXZlbnQoZXZlbnQpIHtcbiAgICBjb25zdCBlID0gbmV3IEN1c3RvbUV2ZW50KGV2ZW50LnR5cGUsIHtcbiAgICAgIGJ1YmJsZXM6IGZhbHNlLFxuICAgICAgY2FuY2VsYWJsZTogdHJ1ZVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuZGlzcGF0Y2hFdmVudChlKTtcbiAgfVxuXG4gIF9zZXRJbnB1dElkKCkge1xuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgnaW5wdXQtaWQnKSkge1xuICAgICAgdGhpcy5faW5wdXQuaWQgPSB0aGlzLmdldEF0dHJpYnV0ZSgnaW5wdXQtaWQnKTtcbiAgICB9XG4gIH1cblxuICBnZXQgX2RlZmF1bHRDbGFzc05hbWUoKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgZ2V0IF9pbnB1dCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCdpbnB1dCcpO1xuICB9XG5cbiAgZ2V0IHZhbHVlKCkge1xuICAgIHJldHVybiB0aGlzLl9pbnB1dCA9PT0gbnVsbFxuICAgICAgPyB0aGlzLmdldEF0dHJpYnV0ZSgndmFsdWUnKVxuICAgICAgOiB0aGlzLl9pbnB1dC52YWx1ZTtcbiAgfVxuXG4gIHNldCB2YWx1ZSh2YWwpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgaWYgKHZhbCBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgdmFsID0gdmFsLnRvSVNPU3RyaW5nKCkuc3Vic3RyaW5nKDAsIDEwKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX2lucHV0LnZhbHVlID0gdmFsO1xuICAgICAgdGhpcy5fdXBkYXRlKCk7XG4gICAgfSk7XG4gIH1cblxuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9pbnB1dC5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuX2JvdW5kRGVsZWdhdGVFdmVudCk7XG4gICAgICB0aGlzLl9pbnB1dC5hZGRFdmVudExpc3RlbmVyKCdibHVyJywgdGhpcy5fYm91bmREZWxlZ2F0ZUV2ZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9pbnB1dC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuX2JvdW5kRGVsZWdhdGVFdmVudCk7XG4gICAgICB0aGlzLl9pbnB1dC5yZW1vdmVFdmVudExpc3RlbmVyKCdibHVyJywgdGhpcy5fYm91bmREZWxlZ2F0ZUV2ZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ2lucHV0LWlkJywgJ2NsYXNzJywgLi4uSU5QVVRfQVRUUklCVVRFU107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHRoaXMuX3NjaGVtZSkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2lucHV0LWlkJzpcbiAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3NldElucHV0SWQoKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICB1dGlsLnJlc3RvcmVDbGFzcyh0aGlzLCB0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lLCB0aGlzLl9zY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBpZiAoSU5QVVRfQVRUUklCVVRFUy5pbmRleE9mKG5hbWUpID49IDApIHtcbiAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVCb3VuZEF0dHJpYnV0ZXMoKSk7XG4gICAgfVxuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUlucHV0RWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1pbnB1dCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnLnRleHQtaW5wdXQnOiAndGV4dC1pbnB1dC0tKicsXG4gICcudGV4dC1pbnB1dF9fbGFiZWwnOiAndGV4dC1pbnB1dC0tKl9fbGFiZWwnXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1pbnB1dFxuICogQGNhdGVnb3J5IGZvcm1cbiAqIEBtb2RpZmllciBtYXRlcmlhbFxuICogIFtlbl1EaXNwbGF5cyBhIE1hdGVyaWFsIERlc2lnbiBpbnB1dC5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIHVuZGVyYmFyXG4gKiAgW2VuXURpc3BsYXlzIGEgaG9yaXpvbnRhbCBsaW5lIHVuZGVybmVhdGggYSB0ZXh0IGlucHV0LlsvZW5dXG4gKiAgW2phXVsvamFdXG4gKiBAbW9kaWZpZXIgdHJhbnNwYXJlbnRcbiAqICBbZW5dRGlzcGxheXMgYSB0cmFuc3BhcmVudCBpbnB1dC4gV29ya3MgZm9yIE1hdGVyaWFsIERlc2lnbi5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgQW4gaW5wdXQgZWxlbWVudC4gVGhlIGB0eXBlYCBhdHRyaWJ1dGUgY2FuIGJlIHVzZWQgdG8gY2hhbmdlIHRoZSBpbnB1dCB0eXBlLiBBbGwgdGV4dCBpbnB1dCB0eXBlcyBhcmUgc3VwcG9ydGVkLlxuICpcbiAqICAgIFRoZSBjb21wb25lbnQgd2lsbCBhdXRvbWF0aWNhbGx5IHJlbmRlciBhcyBhIE1hdGVyaWFsIERlc2lnbiBpbnB1dCBvbiBBbmRyb2lkIGRldmljZXMuXG4gKlxuICogICAgTW9zdCBhdHRyaWJ1dGVzIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGEgbm9ybWFsIGA8aW5wdXQ+YCBlbGVtZW50IGNhbiBhbHNvIGJlIHVzZWQgb24gdGhlIGA8b25zLWlucHV0PmAgZWxlbWVudC5cbiAqICBbL2VuXVxuICogIFtqYV1bL2phXVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL2lucHV0XG4gKiBAc2VlYWxzbyBvbnMtY2hlY2tib3hcbiAqICAgW2VuXVRoZSBgPG9ucy1jaGVja2JveD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgY2hlY2tib3guWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcmFkaW9cbiAqICAgW2VuXVRoZSBgPG9ucy1yYWRpbz5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgcmFkaW8gYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXJhbmdlXG4gKiAgIFtlbl1UaGUgYDxvbnMtcmFuZ2U+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIHJhbmdlIHNsaWRlci5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zd2l0Y2hcbiAqICAgW2VuXVRoZSBgPG9ucy1zd2l0Y2g+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIGRyYWdnYWJsZSB0b2dnbGUgc3dpdGNoLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXNlbGVjdFxuICogICBbZW5dVGhlIGA8b25zLXNlbGVjdD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgc2VsZWN0IGJveC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjbW9kaWZpZXJzIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtaW5wdXQgcGxhY2Vob2xkZXI9XCJVc2VybmFtZVwiIGZsb2F0Pjwvb25zLWlucHV0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJbnB1dEVsZW1lbnQgZXh0ZW5kcyBCYXNlSW5wdXRFbGVtZW50IHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fYm91bmRPbklucHV0ID0gdGhpcy5fdXBkYXRlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fYm91bmRPbkZvY3VzaW4gPSB0aGlzLl91cGRhdGUuYmluZCh0aGlzKTtcbiAgfVxuXG4gIC8qIEluaGVyaXRlZCBwcm9wcyAqL1xuXG4gIF91cGRhdGUoKSB7XG4gICAgdGhpcy5fdXBkYXRlTGFiZWwoKTtcbiAgICB0aGlzLl91cGRhdGVMYWJlbENsYXNzKCk7XG4gIH1cblxuICBnZXQgX3NjaGVtZSgpIHtcbiAgICByZXR1cm4gc2NoZW1lO1xuICB9XG5cbiAgZ2V0IF90ZW1wbGF0ZSgpIHtcbiAgICByZXR1cm4gYFxuICAgICAgPGlucHV0IHR5cGU9XCIke3RoaXMudHlwZX1cIiBjbGFzcz1cInRleHQtaW5wdXRcIj5cbiAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1pbnB1dF9fbGFiZWxcIj48L3NwYW4+XG4gICAgYDtcbiAgfVxuXG4gIGdldCB0eXBlKCkge1xuICAgIGNvbnN0IHR5cGUgPSB0aGlzLmdldEF0dHJpYnV0ZSgndHlwZScpO1xuICAgIHJldHVybiAoWydjaGVja2JveCcsICdyYWRpbyddLmluZGV4T2YodHlwZSkgPCAwKSAmJiB0eXBlIHx8ICd0ZXh0JztcbiAgfVxuXG4gIC8qIE93biBwcm9wcyAqL1xuXG4gIF91cGRhdGVMYWJlbCgpIHtcbiAgICBjb25zdCBsYWJlbCA9IHRoaXMuZ2V0QXR0cmlidXRlKCdwbGFjZWhvbGRlcicpIHx8ICcnO1xuXG4gICAgaWYgKHR5cGVvZiB0aGlzLl9oZWxwZXIudGV4dENvbnRlbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLl9oZWxwZXIudGV4dENvbnRlbnQgPSBsYWJlbDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5faGVscGVyLmlubmVyVGV4dCA9IGxhYmVsO1xuICAgIH1cbiAgfVxuXG4gIF91cGRhdGVMYWJlbENsYXNzKCkge1xuICAgIGlmICh0aGlzLnZhbHVlID09PSAnJykge1xuICAgICAgdGhpcy5faGVscGVyLmNsYXNzTGlzdC5yZW1vdmUoJ3RleHQtaW5wdXQtLW1hdGVyaWFsX19sYWJlbC0tYWN0aXZlJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2hlbHBlci5jbGFzc0xpc3QuYWRkKCd0ZXh0LWlucHV0LS1tYXRlcmlhbF9fbGFiZWwtLWFjdGl2ZScpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBfaGVscGVyKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJ3NwYW4nKTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHN1cGVyLmNvbm5lY3RlZENhbGxiYWNrKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5faW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLCB0aGlzLl9ib3VuZE9uSW5wdXQpO1xuICAgICAgdGhpcy5faW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXNpbicsIHRoaXMuX2JvdW5kT25Gb2N1c2luKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHR5cGUgPSB0aGlzLmdldEF0dHJpYnV0ZSgndHlwZScpO1xuICAgIGlmIChbJ2NoZWNrYm94JywgJ3JhZGlvJ10uaW5kZXhPZih0eXBlKSA+PSAwKSB7XG4gICAgICB1dGlsLndhcm4oYFdhcm46IDxvbnMtaW5wdXQgdHlwZT1cIiR7dHlwZX1cIj4gaXMgZGVwcmVjYXRlZCBzaW5jZSB2Mi40LjAuIFVzZSA8b25zLSR7dHlwZX0+IGluc3RlYWQuYClcbiAgICB9XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBzdXBlci5kaXNjb25uZWN0ZWRDYWxsYmFjaygpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2lucHV0JywgdGhpcy5fYm91bmRPbklucHV0KTtcbiAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2ZvY3VzaW4nLCB0aGlzLl9ib3VuZE9uRm9jdXNpbik7XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWy4uLnN1cGVyLm9ic2VydmVkQXR0cmlidXRlcywgJ3R5cGUnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICd0eXBlJzpcbiAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2lucHV0LnNldEF0dHJpYnV0ZSgndHlwZScsIHRoaXMudHlwZSkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHN1cGVyLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBwbGFjZWhvbGRlclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUGxhY2Vob2xkZXIgdGV4dC4gSW4gTWF0ZXJpYWwgRGVzaWduLCB0aGlzIHBsYWNlaG9sZGVyIHdpbGwgYmUgYSBmbG9hdGluZyBsYWJlbC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBmbG9hdFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBwcmVzZW50LCB0aGUgcGxhY2Vob2xkZXIgd2lsbCBiZSBhbmltYXRlZCBpbiBNYXRlcmlhbCBEZXNpZ24uWy9lbl1cbiAgICogIFtqYV3jgZPjga7lsZ7mgKfjgYzoqK3lrprjgZXjgozjgZ/mmYLjgIHjg6njg5njg6vjga/jgqLjg4vjg6Hjg7zjgrfjg6fjg7PjgZnjgovjgojjgYbjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB0eXBlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVxuICAgKiAgICBTcGVjaWZ5IHRoZSBpbnB1dCB0eXBlLiBUaGlzIGlzIHRoZSBzYW1lIGFzIHRoZSBcInR5cGVcIiBhdHRyaWJ1dGUgZm9yIG5vcm1hbCBpbnB1dHMuIEl0IGV4cGVjdHMgc3RyaWN0IHRleHQgdHlwZXMgc3VjaCBhcyBgdGV4dGAsIGBwYXNzd29yZGAsIGV0Yy4gRm9yIGNoZWNrYm94LCByYWRpbyBidXR0b24sIHNlbGVjdCBvciByYW5nZSwgcGxlYXNlIGhhdmUgYSBsb29rIGF0IHRoZSBjb3JyZXNwb25kaW5nIGVsZW1lbnRzLlxuICAgKlxuICAgKiAgICBQbGVhc2UgdGFrZSBhIGxvb2sgYXQgW01ETl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRNTC9FbGVtZW50L2lucHV0I2F0dHItdHlwZSkgZm9yIGFuIGV4aGF1c3RpdmUgbGlzdCBvZiBwb3NzaWJsZSB2YWx1ZXMuIERlcGVuZGluZyBvbiB0aGUgcGxhdGZvcm0gYW5kIGJyb3dzZXIgdmVyc2lvbiBzb21lIG9mIHRoZXNlIG1pZ2h0IG5vdCB3b3JrLlxuICAgKiAgWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbnB1dC1pZFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBcImlkXCIgYXR0cmlidXRlIG9mIHRoZSBpbm5lciBgPGlucHV0PmAgZWxlbWVudC4gVGhpcyBpcyB1c2VmdWwgd2hlbiB1c2luZyBgPGxhYmVsIGZvcj1cIi4uLlwiPmAgZWxlbWVudHMuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgaW5wdXQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGlucHV0IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbn1cblxub25zRWxlbWVudHMuSW5wdXQgPSBJbnB1dEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1pbnB1dCcsIElucHV0RWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IEJhc2VJbnB1dEVsZW1lbnQgZnJvbSAnLi9iYXNlLWlucHV0JztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBCYXNlQ2hlY2tib3hFbGVtZW50IGV4dGVuZHMgQmFzZUlucHV0RWxlbWVudCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yID09PSBCYXNlQ2hlY2tib3hFbGVtZW50KSB7XG4gICAgICB1dGlsLnRocm93QWJzdHJhY3QoKTtcbiAgICB9XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2soJ2NoZWNrZWQnLCBudWxsLCB0aGlzLmdldEF0dHJpYnV0ZSgnY2hlY2tlZCcpKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qIEluaGVyaXRlZCBwcm9wcyAqL1xuXG4gIGdldCBfdGVtcGxhdGUoKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgIDxpbnB1dCB0eXBlPVwiJHt0aGlzLnR5cGV9XCIgY2xhc3M9XCIke3RoaXMuX2RlZmF1bHRDbGFzc05hbWV9X19pbnB1dFwiPlxuICAgICAgPHNwYW4gY2xhc3M9XCIke3RoaXMuX2RlZmF1bHRDbGFzc05hbWV9X19jaGVja21hcmtcIj48L3NwYW4+XG4gICAgYDtcbiAgfVxuXG4gIC8qIE93biBwcm9wcyAqL1xuXG4gIGdldCBfaGVscGVyKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJ3NwYW4nKTtcbiAgfVxuXG4gIGdldCBjaGVja2VkKCkge1xuICAgIHJldHVybiB0aGlzLl9pbnB1dC5jaGVja2VkO1xuICB9XG5cbiAgc2V0IGNoZWNrZWQodmFsKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2lucHV0LmNoZWNrZWQgPSB2YWw7XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWy4uLnN1cGVyLm9ic2VydmVkQXR0cmlidXRlcywgJ2NoZWNrZWQnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjaGVja2VkJzpcbiAgICAgICAgdGhpcy5jaGVja2VkID0gY3VycmVudCAhPT0gbnVsbDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBzdXBlci5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCk7XG4gICAgfVxuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUNoZWNrYm94RWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1jaGVja2JveCc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5jaGVja2JveCc6ICdjaGVja2JveC0tKicsXG4gICcuY2hlY2tib3hfX2lucHV0JzogJ2NoZWNrYm94LS0qX19pbnB1dCcsXG4gICcuY2hlY2tib3hfX2NoZWNrbWFyayc6ICdjaGVja2JveC0tKl9fY2hlY2ttYXJrJ1xufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtY2hlY2tib3hcbiAqIEBjYXRlZ29yeSBmb3JtXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICBbZW5dRGlzcGxheXMgYSBNYXRlcmlhbCBEZXNpZ24gY2hlY2tib3guWy9lbl1cbiAqICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciBub2JvcmRlclxuICogIFtlbl1pT1MgYm9yZGVybGVzcyBjaGVja2JveC5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgQSBjaGVja2JveCBlbGVtZW50LiBUaGUgY29tcG9uZW50IHdpbGwgYXV0b21hdGljYWxseSByZW5kZXIgYXMgYSBNYXRlcmlhbCBEZXNpZ24gY2hlY2tib3ggb24gQW5kcm9pZCBkZXZpY2VzLlxuICpcbiAqICAgIE1vc3QgYXR0cmlidXRlcyB0aGF0IGNhbiBiZSB1c2VkIGZvciBhIG5vcm1hbCBgPGlucHV0IHR5cGU9XCJjaGVja2JveFwiPmAgZWxlbWVudCBjYW4gYWxzbyBiZSB1c2VkIG9uIHRoZSBgPG9ucy1jaGVja2JveD5gIGVsZW1lbnQuXG4gKiAgWy9lbl1cbiAqICBbamFdWy9qYV1cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9jaGVja2JveFxuICogQHNlZWFsc28gb25zLXN3aXRjaFxuICogICBbZW5dVGhlIGA8b25zLXN3aXRjaD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgZHJhZ2dhYmxlIHRvZ2dsZSBzd2l0Y2guWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcmFkaW9cbiAqICAgW2VuXVRoZSBgPG9ucy1yYWRpbz5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgcmFkaW8gYnV0dG9uLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLWlucHV0XG4gKiAgIFtlbl1UaGUgYDxvbnMtaW5wdXQ+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIHRleHQgaW5wdXQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtc2VhcmNoLWlucHV0XG4gKiAgIFtlbl1UaGUgYDxvbnMtc2VhcmNoLWlucHV0PmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSBzZWFyY2ggaW5wdXQuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcmFuZ2VcbiAqICAgW2VuXVRoZSBgPG9ucy1yYW5nZT5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgcmFuZ2Ugc2xpZGVyLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXNlbGVjdFxuICogICBbZW5dVGhlIGA8b25zLXNlbGVjdD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgc2VsZWN0IGJveC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjbW9kaWZpZXJzIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtY2hlY2tib3ggY2hlY2tlZD48L29ucy1jaGVja2JveD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQ2hlY2tib3hFbGVtZW50IGV4dGVuZHMgQmFzZUNoZWNrYm94RWxlbWVudCB7XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHNjaGVtZTtcbiAgfVxuXG4gIGdldCBfZGVmYXVsdENsYXNzTmFtZSgpIHtcbiAgICByZXR1cm4gJ2NoZWNrYm94JztcbiAgfVxuXG4gIGdldCB0eXBlKCkge1xuICAgIHJldHVybiAnY2hlY2tib3gnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaW5wdXQtaWRcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSB0aGUgXCJpZFwiIGF0dHJpYnV0ZSBvZiB0aGUgaW5uZXIgYDxpbnB1dD5gIGVsZW1lbnQuIFRoaXMgaXMgdXNlZnVsIHdoZW4gdXNpbmcgYDxsYWJlbCBmb3I9XCIuLi5cIj5gIGVsZW1lbnRzLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2YWx1ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGNoZWNrYm94LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2hlY2tlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGNoZWNrYm94IGlzIGNoZWNrZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBjaGVja2JveCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG59XG5cbm9uc0VsZW1lbnRzLkNoZWNrYm94ID0gQ2hlY2tib3hFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtY2hlY2tib3gnLCBDaGVja2JveEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IEJhc2VDaGVja2JveEVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtY2hlY2tib3gnO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcucmFkaW8tYnV0dG9uJzogJ3JhZGlvLWJ1dHRvbi0tKicsXG4gICcucmFkaW8tYnV0dG9uX19pbnB1dCc6ICdyYWRpby1idXR0b24tLSpfX2lucHV0JyxcbiAgJy5yYWRpby1idXR0b25fX2NoZWNrbWFyayc6ICdyYWRpby1idXR0b24tLSpfX2NoZWNrbWFyaydcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXJhZGlvXG4gKiBAY2F0ZWdvcnkgZm9ybVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgW2VuXURpc3BsYXlzIGEgTWF0ZXJpYWwgRGVzaWduIHJhZGlvIGJ1dHRvbi5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgQSByYWRpbyBidXR0b24gZWxlbWVudC4gVGhlIGNvbXBvbmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgcmVuZGVyIGFzIGEgTWF0ZXJpYWwgRGVzaWduIHJhZGlvIGJ1dHRvbiBvbiBBbmRyb2lkIGRldmljZXMuXG4gKlxuICogICAgTW9zdCBhdHRyaWJ1dGVzIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGEgbm9ybWFsIGA8aW5wdXQgdHlwZT1cInJhZGlvXCI+YCBlbGVtZW50IGNhbiBhbHNvIGJlIHVzZWQgb24gdGhlIGA8b25zLXJhZGlvPmAgZWxlbWVudC5cbiAqICBbL2VuXVxuICogIFtqYV1bL2phXVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3JhZGlvXG4gKiBAc2VlYWxzbyBvbnMtc2VsZWN0XG4gKiAgIFtlbl1UaGUgYDxvbnMtc2VsZWN0PmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSBzZWxlY3QgYm94LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLWNoZWNrYm94XG4gKiAgIFtlbl1UaGUgYDxvbnMtY2hlY2tib3g+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIGNoZWNrYm94LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXN3aXRjaFxuICogICBbZW5dVGhlIGA8b25zLXN3aXRjaD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgZHJhZ2dhYmxlIHRvZ2dsZSBzd2l0Y2guWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAc2VlYWxzbyBvbnMtaW5wdXRcbiAqICAgW2VuXVRoZSBgPG9ucy1pbnB1dD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgdGV4dCBpbnB1dC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zZWFyY2gtaW5wdXRcbiAqICAgW2VuXVRoZSBgPG9ucy1zZWFyY2gtaW5wdXQ+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIHNlYXJjaCBpbnB1dC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1yYW5nZVxuICogICBbZW5dVGhlIGA8b25zLXJhbmdlPmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSByYW5nZSBzbGlkZXIuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI21vZGlmaWVycyBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXJhZGlvIGNoZWNrZWQ+PC9vbnMtcmFkaW8+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJhZGlvRWxlbWVudCBleHRlbmRzIEJhc2VDaGVja2JveEVsZW1lbnQge1xuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiBzY2hlbWU7XG4gIH1cblxuICBnZXQgX2RlZmF1bHRDbGFzc05hbWUoKSB7XG4gICAgcmV0dXJuICdyYWRpby1idXR0b24nO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdyYWRpbyc7XG4gIH1cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbnB1dC1pZFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBcImlkXCIgYXR0cmlidXRlIG9mIHRoZSBpbm5lciBgPGlucHV0PmAgZWxlbWVudC4gVGhpcyBpcyB1c2VmdWwgd2hlbiB1c2luZyBgPGxhYmVsIGZvcj1cIi4uLlwiPmAgZWxlbWVudHMuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgcmFkaW8gYnV0dG9uLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2hlY2tlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIHJhZGlvIGJ1dHRvbiBpcyBjaGVja2VkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgcmFkaW8gYnV0dG9uIGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbn1cblxub25zRWxlbWVudHMuUmFkaW8gPSBSYWRpb0VsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1yYWRpbycsIFJhZGlvRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUlucHV0RWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1pbnB1dCc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5zZWFyY2gtaW5wdXQnOiAnc2VhcmNoLWlucHV0LS0qJ1xufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc2VhcmNoLWlucHV0XG4gKiBAY2F0ZWdvcnkgZm9ybVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgW2VuXURpc3BsYXlzIGEgTWF0ZXJpYWwgRGVzaWduIHNlYXJjaCBpbnB1dC5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgQSBzZWFyY2ggaW5wdXQgZWxlbWVudC4gVGhlIGNvbXBvbmVudCB3aWxsIGF1dG9tYXRpY2FsbHkgcmVuZGVyIGFzIGEgTWF0ZXJpYWwgRGVzaWduIHNlYXJjaCBpbnB1dCBvbiBBbmRyb2lkIGRldmljZXMuXG4gKlxuICogICAgTW9zdCBhdHRyaWJ1dGVzIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGEgbm9ybWFsIGA8aW5wdXQ+YCBlbGVtZW50IGNhbiBhbHNvIGJlIHVzZWQgb24gdGhlIGA8b25zLXNlYXJjaC1pbnB1dD5gIGVsZW1lbnQuXG4gKiAgWy9lbl1cbiAqICBbamFdWy9qYV1cbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9zZWFyY2gtaW5wdXRcbiAqIEBzZWVhbHNvIG9ucy1pbnB1dFxuICogICBbZW5dVGhlIGA8b25zLWlucHV0PmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSB0ZXh0IGlucHV0LlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXJhbmdlXG4gKiAgIFtlbl1UaGUgYDxvbnMtcmFuZ2U+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIHJhbmdlIHNsaWRlci5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zd2l0Y2hcbiAqICAgW2VuXVRoZSBgPG9ucy1zd2l0Y2g+YCBlbGVtZW50IGlzIHVzZWQgdG8gZGlzcGxheSBhIGRyYWdnYWJsZSB0b2dnbGUgc3dpdGNoLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLXNlbGVjdFxuICogICBbZW5dVGhlIGA8b25zLXNlbGVjdD5gIGVsZW1lbnQgaXMgdXNlZCB0byBkaXNwbGF5IGEgc2VsZWN0IGJveC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1jaGVja2JveFxuICogICBbZW5dVGhlIGA8b25zLWNoZWNrYm94PmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSBjaGVja2JveC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1yYWRpb1xuICogICBbZW5dVGhlIGA8b25zLXJhZGlvPmAgZWxlbWVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSByYWRpbyBidXR0b24uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI21vZGlmaWVycyBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXNlYXJjaC1pbnB1dCBwbGFjZWhvbGRlcj1cIlNlYXJjaFwiPjwvb25zLXNlYXJjaC1pbnB1dD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2VhcmNoSW5wdXRFbGVtZW50IGV4dGVuZHMgQmFzZUlucHV0RWxlbWVudCB7XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHNjaGVtZTtcbiAgfVxuXG4gIGdldCBfdGVtcGxhdGUoKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgIDxpbnB1dCB0eXBlPVwiJHt0aGlzLnR5cGV9XCIgY2xhc3M9XCJzZWFyY2gtaW5wdXRcIj5cbiAgICBgO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdzZWFyY2gnO1xuICB9XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaW5wdXQtaWRcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSB0aGUgXCJpZFwiIGF0dHJpYnV0ZSBvZiB0aGUgaW5uZXIgYDxpbnB1dD5gIGVsZW1lbnQuIFRoaXMgaXMgdXNlZnVsIHdoZW4gdXNpbmcgYDxsYWJlbCBmb3I9XCIuLi5cIj5gIGVsZW1lbnRzLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2YWx1ZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGlucHV0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBpbnB1dCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG59XG5cbm9uc0VsZW1lbnRzLlNlYXJjaElucHV0ID0gU2VhcmNoSW5wdXRFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc2VhcmNoLWlucHV0JywgU2VhcmNoSW5wdXRFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBCYXNlQW5pbWF0b3IgZnJvbSAnLi4vLi4vb25zL2Jhc2UtYW5pbWF0b3InO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNb2RhbEFuaW1hdG9yIGV4dGVuZHMgQmFzZUFuaW1hdG9yIHtcblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnNcbiAgICogQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMudGltaW5nXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLmR1cmF0aW9uXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBvcHRpb25zLmRlbGF5XG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2xpbmVhcicsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjJ9ID0ge30pIHtcbiAgICBzdXBlcih7IHRpbWluZywgZGVsYXksIGR1cmF0aW9uIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IG1vZGFsXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KG1vZGFsLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbW9kYWxcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUobW9kYWwsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxufVxuIiwiXG4vKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IE1vZGFsQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5cbi8qKlxuICogaU9TIHN0eWxlIGFuaW1hdG9yIGZvciBkaWFsb2cuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZhZGVNb2RhbEFuaW1hdG9yIGV4dGVuZHMgTW9kYWxBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdsaW5lYXInLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4zfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBtb2RhbFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgc2hvdyhtb2RhbCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0KG1vZGFsLCB0aGlzLmRlZilcbiAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMCB9LCB7IG9wYWNpdHk6IDEgfSlcbiAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgZG9uZSgpO1xuICAgICAgfSlcbiAgICAgIC5wbGF5KCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbW9kYWxcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUobW9kYWwsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdChtb2RhbCwgdGhpcy5kZWYpXG4gICAgICAuZGVmYXVsdCh7IG9wYWNpdHk6IDEgfSwgeyBvcGFjaXR5OiAwIH0pXG4gICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH0pXG4gICAgICAucGxheSgpO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IE1vZGFsQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5cbi8qKlxuICogaU9TIHN0eWxlIGFuaW1hdG9yIGZvciBtb2RhbC5cbiAqL1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMaWZ0TW9kYWxBbmltYXRvciBleHRlbmRzIE1vZGFsQW5pbWF0b3JcbntcbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdjdWJpYy1iZXppZXIoIC4xLCAuNywgLjEsIDEpJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuNH0gPSB7fSkge1xuICAgIHN1cGVyKHsgdGltaW5nLCBkZWxheSwgZHVyYXRpb24gfSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbW9kYWxcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHNob3cobW9kYWwsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2sgPSBjYWxsYmFjayA/IGNhbGxiYWNrIDogZnVuY3Rpb24oKSB7fTtcblxuICAgIGFuaW1pdChtb2RhbCwgdGhpcy5kZWYpXG4gICAgICAuZGVmYXVsdChcbiAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAxMDAlLCAwKScgfSxcbiAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScgfVxuICAgICAgKVxuICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KVxuICAgICAgLnBsYXkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBtb2RhbFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgaGlkZShtb2RhbCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0KG1vZGFsLCB0aGlzLmRlZilcbiAgICAgIC5kZWZhdWx0KFxuICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJyB9LFxuICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDEwMCUsIDApJyB9XG4gICAgICApXG4gICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgIGRvbmUoKTtcbiAgICAgIH0pXG4gICAgICAucGxheSgpO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgTW9kYWxBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcbmltcG9ydCBGYWRlTW9kYWxBbmltYXRvciBmcm9tICcuL2ZhZGUtYW5pbWF0b3InO1xuaW1wb3J0IExpZnRNb2RhbEFuaW1hdG9yIGZyb20gJy4vbGlmdC1hbmltYXRvcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRGlhbG9nRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZGlhbG9nJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcnOiAnbW9kYWwtLSonLFxuICAnbW9kYWxfX2NvbnRlbnQnOiAnbW9kYWwtLSpfX2NvbnRlbnQnXG59O1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ21vZGFsJztcblxuY29uc3QgX2FuaW1hdG9yRGljdCA9IHtcbiAgJ2RlZmF1bHQnOiBNb2RhbEFuaW1hdG9yLFxuICAnZmFkZSc6IEZhZGVNb2RhbEFuaW1hdG9yLFxuICAnbGlmdCc6IExpZnRNb2RhbEFuaW1hdG9yLFxuICAnbm9uZSc6IE1vZGFsQW5pbWF0b3Jcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLW1vZGFsXG4gKiBAY2F0ZWdvcnkgZGlhbG9nXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIE1vZGFsIGNvbXBvbmVudCB0aGF0IG1hc2tzIGN1cnJlbnQgc2NyZWVuLiBVbmRlcmx5aW5nIGNvbXBvbmVudHMgYXJlIG5vdCBzdWJqZWN0IHRvIGFueSBldmVudHMgd2hpbGUgdGhlIG1vZGFsIGNvbXBvbmVudCBpcyBzaG93bi5cbiAqXG4gKiAgICAgVGhpcyBjb21wb25lbnQgY2FuIGJlIHVzZWQgdG8gYmxvY2sgdXNlciBpbnB1dCB3aGlsZSBzb21lIG9wZXJhdGlvbiBpcyBydW5uaW5nIG9yIHRvIHNob3cgc29tZSBpbmZvcm1hdGlvbiB0byB0aGUgdXNlci5cbiAqICAgWy9lbl1cbiAqICAgW2phXVxuICogICAgIOeUu+mdouWFqOS9k+OCkuODnuOCueOCr+OBmeOCi+ODouODvOODgOODq+eUqOOCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAguS4i+WBtOOBq+OBguOCi+OCs+ODs+ODneODvOODjeODs+ODiOOBr+OAgVxuICogICAgIOODouODvOODgOODq+OBjOihqOekuuOBleOCjOOBpuOBhOOCi+mWk+OBr+OCpOODmeODs+ODiOmAmuefpeOBjOihjOOCj+OCjOOBvuOBm+OCk+OAglxuICogICBbL2phXVxuICogQHNlZWFsc28gb25zLWRpYWxvZ1xuICogICBbZW5dVGhlIGA8b25zLWRpYWxvZz5gIGNvbXBvbmVudCBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYSBtb2RhbCBkaWFsb2cuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAY29kZXBlbiBkZXZJZ1xuICogQHR1dG9yaWFsIHZhbmlsbGEvcmVmZXJlbmNlL21vZGFsXG4gKiBAZXhhbXBsZVxuICogPG9ucy1tb2RhbCBpZD1cIm1vZGFsXCI+XG4gKiAgIE1vZGFsIGNvbnRlbnRcbiAqIDwvb25zLW1vZGFsPlxuICogPHNjcmlwdD5cbiAqICAgdmFyIG1vZGFsID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21vZGFsJyk7XG4gKiAgIG1vZGFsLnNob3coKTtcbiAqIDwvc2NyaXB0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNb2RhbEVsZW1lbnQgZXh0ZW5kcyBCYXNlRGlhbG9nRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBldmVudCBwcmVzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiBbZW5dRmlyZWQganVzdCBiZWZvcmUgdGhlIG1vZGFsIGlzIGRpc3BsYXllZC5bL2VuXVxuICAgKiBbamFd44Oi44O844OA44Or44GM6KGo56S644GV44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50Lm1vZGFsXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUV4ZWN1dGUgdGhpcyBmdW5jdGlvbiB0byBzdG9wIHRoZSBtb2RhbCBmcm9tIGJlaW5nIHNob3duLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWun+ihjOOBmeOCi+OBqOOAgeODgOOCpOOCouODreOCsOOBruihqOekuuOBjOOCreODo+ODs+OCu+ODq+OBleOCjOOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdHNob3dcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBtb2RhbCBpcyBkaXNwbGF5ZWQuWy9lbl1cbiAgICogW2phXeODouODvOODgOODq+OBjOihqOekuuOBleOCjOOBn+ebtOW+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5tb2RhbFxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlaGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBtb2RhbCBpcyBoaWRkZW4uWy9lbl1cbiAgICogW2phXeODouODvOODgOODq+OBjOmaoOOCjOOCi+ebtOWJjeOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5tb2RhbFxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LmNhbmNlbFxuICAgKiAgIFtlbl1FeGVjdXRlIHRoaXMgZnVuY3Rpb24gdG8gc3RvcCB0aGUgbW9kYWwgZnJvbSBiZWluZyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44GT44Gu6Zai5pWw44KS5a6f6KGM44GZ44KL44Go44CB44OA44Kk44Ki44Ot44Kw44Gu6Z2e6KGo56S644GM44Kt44Oj44Oz44K744Or44GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0aGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIG1vZGFsIGlzIGhpZGRlbi5bL2VuXVxuICAgKiBbamFd44Oi44O844OA44Or44GM6Zqg44KM44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50Lm1vZGFsXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFuaW1hdGlvbiB1c2VkIHdoZW4gc2hvd2luZyBhbmQgaGlkaW5nIHRoZSBtb2RhbC4gQ2FuIGJlIGVpdGhlciBgXCJub25lXCJgLCBgXCJmYWRlXCJgIG9yIGBcImxpZnRcImAuWy9lbl1cbiAgICogIFtqYV3jg6Ljg7zjg4Djg6vjgpLooajnpLrjgZnjgovpmpvjga7jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIuOCguOBl+OBj+OBr1wiZmFkZVwiLFwibGlmdFwi44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCB0aW1pbmcsIGRlbGF544KS44Kq44OW44K444Kn44Kv44OI44Oq44OG44Op44Or44Gn5oyH5a6a44GX44G+44GZ44CCZS5nLiA8Y29kZT57ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfTwvY29kZT5bL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fZGVmYXVsdERCQiA9ICgpID0+IHVuZGVmaW5lZDtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcbiAgfVxuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiBzY2hlbWU7XG4gIH1cblxuICBfdXBkYXRlQW5pbWF0b3JGYWN0b3J5KCkge1xuICAgIHJldHVybiBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogTW9kYWxBbmltYXRvcixcbiAgICAgIGJhc2VDbGFzc05hbWU6ICdNb2RhbEFuaW1hdG9yJyxcbiAgICAgIGRlZmF1bHRBbmltYXRpb246IHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24nKVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIHRoaXMuc3R5bGUuekluZGV4ID0gMTAwMDE7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLm1vZGFsX19jb250ZW50JykpIHtcbiAgICAgIGNvbnN0IGNvbnRlbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIGNvbnRlbnQuY2xhc3NMaXN0LmFkZCgnbW9kYWxfX2NvbnRlbnQnKTtcblxuICAgICAgd2hpbGUgKHRoaXMuY2hpbGROb2Rlc1swXSkge1xuICAgICAgICBjb25zdCBub2RlID0gdGhpcy5jaGlsZE5vZGVzWzBdO1xuICAgICAgICB0aGlzLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICBjb250ZW50Lmluc2VydEJlZm9yZShub2RlLCBudWxsKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZChjb250ZW50KTtcbiAgICB9XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHRoaXMuX3NjaGVtZSk7XG4gIH1cblxuICBfdG9nZ2xlU3R5bGUoc2hvdWxkU2hvdykge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9IHNob3VsZFNob3cgPyAndGFibGUnIDogJ25vbmUnO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgc3VwZXIuY29ubmVjdGVkQ2FsbGJhY2soKTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHN1cGVyLmRpc2Nvbm5lY3RlZENhbGxiYWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZpc2libGVcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyB2aXNpYmxlIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3opoHntKDjgYzopovjgYjjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCBzaG93XG4gICAqIEBzaWduYXR1cmUgc2hvdyhbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcIm5vbmVcImAgYW5kIGBcImZhZGVcImAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJub25lXCIsIFwiZmFkZVwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1UaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBhZnRlciB0aGUgbW9kYWwgaGFzIGJlZW4gcmV2ZWFsZWQuWy9lbl1cbiAgICogICBbamFd44Oi44O844OA44Or44GM6KGo56S644GV44KM57WC44KP44Gj44Gf5b6M44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgbW9kYWwuWy9lbl1cbiAgICogICBbamFd44Oi44O844OA44Or44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGRpc3BsYXllZCBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBtZXRob2QgdG9nZ2xlXG4gICAqIEBzaWduYXR1cmUgdG9nZ2xlKFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgYW5pbWF0aW9ucyBhcmUgYFwibm9uZVwiYCBhbmQgYFwiZmFkZVwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PlkI3jgpLmjIflrprjgZfjgb7jgZnjgIJcIm5vbmVcIiwgXCJmYWRlXCLjga7jgYTjgZrjgozjgYvjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIGFmdGVyIHRoZSBtb2RhbCBoYXMgYmVlbiByZXZlYWxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg6Ljg7zjg4Djg6vjgYzooajnpLrjgZXjgozntYLjgo/jgaPjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVG9nZ2xlIG1vZGFsIHZpc2liaWxpdHkuWy9lbl1cbiAgICogICBbamFd44Oi44O844OA44Or44Gu6KGo56S644KS5YiH44KK5pu/44GI44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZVxuICAgKiBAc2lnbmF0dXJlIGhpZGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJub25lXCJgIGFuZCBgXCJmYWRlXCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwibm9uZVwiLCBcImZhZGVcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgZGVsYXkgYW5kIHRpbWluZy4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIGRlbGF5LCB0aW1pbmfjgpLmjIflrprjgZfjgb7jgZnjgIJlLmcuIHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31bL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYWZ0ZXIgdGhlIG1vZGFsIGhhcyBiZWVuIHJldmVhbGVkLlsvZW5dXG4gICAqICAgW2phXeODouODvOODgOODq+OBjOihqOekuuOBleOCjOe1guOCj+OBo+OBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1IaWRlIG1vZGFsLlsvZW5dXG4gICAqICAgW2phXeODouODvOODgOODq+OCkumdnuihqOekuuOBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBoaWRkZW4gZWxlbWVudFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbLi4uc3VwZXIub2JzZXJ2ZWRBdHRyaWJ1dGVzLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdjbGFzcycpIHtcbiAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN1cGVyLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gQW5pbWF0b3JcbiAgICovXG4gIHN0YXRpYyByZWdpc3RlckFuaW1hdG9yKG5hbWUsIEFuaW1hdG9yKSB7XG4gICAgaWYgKCEoQW5pbWF0b3IucHJvdG90eXBlIGluc3RhbmNlb2YgTW9kYWxBbmltYXRvcikpIHtcbiAgICAgIHV0aWwudGhyb3dBbmltYXRvcignTW9kYWwnKTtcbiAgICB9XG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG5cbiAgc3RhdGljIGdldCBhbmltYXRvcnMoKSB7XG4gICAgcmV0dXJuIF9hbmltYXRvckRpY3Q7XG4gIH1cblxuICBzdGF0aWMgZ2V0IE1vZGFsQW5pbWF0b3IoKSB7XG4gICAgcmV0dXJuIE1vZGFsQW5pbWF0b3I7XG4gIH1cbn1cblxub25zRWxlbWVudHMuTW9kYWwgPSBNb2RhbEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1tb2RhbCcsIE1vZGFsRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgR2VzdHVyZURldGVjdG9yIGZyb20gJy4uLy4uL29ucy9nZXN0dXJlLWRldGVjdG9yJztcblxuY29uc3Qgd2lkdGhUb1B4ID0gKHdpZHRoKSA9PiB7XG4gIGNvbnN0IFt2YWx1ZSwgcHhdID0gW3BhcnNlSW50KHdpZHRoLCAxMCksIC9weC8udGVzdCh3aWR0aCldO1xuICByZXR1cm4gcHggPyB2YWx1ZSA6IE1hdGgucm91bmQoZG9jdW1lbnQuYm9keS5vZmZzZXRXaWR0aCAqIHZhbHVlIC8gMTAwKTtcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN3aXBlUmV2ZWFsIHtcblxuICBjb25zdHJ1Y3RvcihwYXJhbXMpIHtcbiAgICAnZWxlbWVudCBpZ25vcmVTd2lwZSBpc0luaXRpYWxTdGF0ZSBvbkRyYWdDYWxsYmFjayBzd2lwZU1heCBzd2lwZU1pbiBzd2lwZU1pZCdcbiAgICAgIC5zcGxpdCgvXFxzKy8pLmZvckVhY2goa2V5ID0+IHRoaXNba2V5XSA9IHBhcmFtc1trZXldKTtcblxuICAgIHRoaXMuZWxlbWVudEhhbmRsZXIgPSBwYXJhbXMuZWxlbWVudEhhbmRsZXIgfHwgcGFyYW1zLmVsZW1lbnQ7XG4gICAgdGhpcy5nZXRUaHJlc2hvbGQgPSBwYXJhbXMuZ2V0VGhyZXNob2xkIHx8ICgoKSA9PiAuNSk7XG4gICAgdGhpcy5nZXRTaWRlID0gcGFyYW1zLmdldFNpZGUgfHwgKCgpID0+ICdsZWZ0Jyk7XG5cbiAgICB0aGlzLmhhbmRsZUdlc3R1cmUgPSB0aGlzLmhhbmRsZUdlc3R1cmUuYmluZCh0aGlzKTtcblxuICAgIHRoaXMuX3Nob3VsZEZpeFNjcm9sbCA9IHV0aWwuZ2xvYmFscy5hY3R1YWxNb2JpbGVPUyA9PT0gJ2lvcyc7XG4gIH1cblxuICB1cGRhdGUoc3dpcGVhYmxlID0gdGhpcy5lbGVtZW50Lmhhc0F0dHJpYnV0ZSgnc3dpcGVhYmxlJykpIHtcbiAgICBpZiAoIXRoaXMuZ2VzdHVyZURldGVjdG9yKSB7XG4gICAgICB0aGlzLmdlc3R1cmVEZXRlY3RvciA9IG5ldyBHZXN0dXJlRGV0ZWN0b3IodGhpcy5lbGVtZW50SGFuZGxlciwgeyBkcmFnTWluRGlzdGFuY2U6IDEsIHBhc3NpdmU6ICF0aGlzLl9zaG91bGRGaXhTY3JvbGwgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgYWN0aW9uID0gc3dpcGVhYmxlID8gJ29uJyA6ICdvZmYnO1xuICAgIHRoaXMuZ2VzdHVyZURldGVjdG9yW2FjdGlvbl0oJ2RyYWcgZHJhZ3N0YXJ0IGRyYWdlbmQnLCB0aGlzLmhhbmRsZUdlc3R1cmUpO1xuICB9XG5cbiAgaGFuZGxlR2VzdHVyZShlKSB7XG4gICAgaWYgKGUuZ2VzdHVyZSkge1xuICAgICAgaWYgKGUudHlwZSA9PT0gJ2RyYWdzdGFydCcpIHtcbiAgICAgICAgdGhpcy5vbkRyYWdTdGFydChlKTtcbiAgICAgIH0gZWxzZSBpZiAoIXRoaXMuX2lnbm9yZURyYWcpIHtcbiAgICAgICAgZS50eXBlID09PSAnZHJhZ2VuZCcgPyB0aGlzLm9uRHJhZ0VuZChlKSA6IHRoaXMub25EcmFnKGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG9uRHJhZ1N0YXJ0KGV2ZW50KSB7XG4gICAgY29uc3QgZ2V0RGlzdGFuY2UgPSAoKSA9PiB0aGlzLmdldFNpZGUoKSA9PT0gJ2xlZnQnID8gZXZlbnQuZ2VzdHVyZS5jZW50ZXIuY2xpZW50WCA6IHdpbmRvdy5pbm5lcldpZHRoIC0gZXZlbnQuZ2VzdHVyZS5jZW50ZXIuY2xpZW50WDtcbiAgICB0aGlzLl9pZ25vcmVEcmFnID0gZXZlbnQuY29uc3VtZWQgfHwgIXV0aWwuaXNWYWxpZEdlc3R1cmUoZXZlbnQpIHx8IHRoaXMuaWdub3JlU3dpcGUoZXZlbnQsIGdldERpc3RhbmNlKCkpO1xuXG4gICAgaWYgKCF0aGlzLl9pZ25vcmVEcmFnKSB7XG4gICAgICBldmVudC5jb25zdW1lICYmIGV2ZW50LmNvbnN1bWUoKTtcbiAgICAgIGV2ZW50LmNvbnN1bWVkID0gdHJ1ZTtcblxuICAgICAgdGhpcy5fd2lkdGggPSB3aWR0aFRvUHgodGhpcy5lbGVtZW50LnN0eWxlLndpZHRoIHx8ICcxMDAlJyk7XG4gICAgICB0aGlzLl9zdGFydERpc3RhbmNlID0gdGhpcy5fZGlzdGFuY2UgPSAoISh0aGlzLmlzSW5pdGlhbFN0YXRlIGluc3RhbmNlb2YgRnVuY3Rpb24pIHx8IHRoaXMuaXNJbml0aWFsU3RhdGUoKSkgPyAwIDogdGhpcy5fd2lkdGg7XG5cbiAgICAgIHV0aWwuaW9zUHJldmVudFNjcm9sbCh0aGlzLmdlc3R1cmVEZXRlY3Rvcik7XG4gICAgfVxuICB9XG5cbiAgb25EcmFnKGV2ZW50KSB7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICBjb25zdCBkZWx0YSA9IHRoaXMuZ2V0U2lkZSgpID09PSAnbGVmdCcgPyBldmVudC5nZXN0dXJlLmRlbHRhWCA6IC1ldmVudC5nZXN0dXJlLmRlbHRhWDtcbiAgICBjb25zdCBkaXN0YW5jZSA9IE1hdGgubWF4KDAsIE1hdGgubWluKHRoaXMuX3dpZHRoLCB0aGlzLl9zdGFydERpc3RhbmNlICsgZGVsdGEpKTtcbiAgICBpZiAoZGlzdGFuY2UgIT09IHRoaXMuX2Rpc3RhbmNlKSB7XG4gICAgICB0aGlzLl9kaXN0YW5jZSA9IGRpc3RhbmNlO1xuICAgICAgdGhpcy5zd2lwZU1pZCh0aGlzLl9kaXN0YW5jZSwgdGhpcy5fd2lkdGgpO1xuICAgIH1cbiAgfVxuXG4gIG9uRHJhZ0VuZChldmVudCkge1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgY29uc3QgZGlyZWN0aW9uID0gZXZlbnQuZ2VzdHVyZS5pbnRlcmltRGlyZWN0aW9uO1xuICAgIGNvbnN0IGlzU3dpcGVNYXggPSB0aGlzLmdldFNpZGUoKSAhPT0gZGlyZWN0aW9uICYmIHRoaXMuX2Rpc3RhbmNlID4gdGhpcy5fd2lkdGggKiB0aGlzLmdldFRocmVzaG9sZCgpO1xuICAgIGlzU3dpcGVNYXggPyB0aGlzLnN3aXBlTWF4KCkgOiB0aGlzLnN3aXBlTWluKCk7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMuZ2VzdHVyZURldGVjdG9yICYmIHRoaXMuZ2VzdHVyZURldGVjdG9yLmRpc3Bvc2UoKTtcbiAgICB0aGlzLmdlc3R1cmVEZXRlY3RvciA9IHRoaXMuZWxlbWVudCA9IHRoaXMuZWxlbWVudEhhbmRsZXIgPSBudWxsO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgQmFzZUFuaW1hdG9yIGZyb20gJy4uLy4uL29ucy9iYXNlLWFuaW1hdG9yJ1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBOYXZpZ2F0b3JBbmltYXRvciBleHRlbmRzIEJhc2VBbmltYXRvciB7XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnRpbWluZ1xuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kdXJhdGlvblxuICAgKiBAcGFyYW0ge051bWJlcn0gb3B0aW9ucy5kZWxheVxuICAgKi9cbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7XG4gICAgICB0aW1pbmc6ICdsaW5lYXInLFxuICAgICAgZHVyYXRpb246ICcwLjQnLFxuICAgICAgZGVsYXk6ICcwJ1xuICAgIH0sIG9wdGlvbnMgfHwge30pO1xuXG4gICAgc3VwZXIob3B0aW9ucyk7XG4gIH1cblxuICBwdXNoKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrKCk7XG4gIH1cblxuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIGJsb2NrKHBhZ2UpIHtcbiAgICBjb25zdCBibG9ja2VyID0gdXRpbC5jcmVhdGVFbGVtZW50KGBcbiAgICAgIDxkaXYgc3R5bGU9XCJwb3NpdGlvbjogYWJzb2x1dGU7IGJhY2tncm91bmQtY29sb3I6IHRyYW5zcGFyZW50OyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlOyB6LWluZGV4OiAxMDAwMDBcIj48L2Rpdj5cbiAgICBgKTtcbiAgICBwYWdlLnBhcmVudE5vZGUuYXBwZW5kQ2hpbGQoYmxvY2tlcik7XG4gICAgcmV0dXJuICgpID0+IGJsb2NrZXIucmVtb3ZlKCk7XG4gIH1cbn1cblxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE5hdmlnYXRvckFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcblxuLyoqXG4gKiBBYnN0cmFjdCBzd2lwZSBhbmltYXRvciBmb3IgaU9TIG5hdmlnYXRvciB0cmFuc2l0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJT1NTd2lwZU5hdmlnYXRvckFuaW1hdG9yIGV4dGVuZHMgTmF2aWdhdG9yQW5pbWF0b3Ige1xuXG4gIHN0YXRpYyBnZXQgc3dpcGVhYmxlKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3RydWN0b3IoeyBkdXJhdGlvblJlc3RvcmUgPSAwLjEsIGR1cmF0aW9uU3dpcGUgPSAwLjE1LCB0aW1pbmdTd2lwZSA9ICdsaW5lYXInLCAuLi5yZXN0IH0gPSB7fSkge1xuICAgIHN1cGVyKHsuLi5yZXN0fSk7XG5cbiAgICBpZiAodGhpcy5jb25zdHJ1Y3RvciA9PT0gSU9TU3dpcGVOYXZpZ2F0b3JBbmltYXRvcikge1xuICAgICAgdXRpbC50aHJvd0Fic3RyYWN0KCk7XG4gICAgfVxuXG4gICAgdGhpcy5kdXJhdGlvblJlc3RvcmUgPSBkdXJhdGlvblJlc3RvcmU7XG4gICAgdGhpcy5kdXJhdGlvblN3aXBlID0gZHVyYXRpb25Td2lwZTtcbiAgICB0aGlzLnRpbWluZ1N3aXBlID0gdGltaW5nU3dpcGU7XG5cbiAgICB0aGlzLm9wdFN3aXBlID0geyB0aW1pbmc6IHRpbWluZ1N3aXBlLCBkdXJhdGlvbjogZHVyYXRpb25Td2lwZSB9O1xuICAgIHRoaXMub3B0UmVzdG9yZSA9IHsgdGltaW5nOiB0aW1pbmdTd2lwZSwgZHVyYXRpb246IGR1cmF0aW9uUmVzdG9yZSB9O1xuXG4gICAgdGhpcy5zd2lwZVNoYWRvdyA9IHV0aWwuY3JlYXRlRWxlbWVudChcbiAgICAgIGA8ZGl2IHN0eWxlPVwicG9zaXRpb246IGFic29sdXRlOyBoZWlnaHQ6IDEwMCU7IHdpZHRoOiAxMnB4OyByaWdodDogMTAwJTsgdG9wOiAwOyBib3R0b206IDA7IHotaW5kZXg6IC0xO2AgK1xuICAgICAgICBgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KHRvIHJpZ2h0LCB0cmFuc3BhcmVudCAwLCByZ2JhKDAsMCwwLC4wNCkgNDAlLCByZ2JhKDAsMCwwLC4xMikgODAlLCByZ2JhKDAsMCwwLC4xNikgMTAwJSk7XCI+PC9kaXY+YFxuICAgICk7XG5cbiAgICB0aGlzLmlzRHJhZ1N0YXJ0ID0gdHJ1ZTtcbiAgfVxuXG4gIF9kZWNvbXBvc2UoKSB7XG4gICAgdXRpbC50aHJvd01lbWJlcigpO1xuICB9XG5cbiAgX3Nob3VsZEFuaW1hdGVUb29sYmFyKCkge1xuICAgIHV0aWwudGhyb3dNZW1iZXIoKTtcbiAgfVxuXG4gIF9jYWxjdWxhdGVEZWx0YSgpIHtcbiAgICB1dGlsLnRocm93TWVtYmVyKCk7XG4gIH1cblxuICBfZHJhZ1N0YXJ0U2V0dXAoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UpIHtcbiAgICB0aGlzLmlzRHJhZ1N0YXJ0ID0gZmFsc2U7XG5cbiAgICAvLyBBdm9pZCBjb250ZW50IGNsaWNrc1xuICAgIHRoaXMudW5ibG9jayA9IHN1cGVyLmJsb2NrKGxlYXZlUGFnZSk7XG5cbiAgICAvLyBNYXNrXG4gICAgZW50ZXJQYWdlLnBhcmVudEVsZW1lbnQuaW5zZXJ0QmVmb3JlKHRoaXMuYmFja2dyb3VuZE1hc2ssIGVudGVyUGFnZSk7XG5cbiAgICAvLyBEZWNvbXBvc2l0aW9uXG4gICAgdGhpcy50YXJnZXQgPSB7XG4gICAgICBlbnRlcjogdXRpbC5maW5kVG9vbGJhclBhZ2UoZW50ZXJQYWdlKSB8fCBlbnRlclBhZ2UsXG4gICAgICBsZWF2ZTogdXRpbC5maW5kVG9vbGJhclBhZ2UobGVhdmVQYWdlKSB8fCBsZWF2ZVBhZ2UsXG4gICAgfTtcbiAgICB0aGlzLmRlY29tcCA9IHtcbiAgICAgIGVudGVyOiB0aGlzLl9kZWNvbXBvc2UodGhpcy50YXJnZXQuZW50ZXIpLFxuICAgICAgbGVhdmU6IHRoaXMuX2RlY29tcG9zZSh0aGlzLnRhcmdldC5sZWF2ZSlcbiAgICB9O1xuXG4gICAgLy8gQW5pbWF0aW9uIHZhbHVlc1xuICAgIHRoaXMuZGVsdGEgPSB0aGlzLl9jYWxjdWxhdGVEZWx0YShsZWF2ZVBhZ2UsIHRoaXMuZGVjb21wLmxlYXZlKTtcbiAgICB0aGlzLnNob3VsZEFuaW1hdGVUb29sYmFyID0gdGhpcy5fc2hvdWxkQW5pbWF0ZVRvb2xiYXIodGhpcy50YXJnZXQuZW50ZXIsIHRoaXMudGFyZ2V0LmxlYXZlKTtcblxuICAgIC8vIFNoYWRvdyAmJiBzdHlsZXNcbiAgICBpZiAodGhpcy5zaG91bGRBbmltYXRlVG9vbGJhcikge1xuICAgICAgdGhpcy5zd2lwZVNoYWRvdy5zdHlsZS50b3AgPSB0aGlzLmRlY29tcC5sZWF2ZS50b29sYmFyLm9mZnNldEhlaWdodCArICdweCc7XG4gICAgICB0aGlzLnRhcmdldC5sZWF2ZS5hcHBlbmRDaGlsZCh0aGlzLnN3aXBlU2hhZG93KTtcbiAgICAgIHRoaXMuX3NhdmVTdHlsZSh0aGlzLnRhcmdldC5lbnRlciwgdGhpcy50YXJnZXQubGVhdmUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZWF2ZVBhZ2UuYXBwZW5kQ2hpbGQodGhpcy5zd2lwZVNoYWRvdyk7XG4gICAgICB0aGlzLl9zYXZlU3R5bGUoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UpO1xuICAgIH1cbiAgICBsZWF2ZVBhZ2UuY2xhc3NMaXN0LmFkZCgnb3ZlcmZsb3ctdmlzaWJsZScpO1xuICAgIHRoaXMub3ZlcmZsb3dFbGVtZW50ID0gbGVhdmVQYWdlO1xuICAgIHRoaXMuZGVjb21wLmxlYXZlLmNvbnRlbnQuY2xhc3NMaXN0LmFkZCgnY29udGVudC1zd2lwaW5nJyk7XG5cbiAgfVxuXG4gIHRyYW5zbGF0ZShkaXN0YW5jZSwgbWF4V2lkdGgsIGVudGVyUGFnZSwgbGVhdmVQYWdlKSB7XG4gICAgdGhpcy5pc1N3aXBpbmcgPSB0cnVlO1xuXG4gICAgaWYgKGVudGVyUGFnZS5zdHlsZS5kaXNwbGF5ID09PSAnbm9uZScpIHtcbiAgICAgIGVudGVyUGFnZS5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaXNEcmFnU3RhcnQpIHtcbiAgICAgIHRoaXMubWF4V2lkdGggPSBtYXhXaWR0aDtcbiAgICAgIHRoaXMuX2RyYWdTdGFydFNldHVwKGVudGVyUGFnZSwgbGVhdmVQYWdlKTtcbiAgICB9XG5cbiAgICBjb25zdCBzd2lwZVJhdGlvID0gKGRpc3RhbmNlIC0gbWF4V2lkdGgpIC8gbWF4V2lkdGg7XG5cbiAgICBpZiAodGhpcy5zaG91bGRBbmltYXRlVG9vbGJhcikge1xuXG4gICAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICAgIC8qIEVudGVyIHBhZ2UgKi9cblxuICAgICAgICBhbmltaXQoW3RoaXMuZGVjb21wLmVudGVyLmNvbnRlbnQsIHRoaXMuZGVjb21wLmVudGVyLmJvdHRvbVRvb2xiYXIsIHRoaXMuZGVjb21wLmVudGVyLmJhY2tncm91bmRdKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3N3aXBlUmF0aW8gKiAyNX0lLCAwLCAwKWAsXG4gICAgICAgICAgICBvcGFjaXR5OiAxICsgc3dpcGVSYXRpbyAqIDEwIC8gMTAwIC8vIDAuOSAtPiAxXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmVudGVyLnRvb2xiYXJDZW50ZXIpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKCR7dGhpcy5kZWx0YS50aXRsZSAqIHN3aXBlUmF0aW99cHgsIDAsIDApYCxcbiAgICAgICAgICAgIG9wYWNpdHk6IDEgKyBzd2lwZVJhdGlvIC8vIDAgLT4gMVxuICAgICAgICAgIH0pLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5lbnRlci5iYWNrQnV0dG9uTGFiZWwpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDEgKyBzd2lwZVJhdGlvICogMTAgLyAxMDAsIC8vIDAuOSAtPiAxXG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3RoaXMuZGVsdGEubGFiZWwgKiBzd2lwZVJhdGlvfXB4LCAwLCAwKWBcbiAgICAgICAgICB9KSxcblxuICAgICAgICBhbmltaXQodGhpcy5kZWNvbXAuZW50ZXIub3RoZXIpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDEgKyBzd2lwZVJhdGlvIC8vIDAgLT4gMVxuICAgICAgICAgIH0pLFxuXG4gICAgICAgIC8qIExlYXZlIHBhZ2UgKi9cblxuICAgICAgICBhbmltaXQoW3RoaXMuZGVjb21wLmxlYXZlLmNvbnRlbnQsIHRoaXMuZGVjb21wLmxlYXZlLmJvdHRvbVRvb2xiYXIsIHRoaXMuZGVjb21wLmxlYXZlLmJhY2tncm91bmQsIHRoaXMuc3dpcGVTaGFkb3ddKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke2Rpc3RhbmNlfXB4LCAwLCAwKWBcbiAgICAgICAgICB9KSxcblxuICAgICAgICBhbmltaXQodGhpcy5kZWNvbXAubGVhdmUudG9vbGJhcilcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgb3BhY2l0eTogLTEgKiBzd2lwZVJhdGlvIC8vIDEgLT4gMFxuICAgICAgICAgIH0pLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5sZWF2ZS50b29sYmFyQ2VudGVyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgkeygxICsgc3dpcGVSYXRpbykgKiAxMjV9JSwgMCwgMClgXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmxlYXZlLmJhY2tCdXR0b25MYWJlbClcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgb3BhY2l0eTogLTEgKiBzd2lwZVJhdGlvLCAvLyAxIC0+IDBcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKCR7dGhpcy5kZWx0YS50aXRsZSAqICgxICsgc3dpcGVSYXRpbyl9cHgsIDAsIDApYFxuICAgICAgICAgIH0pLFxuXG5cbiAgICAgICAgLyogT3RoZXIgKi9cblxuICAgICAgICBhbmltaXQodGhpcy5zd2lwZVNoYWRvdylcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgb3BhY2l0eTogLTEgKiBzd2lwZVJhdGlvIC8vIDEgLT4gMFxuICAgICAgICAgIH0pXG4gICAgICApO1xuXG5cbiAgICB9IGVsc2Uge1xuICAgICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgICAgYW5pbWl0KGxlYXZlUGFnZSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoJHtkaXN0YW5jZX1weCwgMCwgMClgXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KGVudGVyUGFnZSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoJHtzd2lwZVJhdGlvICogMjV9JSwgMCwgMClgLFxuICAgICAgICAgICAgb3BhY2l0eTogMSArIHN3aXBlUmF0aW8gKiAxMCAvIDEwMCAvLyAwLjkgLT4gMVxuICAgICAgICAgIH0pLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLnN3aXBlU2hhZG93KVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBvcGFjaXR5OiAtMSAqIHN3aXBlUmF0aW8gLy8gMSAtPiAwXG4gICAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcmVzdG9yZShlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy5pc0RyYWdTdGFydCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNob3VsZEFuaW1hdGVUb29sYmFyKSB7XG5cbiAgICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgICAgLyogRW50ZXIgcGFnZSAqL1xuXG4gICAgICAgIGFuaW1pdChbdGhpcy5kZWNvbXAuZW50ZXIuY29udGVudCwgdGhpcy5kZWNvbXAuZW50ZXIuYm90dG9tVG9vbGJhciwgdGhpcy5kZWNvbXAuZW50ZXIuYmFja2dyb3VuZF0pXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC0yNSUsIDAsIDApJyxcbiAgICAgICAgICAgIG9wYWNpdHk6IDAuOVxuICAgICAgICAgIH0sIHRoaXMub3B0UmVzdG9yZSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmVudGVyLnRvb2xiYXJDZW50ZXIpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKC0ke3RoaXMuZGVsdGEudGl0bGV9cHgsIDAsIDApYCxcbiAgICAgICAgICAgIHRyYW5zaXRpb246IGBvcGFjaXR5ICR7dGhpcy5kdXJhdGlvblJlc3RvcmV9cyBsaW5lYXIsIHRyYW5zZm9ybSAke3RoaXMuZHVyYXRpb25SZXN0b3JlfXMgJHt0aGlzLnRpbWluZ1N3aXBlfWAsXG4gICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmVudGVyLmJhY2tCdXR0b25MYWJlbClcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoLSR7dGhpcy5kZWx0YS5sYWJlbH1weCwgMCwgMClgXG4gICAgICAgICAgfSwgdGhpcy5vcHRSZXN0b3JlKSxcblxuICAgICAgICBhbmltaXQodGhpcy5kZWNvbXAuZW50ZXIub3RoZXIpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgICB9LCB0aGlzLm9wdFJlc3RvcmUpLFxuXG4gICAgICAgIC8qIExlYXZlIHBhZ2UgKi9cblxuICAgICAgICBhbmltaXQoW3RoaXMuZGVjb21wLmxlYXZlLmNvbnRlbnQsIHRoaXMuZGVjb21wLmxlYXZlLmJvdHRvbVRvb2xiYXIsIHRoaXMuZGVjb21wLmxlYXZlLmJhY2tncm91bmQsIHRoaXMuc3dpcGVTaGFkb3ddKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAwLCAwKWBcbiAgICAgICAgICB9LCB0aGlzLm9wdFJlc3RvcmUpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5sZWF2ZS50b29sYmFyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgICAgfSwgdGhpcy5vcHRSZXN0b3JlKSxcblxuICAgICAgICBhbmltaXQodGhpcy5kZWNvbXAubGVhdmUudG9vbGJhckNlbnRlcilcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoMCwgMCwgMClgXG4gICAgICAgICAgfSwgdGhpcy5vcHRSZXN0b3JlKSxcblxuICAgICAgICBhbmltaXQodGhpcy5kZWNvbXAubGVhdmUuYmFja0J1dHRvbkxhYmVsKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBvcGFjaXR5OiAxLFxuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoMCwgMCwgMClgLFxuICAgICAgICAgICAgdHJhbnNpdGlvbjogYG9wYWNpdHkgJHt0aGlzLmR1cmF0aW9uUmVzdG9yZX1zIGxpbmVhciwgdHJhbnNmb3JtICR7dGhpcy5kdXJhdGlvblJlc3RvcmV9cyAke3RoaXMudGltaW5nU3dpcGV9YFxuICAgICAgICAgIH0pLFxuXG5cbiAgICAgICAgLyogT3RoZXIgKi9cblxuICAgICAgICBhbmltaXQodGhpcy5zd2lwZVNoYWRvdylcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgb3BhY2l0eTogMFxuICAgICAgICAgIH0sIHRoaXMub3B0UmVzdG9yZSlcbiAgICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9yZXNldCh0aGlzLnRhcmdldC5lbnRlciwgdGhpcy50YXJnZXQubGVhdmUpO1xuICAgICAgICAgICAgZW50ZXJQYWdlLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgIH0pXG4gICAgICApO1xuXG5cbiAgICB9IGVsc2Uge1xuICAgICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgICBhbmltaXQoZW50ZXJQYWdlKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKC0yNSUsIDAsIDApJyxcbiAgICAgICAgICBvcGFjaXR5OiAwLjlcbiAgICAgICAgfSwgdGhpcy5vcHRSZXN0b3JlKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJ1xuICAgICAgICB9LCB0aGlzLm9wdFJlc3RvcmUpXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB0aGlzLl9yZXNldChlbnRlclBhZ2UsIGxlYXZlUGFnZSk7XG4gICAgICAgICAgZW50ZXJQYWdlLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHBvcFN3aXBlKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLmlzRHJhZ1N0YXJ0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2hvdWxkQW5pbWF0ZVRvb2xiYXIpIHtcblxuICAgICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgICAvKiBFbnRlciBwYWdlICovXG5cbiAgICAgICAgYW5pbWl0KFt0aGlzLmRlY29tcC5lbnRlci5jb250ZW50LCB0aGlzLmRlY29tcC5lbnRlci5ib3R0b21Ub29sYmFyLCB0aGlzLmRlY29tcC5lbnRlci5iYWNrZ3JvdW5kXSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLFxuICAgICAgICAgICAgb3BhY2l0eTogMVxuICAgICAgICAgIH0sIHRoaXMub3B0U3dpcGUpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5lbnRlci50b29sYmFyQ2VudGVyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAwLCAwKWAsXG4gICAgICAgICAgICB0cmFuc2l0aW9uOiBgb3BhY2l0eSAke3RoaXMuZHVyYXRpb25Td2lwZX1zIGxpbmVhciwgdHJhbnNmb3JtICR7dGhpcy5kdXJhdGlvblN3aXBlfXMgJHt0aGlzLnRpbWluZ1N3aXBlfWAsXG4gICAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmVudGVyLmJhY2tCdXR0b25MYWJlbClcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoMCwgMCwgMClgXG4gICAgICAgICAgfSwgdGhpcy5vcHRTd2lwZSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmVudGVyLm90aGVyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBvcGFjaXR5OiAxXG4gICAgICAgICAgfSwgdGhpcy5vcHRTd2lwZSksXG5cbiAgICAgICAgLyogTGVhdmUgcGFnZSAqL1xuXG4gICAgICAgIGFuaW1pdChbdGhpcy5kZWNvbXAubGVhdmUuY29udGVudCwgdGhpcy5kZWNvbXAubGVhdmUuYm90dG9tVG9vbGJhciwgdGhpcy5kZWNvbXAubGVhdmUuYmFja2dyb3VuZF0pXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDEwMCUsIDAsIDApYFxuICAgICAgICAgIH0sIHRoaXMub3B0U3dpcGUpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5sZWF2ZS50b29sYmFyKVxuICAgICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgICBvcGFjaXR5OiAwXG4gICAgICAgICAgfSwgdGhpcy5vcHRTd2lwZSksXG5cbiAgICAgICAgYW5pbWl0KHRoaXMuZGVjb21wLmxlYXZlLnRvb2xiYXJDZW50ZXIpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDEyNSUsIDAsIDApYFxuICAgICAgICAgIH0sIHRoaXMub3B0U3dpcGUpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLmRlY29tcC5sZWF2ZS5iYWNrQnV0dG9uTGFiZWwpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIG9wYWNpdHk6IDAsXG4gICAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3RoaXMuZGVsdGEudGl0bGV9cHgsIDAsIDApYCxcbiAgICAgICAgICAgIHRyYW5zaXRpb246IGBvcGFjaXR5ICR7dGhpcy5kdXJhdGlvblN3aXBlfXMgbGluZWFyLCB0cmFuc2Zvcm0gJHt0aGlzLmR1cmF0aW9uU3dpcGV9cyAke3RoaXMudGltaW5nU3dpcGV9YFxuICAgICAgICAgIH0pLFxuXG5cbiAgICAgICAgLyogT3RoZXIgKi9cblxuICAgICAgICBhbmltaXQodGhpcy5zd2lwZVNoYWRvdylcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgb3BhY2l0eTogMCxcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKCR7dGhpcy5tYXhXaWR0aH1weCwgMCwgMClgXG4gICAgICAgICAgfSwgdGhpcy5vcHRTd2lwZSlcbiAgICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9yZXNldCh0aGlzLnRhcmdldC5lbnRlciwgdGhpcy50YXJnZXQubGVhdmUpO1xuICAgICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgICB9KVxuICAgICAgKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICAgIGFuaW1pdChlbnRlclBhZ2UpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknLFxuICAgICAgICAgIG9wYWNpdHk6IDEuMFxuICAgICAgICB9LCB0aGlzLm9wdFN3aXBlKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlKVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDEwMCUsIDAsIDApJ1xuICAgICAgICB9LCB0aGlzLm9wdFN3aXBlKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgdGhpcy5fcmVzZXQoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UpO1xuICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBfc2F2ZVN0eWxlKC4uLmFyZ3MpIHtcbiAgICB0aGlzLl9zYXZlZFN0eWxlID0gbmV3IFdlYWtNYXAoKTtcbiAgICBjb25zdCBzYXZlID0gZWwgPT4gdGhpcy5fc2F2ZWRTdHlsZS5zZXQoZWwsIGVsLmdldEF0dHJpYnV0ZSgnc3R5bGUnKSk7XG4gICAgYXJncy5mb3JFYWNoKHNhdmUpO1xuXG4gICAgT2JqZWN0LmtleXModGhpcy5kZWNvbXApLmZvckVhY2gocCA9PiB7XG4gICAgICBPYmplY3Qua2V5cyh0aGlzLmRlY29tcFtwXSkuZm9yRWFjaChrID0+IHtcbiAgICAgICAgKHRoaXMuZGVjb21wW3BdW2tdIGluc3RhbmNlb2YgQXJyYXkgPyB0aGlzLmRlY29tcFtwXVtrXSA6IFt0aGlzLmRlY29tcFtwXVtrXV0pLmZvckVhY2goc2F2ZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIF9yZXN0b3JlU3R5bGUoLi4uYXJncykge1xuICAgIGNvbnN0IHJlc3RvcmUgPSBlbCA9PiB7XG4gICAgICB0aGlzLl9zYXZlZFN0eWxlLmdldChlbCkgPT09IG51bGwgPyBlbC5yZW1vdmVBdHRyaWJ1dGUoJ3N0eWxlJykgOiBlbC5zZXRBdHRyaWJ1dGUoJ3N0eWxlJywgdGhpcy5fc2F2ZWRTdHlsZS5nZXQoZWwpKVxuICAgICAgdGhpcy5fc2F2ZWRTdHlsZS5kZWxldGUoZWwpXG4gICAgfTtcbiAgICBhcmdzLmZvckVhY2gocmVzdG9yZSk7XG5cbiAgICBPYmplY3Qua2V5cyh0aGlzLmRlY29tcCkuZm9yRWFjaChwID0+IHtcbiAgICAgIE9iamVjdC5rZXlzKHRoaXMuZGVjb21wW3BdKS5mb3JFYWNoKGsgPT4ge1xuICAgICAgICAodGhpcy5kZWNvbXBbcF1ba10gaW5zdGFuY2VvZiBBcnJheSA/IHRoaXMuZGVjb21wW3BdW2tdIDogW3RoaXMuZGVjb21wW3BdW2tdXSkuZm9yRWFjaChyZXN0b3JlKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgX3Jlc2V0KC4uLmFyZ3MpIHtcbiAgICB0aGlzLmlzU3dpcGluZyA9IGZhbHNlO1xuICAgIHRoaXMuX3NhdmVkU3R5bGUgJiYgdGhpcy5fcmVzdG9yZVN0eWxlKC4uLmFyZ3MpO1xuICAgIHRoaXMudW5ibG9jayAmJiB0aGlzLnVuYmxvY2soKTtcbiAgICB0aGlzLnN3aXBlU2hhZG93LnJlbW92ZSgpO1xuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgdGhpcy5vdmVyZmxvd0VsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgnb3ZlcmZsb3ctdmlzaWJsZScpO1xuICAgIHRoaXMuZGVjb21wLmxlYXZlLmNvbnRlbnQuY2xhc3NMaXN0LnJlbW92ZSgnY29udGVudC1zd2lwaW5nJyk7XG4gICAgdGhpcy5kZWNvbXAgPSB0aGlzLnRhcmdldCA9IHRoaXMub3ZlcmZsb3dFbGVtZW50ID0gdGhpcy5fc2F2ZWRTdHlsZSA9IG51bGw7XG4gICAgdGhpcy5pc0RyYWdTdGFydCA9IHRydWU7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBJT1NTd2lwZU5hdmlnYXRvckFuaW1hdG9yIGZyb20gJy4vaW9zLXN3aXBlLWFuaW1hdG9yJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3QgdHJhbnNsYXRlM2QgPSAoeCA9IDAsIHkgPSAwLCB6ID0gMCkgPT4gYHRyYW5zbGF0ZTNkKCR7eH0sICR7eX0sICR7en0pYDtcblxuLyoqXG4gKiBTbGlkZSBhbmltYXRvciBmb3IgbmF2aWdhdG9yIHRyYW5zaXRpb24gbGlrZSBpT1MncyBzY3JlZW4gc2xpZGUgdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSU9TU2xpZGVOYXZpZ2F0b3JBbmltYXRvciBleHRlbmRzIElPU1N3aXBlTmF2aWdhdG9yQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHsgdGltaW5nID0gJ2N1YmljLWJlemllcigwLjMsIC40LCAwLCAuOSknLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC40LCAuLi5yZXN0IH0gPSB7fSkge1xuICAgIHN1cGVyKHsgdGltaW5nLCBkZWxheSwgZHVyYXRpb24sIC4uLnJlc3QgfSk7XG5cbiAgICB0aGlzLmJhY2tncm91bmRNYXNrID0gdXRpbC5jcmVhdGVFbGVtZW50KFxuICAgICAgYDxkaXYgc3R5bGU9XCJwb3NpdGlvbjogYWJzb2x1dGU7IHdpZHRoOiAxMDAlOyBoZWlnaHQ6IDEwMCU7YCArXG4gICAgICAgIGBiYWNrZ3JvdW5kLWNvbG9yOiBibGFjazsgei1pbmRleDogMlwiPjwvZGl2PmBcbiAgICApO1xuICB9XG5cbiAgX2RlY29tcG9zZShwYWdlKSB7XG4gICAgY29uc3QgdG9vbGJhciA9IHBhZ2UuX2dldFRvb2xiYXJFbGVtZW50KCk7XG4gICAgY29uc3QgbGVmdCA9IHRvb2xiYXIuX2dldFRvb2xiYXJMZWZ0SXRlbXNFbGVtZW50KCk7XG4gICAgY29uc3QgcmlnaHQgPSB0b29sYmFyLl9nZXRUb29sYmFyUmlnaHRJdGVtc0VsZW1lbnQoKTtcblxuICAgIGNvbnN0IGV4Y2x1ZGVCYWNrQnV0dG9uID0gZnVuY3Rpb24oZWxlbWVudHMpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChlbGVtZW50c1tpXS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpICE9PSAnb25zLWJhY2stYnV0dG9uJykge1xuICAgICAgICAgIHJlc3VsdC5wdXNoKGVsZW1lbnRzW2ldKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG5cbiAgICBjb25zdCBvdGhlciA9IFtdXG4gICAgICAuY29uY2F0KGxlZnQuY2hpbGRyZW4ubGVuZ3RoID09PSAwID8gbGVmdCA6IGV4Y2x1ZGVCYWNrQnV0dG9uKGxlZnQuY2hpbGRyZW4pKVxuICAgICAgLmNvbmNhdChyaWdodC5jaGlsZHJlbi5sZW5ndGggPT09IDAgPyByaWdodCA6IGV4Y2x1ZGVCYWNrQnV0dG9uKHJpZ2h0LmNoaWxkcmVuKSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdG9vbGJhckNlbnRlcjogdG9vbGJhci5fZ2V0VG9vbGJhckNlbnRlckl0ZW1zRWxlbWVudCgpLFxuICAgICAgYmFja0J1dHRvbkljb246IHRvb2xiYXIuX2dldFRvb2xiYXJCYWNrQnV0dG9uSWNvbkVsZW1lbnQoKSxcbiAgICAgIGJhY2tCdXR0b25MYWJlbDogdG9vbGJhci5fZ2V0VG9vbGJhckJhY2tCdXR0b25MYWJlbEVsZW1lbnQoKSxcbiAgICAgIG90aGVyOiBvdGhlcixcbiAgICAgIGNvbnRlbnQ6IHBhZ2UuX2dldENvbnRlbnRFbGVtZW50KCksXG4gICAgICBiYWNrZ3JvdW5kOiBwYWdlLl9nZXRCYWNrZ3JvdW5kRWxlbWVudCgpLFxuICAgICAgdG9vbGJhcjogdG9vbGJhcixcbiAgICAgIGJvdHRvbVRvb2xiYXI6IHBhZ2UuX2dldEJvdHRvbVRvb2xiYXJFbGVtZW50KClcbiAgICB9O1xuICB9XG5cbiAgX3Nob3VsZEFuaW1hdGVUb29sYmFyKGVudGVyUGFnZSwgbGVhdmVQYWdlKSB7XG4gICAgY29uc3QgdG9vbGJhcnMgPSBlbnRlclBhZ2UuX2NhbkFuaW1hdGVUb29sYmFyKCkgJiYgbGVhdmVQYWdlLl9jYW5BbmltYXRlVG9vbGJhcigpO1xuXG4gICAgY29uc3QgZW50ZXJUb29sYmFyID0gZW50ZXJQYWdlLl9nZXRUb29sYmFyRWxlbWVudCgpO1xuICAgIGNvbnN0IGxlYXZlVG9vbGJhciA9IGxlYXZlUGFnZS5fZ2V0VG9vbGJhckVsZW1lbnQoKTtcblxuICAgIGNvbnN0IGlzU3RhdGljID0gZW50ZXJUb29sYmFyLmhhc0F0dHJpYnV0ZSgnc3RhdGljJykgfHwgbGVhdmVUb29sYmFyLmhhc0F0dHJpYnV0ZSgnc3RhdGljJyk7XG4gICAgY29uc3QgaXNNYXRlcmlhbCA9IHV0aWwuaGFzTW9kaWZpZXIoZW50ZXJUb29sYmFyLCAnbWF0ZXJpYWwnKSB8fCB1dGlsLmhhc01vZGlmaWVyKGxlYXZlVG9vbGJhciwgJ21hdGVyaWFsJyk7XG4gICAgY29uc3QgaXNUcmFuc3BhcmVudCA9IHV0aWwuaGFzTW9kaWZpZXIoZW50ZXJUb29sYmFyLCAndHJhbnNwYXJlbnQnKSB8fCB1dGlsLmhhc01vZGlmaWVyKGxlYXZlVG9vbGJhciwgJ3RyYW5zcGFyZW50Jyk7XG5cbiAgICByZXR1cm4gdG9vbGJhcnMgJiYgIWlzU3RhdGljICYmICFpc01hdGVyaWFsICYmICFpc1RyYW5zcGFyZW50O1xuICB9XG5cbiAgX2NhbGN1bGF0ZURlbHRhKGVsZW1lbnQsIGRlY29tcG9zaXRpb24pIHtcbiAgICBsZXQgdGl0bGUsIGxhYmVsO1xuXG4gICAgY29uc3QgcGFnZVJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGlmIChkZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25MYWJlbC5jbGFzc0xpc3QuY29udGFpbnMoJ2JhY2stYnV0dG9uX19sYWJlbCcpKSB7XG4gICAgICBjb25zdCBsYWJlbFJlY3QgPSBkZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25MYWJlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIHRpdGxlID0gTWF0aC5yb3VuZChwYWdlUmVjdC53aWR0aCAvIDIgLSBsYWJlbFJlY3Qud2lkdGggLyAyIC0gbGFiZWxSZWN0LmxlZnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aXRsZSA9IE1hdGgucm91bmQoKHBhZ2VSZWN0LndpZHRoIC8gMikgKiAwLjYpO1xuICAgIH1cblxuICAgIGlmIChkZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25JY29uLmNsYXNzTGlzdC5jb250YWlucygnYmFjay1idXR0b25fX2ljb24nKSkge1xuICAgICAgbGFiZWwgPSBkZWNvbXBvc2l0aW9uLmJhY2tCdXR0b25JY29uLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnJpZ2h0IC0gMjtcbiAgICB9XG5cbiAgICByZXR1cm4ge3RpdGxlLCBsYWJlbH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHB1c2goZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICBsZWF2ZVBhZ2UucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGhpcy5iYWNrZ3JvdW5kTWFzaywgbGVhdmVQYWdlKTtcblxuICAgIGNvbnN0IHVuYmxvY2sgPSBzdXBlci5ibG9jayhlbnRlclBhZ2UpO1xuXG4gICAgY29udGVudFJlYWR5KGVudGVyUGFnZSwgKCkgPT4ge1xuICAgICAgY29uc3QgZW50ZXJQYWdlVGFyZ2V0ID0gdXRpbC5maW5kVG9vbGJhclBhZ2UoZW50ZXJQYWdlKSB8fCBlbnRlclBhZ2U7XG4gICAgICBjb25zdCBsZWF2ZVBhZ2VUYXJnZXQgPSB1dGlsLmZpbmRUb29sYmFyUGFnZShsZWF2ZVBhZ2UpIHx8IGxlYXZlUGFnZTtcbiAgICAgIGNvbnN0IGVudGVyUGFnZURlY29tcG9zaXRpb24gPSB0aGlzLl9kZWNvbXBvc2UoZW50ZXJQYWdlVGFyZ2V0KTtcbiAgICAgIGNvbnN0IGxlYXZlUGFnZURlY29tcG9zaXRpb24gPSB0aGlzLl9kZWNvbXBvc2UobGVhdmVQYWdlVGFyZ2V0KTtcblxuICAgICAgY29uc3QgZGVsdGEgPSB0aGlzLl9jYWxjdWxhdGVEZWx0YShsZWF2ZVBhZ2UsIGVudGVyUGFnZURlY29tcG9zaXRpb24pO1xuXG4gICAgICBjb25zdCBzaG91bGRBbmltYXRlVG9vbGJhciA9IHRoaXMuX3Nob3VsZEFuaW1hdGVUb29sYmFyKGVudGVyUGFnZVRhcmdldCwgbGVhdmVQYWdlVGFyZ2V0KTtcblxuICAgICAgaWYgKHNob3VsZEFuaW1hdGVUb29sYmFyKSB7XG5cbiAgICAgICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgICAgIGFuaW1pdChbZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5jb250ZW50LCBlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLmJvdHRvbVRvb2xiYXIsIGVudGVyUGFnZURlY29tcG9zaXRpb24uYmFja2dyb3VuZF0sIHRoaXMuZGVmKVxuICAgICAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgnMTAwJScpIH0sXG4gICAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpIH1cbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMCB9LCB7IG9wYWNpdHk6IDEgfSksXG5cbiAgICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyQ2VudGVyLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoJzEyNSUnKSwgb3BhY2l0eTogMSB9LFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSwgb3BhY2l0eTogMSB9XG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgYW5pbWl0KGVudGVyUGFnZURlY29tcG9zaXRpb24uYmFja0J1dHRvbkxhYmVsLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoYCR7ZGVsdGEudGl0bGV9cHhgKSwgb3BhY2l0eTogMCB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpLFxuICAgICAgICAgICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgICAgICAgICAgdHJhbnNpdGlvbjogYG9wYWNpdHkgJHt0aGlzLmR1cmF0aW9ufXMgbGluZWFyLCB0cmFuc2Zvcm0gJHt0aGlzLmR1cmF0aW9ufXMgJHt0aGlzLnRpbWluZ31gXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICksXG5cbiAgICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5vdGhlciwgdGhpcy5kZWYpXG4gICAgICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAgICAgeyBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgICAgIHsgY3NzOiB7IG9wYWNpdHk6IDEgfSwgdGltaW5nOiAnbGluZWFyJyB9XG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgYW5pbWl0KFtsZWF2ZVBhZ2VEZWNvbXBvc2l0aW9uLmNvbnRlbnQsIGxlYXZlUGFnZURlY29tcG9zaXRpb24uYm90dG9tVG9vbGJhciwgbGVhdmVQYWdlRGVjb21wb3NpdGlvbi5iYWNrZ3JvdW5kXSwgdGhpcy5kZWYpXG4gICAgICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCksIG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCctMjUlJyksIG9wYWNpdHk6IDAuOSB9XG4gICAgICAgICAgICApXG4gICAgICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgICAgfSksXG5cbiAgICAgICAgICBhbmltaXQobGVhdmVQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyQ2VudGVyLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSwgb3BhY2l0eTogMSB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZChgLSR7ZGVsdGEudGl0bGV9cHhgKSxcbiAgICAgICAgICAgICAgICBvcGFjaXR5OiAwLFxuICAgICAgICAgICAgICAgIHRyYW5zaXRpb246IGBvcGFjaXR5ICR7dGhpcy5kdXJhdGlvbn1zIGxpbmVhciwgdHJhbnNmb3JtICR7dGhpcy5kdXJhdGlvbn1zICR7dGhpcy50aW1pbmd9YFxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApLFxuXG4gICAgICAgICAgYW5pbWl0KGxlYXZlUGFnZURlY29tcG9zaXRpb24uYmFja0J1dHRvbkxhYmVsLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSwgb3BhY2l0eTogMSB9LFxuICAgICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoYC0ke2RlbHRhLmxhYmVsfXB4YCksIG9wYWNpdHk6IDAgfVxuICAgICAgICAgICAgKSxcblxuICAgICAgICAgIGFuaW1pdChsZWF2ZVBhZ2VEZWNvbXBvc2l0aW9uLm90aGVyLCB0aGlzLmRlZilcbiAgICAgICAgICAgIC5kZWZhdWx0KCB7IG9wYWNpdHk6IDEgfSwgeyBjc3M6IHsgb3BhY2l0eTogMCB9LCB0aW1pbmc6ICdsaW5lYXInIH0pXG5cbiAgICAgICAgKTtcblxuICAgICAgfSBlbHNlIHtcblxuICAgICAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICAgICAgYW5pbWl0KGVudGVyUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgICAgICAuZGVmYXVsdCggeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCcxMDAlJyksIH0sIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpIH0pLFxuXG4gICAgICAgICAgYW5pbWl0KGxlYXZlUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgICAgICAuZGVmYXVsdCggeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCksIG9wYWNpdHk6IDEgfSwgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCctMjUlJyksIG9wYWNpdHk6IC45IH0pXG4gICAgICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcG9wKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLmlzU3dpcGluZykge1xuICAgICAgcmV0dXJuIHRoaXMucG9wU3dpcGUoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGVudGVyUGFnZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBlbnRlclBhZ2UpO1xuXG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBjb25zdCBlbnRlclBhZ2VUYXJnZXQgPSB1dGlsLmZpbmRUb29sYmFyUGFnZShlbnRlclBhZ2UpIHx8IGVudGVyUGFnZTtcbiAgICBjb25zdCBsZWF2ZVBhZ2VUYXJnZXQgPSB1dGlsLmZpbmRUb29sYmFyUGFnZShsZWF2ZVBhZ2UpIHx8IGxlYXZlUGFnZTtcbiAgICBjb25zdCBlbnRlclBhZ2VEZWNvbXBvc2l0aW9uID0gdGhpcy5fZGVjb21wb3NlKGVudGVyUGFnZVRhcmdldCk7XG4gICAgY29uc3QgbGVhdmVQYWdlRGVjb21wb3NpdGlvbiA9IHRoaXMuX2RlY29tcG9zZShsZWF2ZVBhZ2VUYXJnZXQpO1xuXG4gICAgY29uc3QgZGVsdGEgPSB0aGlzLl9jYWxjdWxhdGVEZWx0YShsZWF2ZVBhZ2UsIGxlYXZlUGFnZURlY29tcG9zaXRpb24pO1xuXG4gICAgY29uc3Qgc2hvdWxkQW5pbWF0ZVRvb2xiYXIgPSB0aGlzLl9zaG91bGRBbmltYXRlVG9vbGJhcihlbnRlclBhZ2VUYXJnZXQsIGxlYXZlUGFnZVRhcmdldCk7XG5cbiAgICBpZiAoc2hvdWxkQW5pbWF0ZVRvb2xiYXIpIHtcbiAgICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgICAgYW5pbWl0KFtlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLmNvbnRlbnQsIGVudGVyUGFnZURlY29tcG9zaXRpb24uYm90dG9tVG9vbGJhciwgZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5iYWNrZ3JvdW5kXSwgdGhpcy5kZWYpXG4gICAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoJy0yNSUnKSwgb3BhY2l0eTogLjkgfSxcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpLCBvcGFjaXR5OiAxIH1cbiAgICAgICAgICApLFxuXG4gICAgICAgIGFuaW1pdChlbnRlclBhZ2VEZWNvbXBvc2l0aW9uLnRvb2xiYXJDZW50ZXIsIHRoaXMuZGVmKVxuICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKGAtJHtkZWx0YS50aXRsZX1weGApLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSxcbiAgICAgICAgICAgICAgb3BhY2l0eTogMSxcbiAgICAgICAgICAgICAgdHJhbnNpdGlvbjogYG9wYWNpdHkgJHt0aGlzLmR1cmF0aW9ufXMgbGluZWFyLCB0cmFuc2Zvcm0gJHt0aGlzLmR1cmF0aW9ufXMgJHt0aGlzLnRpbWluZ31gXG4gICAgICAgICAgICB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5iYWNrQnV0dG9uTGFiZWwsIHRoaXMuZGVmKVxuICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKGAtJHtkZWx0YS5sYWJlbH1weGApIH0sXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQoZW50ZXJQYWdlRGVjb21wb3NpdGlvbi5vdGhlciwgdGhpcy5kZWYpXG4gICAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgICB7IG9wYWNpdHk6IDAgfSxcbiAgICAgICAgICAgIHsgY3NzOiB7IG9wYWNpdHk6IDEgfSwgdGltaW5nOiAnbGluZWFyJyB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQoW2xlYXZlUGFnZURlY29tcG9zaXRpb24uY29udGVudCwgbGVhdmVQYWdlRGVjb21wb3NpdGlvbi5ib3R0b21Ub29sYmFyLCBsZWF2ZVBhZ2VEZWNvbXBvc2l0aW9uLmJhY2tncm91bmRdLCB0aGlzLmRlZilcbiAgICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpIH0sXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoJzEwMCUnKSB9XG4gICAgICAgICAgKVxuICAgICAgICAgIC53YWl0KDApXG4gICAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICBkb25lKCk7XG4gICAgICAgICAgfSksXG5cbiAgICAgICAgYW5pbWl0KGxlYXZlUGFnZURlY29tcG9zaXRpb24udG9vbGJhciwgdGhpcy5kZWYpXG4gICAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgICB7IG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICAgIHsgb3BhY2l0eTogMCB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlRGVjb21wb3NpdGlvbi50b29sYmFyQ2VudGVyLCB0aGlzLmRlZilcbiAgICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpIH0sXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoJzEyNSUnKSB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlRGVjb21wb3NpdGlvbi5iYWNrQnV0dG9uTGFiZWwsIHRoaXMuZGVmKVxuICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCksIG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZChgJHtkZWx0YS50aXRsZX1weGApLFxuICAgICAgICAgICAgICBvcGFjaXR5OiAwLFxuICAgICAgICAgICAgICB0cmFuc2l0aW9uOiBgb3BhY2l0eSAke3RoaXMuZHVyYXRpb259cyBsaW5lYXIsIHRyYW5zZm9ybSAke3RoaXMuZHVyYXRpb259cyAke3RoaXMudGltaW5nfWBcbiAgICAgICAgICAgIH1cbiAgICAgICAgICApXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICAgIGFuaW1pdChlbnRlclBhZ2UsIHRoaXMuZGVmKVxuICAgICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgICAgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZTNkKCctMjUlJyksIG9wYWNpdHk6IC45IH0sXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoKSwgb3BhY2l0eTogMSB9XG4gICAgICAgICAgKSxcblxuICAgICAgICBhbmltaXQobGVhdmVQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICAgIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGUzZCgpIH0sXG4gICAgICAgICAgICB7IHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoJzEwMCUnKSB9XG4gICAgICAgICAgKVxuICAgICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgICB1bmJsb2NrKCk7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgZG9uZSgpO1xuICAgICAgICAgIH0pXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE5hdmlnYXRvckFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcblxuLyoqXG4gKiBMaWZ0IHNjcmVlbiB0cmFuc2l0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJT1NMaWZ0TmF2aWdhdG9yQW5pbWF0b3IgZXh0ZW5kcyBOYXZpZ2F0b3JBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuMSwgMSknLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC40fSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcblxuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoXG4gICAgICAnPGRpdiBzdHlsZT1cInBvc2l0aW9uOiBhYnNvbHV0ZTsgd2lkdGg6IDEwMCU7IGhlaWdodDogMTAwJTsnICtcbiAgICAgICAgJ2JhY2tncm91bmQ6IGxpbmVhci1ncmFkaWVudChibGFjaywgd2hpdGUpO1wiPjwvZGl2PidcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcHVzaChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGxlYXZlUGFnZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBsZWF2ZVBhZ2UpO1xuXG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZW50ZXJQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAxMDAlLCAwKScgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJyB9XG4gICAgICAgICksXG5cbiAgICAgIGFuaW1pdChsZWF2ZVBhZ2UsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJywgb3BhY2l0eTogMSB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgLTEwJSwgMCknLCBvcGFjaXR5OiAuOSB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgdW5ibG9jaygpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGVudGVyUGFnZVxuICAgKiBAcGFyYW0ge09iamVjdH0gbGVhdmVQYWdlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgdGhpcy5iYWNrZ3JvdW5kTWFzay5yZW1vdmUoKTtcbiAgICBlbnRlclBhZ2UucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUodGhpcy5iYWNrZ3JvdW5kTWFzaywgZW50ZXJQYWdlKTtcblxuICAgIGNvbnN0IHVuYmxvY2sgPSBzdXBlci5ibG9jayhlbnRlclBhZ2UpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGVudGVyUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgLTQzcHgsIDApJywgb3BhY2l0eTogLjkgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNEKDAsIDAsIDApJywgb3BhY2l0eTogMSB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgdW5ibG9jaygpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGxlYXZlUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgMCwgMCknIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAxMDAlLCAwKScgfVxuICAgICAgICApXG4gICAgKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IE5hdmlnYXRvckFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcblxuY29uc3QgdHJhbnNmb3JtID0gJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJztcblxuLyoqXG4gKiBGYWRlLWluIHNjcmVlbiB0cmFuc2l0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJT1NGYWRlTmF2aWdhdG9yQW5pbWF0b3IgZXh0ZW5kcyBOYXZpZ2F0b3JBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdsaW5lYXInLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC40fSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHB1c2goZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQoZW50ZXJQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm0sIG9wYWNpdHk6IDAgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybSwgb3BhY2l0eTogMSB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSksXG4gICAgKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm0sIG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybSwgb3BhY2l0eTogMCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgTmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuXG4vKipcbiAqIFNsaWRlIGFuaW1hdG9yIGZvciBuYXZpZ2F0b3IgdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTURTbGlkZU5hdmlnYXRvckFuaW1hdG9yIGV4dGVuZHMgTmF2aWdhdG9yQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjQsIDEpJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuM30gPSB7fSkge1xuICAgIHN1cGVyKHt0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbn0pO1xuXG4gICAgdGhpcy5ibGFja01hc2tPcGFjaXR5ID0gMC40O1xuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoXG4gICAgICAnPGRpdiBzdHlsZT1cInBvc2l0aW9uOiBhYnNvbHV0ZTsgd2lkdGg6IDEwMCU7IGhlaWdodDogMTAwJTsgei1pbmRleDogMjsnICtcbiAgICAgICAgJ2JhY2tncm91bmQtY29sb3I6IGJsYWNrOyBvcGFjaXR5OiAwO1wiPjwvZGl2PidcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcHVzaChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGxlYXZlUGFnZS5wYXJlbnRFbGVtZW50Lmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBsZWF2ZVBhZ2UubmV4dFNpYmxpbmcpO1xuXG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQodGhpcy5iYWNrZ3JvdW5kTWFzaywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyBvcGFjaXR5OiB0aGlzLmJsYWNrTWFza09wYWNpdHkgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChlbnRlclBhZ2UsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDEwMCUsIDAsIDApJyB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknIH1cbiAgICAgICAgKSxcblxuICAgICAgYW5pbWl0KGxlYXZlUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgtNDUlLCAwLCAwKScgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB1bmJsb2NrKCk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gZW50ZXJQYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBsZWF2ZVBhZ2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHBvcChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGVudGVyUGFnZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBlbnRlclBhZ2UubmV4dFNpYmxpbmcpO1xuXG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQodGhpcy5iYWNrZ3JvdW5kTWFzaywgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiB0aGlzLmJsYWNrTWFza09wYWNpdHkgfSxcbiAgICAgICAgICB7IG9wYWNpdHk6IDAgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdChlbnRlclBhZ2UsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKC00NSUsIDAsIDApJywgb3BhY2l0eTogLjkgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJywgb3BhY2l0eTogMSB9XG4gICAgICAgICksXG5cbiAgICAgIGFuaW1pdChsZWF2ZVBhZ2UsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJyB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMTAwJSwgMCwgMCknIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgdW5ibG9jaygpO1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBOYXZpZ2F0b3JBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5cbi8qKlxuICogTGlmdCBzY3JlZW4gdHJhbnNpdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTURMaWZ0TmF2aWdhdG9yQW5pbWF0b3IgZXh0ZW5kcyBOYXZpZ2F0b3JBbmltYXRvciB7XG5cbiAgY29uc3RydWN0b3Ioe3RpbWluZyA9ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuMSwgMSknLCBkZWxheSA9IDAuMDUsIGR1cmF0aW9uID0gMC40fSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcblxuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sgPSB1dGlsLmNyZWF0ZUVsZW1lbnQoXG4gICAgICAnPGRpdiBzdHlsZT1cInBvc2l0aW9uOiBhYnNvbHV0ZTsgd2lkdGg6IDEwMCU7IGhlaWdodDogMTAwJTsnICtcbiAgICAgICAgJ2JhY2tncm91bmQtY29sb3I6IGJsYWNrO1wiPjwvZGl2PidcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcHVzaChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgIGxlYXZlUGFnZS5wYXJlbnROb2RlLmluc2VydEJlZm9yZSh0aGlzLmJhY2tncm91bmRNYXNrLCBsZWF2ZVBhZ2UpO1xuXG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBjb25zdCBtYXNrQ2xlYXIgPSBhbmltaXQodGhpcy5iYWNrZ3JvdW5kTWFzaylcbiAgICAgIC53YWl0KHRoaXMuZGVsYXkgKyB0aGlzLmR1cmF0aW9uKVxuICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICB0aGlzLmJhY2tncm91bmRNYXNrLnJlbW92ZSgpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIG1hc2tDbGVhcixcblxuICAgICAgYW5pbWl0KGVudGVyUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMTAwJSwgMCknIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScgfVxuICAgICAgICApLFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAxIH0sIHsgb3BhY2l0eTogLjQgfSlcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcG9wKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgZW50ZXJQYWdlLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMuYmFja2dyb3VuZE1hc2ssIGVudGVyUGFnZSk7XG5cbiAgICBjb25zdCB1bmJsb2NrID0gc3VwZXIuYmxvY2soZW50ZXJQYWdlKTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG5cbiAgICAgIGFuaW1pdCh0aGlzLmJhY2tncm91bmRNYXNrKVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5ICsgdGhpcy5kdXJhdGlvbilcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHRoaXMuYmFja2dyb3VuZE1hc2sucmVtb3ZlKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KGVudGVyUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogLjQgfSwgeyBvcGFjaXR5OiAxIH0pXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB1bmJsb2NrKCk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDEwMCUsIDApJyB9XG4gICAgICAgIClcbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgTmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuXG4vKipcbiAqIEZhZGUtaW4gKyBMaWZ0IHNjcmVlbiB0cmFuc2l0aW9uLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBNREZhZGVOYXZpZ2F0b3JBbmltYXRvciBleHRlbmRzIE5hdmlnYXRvckFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2N1YmljLWJlemllcigwLjQsIDAsIDAuMiwgMSknLCB0aW1pbmdQb3AgPSAnY3ViaWMtYmV6aWVyKDAuNCwgMCwgMSwgMSknLCBkZWxheSA9IDAsIGR1cmF0aW9uID0gMC4yfSA9IHt9KSB7XG4gICAgc3VwZXIoe3RpbWluZywgZGVsYXksIGR1cmF0aW9ufSk7XG4gICAgdGhpcy50aW1pbmdQb3AgPSB0aW1pbmdQb3A7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtPYmplY3R9IGVudGVyUGFnZVxuICAgKiBAcGFyYW0ge09iamVjdH0gbGVhdmVQYWdlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBwdXNoKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBjYWxsYmFjaykge1xuICAgIGNvbnN0IHVuYmxvY2sgPSBzdXBlci5ibG9jayhlbnRlclBhZ2UpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcblxuICAgICAgYW5pbWl0KGVudGVyUGFnZSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM0QoMCwgNDJweCwgMCknLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsIG9wYWNpdHk6IDEgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICB1bmJsb2NrKCk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgKTtcblxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBlbnRlclBhZ2VcbiAgICogQHBhcmFtIHtPYmplY3R9IGxlYXZlUGFnZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBwb3AoZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY29uc3QgdW5ibG9jayA9IHN1cGVyLmJsb2NrKGVudGVyUGFnZSk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuXG4gICAgICBhbmltaXQobGVhdmVQYWdlLCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAwLCAwKScsIG9wYWNpdHk6IDEgfSxcbiAgICAgICAgICB7IGNzczogeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzRCgwLCAzOHB4LCAwKScsIG9wYWNpdHk6IDAgfSwgdGltaW5nOiB0aGlzLnRpbWluZ1BvcCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHVuYmxvY2soKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgTmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE5vbmVOYXZpZ2F0b3JBbmltYXRvciBleHRlbmRzIE5hdmlnYXRvckFuaW1hdG9yIHtcbiAgY29uc3RydWN0b3Iob3B0aW9ucykge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuICB9XG4gIHB1c2goZW50ZXJQYWdlLCBsZWF2ZVBhZ2UsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIHBvcChlbnRlclBhZ2UsIGxlYXZlUGFnZSwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG59XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBpbnRlcm5hbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwnO1xuaW1wb3J0IFN3aXBlUmV2ZWFsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9zd2lwZS1yZXZlYWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgTmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9hbmltYXRvcic7XG5pbXBvcnQgSU9TU2xpZGVOYXZpZ2F0b3JBbmltYXRvciBmcm9tICcuL2lvcy1zbGlkZS1hbmltYXRvcic7XG5pbXBvcnQgSU9TTGlmdE5hdmlnYXRvckFuaW1hdG9yIGZyb20gJy4vaW9zLWxpZnQtYW5pbWF0b3InO1xuaW1wb3J0IElPU0ZhZGVOYXZpZ2F0b3JBbmltYXRvciBmcm9tICcuL2lvcy1mYWRlLWFuaW1hdG9yJztcbmltcG9ydCBNRFNsaWRlTmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9tZC1zbGlkZS1hbmltYXRvcic7XG5pbXBvcnQgTURMaWZ0TmF2aWdhdG9yQW5pbWF0b3IgZnJvbSAnLi9tZC1saWZ0LWFuaW1hdG9yJztcbmltcG9ydCBNREZhZGVOYXZpZ2F0b3JBbmltYXRvciBmcm9tICcuL21kLWZhZGUtYW5pbWF0b3InO1xuaW1wb3J0IE5vbmVOYXZpZ2F0b3JBbmltYXRvciBmcm9tICcuL25vbmUtYW5pbWF0b3InO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uLy4uL29ucy9wbGF0Zm9ybSc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2RldmljZS1iYWNrLWJ1dHRvbi1kaXNwYXRjaGVyJztcbmltcG9ydCB7UGFnZUxvYWRlciwgZGVmYXVsdFBhZ2VMb2FkZXIsIGluc3RhbnRQYWdlTG9hZGVyfSBmcm9tICcuLi8uLi9vbnMvcGFnZS1sb2FkZXInO1xuXG5jb25zdCBfYW5pbWF0b3JEaWN0ID0ge1xuICAnZGVmYXVsdCc6ICgpID0+IHBsYXRmb3JtLmlzQW5kcm9pZCgpID8gTURGYWRlTmF2aWdhdG9yQW5pbWF0b3IgOiBJT1NTbGlkZU5hdmlnYXRvckFuaW1hdG9yLFxuICAnc2xpZGUnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IE1EU2xpZGVOYXZpZ2F0b3JBbmltYXRvciA6IElPU1NsaWRlTmF2aWdhdG9yQW5pbWF0b3IsXG4gICdsaWZ0JzogKCkgPT4gcGxhdGZvcm0uaXNBbmRyb2lkKCkgPyBNRExpZnROYXZpZ2F0b3JBbmltYXRvciA6IElPU0xpZnROYXZpZ2F0b3JBbmltYXRvcixcbiAgJ2ZhZGUnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IE1ERmFkZU5hdmlnYXRvckFuaW1hdG9yIDogSU9TRmFkZU5hdmlnYXRvckFuaW1hdG9yLFxuICAnc2xpZGUtaW9zJzogSU9TU2xpZGVOYXZpZ2F0b3JBbmltYXRvcixcbiAgJ3NsaWRlLW1kJzogTURTbGlkZU5hdmlnYXRvckFuaW1hdG9yLFxuICAnbGlmdC1pb3MnOiBJT1NMaWZ0TmF2aWdhdG9yQW5pbWF0b3IsXG4gICdsaWZ0LW1kJzogTURMaWZ0TmF2aWdhdG9yQW5pbWF0b3IsXG4gICdmYWRlLWlvcyc6IElPU0ZhZGVOYXZpZ2F0b3JBbmltYXRvcixcbiAgJ2ZhZGUtbWQnOiBNREZhZGVOYXZpZ2F0b3JBbmltYXRvcixcbiAgJ25vbmUnOiBOb25lTmF2aWdhdG9yQW5pbWF0b3Jcbn07XG5cbmNvbnN0IHJld3JpdGFibGVzID0ge1xuICAvKipcbiAgICogQHBhcmFtIHtFbGVtZW50fSBuYXZpZ2F0b3JTaWRlRWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcmVhZHkobmF2aWdhdG9yRWxlbWVudCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG59O1xuXG5jb25zdCB2ZXJpZnlQYWdlRWxlbWVudCA9IGVsID0+IChlbC5ub2RlTmFtZSAhPT0gJ09OUy1QQUdFJykgJiYgdXRpbC50aHJvdyggJ09ubHkgcGFnZSBlbGVtZW50cyBjYW4gYmUgY2hpbGRyZW4gb2YgbmF2aWdhdG9yJyk7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLW5hdmlnYXRvclxuICogQGNhdGVnb3J5IG5hdmlnYXRpb25cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgQSBjb21wb25lbnQgdGhhdCBwcm92aWRlcyBwYWdlIHN0YWNrIG1hbmFnZW1lbnQgYW5kIG5hdmlnYXRpb24uIFN0YWNrIG5hdmlnYXRpb24gaXMgdGhlIG1vc3QgY29tbW9uIG5hdmlnYXRpb24gcGF0dGVybiBmb3IgbW9iaWxlIGFwcHMuXG4gKlxuICogICAgIFdoZW4gYSBwYWdlIGlzIHB1c2hlZCBvbiB0b3Agb2YgdGhlIHN0YWNrIGl0IGlzIGRpc3BsYXllZCB3aXRoIGEgdHJhbnNpdGlvbiBhbmltYXRpb24uIFdoZW4gdGhlIHVzZXIgcmV0dXJucyB0byB0aGUgcHJldmlvdXMgcGFnZSB0aGUgdG9wIHBhZ2Ugd2lsbCBiZSBwb3BwZWQgZnJvbSB0aGUgdG9wIG9mIHRoZSBzdGFjayBhbmQgaGlkZGVuIHdpdGggYW4gb3Bwb3NpdGUgdHJhbnNpdGlvbiBhbmltYXRpb24uXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4geXJodHZcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9uYXZpZ2F0b3JcbiAqIEBndWlkZSBsaWZlY3ljbGUuaHRtbCNldmVudHNcbiAqICAgW2VuXU92ZXJ2aWV3IG9mIHBhZ2UgZXZlbnRzWy9lbl1cbiAqICAgW2phXU92ZXJ2aWV3IG9mIHBhZ2UgZXZlbnRzWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy10b29sYmFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtdG9vbGJhcj5gIGNvbXBvbmVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSB0b29sYmFyIG9uIHRoZSB0b3Agb2YgYSBwYWdlLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQHNlZWFsc28gb25zLWJhY2stYnV0dG9uXG4gKiAgIFtlbl1UaGUgYDxvbnMtYmFjay1idXR0b24+YCBjb21wb25lbnQgbGV0cyB0aGUgdXNlciByZXR1cm4gdG8gdGhlIHByZXZpb3VzIHBhZ2UuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1uYXZpZ2F0b3IgaWQ9XCJuYXZpZ2F0b3JcIj5cbiAqICAgPG9ucy1wYWdlPlxuICogICAgIDxvbnMtdG9vbGJhcj5cbiAqICAgICAgIDxkaXYgY2xhc3M9XCJjZW50ZXJcIj5cbiAqICAgICAgICAgVGl0bGVcbiAqICAgICAgIDwvZGl2PlxuICogICAgIDwvb25zLXRvb2xiYXI+XG4gKiAgICAgPHA+XG4gKiAgICAgICA8b25zLWJ1dHRvblxuICogICAgICAgICBvbmNsaWNrPVwiZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ25hdmlnYXRvcicpLnB1c2hQYWdlKCdwYWdlLmh0bWwnKVwiPlxuICogICAgICAgICBQdXNoIHBhZ2VcbiAqICAgICAgIDwvb25zLWJ1dHRvbj5cbiAqICAgICA8L3A+XG4gKiAgIDwvb25zLXBhZ2U+XG4gKiA8L29ucy1uYXZpZ2F0b3I+XG4gKlxuICogPHRlbXBsYXRlIGlkPVwicGFnZS5odG1sXCI+XG4gKiAgIDxvbnMtcGFnZT5cbiAqICAgICA8b25zLXRvb2xiYXI+XG4gKiAgICAgICA8ZGl2IGNsYXNzPVwibGVmdFwiPlxuICogICAgICAgICA8b25zLWJhY2stYnV0dG9uPkJhY2s8L29ucy1iYWNrLWJ1dHRvbj5cbiAqICAgICAgIDwvZGl2PlxuICogICAgICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlxuICogICAgICAgICBBbm90aGVyIHBhZ2VcbiAqICAgICAgIDwvZGl2PlxuICogICAgIDwvb25zLXRvb2xiYXI+XG4gKiAgIDwvb25zLXBhZ2U+XG4gKiA8L3RlbXBsYXRlPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBOYXZpZ2F0b3JFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHBhZ2VcbiAgICogQGluaXRvbmx5XG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJzdCBwYWdlIHRvIHNob3cgd2hlbiBuYXZpZ2F0b3IgaXMgaW5pdGlhbGl6ZWQuWy9lbl1cbiAgICogICBbamFd44OK44OT44Ky44O844K/44O844GM5Yid5pyf5YyW44GV44KM44Gf5pmC44Gr6KGo56S644GZ44KL44Oa44O844K444KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3dpcGVhYmxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRW5hYmxlIGlPUyBcInN3aXBlIHRvIHBvcFwiIGZlYXR1cmUuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3dpcGUtdGFyZ2V0LXdpZHRoXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IDIwcHhcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSB3aWR0aCBvZiBzd2lwZWFibGUgYXJlYSBjYWxjdWxhdGVkIGZyb20gdGhlIGVkZ2UgKGluIHBpeGVscykuIFVzZSB0aGlzIHRvIGVuYWJsZSBzd2lwZSBvbmx5IHdoZW4gdGhlIGZpbmdlciB0b3VjaCBvbiB0aGUgc2NyZWVuIGVkZ2UuWy9lbl1cbiAgICogICBbamFd44K544Ov44Kk44OX44Gu5Yik5a6a6aCY5Z+f44KS44OU44Kv44K744Or5Y2Y5L2N44Gn5oyH5a6a44GX44G+44GZ44CC55S76Z2i44Gu56uv44GL44KJ5oyH5a6a44GX44Gf6Led6Zui44Gr6YGU44GZ44KL44Go44Oa44O844K444GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3dpcGUtdGhyZXNob2xkXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0IDAuMlxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IGhvdyBtdWNoIHRoZSBwYWdlIG5lZWRzIHRvIGJlIHN3aXBlZCBiZWZvcmUgcG9wcGluZy4gQSB2YWx1ZSBiZXR3ZWVuIGAwYCBhbmQgYDFgLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZWZhdWx0IGRlZmF1bHRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJzbGlkZVwiYCwgYFwibGlmdFwiYCwgYFwiZmFkZVwiYCBhbmQgYFwibm9uZVwiYC5cbiAgICpcbiAgICogICAgIFRoZXNlIGFyZSBwbGF0Zm9ybSBiYXNlZCBhbmltYXRpb25zLiBGb3IgZml4ZWQgYW5pbWF0aW9ucywgYWRkIGBcIi1pb3NcImAgb3IgYFwiLW1kXCJgIHN1ZmZpeCB0byB0aGUgYW5pbWF0aW9uIG5hbWUuIEUuZy4gYFwibGlmdC1pb3NcImAsIGBcImxpZnQtbWRcImAuIERlZmF1bHRzIHZhbHVlcyBhcmUgYFwic2xpZGUtaW9zXCJgIGFuZCBgXCJmYWRlLW1kXCJgIGRlcGVuZGluZyBvbiB0aGUgcGxhdGZvcm0uXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YFsvZW5dXG4gICAqICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIHRpbWluZywgZGVsYXnjgpLjgqrjg5bjgrjjgqfjgq/jg4jjg6rjg4bjg6njg6vjgafmjIflrprjgZfjgb7jgZnjgIJlLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWBbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHByZXB1c2hcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYmVmb3JlIGEgcGFnZSBpcyBwdXNoZWQuWy9lbl1cbiAgICogICBbamFdcGFnZeOBjHB1c2jjgZXjgozjgovnm7TliY3jgavnmbrngavjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQubmF2aWdhdG9yXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmN1cnJlbnRQYWdlXG4gICAqICAgW2VuXUN1cnJlbnQgcGFnZSBvYmplY3QuWy9lbl1cbiAgICogICBbamFd54++5Zyo44GucGFnZeOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LmNhbmNlbFxuICAgKiAgIFtlbl1DYWxsIHRoaXMgZnVuY3Rpb24gdG8gY2FuY2VsIHRoZSBwdXNoLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgXB1c2jlh6bnkIbjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHByZXBvcFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBiZWZvcmUgYSBwYWdlIGlzIHBvcHBlZC5bL2VuXVxuICAgKiAgIFtqYV1wYWdl44GMcG9w44GV44KM44KL55u05YmN44Gr55m654Gr44GV44KM44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50Lm5hdmlnYXRvclxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5jdXJyZW50UGFnZVxuICAgKiAgIFtlbl1DdXJyZW50IHBhZ2Ugb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBrnBhZ2Xjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0aGlzIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgcG9wLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgXBhZ2Xjga5wb3DjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RwdXNoXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGFmdGVyIGEgcGFnZSBpcyBwdXNoZWQuWy9lbl1cbiAgICogICBbamFdcGFnZeOBjHB1c2jjgZXjgozjgabjgqLjg4vjg6Hjg7zjgrfjg6fjg7PjgYzntYLkuobjgZfjgabjgYvjgonnmbrngavjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQubmF2aWdhdG9yXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmVudGVyUGFnZVxuICAgKiAgIFtlbl1PYmplY3Qgb2YgdGhlIG5leHQgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV1wdXNo44GV44KM44GfcGFnZeOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5sZWF2ZVBhZ2VcbiAgICogICBbZW5dT2JqZWN0IG9mIHRoZSBwcmV2aW91cyBwYWdlLlsvZW5dXG4gICAqICAgW2phXeS7peWJjeOBrnBhZ2Xjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3Rwb3BcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgYSBwYWdlIGlzIHBvcHBlZC5bL2VuXVxuICAgKiAgIFtqYV1wYWdl44GMcG9w44GV44KM44Gm44Ki44OL44Oh44O844K344On44Oz44GM57WC44KP44Gj44Gf5b6M44Gr55m654Gr44GV44KM44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50Lm5hdmlnYXRvclxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5lbnRlclBhZ2VcbiAgICogICBbZW5dT2JqZWN0IG9mIHRoZSBuZXh0IHBhZ2UuWy9lbl1cbiAgICogICBbamFdcG9w44GV44KM44Gm6KGo56S644GV44KM44KL44Oa44O844K444Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LmxlYXZlUGFnZVxuICAgKiAgIFtlbl1PYmplY3Qgb2YgdGhlIHByZXZpb3VzIHBhZ2UuWy9lbl1cbiAgICogICBbamFdcG9w44GV44KM44Gm5raI44GI44KL44Oa44O844K444Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IGFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICByZXR1cm4gdGhpcy5fYW5pbWF0b3JGYWN0b3J5O1xuICB9XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX2lzUnVubmluZyA9IGZhbHNlO1xuICAgIHRoaXMuX2luaXRpYWxpemVkID0gZmFsc2U7XG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IGRlZmF1bHRQYWdlTG9hZGVyO1xuICAgIHRoaXMuX3BhZ2VNYXAgPSBuZXcgV2Vha01hcCgpO1xuXG4gICAgdGhpcy5fdXBkYXRlQW5pbWF0b3JGYWN0b3J5KCk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHBhZ2VMb2FkZXJcbiAgICogQHR5cGUge1BhZ2VMb2FkZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1QYWdlTG9hZGVyIGluc3RhbmNlLiBJdCBjYW4gYmUgb3ZlcnJpZGVuIHRvIGNoYW5nZSB0aGUgd2F5IHBhZ2VzIGFyZSBsb2FkZWQgYnkgdGhpcyBlbGVtZW50LiBVc2VmdWwgZm9yIGxpYiBkZXZlbG9wZXJzLlsvZW5dXG4gICAqICAgW2phXVBhZ2VMb2FkZXLjgqTjg7Pjgrnjgr/jg7PjgrnjgpLmoLzntI3jgZfjgabjgYTjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHBhZ2VMb2FkZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhZ2VMb2FkZXI7XG4gIH1cblxuICBzZXQgcGFnZUxvYWRlcihwYWdlTG9hZGVyKSB7XG4gICAgaWYgKCEocGFnZUxvYWRlciBpbnN0YW5jZW9mIFBhZ2VMb2FkZXIpKSB7XG4gICAgICB1dGlsLnRocm93UGFnZUxvYWRlcigpO1xuICAgIH1cbiAgICB0aGlzLl9wYWdlTG9hZGVyID0gcGFnZUxvYWRlcjtcbiAgfVxuXG4gIF9nZXRQYWdlVGFyZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdwYWdlJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHBhZ2VcbiAgICogQHR5cGUgeyp9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBwYWdlIHRvIGJlIGxvYWRlZCBkdXJpbmcgaW5pdGlhbGl6YXRpb24uIFRoaXMgdmFsdWUgdGFrZXMgcHJlY2VkZW5jZSBvdmVyIHRoZSBgcGFnZWAgYXR0cmlidXRlLiBVc2VmdWwgZm9yIGxpYiBkZXZlbG9wZXJzLlsvZW5dXG4gICAqICAgW2phXeWIneacn+WMluaZguOBq+iqreOBv+i+vOOCgOODmuODvOOCuOOCkuaMh+WumuOBl+OBvuOBmeOAgmBwYWdlYOWxnuaAp+OBp+aMh+WumuOBl+OBn+WApOOCiOOCiuOCgmBwYWdlYOODl+ODreODkeODhuOCo+OBq+aMh+WumuOBl+OBn+WApOOCkuWEquWFiOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBnZXQgcGFnZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fcGFnZTtcbiAgfVxuXG4gIHNldCBwYWdlKHBhZ2UpIHtcbiAgICB0aGlzLl9wYWdlID0gcGFnZTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMub25EZXZpY2VCYWNrQnV0dG9uID0gdGhpcy5fb25EZXZpY2VCYWNrQnV0dG9uLmJpbmQodGhpcyk7XG5cbiAgICBpZiAoIXBsYXRmb3JtLmlzQW5kcm9pZCgpIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdzd2lwZWFibGUnKSA9PT0gJ2ZvcmNlJykge1xuICAgICAgbGV0IHN3aXBlQW5pbWF0b3I7XG5cbiAgICAgIHRoaXMuX3N3aXBlID0gbmV3IFN3aXBlUmV2ZWFsKHtcbiAgICAgICAgZWxlbWVudDogdGhpcyxcbiAgICAgICAgZ2V0VGhyZXNob2xkOiAoKSA9PiBNYXRoLm1heCgwLjIsIHBhcnNlRmxvYXQodGhpcy5nZXRBdHRyaWJ1dGUoJ3N3aXBlLXRocmVzaG9sZCcpKSB8fCAwKSxcblxuICAgICAgICBzd2lwZU1heDogKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX29uU3dpcGUgJiYgdGhpcy5fb25Td2lwZSgxLCB7IGR1cmF0aW9uOiBzd2lwZUFuaW1hdG9yLmR1cmF0aW9uU3dpcGUsIHRpbWluZzogc3dpcGVBbmltYXRvci50aW1pbmdTd2lwZSB9KTtcbiAgICAgICAgICB0aGlzW3RoaXMuc3dpcGVNYXggPyAnc3dpcGVNYXgnIDogJ3BvcFBhZ2UnXSh7IGFuaW1hdG9yOiBzd2lwZUFuaW1hdG9yIH0pO1xuICAgICAgICAgIHN3aXBlQW5pbWF0b3IgPSBudWxsO1xuICAgICAgICB9LFxuICAgICAgICBzd2lwZU1pZDogKGRpc3RhbmNlLCB3aWR0aCkgPT4ge1xuICAgICAgICAgIHRoaXMuX29uU3dpcGUgJiYgdGhpcy5fb25Td2lwZShkaXN0YW5jZS93aWR0aCk7XG4gICAgICAgICAgc3dpcGVBbmltYXRvci50cmFuc2xhdGUoZGlzdGFuY2UsIHdpZHRoLCB0aGlzLnRvcFBhZ2UucHJldmlvdXNFbGVtZW50U2libGluZywgdGhpcy50b3BQYWdlKTtcbiAgICAgICAgfSxcbiAgICAgICAgc3dpcGVNaW46ICgpID0+IHtcbiAgICAgICAgICB0aGlzLl9vblN3aXBlICYmIHRoaXMuX29uU3dpcGUoMCwgeyBkdXJhdGlvbjogc3dpcGVBbmltYXRvci5kdXJhdGlvblJlc3RvcmUsIHRpbWluZzogc3dpcGVBbmltYXRvci50aW1pbmdTd2lwZSB9KTtcbiAgICAgICAgICBzd2lwZUFuaW1hdG9yLnJlc3RvcmUodGhpcy50b3BQYWdlLnByZXZpb3VzRWxlbWVudFNpYmxpbmcsIHRoaXMudG9wUGFnZSk7XG4gICAgICAgICAgc3dpcGVBbmltYXRvciA9IG51bGw7XG4gICAgICAgIH0sXG5cbiAgICAgICAgaWdub3JlU3dpcGU6IChldmVudCwgZGlzdGFuY2UpID0+IHtcbiAgICAgICAgICAvLyBCYXNpYyBjb25kaXRpb25zXG4gICAgICAgICAgaWYgKCF0aGlzLl9pc1J1bm5pbmcgJiYgdGhpcy5jaGlsZHJlbi5sZW5ndGggPiAxKSB7XG5cbiAgICAgICAgICAgIC8vIEFyZWEgb3IgZGlyZWN0aW9uYWwgaXNzdWVzXG4gICAgICAgICAgICBjb25zdCBhcmVhID0gcGFyc2VJbnQodGhpcy5nZXRBdHRyaWJ1dGUoJ3N3aXBlLXRhcmdldC13aWR0aCcpIHx8IDI1LCAxMCk7XG4gICAgICAgICAgICBpZiAoZXZlbnQuZ2VzdHVyZS5kaXJlY3Rpb24gPT09ICAncmlnaHQnICYmIGFyZWEgPiBkaXN0YW5jZSkge1xuXG4gICAgICAgICAgICAgIC8vIFN3aXBlcyBvbiBvbnMtYmFjay1idXR0b24gYW5kIGl0cyBjaGlsZHJlblxuICAgICAgICAgICAgICBjb25zdCBpc0JCID0gZWwgPT4gL29ucy1iYWNrLWJ1dHRvbi9pLnRlc3QoZWwudGFnTmFtZSk7XG4gICAgICAgICAgICAgIGlmICghaXNCQihldmVudC50YXJnZXQpICYmICF1dGlsLmZpbmRQYXJlbnQoZXZlbnQudGFyZ2V0LCBpc0JCLCBwID0+IC9vbnMtcGFnZS9pLnRlc3QocC50YWdOYW1lKSkpIHtcblxuICAgICAgICAgICAgICAgIC8vIEFuaW1hdG9yIGlzIHN3aXBlYWJsZVxuICAgICAgICAgICAgICAgIGNvbnN0IGFuaW1hdGlvbiA9ICh0aGlzLnRvcFBhZ2UucHVzaGVkT3B0aW9ucyB8fCB7fSkuYW5pbWF0aW9uIHx8IHRoaXMuYW5pbWF0b3JGYWN0b3J5Ll9hbmltYXRpb247XG4gICAgICAgICAgICAgICAgY29uc3QgQW5pbWF0b3IgPSBfYW5pbWF0b3JEaWN0W2FuaW1hdGlvbl0gaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgICAgICAgICAgICAgPyBfYW5pbWF0b3JEaWN0W2FuaW1hdGlvbl0uY2FsbCgpXG4gICAgICAgICAgICAgICAgICA6IF9hbmltYXRvckRpY3RbYW5pbWF0aW9uXTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgQW5pbWF0b3IgIT09ICd1bmRlZmluZWQnICYmIEFuaW1hdG9yLnN3aXBlYWJsZSkge1xuICAgICAgICAgICAgICAgICAgc3dpcGVBbmltYXRvciA9IG5ldyBBbmltYXRvcigpOyAvLyBQcmVwYXJlIGZvciB0aGUgc3dpcGVcbiAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gdHJ1ZTsgLy8gSWdub3JlIHN3aXBlXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnc3dpcGVhYmxlJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2luaXRpYWxpemVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5faW5pdGlhbGl6ZWQgPSB0cnVlO1xuXG4gICAgY29uc3QgZGVmZXJyZWQgPSB1dGlsLmRlZmVyKCk7XG4gICAgdGhpcy5sb2FkZWQgPSBkZWZlcnJlZC5wcm9taXNlO1xuXG4gICAgcmV3cml0YWJsZXMucmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgY29uc3Qgc2hvdyA9ICF1dGlsLmhhc0FueUNvbXBvbmVudEFzUGFyZW50KHRoaXMpO1xuICAgICAgY29uc3Qgb3B0aW9ucyA9IHsgYW5pbWF0aW9uOiAnbm9uZScsIHNob3cgfTtcblxuICAgICAgaWYgKHRoaXMucGFnZXMubGVuZ3RoID09PSAwICYmIHRoaXMuX2dldFBhZ2VUYXJnZXQoKSkge1xuICAgICAgICB0aGlzLnB1c2hQYWdlKHRoaXMuX2dldFBhZ2VUYXJnZXQoKSwgb3B0aW9ucykudGhlbigoKSA9PiBkZWZlcnJlZC5yZXNvbHZlKCkpO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLnBhZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnBhZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmVyaWZ5UGFnZUVsZW1lbnQodGhpcy5wYWdlc1tpXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy50b3BQYWdlKSB7XG4gICAgICAgICAgY29udGVudFJlYWR5KHRoaXMudG9wUGFnZSwgKCkgPT5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgIHNob3cgJiYgdGhpcy50b3BQYWdlLl9zaG93KCk7XG4gICAgICAgICAgICAgIHRoaXMuX3VwZGF0ZUxhc3RQYWdlQmFja0J1dHRvbigpO1xuICAgICAgICAgICAgfSwgMClcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLnBhZ2VzLmxlbmd0aCA9PT0gMCAmJiB0aGlzLl9nZXRQYWdlVGFyZ2V0KCkpIHtcbiAgICAgICAgICAgIHRoaXMucHVzaFBhZ2UodGhpcy5fZ2V0UGFnZVRhcmdldCgpLCBvcHRpb25zKS50aGVuKCgpID0+IGRlZmVycmVkLnJlc29sdmUoKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogTmF2aWdhdG9yQW5pbWF0b3IsXG4gICAgICBiYXNlQ2xhc3NOYW1lOiAnTmF2aWdhdG9yQW5pbWF0b3InLFxuICAgICAgZGVmYXVsdEFuaW1hdGlvbjogdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpXG4gICAgfSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlci5kZXN0cm95KCk7XG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIgPSBudWxsO1xuXG4gICAgdGhpcy5fc3dpcGUgJiYgdGhpcy5fc3dpcGUuZGlzcG9zZSgpO1xuICAgIHRoaXMuX3N3aXBlID0gbnVsbDtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ2FuaW1hdGlvbicsICdzd2lwZWFibGUnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdhbmltYXRpb24nOlxuICAgICAgICB0aGlzLl91cGRhdGVBbmltYXRvckZhY3RvcnkoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzd2lwZWFibGUnOlxuICAgICAgICB0aGlzLl9zd2lwZSAmJiB0aGlzLl9zd2lwZS51cGRhdGUoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgcG9wUGFnZVxuICAgKiBAc2lnbmF0dXJlIHBvcFBhZ2UoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dXG4gICAqICAgICBBbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcInNsaWRlXCJgLCBgXCJsaWZ0XCJgLCBgXCJmYWRlXCJgIGFuZCBgXCJub25lXCJgLlxuICAgKlxuICAgKiAgICAgVGhlc2UgYXJlIHBsYXRmb3JtIGJhc2VkIGFuaW1hdGlvbnMuIEZvciBmaXhlZCBhbmltYXRpb25zLCBhZGQgYFwiLWlvc1wiYCBvciBgXCItbWRcImAgc3VmZml4IHRvIHRoZSBhbmltYXRpb24gbmFtZS4gRS5nLiBgXCJsaWZ0LWlvc1wiYCwgYFwibGlmdC1tZFwiYC4gRGVmYXVsdHMgdmFsdWVzIGFyZSBgXCJzbGlkZS1pb3NcImAgYW5kIGBcImZhZGUtbWRcImAuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1GdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoZSB0cmFuc2l0aW9uIGhhcyBlbmRlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jg6Hjgr3jg4Pjg4njgavjgojjgovnlLvpnaLpgbfnp7vjgYzntYLkuobjgZfjgZ/pmpvjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuZGF0YV1cbiAgICogICBbZW5dQ3VzdG9tIGRhdGEgdGhhdCB3aWxsIGJlIHN0b3JlZCBpbiB0aGUgbmV3IHBhZ2UgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMudGltZXNdXG4gICAqICAgW2VuXU51bWJlciBvZiBwYWdlcyB0byBiZSBwb3BwZWQuIE9ubHkgb25lIGFuaW1hdGlvbiB3aWxsIGJlIHNob3duLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgdG8gdGhlIHJldmVhbGVkIHBhZ2UuWy9lbl1cbiAgICogICBbamFd5piO44KJ44GL44Gr44GX44Gf44Oa44O844K444KS6Kej5rG644GZ44KLUHJvbWlzZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Qb3BzIHRoZSBjdXJyZW50IHBhZ2UgZnJvbSB0aGUgcGFnZSBzdGFjay4gVGhlIHByZXZpb3VzIHBhZ2Ugd2lsbCBiZSBkaXNwbGF5ZWQuWy9lbl1cbiAgICogICBbamFd54++5Zyo6KGo56S65Lit44Gu44Oa44O844K444KS44Oa44O844K444K544K/44OD44Kv44GL44KJ5Y+W44KK6Zmk44GN44G+44GZ44CC5LiA44Gk5YmN44Gu44Oa44O844K444Gr5oi744KK44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHBvcFBhZ2Uob3B0aW9ucyA9IHt9KSB7XG4gICAgKHtvcHRpb25zfSA9IHRoaXMuX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyhudWxsLCBvcHRpb25zKSk7XG5cbiAgICBpZiAodXRpbC5pc0ludGVnZXIob3B0aW9ucy50aW1lcykgJiYgb3B0aW9ucy50aW1lcyA+IDEpIHtcbiAgICAgIHRoaXMuX3JlbW92ZVBhZ2VzKG9wdGlvbnMudGltZXMpO1xuICAgIH1cblxuICAgIGNvbnN0IHBvcFVwZGF0ZSA9ICgpID0+IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICB0aGlzLl9wYWdlTG9hZGVyLnVubG9hZCh0aGlzLnBhZ2VzW3RoaXMucGFnZXMubGVuZ3RoIC0gMV0pO1xuICAgICAgcmVzb2x2ZSgpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuX3BvcFBhZ2Uob3B0aW9ucywgcG9wVXBkYXRlKTtcbiAgfVxuXG4gIF9wb3BQYWdlKG9wdGlvbnMsIHVwZGF0ZSA9ICgpID0+IFByb21pc2UucmVzb2x2ZSgpKSB7XG4gICAgaWYgKHRoaXMuX2lzUnVubmluZykge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdwb3BQYWdlIGlzIGFscmVhZHkgcnVubmluZy4nKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wYWdlcy5sZW5ndGggPD0gMSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdvbnMtbmF2aWdhdG9yXFwncyBwYWdlIHN0YWNrIGlzIGVtcHR5LicpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9lbWl0UHJlUG9wRXZlbnQoKSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdDYW5jZWxlZCBpbiBwcmVwb3AgZXZlbnQuJyk7XG4gICAgfVxuXG4gICAgY29uc3QgbGVuZ3RoID0gdGhpcy5wYWdlcy5sZW5ndGg7XG5cbiAgICB0aGlzLl9pc1J1bm5pbmcgPSB0cnVlO1xuXG4gICAgdGhpcy5wYWdlc1tsZW5ndGggLSAyXS51cGRhdGVCYWNrQnV0dG9uKChsZW5ndGggLSAyKSA+IDApO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgY29uc3QgbGVhdmVQYWdlID0gdGhpcy5wYWdlc1tsZW5ndGggLSAxXTtcbiAgICAgIGNvbnN0IGVudGVyUGFnZSA9IHRoaXMucGFnZXNbbGVuZ3RoIC0gMl07XG5cbiAgICAgIG9wdGlvbnMgPSB1dGlsLmV4dGVuZCh7fSwgdGhpcy5vcHRpb25zIHx8IHt9LCBsZWF2ZVBhZ2UucHVzaGVkT3B0aW9ucyB8fCB7fSwgb3B0aW9ucyk7XG5cbiAgICAgIGlmIChvcHRpb25zLmRhdGEpIHtcbiAgICAgICAgZW50ZXJQYWdlLmRhdGEgPSB1dGlsLmV4dGVuZCh7fSwgZW50ZXJQYWdlLmRhdGEgfHwge30sIG9wdGlvbnMuZGF0YSB8fCB7fSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRvbmUgPSAoKSA9PiB7XG4gICAgICAgIHVwZGF0ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHRoaXMuX2lzUnVubmluZyA9IGZhbHNlO1xuXG4gICAgICAgICAgZW50ZXJQYWdlLl9zaG93KCk7XG4gICAgICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwb3N0cG9wJywge2xlYXZlUGFnZSwgZW50ZXJQYWdlLCBuYXZpZ2F0b3I6IHRoaXN9KTtcblxuICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2sgJiYgb3B0aW9ucy5jYWxsYmFjayhlbnRlclBhZ2UpO1xuXG4gICAgICAgICAgcmVzb2x2ZShlbnRlclBhZ2UpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIGxlYXZlUGFnZS5faGlkZSgpO1xuICAgICAgZW50ZXJQYWdlLnN0eWxlLmRpc3BsYXkgPSAnJztcblxuICAgICAgY29uc3QgYW5pbWF0b3IgPSBvcHRpb25zLmFuaW1hdG9yIHx8IHRoaXMuX2FuaW1hdG9yRmFjdG9yeS5uZXdBbmltYXRvcihvcHRpb25zKTtcbiAgICAgIGFuaW1hdG9yLnBvcCh0aGlzLnBhZ2VzW2xlbmd0aCAtIDJdLCB0aGlzLnBhZ2VzW2xlbmd0aCAtIDFdLCBkb25lKTtcbiAgICB9KS5jYXRjaCgoKSA9PiB0aGlzLl9pc1J1bm5pbmcgPSBmYWxzZSk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHB1c2hQYWdlXG4gICAqIEBzaWduYXR1cmUgcHVzaFBhZ2UocGFnZSwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge1N0cmluZ30gcGFnZVxuICAgKiAgIFtlbl1QYWdlIFVSTC4gQ2FuIGJlIGVpdGhlciBhIEhUTUwgZG9jdW1lbnQgb3IgYSB0ZW1wbGF0ZSBkZWZpbmVkIHdpdGggdGhlIGA8dGVtcGxhdGU+YCB0YWcuWy9lbl1cbiAgICogICBbamFdcGFnZeOBrlVSTOOBi+OAgeOCguOBl+OBj+OBr2A8dGVtcGxhdGU+YOOBp+Wuo+iogOOBl+OBn+ODhuODs+ODl+ODrOODvOODiOOBrmlk5bGe5oCn44Gu5YCk44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5wYWdlXVxuICAgKiAgIFtlbl1QYWdlIFVSTC4gT25seSBuZWNlc3NhcnkgaWYgYHBhZ2VgIHBhcmFtZXRlciBpcyBudWxsIG9yIHVuZGVmaW5lZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMucGFnZUhUTUxdXG4gICAqICAgW2VuXUhUTUwgY29kZSB0aGF0IHdpbGwgYmUgY29tcHV0ZWQgYXMgYSBuZXcgcGFnZS4gT3ZlcndyaXRlcyBgcGFnZWAgcGFyYW1ldGVyLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXVxuICAgKiAgICAgQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJzbGlkZVwiYCwgYFwibGlmdFwiYCwgYFwiZmFkZVwiYCBhbmQgYFwibm9uZVwiYC5cbiAgICpcbiAgICogICAgIFRoZXNlIGFyZSBwbGF0Zm9ybSBiYXNlZCBhbmltYXRpb25zLiBGb3IgZml4ZWQgYW5pbWF0aW9ucywgYWRkIGBcIi1pb3NcImAgb3IgYFwiLW1kXCJgIHN1ZmZpeCB0byB0aGUgYW5pbWF0aW9uIG5hbWUuIEUuZy4gYFwibGlmdC1pb3NcImAsIGBcImxpZnQtbWRcImAuIERlZmF1bHRzIHZhbHVlcyBhcmUgYFwic2xpZGUtaW9zXCJgIGFuZCBgXCJmYWRlLW1kXCJgLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgZGVsYXkgYW5kIHRpbWluZy4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWBbL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gIFsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1GdW5jdGlvbiB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoZSB0cmFuc2l0aW9uIGhhcyBlbmRlZC5bL2VuXVxuICAgKiAgIFtqYV1wdXNoUGFnZSgp44Gr44KI44KL55S76Z2i6YG356e744GM57WC5LqG44GX44Gf5pmC44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLmRhdGFdXG4gICAqICAgW2VuXUN1c3RvbSBkYXRhIHRoYXQgd2lsbCBiZSBzdG9yZWQgaW4gdGhlIG5ldyBwYWdlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgcHVzaGVkIHBhZ2UuWy9lbl1cbiAgICogICBbamFd6L+95Yqg44GX44Gf44Oa44O844K444KS6Kej5rG644GZ44KLUHJvbWlzZeOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1QdXNoZXMgdGhlIHNwZWNpZmllZCBwYWdlIGludG8gdGhlIHN0YWNrLlsvZW5dXG4gICAqICAgW2phXeaMh+WumuOBl+OBn3BhZ2XjgpLmlrDjgZfjgYTjg5rjg7zjgrjjgrnjgr/jg4Pjgq/jgavov73liqDjgZfjgb7jgZnjgILmlrDjgZfjgYTjg5rjg7zjgrjjgYzooajnpLrjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgcHVzaFBhZ2UocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgKHtwYWdlLCBvcHRpb25zfSA9IHRoaXMuX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyhwYWdlLCBvcHRpb25zKSk7XG5cbiAgICBjb25zdCBwcmVwYXJlID0gcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgdmVyaWZ5UGFnZUVsZW1lbnQocGFnZUVsZW1lbnQpO1xuICAgICAgdGhpcy5fcGFnZU1hcC5zZXQocGFnZUVsZW1lbnQsIHBhZ2UpO1xuICAgICAgcGFnZUVsZW1lbnQgPSB1dGlsLmV4dGVuZChwYWdlRWxlbWVudCwge1xuICAgICAgICBkYXRhOiBvcHRpb25zLmRhdGFcbiAgICAgIH0pO1xuICAgICAgcGFnZUVsZW1lbnQuc3R5bGUudmlzaWJpbGl0eSA9ICdoaWRkZW4nO1xuICAgIH07XG5cbiAgICBpZiAob3B0aW9ucy5wYWdlSFRNTCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3B1c2hQYWdlKG9wdGlvbnMsICgpID0+IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICBpbnN0YW50UGFnZUxvYWRlci5sb2FkKHtwYWdlOiBvcHRpb25zLnBhZ2VIVE1MLCBwYXJlbnQ6IHRoaXMsIHBhcmFtczogb3B0aW9ucy5kYXRhfSwgcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgICAgIHByZXBhcmUocGFnZUVsZW1lbnQpO1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfSk7XG4gICAgICB9KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX3B1c2hQYWdlKG9wdGlvbnMsICgpID0+IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5fcGFnZUxvYWRlci5sb2FkKHtwYWdlLCBwYXJlbnQ6IHRoaXMsIHBhcmFtczogb3B0aW9ucy5kYXRhfSwgcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgICBwcmVwYXJlKHBhZ2VFbGVtZW50KTtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfSkpO1xuICB9XG5cbiAgX3B1c2hQYWdlKG9wdGlvbnMgPSB7fSwgdXBkYXRlID0gKCkgPT4gUHJvbWlzZS5yZXNvbHZlKCkpIHtcbiAgICBpZiAodGhpcy5faXNSdW5uaW5nKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ3B1c2hQYWdlIGlzIGFscmVhZHkgcnVubmluZy4nKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZW1pdFByZVB1c2hFdmVudCgpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0NhbmNlbGVkIGluIHByZXB1c2ggZXZlbnQuJyk7XG4gICAgfVxuXG4gICAgdGhpcy5faXNSdW5uaW5nID0gdHJ1ZTtcblxuICAgIGNvbnN0IGFuaW1hdGlvbk9wdGlvbnMgPSBBbmltYXRvckZhY3RvcnkucGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKTtcbiAgICBvcHRpb25zID0gdXRpbC5leHRlbmQoe30sIHRoaXMub3B0aW9ucyB8fCB7fSwge2FuaW1hdGlvbk9wdGlvbnN9LCBvcHRpb25zKTtcblxuICAgIGNvbnN0IGFuaW1hdG9yID0gdGhpcy5fYW5pbWF0b3JGYWN0b3J5Lm5ld0FuaW1hdG9yKG9wdGlvbnMpO1xuXG4gICAgcmV0dXJuIHVwZGF0ZSgpLnRoZW4oKCkgPT4ge1xuICAgICAgY29uc3QgcGFnZUxlbmd0aCA9IHRoaXMucGFnZXMubGVuZ3RoO1xuXG4gICAgICBjb25zdCBlbnRlclBhZ2UgID0gdGhpcy5wYWdlc1twYWdlTGVuZ3RoIC0gMV07XG4gICAgICBjb25zdCBsZWF2ZVBhZ2UgPSBvcHRpb25zLmxlYXZlUGFnZSB8fCB0aGlzLnBhZ2VzW3BhZ2VMZW5ndGggLSAyXTtcblxuICAgICAgdmVyaWZ5UGFnZUVsZW1lbnQoZW50ZXJQYWdlKTtcblxuICAgICAgZW50ZXJQYWdlLnVwZGF0ZUJhY2tCdXR0b24ocGFnZUxlbmd0aCA+IChvcHRpb25zLl9yZXBsYWNlUGFnZSA/IDIgOiAxKSk7XG5cbiAgICAgIGVudGVyUGFnZS5wdXNoZWRPcHRpb25zID0gdXRpbC5leHRlbmQoe30sIGVudGVyUGFnZS5wdXNoZWRPcHRpb25zIHx8IHt9LCBvcHRpb25zIHx8IHt9KTtcbiAgICAgIGVudGVyUGFnZS5kYXRhID0gdXRpbC5leHRlbmQoe30sIGVudGVyUGFnZS5kYXRhIHx8IHt9LCBvcHRpb25zLmRhdGEgfHwge30pO1xuICAgICAgZW50ZXJQYWdlLnVubG9hZCA9IGVudGVyUGFnZS51bmxvYWQgfHwgb3B0aW9ucy51bmxvYWQ7XG5cbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgY29uc3QgZG9uZSA9ICgpID0+IHtcbiAgICAgICAgICB0aGlzLl9pc1J1bm5pbmcgPSBmYWxzZTtcblxuICAgICAgICAgIG9wdGlvbnMuc2hvdyAhPT0gZmFsc2UgJiYgc2V0SW1tZWRpYXRlKCgpID0+IGVudGVyUGFnZS5fc2hvdygpKTtcbiAgICAgICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ3Bvc3RwdXNoJywge2xlYXZlUGFnZSwgZW50ZXJQYWdlLCBuYXZpZ2F0b3I6IHRoaXN9KTtcblxuICAgICAgICAgIGlmIChsZWF2ZVBhZ2UpIHtcbiAgICAgICAgICAgIGxlYXZlUGFnZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2sgJiYgb3B0aW9ucy5jYWxsYmFjayhlbnRlclBhZ2UpO1xuXG4gICAgICAgICAgcmVzb2x2ZShlbnRlclBhZ2UpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGVudGVyUGFnZS5zdHlsZS52aXNpYmlsaXR5ID0gJyc7XG4gICAgICAgIGlmIChsZWF2ZVBhZ2UpIHtcbiAgICAgICAgICBsZWF2ZVBhZ2UuX2hpZGUoKTtcbiAgICAgICAgICBhbmltYXRvci5wdXNoKGVudGVyUGFnZSwgbGVhdmVQYWdlLCBkb25lKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgdGhpcy5faXNSdW5uaW5nID0gZmFsc2U7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHJlcGxhY2VQYWdlXG4gICAqIEBzaWduYXR1cmUgcmVwbGFjZVBhZ2UocGFnZSwgW29wdGlvbnNdKVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1Qcm9taXNlIHdoaWNoIHJlc29sdmVzIHRvIHRoZSBuZXcgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV3mlrDjgZfjgYTjg5rjg7zjgrjjgpLop6PmsbrjgZnjgotQcm9taXNl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJlcGxhY2VzIHRoZSBjdXJyZW50IHRvcCBwYWdlIHdpdGggdGhlIHNwZWNpZmllZCBvbmUuIEV4dGVuZHMgYHB1c2hQYWdlKClgIHBhcmFtZXRlcnMuWy9lbl1cbiAgICogICBbamFd54++5Zyo6KGo56S65Lit44Gu44Oa44O844K444KS44KS5oyH5a6a44GX44Gf44Oa44O844K444Gr572u44GN5o+b44GI44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHJlcGxhY2VQYWdlKHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiB0aGlzLnB1c2hQYWdlKHBhZ2UsIG9wdGlvbnMpXG4gICAgICAudGhlbihyZXNvbHZlZFZhbHVlID0+IHtcbiAgICAgICAgaWYgKHRoaXMucGFnZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgIHRoaXMuX3BhZ2VMb2FkZXIudW5sb2FkKHRoaXMucGFnZXNbdGhpcy5wYWdlcy5sZW5ndGggLSAyXSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fdXBkYXRlTGFzdFBhZ2VCYWNrQnV0dG9uKCk7XG5cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXNvbHZlZFZhbHVlKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaW5zZXJ0UGFnZVxuICAgKiBAc2lnbmF0dXJlIGluc2VydFBhZ2UoaW5kZXgsIHBhZ2UsIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4XG4gICAqICAgW2VuXVRoZSBpbmRleCB3aGVyZSBpdCBzaG91bGQgYmUgaW5zZXJ0ZWQuWy9lbl1cbiAgICogICBbamFd44K544K/44OD44Kv44Gr5oy/5YWl44GZ44KL5L2N572u44Gu44Kk44Oz44OH44OD44Kv44K544KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgaW5zZXJ0ZWQgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV3mjIflrprjgZfjgZ/jg5rjg7zjgrjjgpLop6PmsbrjgZnjgotQcm9taXNl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUluc2VydCB0aGUgc3BlY2lmaWVkIHBhZ2UgaW50byB0aGUgc3RhY2sgd2l0aCBhdCBhIHBvc2l0aW9uIGRlZmluZWQgYnkgdGhlIGBpbmRleGAgYXJndW1lbnQuIEV4dGVuZHMgYHB1c2hQYWdlKClgIHBhcmFtZXRlcnMuWy9lbl1cbiAgICogICBbamFd5oyH5a6a44GX44GfcGFnZeOCkuODmuODvOOCuOOCueOCv+ODg+OCr+OBrmluZGV444Gn5oyH5a6a44GX44Gf5L2N572u44Gr6L+95Yqg44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGluc2VydFBhZ2UoaW5kZXgsIHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuICAgICh7cGFnZSwgb3B0aW9uc30gPSB0aGlzLl9wcmVwYXJlUGFnZUFuZE9wdGlvbnMocGFnZSwgb3B0aW9ucykpO1xuICAgIGluZGV4ID0gdGhpcy5fbm9ybWFsaXplSW5kZXgoaW5kZXgpO1xuXG4gICAgaWYgKGluZGV4ID49IHRoaXMucGFnZXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGhpcy5wdXNoUGFnZShwYWdlLCBvcHRpb25zKTtcbiAgICB9XG5cbiAgICBwYWdlID0gdHlwZW9mIG9wdGlvbnMucGFnZUhUTUwgPT09ICdzdHJpbmcnID8gb3B0aW9ucy5wYWdlSFRNTCA6IHBhZ2U7XG4gICAgY29uc3QgbG9hZGVyID0gdHlwZW9mIG9wdGlvbnMucGFnZUhUTUwgPT09ICdzdHJpbmcnID8gaW5zdGFudFBhZ2VMb2FkZXIgOiB0aGlzLl9wYWdlTG9hZGVyO1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgbG9hZGVyLmxvYWQoe3BhZ2UsIHBhcmVudDogdGhpc30sIHBhZ2VFbGVtZW50ID0+IHtcbiAgICAgICAgdmVyaWZ5UGFnZUVsZW1lbnQocGFnZUVsZW1lbnQpO1xuICAgICAgICB0aGlzLl9wYWdlTWFwLnNldChwYWdlRWxlbWVudCwgcGFnZSk7XG4gICAgICAgIHBhZ2VFbGVtZW50ID0gdXRpbC5leHRlbmQocGFnZUVsZW1lbnQsIHtcbiAgICAgICAgICBkYXRhOiBvcHRpb25zLmRhdGEsXG4gICAgICAgICAgcHVzaGVkT3B0aW9uczogb3B0aW9uc1xuICAgICAgICB9KTtcblxuICAgICAgICBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnMgPSB1dGlsLmV4dGVuZChcbiAgICAgICAgICB7fSxcbiAgICAgICAgICBBbmltYXRvckZhY3RvcnkucGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKSxcbiAgICAgICAgICBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnMgfHwge31cbiAgICAgICAgKTtcblxuICAgICAgICBwYWdlRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICB0aGlzLmluc2VydEJlZm9yZShwYWdlRWxlbWVudCwgdGhpcy5wYWdlc1tpbmRleF0pO1xuICAgICAgICB0aGlzLnRvcFBhZ2UudXBkYXRlQmFja0J1dHRvbih0cnVlKTtcblxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICBwYWdlRWxlbWVudCA9IG51bGw7XG4gICAgICAgICAgcmVzb2x2ZSh0aGlzLnBhZ2VzW2luZGV4XSk7XG4gICAgICAgIH0sIDEwMDAgLyA2MCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHJlbW92ZVBhZ2VcbiAgICogQHNpZ25hdHVyZSByZW1vdmVQYWdlKGluZGV4LCBbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBpbmRleFxuICAgKiAgIFtlbl1UaGUgaW5kZXggd2hlcmUgaXQgc2hvdWxkIGJlIHJlbW92ZWQuWy9lbl1cbiAgICogICBbamFd44K544K/44OD44Kv44GL44KJ5YmK6Zmk44GZ44KL44Oa44O844K444Gu44Kk44Oz44OH44OD44Kv44K544KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgcmV2ZWFsZWQgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV3liYrpmaTjgavjgojjgaPjgabooajnpLrjgZXjgozjgZ/jg5rjg7zjgrjjgpLop6PmsbrjgZnjgotQcm9taXNl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJlbW92ZSB0aGUgc3BlY2lmaWVkIHBhZ2UgYXQgYSBwb3NpdGlvbiBpbiB0aGUgc3RhY2sgZGVmaW5lZCBieSB0aGUgYGluZGV4YCBhcmd1bWVudC4gRXh0ZW5kcyBgcG9wUGFnZSgpYCBwYXJhbWV0ZXJzLlsvZW5dXG4gICAqICAgW2phXeaMh+WumuOBl+OBn+OCpOODs+ODh+ODg+OCr+OCueOBq+OBguOCi+ODmuODvOOCuOOCkuWJiumZpOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICByZW1vdmVQYWdlKGluZGV4LCBvcHRpb25zID0ge30pIHtcbiAgICBpbmRleCA9IHRoaXMuX25vcm1hbGl6ZUluZGV4KGluZGV4KTtcblxuICAgIGlmIChpbmRleCA8IHRoaXMucGFnZXMubGVuZ3RoIC0gMSkge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgICBjb25zdCBsZWF2ZVBhZ2UgPSB0aGlzLnBhZ2VzW2luZGV4XTtcbiAgICAgICAgY29uc3QgZW50ZXJQYWdlID0gdGhpcy50b3BQYWdlO1xuXG4gICAgICAgIHRoaXMuX3BhZ2VNYXAuZGVsZXRlKGxlYXZlUGFnZSk7XG4gICAgICAgIHRoaXMuX3BhZ2VMb2FkZXIudW5sb2FkKGxlYXZlUGFnZSk7XG4gICAgICAgIGlmICh0aGlzLnBhZ2VzLmxlbmd0aCA9PT0gMSkgeyAvLyBlZGdlIGNhc2VcbiAgICAgICAgICB0aGlzLnRvcFBhZ2UudXBkYXRlQmFja0J1dHRvbihmYWxzZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXNvbHZlKGVudGVyUGFnZSk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMucG9wUGFnZShvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCByZXNldFRvUGFnZVxuICAgKiBAc2lnbmF0dXJlIHJlc2V0VG9QYWdlKHBhZ2UsIFtvcHRpb25zXSlcbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUHJvbWlzZSB3aGljaCByZXNvbHZlcyB0byB0aGUgbmV3IHRvcCBwYWdlLlsvZW5dXG4gICAqICAgW2phXeaWsOOBl+OBhOODiOODg+ODl+ODmuODvOOCuOOCkuino+axuuOBmeOCi1Byb21pc2XjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLnBvcF1cbiAgICogICBbZW5dUGVyZm9ybXMgJ3BvcCcgZWZmZWN0IGlmIGB0cnVlYCBpbnN0ZWFkIG9mICdwdXNoJyBvciBub25lLiBUaGlzIGFsc28gc2V0cyBgb3B0aW9ucy5hbmltYXRpb25gIHZhbHVlIHRvIGBkZWZhdWx0YCBpbnN0ZWFkIG9mIGBub25lYC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ2xlYXJzIHBhZ2Ugc3RhY2sgYW5kIGFkZHMgdGhlIHNwZWNpZmllZCBwYWdlIHRvIHRoZSBzdGFjay4gRXh0ZW5kcyBgcHVzaFBhZ2UoKWAgcGFyYW1ldGVycy5bL2VuXVxuICAgKiAgIFtqYV3jg5rjg7zjgrjjgrnjgr/jg4Pjgq/jgpLjg6rjgrvjg4Pjg4jjgZfjgIHmjIflrprjgZfjgZ/jg5rjg7zjgrjjgpLooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgcmVzZXRUb1BhZ2UocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgKHtwYWdlLCBvcHRpb25zfSA9IHRoaXMuX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyhwYWdlLCBvcHRpb25zKSk7XG5cbiAgICBpZiAoIW9wdGlvbnMuYW5pbWF0b3IgJiYgIW9wdGlvbnMuYW5pbWF0aW9uICYmICFvcHRpb25zLnBvcCkge1xuICAgICAgb3B0aW9ucy5hbmltYXRpb24gPSAnbm9uZSc7XG4gICAgfVxuXG4gICAgaWYgKCFvcHRpb25zLnBhZ2UgJiYgIW9wdGlvbnMucGFnZUhUTUwgJiYgdGhpcy5fZ2V0UGFnZVRhcmdldCgpKSB7XG4gICAgICBwYWdlID0gb3B0aW9ucy5wYWdlID0gdGhpcy5fZ2V0UGFnZVRhcmdldCgpO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zLnBvcCkge1xuICAgICAgdGhpcy5fcmVtb3ZlUGFnZXMoKVxuICAgICAgcmV0dXJuIHRoaXMuaW5zZXJ0UGFnZSgwLCBwYWdlLCB7IGRhdGE6IG9wdGlvbnMuZGF0YSB9KVxuICAgICAgICAudGhlbigoKSA9PiB0aGlzLnBvcFBhZ2Uob3B0aW9ucykpO1xuICAgIH1cblxuICAgIC8vIFRpcDogY2FsbGJhY2sgcnVucyBiZWZvcmUgcmVzb2x2ZWQgcHJvbWlzZVxuICAgIGNvbnN0IGNhbGxiYWNrID0gb3B0aW9ucy5jYWxsYmFjaztcbiAgICBvcHRpb25zLmNhbGxiYWNrID0gbmV3UGFnZSA9PiB7XG4gICAgICB0aGlzLl9yZW1vdmVQYWdlcygpXG4gICAgICBuZXdQYWdlLnVwZGF0ZUJhY2tCdXR0b24oZmFsc2UpO1xuICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2sobmV3UGFnZSk7XG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLnB1c2hQYWdlKHBhZ2UsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgYnJpbmdQYWdlVG9wXG4gICAqIEBzaWduYXR1cmUgYnJpbmdQYWdlVG9wKGl0ZW0sIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtTdHJpbmd8TnVtYmVyfSBpdGVtXG4gICAqICAgW2VuXVBhZ2UgVVJMIG9yIGluZGV4IG9mIGFuIGV4aXN0aW5nIHBhZ2UgaW4gbmF2aWdhdG9yJ3Mgc3RhY2suWy9lbl1cbiAgICogICBbamFd44Oa44O844K444GuVVJM44GL44KC44GX44GP44Gvb25zLW5hdmlnYXRvcuOBruODmuODvOOCuOOCueOCv+ODg+OCr+OBruOCpOODs+ODh+ODg+OCr+OCueWApOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgdG8gdGhlIG5ldyB0b3AgcGFnZS5bL2VuXVxuICAgKiAgIFtqYV3mlrDjgZfjgYTjg4jjg4Pjg5fjg5rjg7zjgrjjgpLop6PmsbrjgZnjgotQcm9taXNl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJyaW5ncyB0aGUgZ2l2ZW4gcGFnZSB0byB0aGUgdG9wIG9mIHRoZSBwYWdlIHN0YWNrIGlmIGl0IGFscmVhZHkgZXhpc3RzIG9yIHB1c2hlcyBpdCBpbnRvIHRoZSBzdGFjayBpZiBkb2Vzbid0LiBFeHRlbmRzIGBwdXNoUGFnZSgpYCBwYXJhbWV0ZXJzLlsvZW5dXG4gICAqICAgW2phXeaMh+WumuOBl+OBn+ODmuODvOOCuOOCkuODmuODvOOCuOOCueOCv+ODg+OCr+OBruS4gOeVquS4iuOBq+enu+WLleOBl+OBvuOBmeOAguOCguOBl+aMh+WumuOBl+OBn+ODmuODvOOCuOOBjOeEoeOBi+OBo+OBn+WgtOWQiOaWsOOBl+OBj3B1c2jjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgYnJpbmdQYWdlVG9wKGl0ZW0sIG9wdGlvbnMgPSB7fSkge1xuICAgIGlmIChbJ251bWJlcicsICdzdHJpbmcnXS5pbmRleE9mKHR5cGVvZiBpdGVtKSA9PT0gLTEpIHtcbiAgICAgIHV0aWwudGhyb3coJ0ZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYSBwYWdlIG5hbWUgb3IgdGhlIGluZGV4IG9mIGFuIGV4aXN0aW5nIHBhZ2UuIFlvdSBzdXBwbGllZCAnICsgaXRlbSk7XG4gICAgfVxuICAgIGNvbnN0IGluZGV4ID0gdHlwZW9mIGl0ZW0gPT09ICdudW1iZXInID8gdGhpcy5fbm9ybWFsaXplSW5kZXgoaXRlbSkgOiB0aGlzLl9sYXN0SW5kZXhPZlBhZ2UoaXRlbSk7XG4gICAgY29uc3QgcGFnZSA9IHRoaXMucGFnZXNbaW5kZXhdO1xuXG4gICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgcmV0dXJuIHRoaXMucHVzaFBhZ2UoaXRlbSwgb3B0aW9ucyk7XG4gICAgfVxuICAgICh7b3B0aW9uc30gPSB0aGlzLl9wcmVwYXJlUGFnZUFuZE9wdGlvbnMocGFnZSwgb3B0aW9ucykpO1xuXG4gICAgaWYgKGluZGV4ID09PSB0aGlzLnBhZ2VzLmxlbmd0aCAtIDEpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUocGFnZSk7XG4gICAgfVxuICAgIGlmICghcGFnZSkge1xuICAgICAgdXRpbC50aHJvdygnRmFpbGVkIHRvIGZpbmQgaXRlbSAnICsgaXRlbSk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9pc1J1bm5pbmcpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgncHVzaFBhZ2UgaXMgYWxyZWFkeSBydW5uaW5nLicpO1xuICAgIH1cbiAgICBpZiAodGhpcy5fZW1pdFByZVB1c2hFdmVudCgpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0NhbmNlbGVkIGluIHByZXB1c2ggZXZlbnQuJyk7XG4gICAgfVxuXG4gICAgcGFnZS5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgcGFnZS5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7XG4gICAgcGFnZS5wYXJlbnROb2RlLmFwcGVuZENoaWxkKHBhZ2UpO1xuICAgIHJldHVybiB0aGlzLl9wdXNoUGFnZShvcHRpb25zKTtcbiAgfVxuXG4gIF9wcmVwYXJlUGFnZUFuZE9wdGlvbnMocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zICE9ICdvYmplY3QnKSB7XG4gICAgICB1dGlsLnRocm93KCdvcHRpb25zIG11c3QgYmUgYW4gb2JqZWN0LiBZb3Ugc3VwcGxpZWQgJyArIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGlmICgocGFnZSA9PT0gbnVsbCB8fCBwYWdlID09PSB1bmRlZmluZWQpICYmIG9wdGlvbnMucGFnZSkge1xuICAgICAgcGFnZSA9IG9wdGlvbnMucGFnZTtcbiAgICB9XG5cbiAgICBvcHRpb25zID0gdXRpbC5leHRlbmQoe30sIHRoaXMub3B0aW9ucyB8fCB7fSwgb3B0aW9ucywge3BhZ2V9KTtcblxuICAgIHJldHVybiB7cGFnZSwgb3B0aW9uc307XG4gIH1cblxuICBfcmVtb3ZlUGFnZXModGltZXMpIHtcbiAgICBjb25zdCBwYWdlcyA9IHRoaXMucGFnZXM7XG4gICAgbGV0IHVudGlsID0gdGltZXMgPT09IHVuZGVmaW5lZCA/IDAgOiBwYWdlcy5sZW5ndGggLSB0aW1lcztcbiAgICB1bnRpbCA9IHVudGlsIDwgMCA/IDEgOiB1bnRpbDtcblxuICAgIGZvciAobGV0IGkgPSBwYWdlcy5sZW5ndGggLSAyOyBpID49IHVudGlsOyBpLS0pIHtcbiAgICAgIHRoaXMuX3BhZ2VNYXAuZGVsZXRlKHBhZ2VzW2ldKTtcbiAgICAgIHRoaXMuX3BhZ2VMb2FkZXIudW5sb2FkKHBhZ2VzW2ldKTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlTGFzdFBhZ2VCYWNrQnV0dG9uKCkge1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5wYWdlcy5sZW5ndGggLSAxO1xuICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICB0aGlzLnBhZ2VzW2luZGV4XS51cGRhdGVCYWNrQnV0dG9uKGluZGV4ID4gMCk7XG4gICAgfVxuICB9XG5cbiAgX25vcm1hbGl6ZUluZGV4KGluZGV4KSB7XG4gICAgcmV0dXJuIGluZGV4ID49IDAgPyBpbmRleCA6IE1hdGguYWJzKHRoaXMucGFnZXMubGVuZ3RoICsgaW5kZXgpICUgdGhpcy5wYWdlcy5sZW5ndGg7XG4gIH1cblxuICBfb25EZXZpY2VCYWNrQnV0dG9uKGV2ZW50KSB7XG4gICAgaWYgKHRoaXMucGFnZXMubGVuZ3RoID4gMSkge1xuICAgICAgdGhpcy5wb3BQYWdlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV2ZW50LmNhbGxQYXJlbnRIYW5kbGVyKCk7XG4gICAgfVxuICB9XG5cbiAgX2xhc3RJbmRleE9mUGFnZShwYWdlTmFtZSkge1xuICAgIGxldCBpbmRleDtcbiAgICBmb3IgKGluZGV4ID0gdGhpcy5wYWdlcy5sZW5ndGggLSAxOyBpbmRleCA+PSAwOyBpbmRleC0tKSB7XG4gICAgICBpZiAocGFnZU5hbWUgPT09IHRoaXMuX3BhZ2VNYXAuZ2V0KHRoaXMucGFnZXNbaW5kZXhdKSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgX2VtaXRQcmVFdmVudChuYW1lLCBkYXRhID0ge30pIHtcbiAgICBsZXQgaXNDYW5jZWxlZCA9IGZhbHNlO1xuXG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwcmUnICsgbmFtZSwgdXRpbC5leHRlbmQoe1xuICAgICAgbmF2aWdhdG9yOiB0aGlzLFxuICAgICAgY3VycmVudFBhZ2U6IHRoaXMucGFnZXNbdGhpcy5wYWdlcy5sZW5ndGggLSAxXSxcbiAgICAgIGNhbmNlbDogKCkgPT4gaXNDYW5jZWxlZCA9IHRydWVcbiAgICB9LCBkYXRhKSk7XG5cbiAgICByZXR1cm4gaXNDYW5jZWxlZDtcbiAgfVxuXG4gIF9lbWl0UHJlUHVzaEV2ZW50KCkge1xuICAgIHJldHVybiB0aGlzLl9lbWl0UHJlRXZlbnQoJ3B1c2gnKTtcbiAgfVxuXG4gIF9lbWl0UHJlUG9wRXZlbnQoKSB7XG4gICAgY29uc3QgbCA9IHRoaXMucGFnZXMubGVuZ3RoO1xuICAgIHJldHVybiB0aGlzLl9lbWl0UHJlRXZlbnQoJ3BvcCcsIHtcbiAgICAgIGxlYXZlUGFnZTogdGhpcy5wYWdlc1tsIC0gMV0sXG4gICAgICBlbnRlclBhZ2U6IHRoaXMucGFnZXNbbCAtIDJdXG4gICAgfSk7XG4gIH1cblxuICAvLyBUT0RPOiDmm7jjgY3nm7TjgZlcbiAgX2NyZWF0ZVBhZ2VFbGVtZW50KHRlbXBsYXRlSFRNTCkge1xuICAgIGNvbnN0IHBhZ2VFbGVtZW50ID0gdXRpbC5jcmVhdGVFbGVtZW50KGludGVybmFsLm5vcm1hbGl6ZVBhZ2VIVE1MKHRlbXBsYXRlSFRNTCkpO1xuICAgIHZlcmlmeVBhZ2VFbGVtZW50KHBhZ2VFbGVtZW50KTtcbiAgICByZXR1cm4gcGFnZUVsZW1lbnQ7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9uRGV2aWNlQmFja0J1dHRvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQmFjay1idXR0b24gaGFuZGxlci5bL2VuXVxuICAgKiAgIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjg4/jg7Pjg4njg6njgIJbL2phXVxuICAgKi9cbiAgZ2V0IG9uRGV2aWNlQmFja0J1dHRvbigpIHtcbiAgICByZXR1cm4gdGhpcy5fYmFja0J1dHRvbkhhbmRsZXI7XG4gIH1cblxuICBzZXQgb25EZXZpY2VCYWNrQnV0dG9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyKSB7XG4gICAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlci5kZXN0cm95KCk7XG4gICAgfVxuXG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIgPSBkZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlci5jcmVhdGVIYW5kbGVyKHRoaXMsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdG9wUGFnZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCB0b3AgcGFnZSBlbGVtZW50LiBVc2UgdGhpcyBtZXRob2QgdG8gYWNjZXNzIG9wdGlvbnMgcGFzc2VkIGJ5IGBwdXNoUGFnZSgpYC1saWtlIG1ldGhvZHMuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu44Oa44O844K444KS5Y+W5b6X44GX44G+44GZ44CCcHVzaFBhZ2UoKeOChHJlc2V0VG9QYWdlKCnjg6Hjgr3jg4Pjg4njga7lvJXmlbDjgpLlj5blvpfjgafjgY3jgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHRvcFBhZ2UoKSB7XG4gICAgbGV0IGxhc3QgPSB0aGlzLmxhc3RFbGVtZW50Q2hpbGQ7XG4gICAgd2hpbGUgKGxhc3QgJiYgbGFzdC50YWdOYW1lICE9PSAnT05TLVBBR0UnKSB7IGxhc3QgPSBsYXN0LnByZXZpb3VzRWxlbWVudFNpYmxpbmc7IH1cbiAgICByZXR1cm4gbGFzdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgcGFnZXNcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtBcnJheX1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUNvcHkgb2YgdGhlIG5hdmlnYXRvcidzIHBhZ2Ugc3RhY2suWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBwYWdlcygpIHtcbiAgICByZXR1cm4gdXRpbC5hcnJheUZyb20odGhpcy5jaGlsZHJlbilcbiAgICAgIC5maWx0ZXIoZWxlbWVudCA9PiBlbGVtZW50LnRhZ05hbWUgPT09ICdPTlMtUEFHRScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvblN3aXBlXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUhvb2sgY2FsbGVkIHdoZW5ldmVyIHRoZSB1c2VyIHNsaWRlcyB0aGUgbmF2aWdhdG9yIChzd2lwZS10by1wb3ApLiBJdCBnZXRzIGEgZGVjaW1hbCByYXRpbyAoMC0xKSBhbmQgYW4gYW5pbWF0aW9uT3B0aW9ucyBvYmplY3QgYXMgYXJndW1lbnRzLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgb25Td2lwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fb25Td2lwZTtcbiAgfVxuXG4gIHNldCBvblN3aXBlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHV0aWwudGhyb3coJ1wib25Td2lwZVwiIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgIH1cbiAgICB0aGlzLl9vblN3aXBlID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9wdGlvbnNcbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXURlZmF1bHQgb3B0aW9ucyBvYmplY3QuIEF0dHJpYnV0ZXMgaGF2ZSBwcmlvcml0eSBvdmVyIHRoaXMgcHJvcGVydHkuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zLmFuaW1hdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dXG4gICAqICAgICBBbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcInNsaWRlXCJgLCBgXCJsaWZ0XCJgLCBgXCJmYWRlXCJgIGFuZCBgXCJub25lXCJgLlxuICAgKiAgICAgVGhlc2UgYXJlIHBsYXRmb3JtIGJhc2VkIGFuaW1hdGlvbnMuIEZvciBmaXhlZCBhbmltYXRpb25zLCBhZGQgYFwiLWlvc1wiYCBvciBgXCItbWRcImAgc3VmZml4IHRvIHRoZSBhbmltYXRpb24gbmFtZS4gRS5nLiBgXCJsaWZ0LWlvc1wiYCwgYFwibGlmdC1tZFwiYC4gRGVmYXVsdHMgdmFsdWVzIGFyZSBgXCJzbGlkZS1pb3NcImAgYW5kIGBcImZhZGUtbWRcImAuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb3B0aW9ucy5jYWxsYmFja1xuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbiB0aGUgdHJhbnNpdGlvbiBoYXMgZW5kZWQuWy9lbl1cbiAgICogICBbamFd44GT44Gu44Oh44K944OD44OJ44Gr44KI44KL55S76Z2i6YG356e744GM57WC5LqG44GX44Gf6Zqb44Gr5ZG844Gz5Ye644GV44KM44KL6Zai5pWw44Kq44OW44K444Kn44Kv44OI44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IG9wdGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX29wdGlvbnM7XG4gIH1cbiAgc2V0IG9wdGlvbnMob2JqZWN0KSB7XG4gICAgdGhpcy5fb3B0aW9ucyA9IG9iamVjdDtcbiAgfVxuXG4gIHNldCBfaXNSdW5uaW5nKHZhbHVlKSB7XG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ19pcy1ydW5uaW5nJywgdmFsdWUgPyAndHJ1ZScgOiAnZmFsc2UnKTtcbiAgfVxuICBnZXQgX2lzUnVubmluZygpIHtcbiAgIHJldHVybiBKU09OLnBhcnNlKHRoaXMuZ2V0QXR0cmlidXRlKCdfaXMtcnVubmluZycpKTtcbiAgfVxuXG4gIF9zaG93KCkge1xuICAgIHRoaXMubG9hZGVkLnRoZW4oKCkgPT4gdGhpcy50b3BQYWdlICYmIHRoaXMudG9wUGFnZS5fc2hvdygpKVxuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgdGhpcy50b3BQYWdlICYmIHRoaXMudG9wUGFnZS5faGlkZSgpXG4gIH1cblxuICBfZGVzdHJveSgpIHtcbiAgICBmb3IgKGxldCBpID0gdGhpcy5wYWdlcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdGhpcy5fcGFnZUxvYWRlci51bmxvYWQodGhpcy5wYWdlc1tpXSk7XG4gICAgfVxuXG4gICAgdGhpcy5yZW1vdmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBBbmltYXRvclxuICAgKi9cbiAgc3RhdGljIHJlZ2lzdGVyQW5pbWF0b3IobmFtZSwgQW5pbWF0b3IpIHtcbiAgICBpZiAoIShBbmltYXRvci5wcm90b3R5cGUgaW5zdGFuY2VvZiBOYXZpZ2F0b3JBbmltYXRvcikpIHtcbiAgICAgIHV0aWwudGhyb3dBbmltYXRvcignTmF2aWdhdG9yJyk7XG4gICAgfVxuXG4gICAgX2FuaW1hdG9yRGljdFtuYW1lXSA9IEFuaW1hdG9yO1xuICB9XG5cbiAgc3RhdGljIGdldCBhbmltYXRvcnMoKSB7XG4gICAgcmV0dXJuIF9hbmltYXRvckRpY3Q7XG4gIH1cblxuICBzdGF0aWMgZ2V0IE5hdmlnYXRvckFuaW1hdG9yKCkge1xuICAgIHJldHVybiBOYXZpZ2F0b3JBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgZXZlbnRzKCkge1xuICAgIHJldHVybiBbJ3ByZXB1c2gnLCAncG9zdHB1c2gnLCAncHJlcG9wJywgJ3Bvc3Rwb3AnXTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgcmV3cml0YWJsZXMoKSB7XG4gICAgcmV0dXJuIHJld3JpdGFibGVzO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLk5hdmlnYXRvciA9IE5hdmlnYXRvckVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1uYXZpZ2F0b3InLCBOYXZpZ2F0b3JFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3QgZGVmYXVsdENsYXNzTmFtZSA9ICd0b29sYmFyJztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ3Rvb2xiYXItLSonLFxuICAnLnRvb2xiYXJfX2xlZnQnOiAndG9vbGJhci0tKl9fbGVmdCcsXG4gICcudG9vbGJhcl9fY2VudGVyJzogJ3Rvb2xiYXItLSpfX2NlbnRlcicsXG4gICcudG9vbGJhcl9fcmlnaHQnOiAndG9vbGJhci0tKl9fcmlnaHQnXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy10b29sYmFyXG4gKiBAY2F0ZWdvcnkgcGFnZVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gdG9vbGJhci5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciB0cmFuc3BhcmVudFxuICogICBbZW5dVHJhbnNwYXJlbnQgdG9vbGJhci5bL2VuXVxuICogICBbamFd6YCP5piO44Gq6IOM5pmv44KS5oyB44Gk44OE44O844Or44OQ44O844KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBtb2RpZmllciBjb3Zlci1jb250ZW50XG4gKiAgIFtlbl1EaXNwbGF5cyB0aGUgdG9vbGJhciBvbiB0b3Agb2YgdGhlIHBhZ2UncyBjb250ZW50LiBTaG91bGQgYmUgY29tYmluZWQgd2l0aCBgdHJhbnNwYXJlbnRgIG1vZGlmaWVyLlsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIG5vc2hhZG93XG4gKiAgIFtlbl1Ub29sYmFyIHdpdGhvdXQgc2hhZG93LlsvZW5dXG4gKiAgIFtqYV3jg4Tjg7zjg6vjg5Djg7zjgavlvbHjgpLku5jjgZHjgZrjgavooajnpLrjgZfjgb7jgZnjgIJbL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBUb29sYmFyIGNvbXBvbmVudCB0aGF0IGNhbiBiZSB1c2VkIHdpdGggbmF2aWdhdGlvbi5cbiAqXG4gKiAgICAgTGVmdCwgY2VudGVyIGFuZCByaWdodCBjb250YWluZXJzIGNhbiBiZSBzcGVjaWZpZWQgYnkgY2xhc3MgbmFtZXMuXG4gKlxuICogICAgIFRoaXMgY29tcG9uZW50IHdpbGwgYXV0b21hdGljYWxseSBkaXNwbGF5IGFzIGEgTWF0ZXJpYWwgRGVzaWduIHRvb2xiYXIgd2hlbiBydW5uaW5nIG9uIEFuZHJvaWQgZGV2aWNlcy5cbiAqICAgWy9lbl1cbiAqICAgW2phXeODiuODk+OCsuODvOOCt+ODp+ODs+OBp+S9v+eUqOOBmeOCi+ODhOODvOODq+ODkOODvOeUqOOCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAguOCr+ODqeOCueWQjeOBq+OCiOOCiuOAgeW3puOAgeS4reWkruOAgeWPs+OBruOCs+ODs+ODhuODiuOCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gKiBAY29kZXBlbiBhSG1HTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3Rvb2xiYXJcbiAqIEBndWlkZSBjb21waWxhdGlvbi5odG1sI3Rvb2xiYXItY29tcGlsYXRpb24gW2VuXUFkZGluZyBhIHRvb2xiYXJbL2VuXVtqYV3jg4Tjg7zjg6vjg5Djg7zjga7ov73liqBbL2phXVxuICogQHNlZWFsc28gb25zLWJvdHRvbS10b29sYmFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtYm90dG9tLXRvb2xiYXI+YCBkaXNwbGF5cyBhIHRvb2xiYXIgb24gdGhlIGJvdHRvbSBvZiB0aGUgcGFnZS5bL2VuXVxuICogICBbamFdb25zLWJvdHRvbS10b29sYmFy44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1iYWNrLWJ1dHRvblxuICogICBbZW5dVGhlIGA8b25zLWJhY2stYnV0dG9uPmAgY29tcG9uZW50IGRpc3BsYXlzIGEgYmFjayBidXR0b24gaW5zaWRlIHRoZSB0b29sYmFyLlsvZW5dXG4gKiAgIFtqYV1vbnMtYmFjay1idXR0b27jgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLXRvb2xiYXItYnV0dG9uXG4gKiAgIFtlbl1UaGUgYDxvbnMtdG9vbGJhci1idXR0b24+YCBjb21wb25lbnQgZGlzcGxheXMgYSB0b29sYmFyIGJ1dHRvbiBpbnNpZGUgdGhlIHRvb2xiYXIuWy9lbl1cbiAqICAgW2phXW9ucy10b29sYmFyLWJ1dHRvbuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1wYWdlPlxuICogICA8b25zLXRvb2xiYXI+XG4gKiAgICAgPGRpdiBjbGFzcz1cImxlZnRcIj5cbiAqICAgICAgIDxvbnMtYmFjay1idXR0b24+XG4gKiAgICAgICAgIEJhY2tcbiAqICAgICAgIDwvb25zLWJhY2stYnV0dG9uPlxuICogICAgIDwvZGl2PlxuICogICAgIDxkaXYgY2xhc3M9XCJjZW50ZXJcIj5cbiAqICAgICAgIFRpdGxlXG4gKiAgICAgPC9kaXY+XG4gKiAgICAgPGRpdiBjbGFzcz1cInJpZ2h0XCI+XG4gKiAgICAgICA8b25zLXRvb2xiYXItYnV0dG9uPlxuICogICAgICAgICA8b25zLWljb24gaWNvbj1cIm1kLW1lbnVcIj48L29ucy1pY29uPlxuICogICAgICAgPC9vbnMtdG9vbGJhci1idXR0b24+XG4gKiAgICAgPC9kaXY+XG4gKiAgIDwvb25zLXRvb2xiYXI+XG4gKiA8L29ucy1wYWdlPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRvb2xiYXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGlubGluZVxuICAgKiBAaW5pdG9ubHlcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXURpc3BsYXkgdGhlIHRvb2xiYXIgYXMgYW4gaW5saW5lIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFd44OE44O844Or44OQ44O844KS44Kk44Oz44Op44Kk44Oz44Gr572u44GN44G+44GZ44CC44K544Kv44Ot44O844Or6aCY5Z+f5YaF44Gr44Gd44Gu44G+44G+6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3RhdGljXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TdGF0aWMgdG9vbGJhcnMgYXJlIG5vdCBhbmltYXRlZCBieSBgb25zLW5hdmlnYXRvcmAgd2hlbiBwdXNoaW5nIG9yIHBvcHBpbmcgcGFnZXMuIFRoaXMgY2FuIGJlIHVzZWZ1bCB0byBpbXByb3ZlIHBlcmZvcm1hbmNlIGluIHNvbWUgc2l0dWF0aW9ucy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHRvb2xiYXIuWy9lbl1cbiAgICogICBbamFd44OE44O844Or44OQ44O844Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgfSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdjbGFzcyddO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBzd2l0Y2ggKG5hbWUpIHtcbiAgICAgIGNhc2UgJ2NsYXNzJzpcbiAgICAgICAgdXRpbC5yZXN0b3JlQ2xhc3ModGhpcywgZGVmYXVsdENsYXNzTmFtZSwgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdtb2RpZmllcic6XG4gICAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzZXRWaXNpYmlsaXR5XG4gICAqIEBzaWduYXR1cmUgc2V0VmlzaWJpbGl0eSh2aXNpYmxlKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IHZpc2libGVcbiAgICogICBbZW5dU2V0IHRvIHRydWUgdG8gc2hvdyB0aGUgdG9vbGJhciwgZmFsc2UgdG8gaGlkZSBpdFsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TaG93cyB0aGUgdG9vbGJhciBpZiB2aXNpYmxlIGlzIHRydWUsIG90aGVyd2lzZSBoaWRlcyBpdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgc2V0VmlzaWJpbGl0eSh2aXNpYmxlKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9IHZpc2libGUgPyAnJyA6ICdub25lJztcblxuICAgICAgaWYgKHRoaXMucGFyZW50Tm9kZSkge1xuICAgICAgICBjb25zdCBzaWJsaW5nQmFja2dyb3VuZCA9IHV0aWwuZmluZENoaWxkKHRoaXMucGFyZW50Tm9kZSwgJy5wYWdlX19iYWNrZ3JvdW5kJyk7XG4gICAgICAgIGlmIChzaWJsaW5nQmFja2dyb3VuZCkge1xuICAgICAgICAgIHNpYmxpbmdCYWNrZ3JvdW5kLnN0eWxlLnRvcCA9IHZpc2libGUgPyBudWxsIDogMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNpYmxpbmdDb250ZW50ID0gdXRpbC5maW5kQ2hpbGQodGhpcy5wYXJlbnROb2RlLCAnLnBhZ2VfX2NvbnRlbnQnKTtcbiAgICAgICAgaWYgKHNpYmxpbmdDb250ZW50KSB7XG4gICAgICAgICAgc2libGluZ0NvbnRlbnQuc3R5bGUudG9wID0gdmlzaWJsZSA/IG51bGwgOiAwO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzaG93XG4gICAqIEBzaWduYXR1cmUgc2hvdygpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TaG93IHRoZSB0b29sYmFyLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBzaG93KCkge1xuICAgIHRoaXMuc2V0VmlzaWJpbGl0eSh0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGhpZGVcbiAgICogQHNpZ25hdHVyZSBoaWRlKClcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUhpZGUgdGhlIHRvb2xiYXIuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGhpZGUoKSB7XG4gICAgdGhpcy5zZXRWaXNpYmlsaXR5KGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIF9nZXRUb29sYmFyTGVmdEl0ZW1zRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCcubGVmdCcpIHx8IGludGVybmFsLm51bGxFbGVtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fVxuICAgKi9cbiAgX2dldFRvb2xiYXJDZW50ZXJJdGVtc0VsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3RvcignLmNlbnRlcicpIHx8IGludGVybmFsLm51bGxFbGVtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fVxuICAgKi9cbiAgX2dldFRvb2xiYXJSaWdodEl0ZW1zRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCcucmlnaHQnKSB8fCBpbnRlcm5hbC5udWxsRWxlbWVudDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJuIHtIVE1MRWxlbWVudH1cbiAgICovXG4gIF9nZXRUb29sYmFyQmFja0J1dHRvbkxhYmVsRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCdvbnMtYmFjay1idXR0b24gLmJhY2stYnV0dG9uX19sYWJlbCcpIHx8IGludGVybmFsLm51bGxFbGVtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0hUTUxFbGVtZW50fVxuICAgKi9cbiAgX2dldFRvb2xiYXJCYWNrQnV0dG9uSWNvbkVsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMucXVlcnlTZWxlY3Rvcignb25zLWJhY2stYnV0dG9uIC5iYWNrLWJ1dHRvbl9faWNvbicpIHx8IGludGVybmFsLm51bGxFbGVtZW50O1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuICAgIHRoaXMuX2Vuc3VyZVRvb2xiYXJJdGVtRWxlbWVudHMoKTtcbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gIH1cblxuICBfZW5zdXJlVG9vbGJhckl0ZW1FbGVtZW50cygpIHtcbiAgICBmb3IgKGxldCBpID0gdGhpcy5jaGlsZE5vZGVzLmxlbmd0aCAtIDE7IGkgPj0gMCA7IGktLSkge1xuICAgICAgLy8gY2FzZSBvZiBub3QgZWxlbWVudFxuICAgICAgaWYgKHRoaXMuY2hpbGROb2Rlc1tpXS5ub2RlVHlwZSAhPSAxKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlQ2hpbGQodGhpcy5jaGlsZE5vZGVzW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBjZW50ZXIgPSB0aGlzLl9lbnN1cmVUb29sYmFyRWxlbWVudCgnY2VudGVyJyk7XG4gICAgY2VudGVyLmNsYXNzTGlzdC5hZGQoJ3Rvb2xiYXJfX3RpdGxlJyk7XG5cbiAgICBpZiAodGhpcy5jaGlsZHJlbi5sZW5ndGggIT09IDEgfHwgIXRoaXMuY2hpbGRyZW5bMF0uY2xhc3NMaXN0LmNvbnRhaW5zKCdjZW50ZXInKSkge1xuICAgICAgY29uc3QgbGVmdCA9IHRoaXMuX2Vuc3VyZVRvb2xiYXJFbGVtZW50KCdsZWZ0Jyk7XG4gICAgICBjb25zdCByaWdodCA9IHRoaXMuX2Vuc3VyZVRvb2xiYXJFbGVtZW50KCdyaWdodCcpO1xuXG4gICAgICBpZiAodGhpcy5jaGlsZHJlblswXSAhPT0gbGVmdCB8fCB0aGlzLmNoaWxkcmVuWzFdICE9PSBjZW50ZXIgfHwgdGhpcy5jaGlsZHJlblsyXSAhPT0gcmlnaHQpIHtcbiAgICAgICAgdGhpcy5hcHBlbmRDaGlsZChsZWZ0KTtcbiAgICAgICAgdGhpcy5hcHBlbmRDaGlsZChjZW50ZXIpO1xuICAgICAgICB0aGlzLmFwcGVuZENoaWxkKHJpZ2h0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBfZW5zdXJlVG9vbGJhckVsZW1lbnQobmFtZSkge1xuICAgIGlmICh1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnRvb2xiYXJfXycgKyBuYW1lKSkge1xuICAgICAgY29uc3QgZWxlbWVudCA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcudG9vbGJhcl9fJyArIG5hbWUpO1xuICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKG5hbWUpO1xuICAgICAgcmV0dXJuIGVsZW1lbnQ7XG4gICAgfVxuXG4gICAgY29uc3QgZWxlbWVudCA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcuJyArIG5hbWUpIHx8IHV0aWwuY3JlYXRlKCcuJyArIG5hbWUpO1xuICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZCgndG9vbGJhcl9fJyArIG5hbWUpO1xuXG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cbn1cblxub25zRWxlbWVudHMuVG9vbGJhciA9IFRvb2xiYXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtdG9vbGJhcicsIFRvb2xiYXJFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgYXV0b1N0eWxlIGZyb20gJy4uL29ucy9hdXRvc3R5bGUnO1xuaW1wb3J0IE1vZGlmaWVyVXRpbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvbW9kaWZpZXItdXRpbCc7XG5pbXBvcnQgQmFzZUVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi4vb25zL2ludGVybmFsL2RldmljZS1iYWNrLWJ1dHRvbi1kaXNwYXRjaGVyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5pbXBvcnQgJy4vb25zLXRvb2xiYXInOyAvLyBlbnN1cmVzIHRoYXQgJ29ucy10b29sYmFyJyBlbGVtZW50IGlzIHJlZ2lzdGVyZWRcblxuY29uc3QgZGVmYXVsdENsYXNzTmFtZSA9ICdwYWdlJztcbmNvbnN0IHNjaGVtZSA9IHtcbiAgJyc6ICdwYWdlLS0qJyxcbiAgJy5wYWdlX19jb250ZW50JzogJ3BhZ2UtLSpfX2NvbnRlbnQnLFxuICAnLnBhZ2VfX2JhY2tncm91bmQnOiAncGFnZS0tKl9fYmFja2dyb3VuZCdcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXBhZ2VcbiAqIEBjYXRlZ29yeSBwYWdlXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiBzdHlsZVsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBUaGlzIGNvbXBvbmVudCBkZWZpbmVzIHRoZSByb290IG9mIGVhY2ggcGFnZS4gSWYgdGhlIGNvbnRlbnQgaXMgbGFyZ2UgaXQgd2lsbCBiZWNvbWUgc2Nyb2xsYWJsZS5cbiAqXG4gKiAgICAgQSBuYXZpZ2F0aW9uIGJhciBjYW4gYmUgYWRkZWQgdG8gdGhlIHRvcCBvZiB0aGUgcGFnZSB1c2luZyB0aGUgYDxvbnMtdG9vbGJhcj5gIGVsZW1lbnQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg5rjg7zjgrjlrprnvqnjga7jgZ/jgoHjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgafjgZnjgILjgZPjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7lhoXlrrnjga/jgrnjgq/jg63jg7zjg6vjgYzoqLHlj6/jgZXjgozjgb7jgZnjgIJbL2phXVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3BhZ2VcbiAqIEBndWlkZSBsaWZlY3ljbGUuaHRtbCNldmVudHNcbiAqICAgW2VuXU92ZXJ2aWV3IG9mIHBhZ2UgZXZlbnRzWy9lbl1cbiAqICAgW2phXU92ZXJ2aWV3IG9mIHBhZ2UgZXZlbnRzWy9qYV1cbiAqIEBndWlkZSBmdW5kYW1lbnRhbHMuaHRtbCNtYW5hZ2luZy1wYWdlc1xuICogICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXNbL2VuXVxuICogICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1cbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjbW9kaWZpZXJzIFtlbl1Nb3JlIGRldGFpbHMgYWJvdXQgdGhlIGBtb2RpZmllcmAgYXR0cmlidXRlWy9lbl1bamFdbW9kaWZpZXLlsZ7mgKfjga7kvb/jgYTmlrlbL2phXVxuICogQHNlZWFsc28gb25zLXRvb2xiYXJcbiAqICAgW2VuXVVzZSB0aGUgYDxvbnMtdG9vbGJhcj5gIGVsZW1lbnQgdG8gYWRkIGEgbmF2aWdhdGlvbiBiYXIgdG8gdGhlIHRvcCBvZiB0aGUgcGFnZS5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXBhZ2U+XG4gKiAgIDxvbnMtdG9vbGJhcj5cbiAqICAgICA8ZGl2IGNsYXNzPVwibGVmdFwiPlxuICogICAgICAgPG9ucy1iYWNrLWJ1dHRvbj5CYWNrPC9vbnMtYmFjay1idXR0b24+XG4gKiAgICAgPC9kaXY+XG4gKiAgICAgPGRpdiBjbGFzcz1cImNlbnRlclwiPlRpdGxlPC9kaXY+XG4gKiAgICAgPGRpdiBjbGFzcz1cInJpZ2h0XCI+XG4gKiAgICAgICA8b25zLXRvb2xiYXItYnV0dG9uPlxuICogICAgICAgICA8b25zLWljb24gaWNvbj1cIm1kLW1lbnVcIj48L29ucy1pY29uPlxuICogICAgICAgPC9vbnMtdG9vbGJhci1idXR0b24+XG4gKiAgICAgPC9kaXY+XG4gKiAgIDwvb25zLXRvb2xiYXI+XG4gKlxuICogICA8cD5QYWdlIGNvbnRlbnQ8L3A+XG4gKiA8L29ucy1wYWdlPlxuICpcbiAqIEBleGFtcGxlXG4gKiA8c2NyaXB0PlxuICogICBteUFwcC5oYW5kbGVyID0gZnVuY3Rpb24oZG9uZSkge1xuICogICAgIGxvYWRNb3JlKCkudGhlbihkb25lKTtcbiAqICAgfVxuICogPC9zY3JpcHQ+XG4gKlxuICogPG9ucy1wYWdlIG9uLWluZmluaXRlLXNjcm9sbD1cIm15QXBwLmhhbmRsZXJcIj5cbiAqICAgPG9ucy10b29sYmFyPlxuICogICAgIDxkaXYgY2xhc3M9XCJjZW50ZXJcIj5MaXN0PC9kaXY+XG4gKiAgIDwvb25zLXRvb2xiYXI+XG4gKlxuICogICA8b25zLWxpc3Q+XG4gKiAgICAgPG9ucy1saXN0LWl0ZW0+IzE8L29ucy1saXN0LWl0ZW0+XG4gKiAgICAgPG9ucy1saXN0LWl0ZW0+IzI8L29ucy1saXN0LWl0ZW0+XG4gKiAgICAgPG9ucy1saXN0LWl0ZW0+IzM8L29ucy1saXN0LWl0ZW0+XG4gKiAgICAgLi4uXG4gKiAgIDwvb25zLWxpc3Q+XG4gKiA8L29ucy1wYWdlPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBQYWdlRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGV2ZW50IGluaXRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHJpZ2h0IGFmdGVyIHRoZSBwYWdlIGlzIGF0dGFjaGVkLlsvZW5dXG4gICAqICAgW2phXeODmuODvOOCuOOBjOOCouOCv+ODg+ODgeOBleOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgc2hvd1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQgcmlnaHQgYWZ0ZXIgdGhlIHBhZ2UgaXMgc2hvd24uWy9lbl1cbiAgICogICBbamFd44Oa44O844K444GM6KGo56S644GV44KM44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBoaWRlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCByaWdodCBhZnRlciB0aGUgcGFnZSBpcyBoaWRkZW4uWy9lbl1cbiAgICogICBbamFd44Oa44O844K444GM6Zqg44KM44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBkZXN0cm95XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCByaWdodCBiZWZvcmUgdGhlIHBhZ2UgaXMgZGVzdHJveWVkLlsvZW5dXG4gICAqICAgW2phXeODmuODvOOCuOOBjOegtOajhOOBleOCjOOCi+WJjeOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IG1vZGlmaWVyIG5hbWUgdG8gc3BlY2lmeSBjdXN0b20gc3R5bGVzLlsvZW5dXG4gICAqICAgW2phXeOCueOCv+OCpOODq+Wumue+qeOCkuOCq+OCueOCv+ODnuOCpOOCuuOBmeOCi+OBn+OCgeOBruWQjeWJjeOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG9uLWluZmluaXRlLXNjcm9sbFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUGF0aCBvZiB0aGUgZnVuY3Rpb24gdG8gYmUgZXhlY3V0ZWQgb24gaW5maW5pdGUgc2Nyb2xsaW5nLiBFeGFtcGxlOiBgYXBwLmxvYWREYXRhYC4gVGhlIGZ1bmN0aW9uIHJlY2VpdmVzIGEgZG9uZSBjYWxsYmFjayB0aGF0IG11c3QgYmUgY2FsbGVkIHdoZW4gaXQncyBmaW5pc2hlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fZGVyaXZlSG9va3MoKTtcblxuICAgIHRoaXMuX2RlZmF1bHRDbGFzc05hbWUgPSBkZWZhdWx0Q2xhc3NOYW1lO1xuICAgIHRoaXMuY2xhc3NMaXN0LmFkZChkZWZhdWx0Q2xhc3NOYW1lKTtcblxuICAgIHRoaXMuX2luaXRpYWxpemVkID0gZmFsc2U7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpO1xuXG4gICAgICB0aGlzLl9pc1Nob3duID0gZmFsc2U7XG4gICAgICB0aGlzLl9jb250ZW50RWxlbWVudCA9IHRoaXMuX2dldENvbnRlbnRFbGVtZW50KCk7XG4gICAgICB0aGlzLl9iYWNrZ3JvdW5kRWxlbWVudCA9IHRoaXMuX2dldEJhY2tncm91bmRFbGVtZW50KCk7XG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIGNvbnN0IHRvb2xiYXIgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnb25zLXRvb2xiYXInKTtcblxuICAgIGNvbnN0IGJhY2tncm91bmQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBhZ2VfX2JhY2tncm91bmQnKSB8fCB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLmJhY2tncm91bmQnKSB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBiYWNrZ3JvdW5kLmNsYXNzTGlzdC5hZGQoJ3BhZ2VfX2JhY2tncm91bmQnKTtcbiAgICB0aGlzLmluc2VydEJlZm9yZShiYWNrZ3JvdW5kLCAhdG9vbGJhciAmJiB0aGlzLmZpcnN0Q2hpbGQgfHwgdG9vbGJhciAmJiB0b29sYmFyLm5leHRTaWJsaW5nKTtcblxuICAgIGNvbnN0IGNvbnRlbnQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBhZ2VfX2NvbnRlbnQnKSB8fCB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLmNvbnRlbnQnKSB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBjb250ZW50LmNsYXNzTGlzdC5hZGQoJ3BhZ2VfX2NvbnRlbnQnKTtcbiAgICBpZiAoIWNvbnRlbnQucGFyZW50RWxlbWVudCkge1xuICAgICAgdXRpbC5hcnJheUZyb20odGhpcy5jaGlsZE5vZGVzKS5mb3JFYWNoKG5vZGUgPT4ge1xuICAgICAgICBpZiAobm9kZS5ub2RlVHlwZSAhPT0gMSB8fCB0aGlzLl9lbGVtZW50U2hvdWxkQmVNb3ZlZChub2RlKSkge1xuICAgICAgICAgIGNvbnRlbnQuYXBwZW5kQ2hpbGQobm9kZSk7IC8vIENhbiB0cmlnZ2VyIGRldGFjaGVkIGNvbm5lY3RlZENhbGxiYWNrc1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLl90cnlUb0ZpbGxTdGF0dXNCYXIoY29udGVudCk7IC8vIE11c3QgcnVuIGJlZm9yZSBjaGlsZCBwYWdlcyB0cnkgdG8gZmlsbCBzdGF0dXMgYmFyLlxuICAgIHRoaXMuaW5zZXJ0QmVmb3JlKGNvbnRlbnQsIGJhY2tncm91bmQubmV4dFNpYmxpbmcpOyAvLyBDYW4gdHJpZ2dlciBhdHRhY2hlZCBjb25uZWN0ZWRDYWxsYmFja3NcblxuICAgIGlmICgoIXRvb2xiYXIgfHwgIXV0aWwuaGFzTW9kaWZpZXIodG9vbGJhciwgJ3RyYW5zcGFyZW50JykpXG4gICAgICAmJiBjb250ZW50LmNoaWxkcmVuLmxlbmd0aCA9PT0gMVxuICAgICAgJiYgdXRpbC5pc1BhZ2VDb250cm9sKGNvbnRlbnQuY2hpbGRyZW5bMF0pXG4gICAgKSB7XG4gICAgICB0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lICs9ICcgcGFnZS0td3JhcHBlcic7XG4gICAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnY2xhc3MnKTtcbiAgICB9XG5cbiAgICBjb25zdCBib3R0b21Ub29sYmFyID0gdXRpbC5maW5kQ2hpbGQodGhpcywgJ29ucy1ib3R0b20tdG9vbGJhcicpO1xuICAgIGlmIChib3R0b21Ub29sYmFyKSB7XG4gICAgICB0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lICs9ICcgcGFnZS13aXRoLWJvdHRvbS10b29sYmFyJztcbiAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKCdjbGFzcycpO1xuICAgIH1cblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIF9lbGVtZW50U2hvdWxkQmVNb3ZlZChlbCkge1xuICAgIGlmIChlbC5jbGFzc0xpc3QuY29udGFpbnMoJ3BhZ2VfX2JhY2tncm91bmQnKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCB0YWdOYW1lID0gZWwudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICh0YWdOYW1lID09PSAnb25zLWZhYicpIHtcbiAgICAgIHJldHVybiAhZWwuaGFzQXR0cmlidXRlKCdwb3NpdGlvbicpO1xuICAgIH1cbiAgICBjb25zdCBmaXhlZEVsZW1lbnRzID0gWydzY3JpcHQnLCAnb25zLXRvb2xiYXInLCAnb25zLWJvdHRvbS10b29sYmFyJywgJ29ucy1tb2RhbCcsICdvbnMtc3BlZWQtZGlhbCcsICdvbnMtZGlhbG9nJywgJ29ucy1hbGVydC1kaWFsb2cnLCAnb25zLXBvcG92ZXInLCAnb25zLWFjdGlvbi1zaGVldCddO1xuICAgIHJldHVybiBlbC5oYXNBdHRyaWJ1dGUoJ2lubGluZScpIHx8IGZpeGVkRWxlbWVudHMuaW5kZXhPZih0YWdOYW1lKSA9PT0gLTE7XG4gIH1cblxuICBfdHJ5VG9GaWxsU3RhdHVzQmFyKGNvbnRlbnQgPSB0aGlzLl9jb250ZW50RWxlbWVudCkge1xuICAgIGludGVybmFsLmF1dG9TdGF0dXNCYXJGaWxsKCgpID0+IHtcbiAgICAgIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdzdGF0dXMtYmFyLWZpbGwnLFxuICAgICAgICAhdXRpbC5maW5kUGFyZW50KHRoaXMsIGUgPT4gZS5oYXNBdHRyaWJ1dGUoJ3N0YXR1cy1iYXItZmlsbCcpKSAvLyBOb3QgYWxyZWFkeSBmaWxsZWRcbiAgICAgICAgJiYgKHRoaXMuX2NhbkFuaW1hdGVUb29sYmFyKGNvbnRlbnQpIHx8ICF1dGlsLmZpbmRDaGlsZChjb250ZW50LCB1dGlsLmlzUGFnZUNvbnRyb2wpKSAvLyBIYXMgdG9vbGJhciBvciBjYW5ub3QgZGVsZWdhdGVcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBfY2FuQW5pbWF0ZVRvb2xiYXIoY29udGVudCA9IHRoaXMuX2NvbnRlbnRFbGVtZW50KSB7XG4gICAgaWYgKHV0aWwuZmluZENoaWxkKHRoaXMsICdvbnMtdG9vbGJhcicpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gISF1dGlsLmZpbmRDaGlsZChjb250ZW50LCBlbCA9PiB7XG4gICAgICByZXR1cm4gdXRpbC5tYXRjaChlbCwgJ29ucy10b29sYmFyJykgJiYgIWVsLmhhc0F0dHJpYnV0ZSgnaW5saW5lJyk7XG4gICAgfSk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBpZiAoIXV0aWwuaXNBdHRhY2hlZCh0aGlzKSkgeyAvLyBBdm9pZCBkZXRhY2hlZCBjYWxsc1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl90cnlUb0ZpbGxTdGF0dXNCYXIoKTsgLy8gRW5zdXJlIHN0YXR1cyBiYXIgd2hlbiB0aGUgZWxlbWVudCB3YXMgY29tcGlsZWQgYmVmb3JlIGNvbm5lY3RlZFxuXG4gICAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ29uLWluZmluaXRlLXNjcm9sbCcpKSB7XG4gICAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKCdvbi1pbmZpbml0ZS1zY3JvbGwnLCBudWxsLCB0aGlzLmdldEF0dHJpYnV0ZSgnb24taW5maW5pdGUtc2Nyb2xsJykpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXRoaXMuX2luaXRpYWxpemVkKSB7XG4gICAgICAgIHRoaXMuX2luaXRpYWxpemVkID0gdHJ1ZTtcblxuICAgICAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgICAgIHRoaXMub25Jbml0ICYmIHRoaXMub25Jbml0KCk7XG4gICAgICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdpbml0Jyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICghdXRpbC5oYXNBbnlDb21wb25lbnRBc1BhcmVudCh0aGlzKSkge1xuICAgICAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLl9zaG93KCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICB1cGRhdGVCYWNrQnV0dG9uKHNob3cpIHtcbiAgICBpZiAodGhpcy5iYWNrQnV0dG9uKSB7XG4gICAgICBzaG93ID8gdGhpcy5iYWNrQnV0dG9uLnNob3coKSA6IHRoaXMuYmFja0J1dHRvbi5oaWRlKCk7XG4gICAgfVxuICB9XG5cbiAgc2V0IG5hbWUoc3RyKSB7XG4gICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ25hbWUnLCBzdHIpO1xuICB9XG5cbiAgZ2V0IG5hbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0QXR0cmlidXRlKCduYW1lJyk7XG4gIH1cblxuICBnZXQgYmFja0J1dHRvbigpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCdvbnMtYmFjay1idXR0b24nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25JbmZpbml0ZVNjcm9sbFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1GdW5jdGlvbiB0byBiZSBleGVjdXRlZCB3aGVuIHNjcm9sbGluZyB0byB0aGUgYm90dG9tIG9mIHRoZSBwYWdlLiBUaGUgZnVuY3Rpb24gcmVjZWl2ZXMgYSBkb25lIGNhbGxiYWNrIGFzIGFuIGFyZ3VtZW50IHRoYXQgbXVzdCBiZSBjYWxsZWQgd2hlbiBpdCdzIGZpbmlzaGVkLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG4gIHNldCBvbkluZmluaXRlU2Nyb2xsKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHV0aWwudGhyb3coJ1wib25JbmZpbml0ZVNjcm9sbFwiIG11c3QgYmUgZnVuY3Rpb24gb3IgbnVsbCcpO1xuICAgIH1cblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2NvbnRlbnRFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuX2JvdW5kT25TY3JvbGwpO1xuICAgICAgfSBlbHNlIGlmICghdGhpcy5fb25JbmZpbml0ZVNjcm9sbCkge1xuICAgICAgICB0aGlzLl9pbmZpbml0ZVNjcm9sbExpbWl0ID0gMC45O1xuICAgICAgICB0aGlzLl9ib3VuZE9uU2Nyb2xsID0gdGhpcy5fb25TY3JvbGwuYmluZCh0aGlzKTtcbiAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHRoaXMuX2NvbnRlbnRFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMuX2JvdW5kT25TY3JvbGwpKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX29uSW5maW5pdGVTY3JvbGwgPSB2YWx1ZTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldCBvbkluZmluaXRlU2Nyb2xsKCkge1xuICAgIHJldHVybiB0aGlzLl9vbkluZmluaXRlU2Nyb2xsO1xuICB9XG5cbiAgX29uU2Nyb2xsKCkge1xuICAgIGNvbnN0IGMgPSB0aGlzLl9jb250ZW50RWxlbWVudCxcbiAgICAgIG92ZXJMaW1pdCA9IChjLnNjcm9sbFRvcCArIGMuY2xpZW50SGVpZ2h0KSAvIGMuc2Nyb2xsSGVpZ2h0ID49IHRoaXMuX2luZmluaXRlU2Nyb2xsTGltaXQ7XG5cbiAgICBpZiAodGhpcy5fb25JbmZpbml0ZVNjcm9sbCAmJiAhdGhpcy5fbG9hZGluZ0NvbnRlbnQgJiYgb3ZlckxpbWl0KSB7XG4gICAgICB0aGlzLl9sb2FkaW5nQ29udGVudCA9IHRydWU7XG4gICAgICB0aGlzLl9vbkluZmluaXRlU2Nyb2xsKCgpID0+IHRoaXMuX2xvYWRpbmdDb250ZW50ID0gZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25EZXZpY2VCYWNrQnV0dG9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1CYWNrLWJ1dHRvbiBoYW5kbGVyLlsvZW5dXG4gICAqICAgW2phXeODkOODg+OCr+ODnOOCv+ODs+ODj+ODs+ODieODqeOAglsvamFdXG4gICAqL1xuICBnZXQgb25EZXZpY2VCYWNrQnV0dG9uKCkge1xuICAgIHJldHVybiB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlcjtcbiAgfVxuXG4gIHNldCBvbkRldmljZUJhY2tCdXR0b24oY2FsbGJhY2spIHtcbiAgICBpZiAodGhpcy5fYmFja0J1dHRvbkhhbmRsZXIpIHtcbiAgICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyLmRlc3Ryb3koKTtcbiAgICB9XG5cbiAgICB0aGlzLl9iYWNrQnV0dG9uSGFuZGxlciA9IGRldmljZUJhY2tCdXR0b25EaXNwYXRjaGVyLmNyZWF0ZUhhbmRsZXIodGhpcywgY2FsbGJhY2spO1xuICB9XG5cbiAgZ2V0IHNjcm9sbFRvcCgpIHtcbiAgICByZXR1cm4gdGhpcy5fY29udGVudEVsZW1lbnQuc2Nyb2xsVG9wO1xuICB9XG5cbiAgc2V0IHNjcm9sbFRvcChuZXdWYWx1ZSkge1xuICAgIHRoaXMuX2NvbnRlbnRFbGVtZW50LnNjcm9sbFRvcCA9IG5ld1ZhbHVlO1xuICB9XG5cbiAgX2dldENvbnRlbnRFbGVtZW50KCkge1xuICAgIGNvbnN0IHJlc3VsdCA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcucGFnZV9fY29udGVudCcpO1xuICAgIGlmIChyZXN1bHQpIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIHV0aWwudGhyb3coJ0ZhaWwgdG8gZ2V0IFwiLnBhZ2VfX2NvbnRlbnRcIiBlbGVtZW50Jyk7XG4gIH1cblxuICBfZ2V0QmFja2dyb3VuZEVsZW1lbnQoKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gdXRpbC5maW5kQ2hpbGQodGhpcywgJy5wYWdlX19iYWNrZ3JvdW5kJyk7XG4gICAgaWYgKHJlc3VsdCkge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gICAgdXRpbC50aHJvdygnRmFpbCB0byBnZXQgXCIucGFnZV9fYmFja2dyb3VuZFwiIGVsZW1lbnQnKTtcbiAgfVxuXG4gIF9nZXRCb3R0b21Ub29sYmFyRWxlbWVudCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJ29ucy1ib3R0b20tdG9vbGJhcicpIHx8IGludGVybmFsLm51bGxFbGVtZW50O1xuICB9XG5cbiAgX2dldFRvb2xiYXJFbGVtZW50KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnb25zLXRvb2xiYXInKSB8fCBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdvbnMtdG9vbGJhcicpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAnb24taW5maW5pdGUtc2Nyb2xsJywgJ2NsYXNzJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICB1dGlsLnJlc3RvcmVDbGFzcyh0aGlzLCB0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21vZGlmaWVyJzpcbiAgICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnb24taW5maW5pdGUtc2Nyb2xsJzpcbiAgICAgICAgaWYgKGN1cnJlbnQgPT09IG51bGwpIHtcbiAgICAgICAgICB0aGlzLm9uSW5maW5pdGVTY3JvbGwgPSBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMub25JbmZpbml0ZVNjcm9sbCA9IChkb25lKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmID0gdXRpbC5maW5kRnJvbVBhdGgoY3VycmVudCk7XG4gICAgICAgICAgICB0aGlzLm9uSW5maW5pdGVTY3JvbGwgPSBmO1xuICAgICAgICAgICAgZihkb25lKTtcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIF9zaG93KCkge1xuICAgIGlmICghdGhpcy5faXNTaG93biAmJiB1dGlsLmlzQXR0YWNoZWQodGhpcykpIHtcbiAgICAgIHRoaXMuX2lzU2hvd24gPSB0cnVlO1xuICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ3Nob3duJywgJycpO1xuICAgICAgdGhpcy5vblNob3cgJiYgdGhpcy5vblNob3coKTtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnc2hvdycpO1xuICAgICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ19zaG93Jyk7XG4gICAgfVxuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgaWYgKHRoaXMuX2lzU2hvd24pIHtcbiAgICAgIHRoaXMuX2lzU2hvd24gPSBmYWxzZTtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKCdzaG93bicpO1xuICAgICAgdGhpcy5vbkhpZGUgJiYgdGhpcy5vbkhpZGUoKTtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnaGlkZScpO1xuICAgICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ19oaWRlJyk7XG4gICAgfVxuICB9XG5cbiAgX2Rlc3Ryb3koKSB7XG4gICAgdGhpcy5faGlkZSgpO1xuXG4gICAgdGhpcy5vbkRlc3Ryb3kgJiYgdGhpcy5vbkRlc3Ryb3koKTtcbiAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ2Rlc3Ryb3knKTtcblxuICAgIGlmICh0aGlzLm9uRGV2aWNlQmFja0J1dHRvbikge1xuICAgICAgdGhpcy5vbkRldmljZUJhY2tCdXR0b24uZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKHRoaXMsICdfZGVzdHJveScpO1xuXG4gICAgdGhpcy5yZW1vdmUoKTtcbiAgfVxuXG4gIF9kZXJpdmVIb29rcygpIHtcbiAgICB0aGlzLmNvbnN0cnVjdG9yLmV2ZW50cy5mb3JFYWNoKGV2ZW50ID0+IHtcbiAgICAgIGNvbnN0IGtleSA9ICdvbicgKyBldmVudC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGV2ZW50LnNsaWNlKDEpO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIGtleSwge1xuICAgICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGdldDogKCkgPT4gdGhpc1tgXyR7a2V5fWBdLFxuICAgICAgICBzZXQ6IHZhbHVlID0+IHtcbiAgICAgICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSkge1xuICAgICAgICAgICAgdXRpbC50aHJvdyhgXCIke2tleX1cIiBob29rIG11c3QgYmUgYSBmdW5jdGlvbmApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzW2BfJHtrZXl9YF0gPSB2YWx1ZS5iaW5kKHRoaXMpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgZXZlbnRzKCkge1xuICAgIHJldHVybiBbJ2luaXQnLCAnc2hvdycsICdoaWRlJywgJ2Rlc3Ryb3knXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGF0YVxuICAgKiBAdHlwZSB7Kn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVVzZXIncyBjdXN0b20gZGF0YSBwYXNzZWQgdG8gYHB1c2hQYWdlKClgLWxpa2UgbWV0aG9kcy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbn1cblxub25zRWxlbWVudHMuUGFnZSA9IFBhZ2VFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcGFnZScsIFBhZ2VFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IEJhc2VBbmltYXRvciBmcm9tICcuLi8uLi9vbnMvYmFzZS1hbmltYXRvcic7XG5cbmV4cG9ydCBjbGFzcyBQb3BvdmVyQW5pbWF0b3IgZXh0ZW5kcyBCYXNlQW5pbWF0b3Ige1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy50aW1pbmdcbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuZHVyYXRpb25cbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuZGVsYXlcbiAgICovXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjQsIDEpJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMn0gPSB7fSkge1xuICAgIHN1cGVyKHsgdGltaW5nLCBkZWxheSwgZHVyYXRpb24gfSk7XG4gIH1cblxuICBzaG93KHBvcG92ZXIsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIGhpZGUocG9wb3ZlciwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG5cbiAgX2FuaW1hdGUoZWxlbWVudCwge2Zyb20sIHRvLCBvcHRpb25zLCBjYWxsYmFjaywgcmVzdG9yZSA9IGZhbHNlLCBhbmltYXRpb259KSB7XG4gICAgb3B0aW9ucyA9IHV0aWwuZXh0ZW5kKHt9LCB0aGlzLm9wdGlvbnMsIG9wdGlvbnMpO1xuXG4gICAgaWYgKGFuaW1hdGlvbikge1xuICAgICAgZnJvbSA9IGFuaW1hdGlvbi5mcm9tO1xuICAgICAgdG8gPSBhbmltYXRpb24udG87XG4gICAgfVxuXG4gICAgYW5pbWF0aW9uID0gYW5pbWl0KGVsZW1lbnQpO1xuICAgIGlmIChyZXN0b3JlKSB7XG4gICAgICBhbmltYXRpb24gPSBhbmltYXRpb24uc2F2ZVN0eWxlKCk7XG4gICAgfVxuICAgIGFuaW1hdGlvbiA9IGFuaW1hdGlvbi5xdWV1ZShmcm9tKS53YWl0KHRoaXMuZGVsYXkpLnF1ZXVlKHtcbiAgICAgIGNzczogdG8sXG4gICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgIHRpbWluZzogdGhpcy50aW1pbmdcbiAgICB9KTtcbiAgICBpZiAocmVzdG9yZSkge1xuICAgICAgYW5pbWF0aW9uID0gYW5pbWF0aW9uLnJlc3RvcmVTdHlsZSgpO1xuICAgIH1cbiAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgIGFuaW1hdGlvbiA9IGFuaW1hdGlvbi5xdWV1ZSgoZG9uZSkgPT4ge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGFuaW1hdGlvbjtcbiAgfVxuXG4gIF9hbmltYXRlQWxsKGVsZW1lbnQsIGFuaW1hdGlvbnMpIHtcbiAgICBPYmplY3Qua2V5cyhhbmltYXRpb25zKS5mb3JFYWNoKGtleSA9PiB0aGlzLl9hbmltYXRlKGVsZW1lbnRba2V5XSwgYW5pbWF0aW9uc1trZXldKS5wbGF5KCkpO1xuICB9XG5cbn1cblxuY29uc3QgZmFkZSA9IHtcbiAgb3V0OiB7XG4gICAgZnJvbToge29wYWNpdHk6IDEuMH0sXG4gICAgdG86IHtvcGFjaXR5OiAwfVxuICB9LFxuICBpbjoge1xuICAgIGZyb206IHtvcGFjaXR5OiAwfSxcbiAgICB0bzoge29wYWNpdHk6IDEuMH1cbiAgfVxufTtcblxuZXhwb3J0IGNsYXNzIE1ERmFkZVBvcG92ZXJBbmltYXRvciBleHRlbmRzIFBvcG92ZXJBbmltYXRvciB7XG4gIHNob3cocG9wb3ZlciwgY2FsbGJhY2spIHtcbiAgICB0aGlzLl9hbmltYXRlQWxsKHBvcG92ZXIsIHtcbiAgICAgIF9tYXNrOiBmYWRlLmluLFxuICAgICAgX3BvcG92ZXI6IHthbmltYXRpb246IGZhZGUuaW4sIHJlc3RvcmU6IHRydWUsIGNhbGxiYWNrfVxuICAgIH0pO1xuICB9XG5cbiAgaGlkZShwb3BvdmVyLCBjYWxsYmFjaykge1xuICAgIHRoaXMuX2FuaW1hdGVBbGwocG9wb3Zlciwge1xuICAgICAgX21hc2s6IGZhZGUub3V0LFxuICAgICAgX3BvcG92ZXI6IHthbmltYXRpb246IGZhZGUub3V0LCByZXN0b3JlOiB0cnVlLCBjYWxsYmFja31cbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgSU9TRmFkZVBvcG92ZXJBbmltYXRvciBleHRlbmRzIE1ERmFkZVBvcG92ZXJBbmltYXRvciB7XG4gIHNob3cocG9wb3ZlciwgY2FsbGJhY2spIHtcbiAgICB0aGlzLl9hbmltYXRlQWxsKHBvcG92ZXIsIHtcbiAgICAgIF9tYXNrOiBmYWRlLmluLFxuICAgICAgX3BvcG92ZXI6IHtcbiAgICAgICAgZnJvbToge1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3NjYWxlM2QoMS4zLCAxLjMsIDEuMCknLFxuICAgICAgICAgIG9wYWNpdHk6IDBcbiAgICAgICAgfSxcbiAgICAgICAgdG86IHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICdzY2FsZTNkKDEuMCwgMS4wLCAgMS4wKScsXG4gICAgICAgICAgb3BhY2l0eTogMS4wXG4gICAgICAgIH0sXG4gICAgICAgIHJlc3RvcmU6IHRydWUsXG4gICAgICAgIGNhbGxiYWNrXG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi8uLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi8uLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgeyBQb3BvdmVyQW5pbWF0b3IsIElPU0ZhZGVQb3BvdmVyQW5pbWF0b3IsIE1ERmFkZVBvcG92ZXJBbmltYXRvciB9IGZyb20gJy4vYW5pbWF0b3InO1xuaW1wb3J0IHBsYXRmb3JtIGZyb20gJy4uLy4uL29ucy9wbGF0Zm9ybSc7XG5pbXBvcnQgaVBob25lWFBhdGNoIGZyb20gJy4uLy4uL29ucy9pcGhvbmV4LXBhdGNoJztcbmltcG9ydCBCYXNlRGlhbG9nRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZGlhbG9nJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcucG9wb3Zlcic6ICdwb3BvdmVyLS0qJyxcbiAgJy5wb3BvdmVyLW1hc2snOiAncG9wb3Zlci1tYXNrLS0qJyxcbiAgJy5wb3BvdmVyX19jb250ZW50JzogJ3BvcG92ZXItLSpfX2NvbnRlbnQnLFxuICAnLnBvcG92ZXJfX2Fycm93JzogJ3BvcG92ZXItLSpfX2Fycm93J1xufTtcblxuY29uc3QgX2FuaW1hdG9yRGljdCA9IHtcbiAgJ2RlZmF1bHQnOiAoKSA9PiBwbGF0Zm9ybS5pc0FuZHJvaWQoKSA/IE1ERmFkZVBvcG92ZXJBbmltYXRvciA6IElPU0ZhZGVQb3BvdmVyQW5pbWF0b3IsXG4gICdub25lJzogUG9wb3ZlckFuaW1hdG9yLFxuICAnZmFkZS1pb3MnOiBJT1NGYWRlUG9wb3ZlckFuaW1hdG9yLFxuICAnZmFkZS1tZCc6IE1ERmFkZVBvcG92ZXJBbmltYXRvclxufTtcblxuY29uc3QgcG9zaXRpb25zID0ge1xuICB1cDogJ2JvdHRvbScsXG4gIGxlZnQ6ICdyaWdodCcsXG4gIGRvd246ICd0b3AnLFxuICByaWdodDogJ2xlZnQnXG59O1xuXG5jb25zdCBkaXJlY3Rpb25zID0gT2JqZWN0LmtleXMocG9zaXRpb25zKTtcbi8qKlxuICogQGVsZW1lbnQgb25zLXBvcG92ZXJcbiAqIEBjYXRlZ29yeSBkaWFsb2dcbiAqIEBkZXNjcmlwdGlvblxuICogIFtlbl1cbiAqICAgIEEgY29tcG9uZW50IHRoYXQgZGlzcGxheXMgYSBwb3BvdmVyIG5leHQgdG8gYW4gZWxlbWVudC4gVGhlIHBvcG92ZXIgY2FuIGJlIHVzZWQgdG8gZGlzcGxheSBleHRyYSBpbmZvcm1hdGlvbiBhYm91dCBhIGNvbXBvbmVudCBvciBhIHRvb2x0aXAuXG4gKlxuICogICAgVG8gdXNlIHRoZSBlbGVtZW50IGl0IGNhbiBlaXRoZXIgYmUgYXR0YWNoZWQgZGlyZWN0bHkgdG8gdGhlIGA8Ym9keT5gIGVsZW1lbnQgb3IgZHluYW1pY2FsbHkgY3JlYXRlZCBmcm9tIGEgdGVtcGxhdGUgdXNpbmcgdGhlIGBvbnMuY3JlYXRlUG9wb3Zlcih0ZW1wbGF0ZSlgIHV0aWxpdHkgZnVuY3Rpb24gYW5kIHRoZSBgPHRlbXBsYXRlPmAgdGFnLlxuICpcbiAqICAgIEFub3RoZXIgY29tbW9uIHdheSB0byB1c2UgdGhlIHBvcG92ZXIgaXMgdG8gZGlzcGxheSBhIG1lbnUgd2hlbiBhIGJ1dHRvbiBvbiB0aGUgc2NyZWVuIGlzIHRhcHBlZC4gRm9yIE1hdGVyaWFsIERlc2lnbiwgcG9wb3ZlciBsb29rcyBleGFjdGx5IGFzIGEgZHJvcGRvd24gbWVudS5cbiAqICBbL2VuXVxuICogIFtqYV3jgYLjgovopoHntKDjgpLlr77osaHjgajjgZnjgovjg53jg4Pjg5fjgqrjg7zjg5Djg7zjgpLooajnpLrjgZnjgovjgrPjg7Pjg53jg7zjg43jg7Pjg4jjgafjgZnjgIJbL2phXVxuICogQGNvZGVwZW4gWllZUktvXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvcG9wb3ZlclxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNtb2RpZmllcnMgW2VuXU1vcmUgZGV0YWlscyBhYm91dCB0aGUgYG1vZGlmaWVyYCBhdHRyaWJ1dGVbL2VuXVtqYV1tb2RpZmllcuWxnuaAp+OBruS9v+OBhOaWuVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1idXR0b24gb25jbGljaz1cInNob3dQb3BvdmVyKHRoaXMpXCI+XG4gKiAgIENsaWNrIG1lIVxuICogPC9vbnMtYnV0dG9uPlxuICpcbiAqIDxvbnMtcG9wb3ZlciBkaXJlY3Rpb249XCJkb3duXCIgaWQ9XCJwb3BvdmVyXCI+XG4gKiAgIDxwPlRoaXMgaXMgYSBwb3BvdmVyITwvcD5cbiAqIDwvb25zLXBvcG92ZXI+XG4gKlxuICogPHNjcmlwdD5cbiAqICAgdmFyIHNob3dQb3BvdmVyID0gZnVuY3Rpb24oZWxlbWVudCkge1xuICogICAgIHZhciBwb3BvdmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3BvcG92ZXInKTtcbiAqICAgICBwb3BvdmVyLnNob3coZWxlbWVudCk7XG4gKiAgIH07XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUG9wb3ZlckVsZW1lbnQgZXh0ZW5kcyBCYXNlRGlhbG9nRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBldmVudCBwcmVzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgcG9wb3ZlciBpcyBkaXNwbGF5ZWQuWy9lbl1cbiAgICogICBbamFd44Od44OD44OX44Kq44O844OQ44O844GM6KGo56S644GV44KM44KL55u05YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50IFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnBvcG92ZXJcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0aGlzIGZ1bmN0aW9uIHRvIHN0b3AgdGhlIHBvcG92ZXIgZnJvbSBiZWluZyBzaG93bi5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7plqLmlbDjgpLlkbzjgbPlh7rjgZnjgajjgIHjg53jg4Pjg5fjgqrjg7zjg5Djg7zjga7ooajnpLrjgYzjgq3jg6Pjg7Pjgrvjg6vjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHBvc3RzaG93XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGFmdGVyIHRoZSBwb3BvdmVyIGlzIGRpc3BsYXllZC5bL2VuXVxuICAgKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjgYzooajnpLrjgZXjgozjgZ/nm7TlvozjgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQucG9wb3ZlclxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlaGlkZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBiZWZvcmUgdGhlIHBvcG92ZXIgaXMgaGlkZGVuLlsvZW5dXG4gICAqICAgW2phXeODneODg+ODl+OCquODvOODkOODvOOBjOmaoOOCjOOCi+ebtOWJjeOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5wb3BvdmVyXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZXZlbnQuY2FuY2VsXG4gICAqICAgW2VuXUNhbGwgdGhpcyBmdW5jdGlvbiB0byBzdG9wIHRoZSBwb3BvdmVyIGZyb20gYmVpbmcgaGlkZGVuLlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgeODneODg+ODl+OCquODvOODkOODvOOBjOmaoOOCjOOCi+WHpueQhuOCkuOCreODo+ODs+OCu+ODq+OBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGhpZGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIHBvcG92ZXIgaXMgaGlkZGVuLlsvZW5dXG4gICAqICAgW2phXeODneODg+ODl+OCquODvOODkOODvOOBjOmaoOOCjOOBn+W+jOOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudCBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5wb3BvdmVyXG4gICAqICAgW2VuXUNvbXBvbmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHBvcG92ZXIuWy9lbl1cbiAgICogIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXJlY3Rpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dXG4gICAqICAgIEEgc3BhY2Ugc2VwYXJhdGVkIGxpc3Qgb2YgZGlyZWN0aW9ucy4gSWYgbW9yZSB0aGFuIG9uZSBkaXJlY3Rpb24gaXMgc3BlY2lmaWVkLFxuICAgKiAgICBpdCB3aWxsIGJlIGNob3NlbiBhdXRvbWF0aWNhbGx5LiBWYWxpZCBkaXJlY3Rpb25zIGFyZSBgXCJ1cFwiYCwgYFwiZG93blwiYCwgYFwibGVmdFwiYCBhbmQgYFwicmlnaHRcImAuXG4gICAqICBbL2VuXVxuICAgKiAgW2phXVxuICAgKiAgICDjg53jg4Pjg5fjgqrjg7zjg5Djg7zjgpLooajnpLrjgZnjgovmlrnlkJHjgpLnqbrnmb3ljLrliIfjgorjgafopIfmlbDmjIflrprjgafjgY3jgb7jgZnjgIJcbiAgICogICAg5oyH5a6a44Gn44GN44KL5pa55ZCR44Gv44CBXCJ1cFwiLCBcImRvd25cIiwgXCJsZWZ0XCIsIFwicmlnaHRcIuOBrjTjgaTjgafjgZnjgILnqbrnmb3ljLrliIfjgorjgafopIfmlbDmjIflrprjgZnjgovjgZPjgajjgoLjgafjgY3jgb7jgZnjgIJcbiAgICogICAg6KSH5pWw5oyH5a6a44GV44KM44Gf5aC05ZCI44CB5a++6LGh44Go44GZ44KL6KaB57Sg44Gr5ZCI44KP44Gb44Gm5oyH5a6a44GX44Gf5YCk44GL44KJ6Ieq5YuV55qE44Gr6YG45oqe44GV44KM44G+44GZ44CCXG4gICAqICBbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBjYW5jZWxhYmxlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIHBvcG92ZXIgY2FuIGJlIGNsb3NlZCBieSB0YXBwaW5nIHRoZSBiYWNrZ3JvdW5kIG9yIGJ5IHByZXNzaW5nIHRoZSBiYWNrIGJ1dHRvbi5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovjgajjgIHjg53jg4Pjg5fjgqrjg7zjg5Djg7zjgYzooajnpLrjgZXjgozjgZ/mmYLjgavjgIHog4zmma/jgoTjg5Djg4Pjgq/jg5zjgr/jg7PjgpLjgr/jg4Pjg5fjgZfjgZ/mmYLjgavjgpLjg53jg4Pjg5fjgqrjg7zjg5Djg7zplonjgZjjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBjb3Zlci10YXJnZXRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHNldCB0aGUgcG9wb3ZlciB3aWxsIGNvdmVyIHRoZSB0YXJnZXQgb24gdGhlIHNjcmVlbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhbmltYXRpb24gdXNlZCB3aGVuIHNob3dpbmcgYW4gaGlkaW5nIHRoZSBwb3BvdmVyLiBDYW4gYmUgZWl0aGVyIGBcIm5vbmVcImAsIGBcImRlZmF1bHRcImAsIGBcImZhZGUtaW9zXCJgIG9yIGBcImZhZGUtbWRcImAuWy9lbl1cbiAgICogICBbamFd44Od44OD44OX44Kq44O844OQ44O844KS6KGo56S644GZ44KL6Zqb44Gu44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCB0aW1pbmcsIGRlbGF544KS44Kq44OW44K444Kn44Kv44OI44Oq44OG44Op44Or44Gn5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1hc2stY29sb3JcbiAgICogQHR5cGUge0NvbG9yfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ29sb3Igb2YgdGhlIGJhY2tncm91bmQgbWFzay4gRGVmYXVsdCBpcyBgXCJyZ2JhKDAsIDAsIDAsIDAuMilcImAuWy9lbl1cbiAgICogICBbamFd6IOM5pmv44Gu44Oe44K544Kv44Gu6Imy44KS5oyH5a6a44GX44G+44GZ44CC44OH44OV44Kp44Or44OI44GvXCJyZ2JhKDAsIDAsIDAsIDAuMilcIuOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9ib3VuZE9uQ2hhbmdlID0gdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9jb21waWxlKCk7XG4gICAgICB0aGlzLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgX3NjaGVtZSgpIHtcbiAgICByZXR1cm4gc2NoZW1lO1xuICB9XG5cbiAgZ2V0IF9tYXNrKCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBvcG92ZXItbWFzaycpO1xuICB9XG5cbiAgZ2V0IF9wb3BvdmVyKCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnBvcG92ZXInKTtcbiAgfVxuXG4gIGdldCBfY29udGVudCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcy5fcG9wb3ZlciwgJy5wb3BvdmVyX19jb250ZW50Jyk7XG4gIH1cblxuICBnZXQgX2Fycm93KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLl9wb3BvdmVyLCAnLnBvcG92ZXJfX2Fycm93Jyk7XG4gIH1cblxuICBfdXBkYXRlQW5pbWF0b3JGYWN0b3J5KCkge1xuICAgIHJldHVybiBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogX2FuaW1hdG9yRGljdCxcbiAgICAgIGJhc2VDbGFzczogUG9wb3ZlckFuaW1hdG9yLFxuICAgICAgYmFzZUNsYXNzTmFtZTogJ1BvcG92ZXJBbmltYXRvcicsXG4gICAgICBkZWZhdWx0QW5pbWF0aW9uOiB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uJykgfHwgJ2RlZmF1bHQnXG4gICAgfSk7XG4gIH1cblxuICBfdG9nZ2xlU3R5bGUoc2hvdWxkU2hvdywgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKHNob3VsZFNob3cpIHtcbiAgICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICB0aGlzLl9jdXJyZW50VGFyZ2V0ID0gb3B0aW9ucy50YXJnZXQ7XG4gICAgICB0aGlzLl9wb3NpdGlvblBvcG92ZXIob3B0aW9ucy50YXJnZXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICB0aGlzLl9jbGVhclN0eWxlcygpO1xuICAgIH1cbiAgfVxuXG4gIF9wb3NpdGlvblBvcG92ZXIodGFyZ2V0KSB7XG4gICAgY29uc3Qge19yYWRpdXM6IHJhZGl1cywgX2NvbnRlbnQ6IGNvbnRlbnRFbGVtZW50LCBfbWFyZ2luOiBtYXJnaW59ID0gdGhpcztcbiAgICBjb25zdCBzYWZlQXJlYUxlbmd0aHMgPSBpUGhvbmVYUGF0Y2guZ2V0U2FmZUFyZWFMZW5ndGhzKCk7XG4gICAgY29uc3Qgc2FmZUFyZWFSZWN0ID0gaVBob25lWFBhdGNoLmdldFNhZmVBcmVhRE9NUmVjdCgpO1xuICAgIGNvbnN0IHRhcmdldFJlY3QgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgY29uc3QgaXNNRCA9IHV0aWwuaGFzTW9kaWZpZXIodGhpcywgJ21hdGVyaWFsJyk7XG4gICAgY29uc3QgY292ZXIgPSBpc01EICYmIHRoaXMuaGFzQXR0cmlidXRlKCdjb3Zlci10YXJnZXQnKTtcbiAgICBjb25zdCBwYXJlbnQgPSB1dGlsLmZpbmRQYXJlbnQodGhpcywgJ29ucy1wYWdlJykgfHwgZG9jdW1lbnQuYm9keTtcbiAgICBjb25zdCBwYXJlbnREaW1lbnNpb25zID0gcGFyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIGNvbnN0IG1heFBvc2l0aW9ucyA9IHtcbiAgICAgIHRvcDogTWF0aC5tYXgocGFyZW50RGltZW5zaW9ucy50b3AsIHNhZmVBcmVhUmVjdC50b3ApLFxuICAgICAgbGVmdDogTWF0aC5tYXgocGFyZW50RGltZW5zaW9ucy5sZWZ0LCBzYWZlQXJlYVJlY3QubGVmdCksXG4gICAgICBib3R0b206IE1hdGgubWluKHBhcmVudERpbWVuc2lvbnMuYm90dG9tLCBzYWZlQXJlYVJlY3QuYm90dG9tKSxcbiAgICAgIHJpZ2h0OiBNYXRoLm1pbihwYXJlbnREaW1lbnNpb25zLnJpZ2h0LCBzYWZlQXJlYVJlY3QucmlnaHQpLFxuICAgIH07XG5cbiAgICAvLyBEaXN0YW5jZSBmcm9tIGVhY2ggc2lkZSBvZiB0aGUgc2FmZSBhcmVhICh3aXRoIG1hcmdpbikgdG8gdGhlIHRhcmdldCBlbGVtZW50XG4gICAgY29uc3QgdGFyZ2V0RGlzdGFuY2UgPSB7XG4gICAgICB0b3A6IHRhcmdldFJlY3QudG9wIC0gKG1heFBvc2l0aW9ucy50b3AgKyBtYXJnaW4pLFxuICAgICAgbGVmdDogdGFyZ2V0UmVjdC5sZWZ0IC0gKG1heFBvc2l0aW9ucy5sZWZ0ICsgbWFyZ2luKSxcbiAgICAgIGJvdHRvbTogKG1heFBvc2l0aW9ucy5ib3R0b20gLSBtYXJnaW4pIC0gdGFyZ2V0UmVjdC5ib3R0b20sXG4gICAgICByaWdodDogKG1heFBvc2l0aW9ucy5yaWdodCAtIG1hcmdpbikgLSB0YXJnZXRSZWN0LnJpZ2h0XG4gICAgfTtcblxuICAgIC8vIERpc3RhbmNlIGZyb20gZWFjaCBzaWRlIG9mIHRoZSBzYWZlIGFyZWEgKHdpdGggbWFyZ2luKSB0byB0aGUgZ2VvbWV0cmljIGNlbnRlciBvZiB0aGUgdGFyZ2V0IGVsZW1lbnRcbiAgICBjb25zdCB0YXJnZXRDZW50ZXJEaXN0YW5jZUZyb20gPSB7XG4gICAgICB0b3A6IHRhcmdldFJlY3QudG9wICsgTWF0aC5yb3VuZCh0YXJnZXRSZWN0LmhlaWdodCAvIDIpIC0gKG1heFBvc2l0aW9ucy50b3AgKyBtYXJnaW4pLFxuICAgICAgbGVmdDogdGFyZ2V0UmVjdC5sZWZ0ICsgTWF0aC5yb3VuZCh0YXJnZXRSZWN0LndpZHRoIC8gMikgLSAobWF4UG9zaXRpb25zLmxlZnQgKyBtYXJnaW4pLFxuICAgICAgYm90dG9tOiAobWF4UG9zaXRpb25zLmJvdHRvbSAtIG1hcmdpbikgLSB0YXJnZXRSZWN0LmJvdHRvbSArIE1hdGgucm91bmQodGFyZ2V0UmVjdC5oZWlnaHQgLyAyKSxcbiAgICAgIHJpZ2h0OiAobWF4UG9zaXRpb25zLnJpZ2h0IC0gbWFyZ2luKSAtIHRhcmdldFJlY3QucmlnaHQgKyBNYXRoLnJvdW5kKHRhcmdldFJlY3Qud2lkdGggLyAyKVxuICAgIH07XG5cbiAgICBjb25zdCB7dmVydGljYWwsIHByaW1hcnk6IHByaW1hcnlEaXJlY3Rpb24sIHNlY29uZGFyeTogc2Vjb25kYXJ5RGlyZWN0aW9ufSA9IHRoaXMuX2NhbGN1bGF0ZURpcmVjdGlvbnModGFyZ2V0RGlzdGFuY2UpO1xuICAgIHRoaXMuX2N1cnJlbnREaXJlY3Rpb24gPSBwcmltYXJ5RGlyZWN0aW9uO1xuICAgIHV0aWwuYWRkTW9kaWZpZXIodGhpcywgcHJpbWFyeURpcmVjdGlvbik7XG5cbiAgICBjb25zdCBzaXplTmFtZSA9IHZlcnRpY2FsID8gJ3dpZHRoJyA6ICdoZWlnaHQnO1xuICAgIC8vIEdldCAucG9wb3Zlcl9fY29udGVudCBzaXplXG4gICAgY29uc3QgY29udGVudFNpemUgPSAoc3R5bGUgPT4gKHtcbiAgICAgIHdpZHRoOiBwYXJzZUludChzdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCd3aWR0aCcpLCAxMCksXG4gICAgICBoZWlnaHQ6IHBhcnNlSW50KHN0eWxlLmdldFByb3BlcnR5VmFsdWUoJ2hlaWdodCcpLCAxMClcbiAgICB9KSkod2luZG93LmdldENvbXB1dGVkU3R5bGUoY29udGVudEVsZW1lbnQpKTtcblxuICAgIC8vIFNldHRpbmcgLnBvcG92ZXIgcG9zaXRpb24uXG4gICAgY29uc3QgdGFyZ2V0QW5kQXJyb3dMZW5ndGggPSBjb3ZlciA/IDAgOiAodmVydGljYWwgPyB0YXJnZXRSZWN0LmhlaWdodCA6IHRhcmdldFJlY3Qud2lkdGgpICsgKGlzTUQgPyAwIDogMTQpO1xuICAgIGNvbnN0IHByaW1hcnlPZmZzZXQgPSBNYXRoLm1heChcbiAgICAgIHNhZmVBcmVhTGVuZ3Roc1twcmltYXJ5RGlyZWN0aW9uXSArIG1hcmdpbixcbiAgICAgIHNhZmVBcmVhTGVuZ3Roc1twcmltYXJ5RGlyZWN0aW9uXSArIG1hcmdpbiArIHRhcmdldERpc3RhbmNlW3ByaW1hcnlEaXJlY3Rpb25dICsgdGFyZ2V0QW5kQXJyb3dMZW5ndGhcbiAgICApO1xuICAgIGNvbnN0IHNlY29uZGFyeU9mZnNldCA9IE1hdGgubWF4KFxuICAgICAgc2FmZUFyZWFMZW5ndGhzW3NlY29uZGFyeURpcmVjdGlvbl0gKyBtYXJnaW4sXG4gICAgICBzYWZlQXJlYUxlbmd0aHNbc2Vjb25kYXJ5RGlyZWN0aW9uXSArIG1hcmdpbiArIHRhcmdldENlbnRlckRpc3RhbmNlRnJvbVtzZWNvbmRhcnlEaXJlY3Rpb25dIC0gKGNvbnRlbnRTaXplW3NpemVOYW1lXSAvIDIpXG4gICAgKTtcbiAgICB0aGlzLl9wb3BvdmVyLnN0eWxlW3ByaW1hcnlEaXJlY3Rpb25dID0gcHJpbWFyeU9mZnNldCArICdweCc7XG4gICAgdGhpcy5fcG9wb3Zlci5zdHlsZVtzZWNvbmRhcnlEaXJlY3Rpb25dID0gc2Vjb25kYXJ5T2Zmc2V0ICsgJ3B4JztcblxuICAgIC8vIFNldHRpbmcgLnBvcG92ZXJfX2Fycm93IHBvc2l0aW9uLlxuICAgIHRoaXMuX2Fycm93LnN0eWxlW3NlY29uZGFyeURpcmVjdGlvbl0gPSBNYXRoLm1heChcbiAgICAgIHJhZGl1cyxcbiAgICAgIChzYWZlQXJlYUxlbmd0aHNbc2Vjb25kYXJ5RGlyZWN0aW9uXSArIG1hcmdpbikgKyB0YXJnZXRDZW50ZXJEaXN0YW5jZUZyb21bc2Vjb25kYXJ5RGlyZWN0aW9uXSAtIHNlY29uZGFyeU9mZnNldFxuICAgICkgKyAncHgnO1xuICB9XG5cbiAgX2NhbGN1bGF0ZURpcmVjdGlvbnMoZGlzdGFuY2UpIHtcbiAgICBjb25zdCBvcHRpb25zID0gKHRoaXMuZ2V0QXR0cmlidXRlKCdkaXJlY3Rpb24nKSB8fCAndXAgZG93biBsZWZ0IHJpZ2h0Jykuc3BsaXQoL1xccysvKS5tYXAoZSA9PiBwb3NpdGlvbnNbZV0pO1xuICAgIGNvbnN0IHByaW1hcnkgPSBvcHRpb25zLnNvcnQoKGEsIGIpID0+IGRpc3RhbmNlW2FdIC0gZGlzdGFuY2VbYl0pWzBdO1xuICAgIGNvbnN0IHZlcnRpY2FsID0gJ3RvcCcgPT0gcHJpbWFyeSB8fCAnYm90dG9tJyA9PSBwcmltYXJ5O1xuICAgIGxldCBzZWNvbmRhcnk7XG5cbiAgICBpZiAodmVydGljYWwpIHtcbiAgICAgIHNlY29uZGFyeSA9IGRpc3RhbmNlLmxlZnQgPCBkaXN0YW5jZS5yaWdodCA/ICdsZWZ0JyA6ICdyaWdodCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNlY29uZGFyeSA9IGRpc3RhbmNlLnRvcCA8IGRpc3RhbmNlLmJvdHRvbSA/ICd0b3AnIDogJ2JvdHRvbSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHt2ZXJ0aWNhbCwgcHJpbWFyeSwgc2Vjb25kYXJ5fTtcbiAgfVxuXG4gIF9jbGVhclN0eWxlcygpIHtcbiAgICB0aGlzLl9jdXJyZW50RGlyZWN0aW9uID0gbnVsbDtcbiAgICBbJ3RvcCcsICdib3R0b20nLCAnbGVmdCcsICdyaWdodCddLmZvckVhY2goZSA9PiB7XG4gICAgICB0aGlzLl9hcnJvdy5zdHlsZVtlXSA9IHRoaXMuX2NvbnRlbnQuc3R5bGVbZV0gPSB0aGlzLl9wb3BvdmVyLnN0eWxlW2VdID0gJyc7XG4gICAgICB1dGlsLnJlbW92ZU1vZGlmaWVyKHRoaXMsIGUpO1xuICAgIH0pO1xuICB9XG5cbiAgX29uQ2hhbmdlKCkge1xuICAgIHNldEltbWVkaWF0ZSgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5fY3VycmVudFRhcmdldCkge1xuICAgICAgICB0aGlzLl9wb3NpdGlvblBvcG92ZXIodGhpcy5fY3VycmVudFRhcmdldCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIGlmICh0aGlzLl9wb3BvdmVyICYmIHRoaXMuX21hc2spIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBoYXNEZWZhdWx0Q29udGFpbmVyID0gdGhpcy5fcG9wb3ZlciAmJiB0aGlzLl9jb250ZW50O1xuXG4gICAgaWYgKGhhc0RlZmF1bHRDb250YWluZXIpIHtcblxuICAgICAgaWYgKCF0aGlzLl9tYXNrKSB7XG4gICAgICAgIGNvbnN0IG1hc2sgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgbWFzay5jbGFzc0xpc3QuYWRkKCdwb3BvdmVyLW1hc2snKTtcbiAgICAgICAgdGhpcy5pbnNlcnRCZWZvcmUobWFzaywgdGhpcy5maXJzdENoaWxkKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLl9hcnJvdykge1xuICAgICAgICBjb25zdCBhcnJvdyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBhcnJvdy5jbGFzc0xpc3QuYWRkKCdwb3BvdmVyX19hcnJvdycpO1xuICAgICAgICB0aGlzLl9wb3BvdmVyLmFwcGVuZENoaWxkKGFycm93KTtcbiAgICAgIH1cblxuICAgIH0gZWxzZSB7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gdXRpbC5jcmVhdGVGcmFnbWVudChgXG4gICAgICAgIDxkaXYgY2xhc3M9XCJwb3BvdmVyLW1hc2tcIj48L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInBvcG92ZXJcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwicG9wb3Zlcl9fY29udGVudFwiPjwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJwb3BvdmVyX19hcnJvd1wiPjwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIGApO1xuICAgICAgY29uc3QgY29udGVudCA9IHRlbXBsYXRlLnF1ZXJ5U2VsZWN0b3IoJy5wb3BvdmVyX19jb250ZW50Jyk7XG5cbiAgICAgIHdoaWxlICh0aGlzLmNoaWxkTm9kZXNbMF0pIHtcbiAgICAgICAgY29udGVudC5hcHBlbmRDaGlsZCh0aGlzLmNoaWxkTm9kZXNbMF0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmFwcGVuZENoaWxkKHRlbXBsYXRlKTtcbiAgICB9XG5cbiAgICAvLyBGSVhNRSFcbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ3N0eWxlJykpIHtcbiAgICAgIHRoaXMuX3BvcG92ZXIuc2V0QXR0cmlidXRlKCdzdHlsZScsIHRoaXMuZ2V0QXR0cmlidXRlKCdzdHlsZScpKTtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKCdzdHlsZScpO1xuICAgIH1cblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgdGhpcy5fc2NoZW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KHRhcmdldCwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge1N0cmluZ3xFdmVudHxIVE1MRWxlbWVudH0gdGFyZ2V0XG4gICAqICAgW2VuXVRhcmdldCBlbGVtZW50LiBDYW4gYmUgZWl0aGVyIGEgQ1NTIHNlbGVjdG9yLCBhbiBldmVudCBvYmplY3Qgb3IgYSBET00gZWxlbWVudC4gSXQgY2FuIGJlIGFsc28gcHJvdmlkZWQgYXMgJ29wdGlvbnMudGFyZ2V0JyBpbnN0ZWFkLiBbL2VuXVxuICAgKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjga7jgr/jg7zjgrLjg4Pjg4jjgajjgarjgovopoHntKDjgpLmjIflrprjgZfjgb7jgZnjgIJDU1Pjgrvjg6zjgq/jgr/jgYtldmVudOOCquODluOCuOOCp+OCr+ODiOOBi0RPTeimgee0oOOBruOBhOOBmuOCjOOBi+OCkua4oeOBm+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gIFVzZSBvbmUgb2YgYFwiZmFkZS1pb3NcImAsIGBcImZhZGUtbWRcImAsIGBcIm5vbmVcImAgYW5kIGBcImRlZmF1bHRcImAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCXCJmYWRlLWlvc1wiLCBcImZhZGUtbWRcIiwgXCJub25lXCIsIFwiZGVmYXVsdFwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1UaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBhZnRlciB0aGUgcG9wb3ZlciBoYXMgYmVlbiByZXZlYWxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjgYzooajnpLrjgZXjgozntYLjgo/jgaPjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dT3BlbiB0aGUgcG9wb3ZlciBhbmQgcG9pbnQgaXQgYXQgYSB0YXJnZXQuIFRoZSB0YXJnZXQgY2FuIGJlIGVpdGhlciBhbiBldmVudCwgYSBDU1Mgc2VsZWN0b3Igb3IgYSBET00gZWxlbWVudC4uWy9lbl1cbiAgICogICBbamFd5a++6LGh44Go44GZ44KL6KaB57Sg44Gr44Od44OD44OX44Kq44O844OQ44O844KS6KGo56S644GX44G+44GZ44CCdGFyZ2V05byV5pWw44Gr44Gv44CBJGV2ZW5044Kq44OW44K444Kn44Kv44OI44KERE9N44Ko44Os44Oh44Oz44OI44KEQ1NT44K744Os44Kv44K/44KS5rih44GZ44GT44Go44GM5Ye65p2l44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGRpc3BsYXllZCBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNob3codGFyZ2V0LCBvcHRpb25zID0ge30pIHtcbiAgICAvLyBDb3B5IG9wdGlvbnMgYW5kIGluY2x1ZGUgb3B0aW9ucy50YXJnZXRcbiAgICBpZiAodGFyZ2V0ICYmIHR5cGVvZiB0YXJnZXQgPT09ICdvYmplY3QnICYmICEodGFyZ2V0IGluc3RhbmNlb2YgRXZlbnQpICYmICEodGFyZ2V0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpKSB7XG4gICAgICBvcHRpb25zID0geyAuLi50YXJnZXQgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3B0aW9ucyA9IHsgLi4ub3B0aW9ucywgdGFyZ2V0IH07XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLnRhcmdldCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIG9wdGlvbnMudGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihvcHRpb25zLnRhcmdldCk7XG4gICAgfSBlbHNlIGlmIChvcHRpb25zLnRhcmdldCBpbnN0YW5jZW9mIEV2ZW50KSB7XG4gICAgICBvcHRpb25zLnRhcmdldCA9IG9wdGlvbnMudGFyZ2V0LnRhcmdldDtcbiAgICB9XG5cbiAgICBpZiAoIShvcHRpb25zLnRhcmdldCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSkge1xuICAgICB1dGlsLnRocm93KCdJbnZhbGlkIHRhcmdldCB0eXBlIG9yIHVuZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIHJldHVybiBzdXBlci5zaG93KG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgaGlkZVxuICAgKiBAc2lnbmF0dXJlIGhpZGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuICBVc2Ugb25lIG9mIGBcImZhZGUtaW9zXCJgLCBgXCJmYWRlLW1kXCJgLCBgXCJub25lXCJgIGFuZCBgXCJkZWZhdWx0XCJgLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAglwiZmFkZS1pb3NcIiwgXCJmYWRlLW1kXCIsIFwibm9uZVwiLCBcImRlZmF1bHRcIuOBruOBhOOBmuOCjOOBi+OCkuaMh+WumuOBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgZGVsYXkgYW5kIHRpbWluZy4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIGRlbGF5LCB0aW1pbmfjgpLmjIflrprjgZfjgb7jgZnjgIJlLmcuIHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31bL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogICBbZW5dVGhpcyBmdW5jdGlvbnMgaXMgY2FsbGVkIGFmdGVyIHRoZSBwb3BvdmVyIGhhcyBiZWVuIGhpZGRlbi5bL2VuXVxuICAgKiAgIFtqYV3jg53jg4Pjg5fjgqrjg7zjg5Djg7zjgYzpmqDjgozjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ2xvc2UgdGhlIHBvcG92ZXIuWy9lbl1cbiAgICogICBbamFd44Od44OD44OX44Kq44O844OQ44O844KS6ZaJ44GY44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGhpZGRlbiBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2aXNpYmxlXG4gICAqIEByZWFkb25seVxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd6KaB57Sg44GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBjYW5jZWxhYmxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dXG4gICAqICAgICBBIGJvb2xlYW4gdmFsdWUgdGhhdCBzcGVjaWZpZXMgd2hldGhlciB0aGUgcG9wb3ZlciBpcyBjYW5jZWxhYmxlIG9yIG5vdC5cbiAgICpcbiAgICogICAgIFdoZW4gdGhlIHBvcG92ZXIgaXMgY2FuY2VsYWJsZSBpdCBjYW4gYmUgY2xvc2VkIGJ5IHRhcHBpbmcgdGhlIGJhY2tncm91bmQgb3IgYnkgcHJlc3NpbmcgdGhlIGJhY2sgYnV0dG9uIG9uIEFuZHJvaWQgZGV2aWNlcy5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IG9uRGV2aWNlQmFja0J1dHRvblxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQmFjay1idXR0b24gaGFuZGxlci5bL2VuXVxuICAgKiAgIFtqYV3jg5Djg4Pjgq/jg5zjgr/jg7Pjg4/jg7Pjg4njg6njgIJbL2phXVxuICAgKi9cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBzdXBlci5jb25uZWN0ZWRDYWxsYmFjaygpO1xuXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMuX2JvdW5kT25DaGFuZ2UsIGZhbHNlKTtcbiAgICB0aGlzLl9tYXJnaW4gPSB0aGlzLl9tYXJnaW4gfHwgcGFyc2VJbnQod2luZG93LmdldENvbXB1dGVkU3R5bGUodGhpcykuZ2V0UHJvcGVydHlWYWx1ZSgndG9wJykpO1xuICAgIHRoaXMuX21hcmdpbiA9IHRoaXMuX21hcmdpbiB8fCA2OyAvLyBGaXggZm9yIGlmcmFtZXNcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9yYWRpdXMgPSBwYXJzZUludCh3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLl9jb250ZW50KS5nZXRQcm9wZXJ0eVZhbHVlKCdib3JkZXItdG9wLWxlZnQtcmFkaXVzJykpO1xuICAgIH0pO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgc3VwZXIuZGlzY29ubmVjdGVkQ2FsbGJhY2soKTtcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fYm91bmRPbkNoYW5nZSwgZmFsc2UpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsuLi5zdXBlci5vYnNlcnZlZEF0dHJpYnV0ZXMsICdkaXJlY3Rpb24nXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdkaXJlY3Rpb24nKSB7XG4gICAgICByZXR1cm4gdGhpcy5fYm91bmRPbkNoYW5nZSgpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ21vZGlmaWVyJykge1xuICAgICAgdGhpcy5fY3VycmVudERpcmVjdGlvbiAmJiB1dGlsLmFkZE1vZGlmaWVyKHRoaXMsIHRoaXMuX2N1cnJlbnREaXJlY3Rpb24pO1xuICAgIH1cbiAgICBzdXBlci5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtQb3BvdmVyQW5pbWF0b3J9IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIFBvcG92ZXJBbmltYXRvcikpIHtcbiAgICAgIHV0aWwudGhyb3dBbmltYXRvcignUG9wb3ZlcicpO1xuICAgIH1cbiAgICBfYW5pbWF0b3JEaWN0W25hbWVdID0gQW5pbWF0b3I7XG4gIH1cblxuICBzdGF0aWMgZ2V0IGFuaW1hdG9ycygpIHtcbiAgICByZXR1cm4gX2FuaW1hdG9yRGljdDtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgUG9wb3ZlckFuaW1hdG9yKCkge1xuICAgIHJldHVybiBQb3BvdmVyQW5pbWF0b3I7XG4gIH1cbn1cblxub25zRWxlbWVudHMuUG9wb3ZlciA9IFBvcG92ZXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcG9wb3ZlcicsIFBvcG92ZXJFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5wcm9ncmVzcy1iYXInOiAncHJvZ3Jlc3MtYmFyLS0qJyxcbiAgJy5wcm9ncmVzcy1iYXJfX3ByaW1hcnknOiAncHJvZ3Jlc3MtYmFyLS0qX19wcmltYXJ5JyxcbiAgJy5wcm9ncmVzcy1iYXJfX3NlY29uZGFyeSc6ICdwcm9ncmVzcy1iYXItLSpfX3NlY29uZGFyeSdcbn07XG5cbmNvbnN0IHRlbXBsYXRlID0gdXRpbC5jcmVhdGVFbGVtZW50KGBcbiAgPGRpdiBjbGFzcz1cInByb2dyZXNzLWJhclwiPlxuICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJfX3NlY29uZGFyeVwiPjwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJfX3ByaW1hcnlcIj48L2Rpdj5cbiAgPC9kaXY+XG5gKTtcblxuY29uc3QgSU5ERVQgPSAnaW5kZXRlcm1pbmF0ZSc7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXByb2dyZXNzLWJhclxuICogQGNhdGVnb3J5IHZpc3VhbFxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1EaXNwbGF5IGEgTWF0ZXJpYWwgRGVzaWduIHByb2dyZXNzIGJhci5bL2VuXVxuICogICBbamFd44Oe44OG44Oq44Ki44Or44OH44K244Kk44Oz44Gu44K544K/44Kk44Or44Gn44OX44Ot44Kw44Os44K544OQ44O844KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgVGhlIGNvbXBvbmVudCBpcyB1c2VkIHRvIGRpc3BsYXkgYSBsaW5lYXIgcHJvZ3Jlc3MgYmFyLiBJdCBjYW4gZWl0aGVyIGRpc3BsYXkgYSBwcm9ncmVzcyBiYXIgdGhhdCBzaG93cyB0aGUgdXNlciBob3cgbXVjaCBvZiBhIHRhc2sgaGFzIGJlZW4gY29tcGxldGVkLiBJbiB0aGUgY2FzZSB3aGVyZSB0aGUgcGVyY2VudGFnZSBpcyBub3Qga25vd24gaXQgY2FuIGJlIHVzZWQgdG8gZGlzcGxheSBhbiBhbmltYXRlZCBwcm9ncmVzcyBiYXIgc28gdGhlIHVzZXIgY2FuIHNlZSB0aGF0IGFuIG9wZXJhdGlvbiBpcyBpbiBwcm9ncmVzcy5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAY29kZXBlbiB6dlFiR2pcbiAqIEB0dXRvcmlhbCB2YW5pbGxhL1JlZmVyZW5jZS9wcm9ncmVzc1xuICogQHNlZWFsc28gb25zLXByb2dyZXNzLWNpcmN1bGFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtcHJvZ3Jlc3MtY2lyY3VsYXI+YCBjb21wb25lbnQgZGlzcGxheXMgYSBjaXJjdWxhciBwcm9ncmVzcyBpbmRpY2F0b3IuWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1wcm9ncmVzcy1iYXJcbiAqICB2YWx1ZT1cIjU1XCJcbiAqICBzZWNvbmRhcnktdmFsdWU9XCI4N1wiPlxuICogPC9vbnMtcHJvZ3Jlc3MtYmFyPlxuICpcbiAqIDxvbnMtcHJvZ3Jlc3MtYmFyXG4gKiAgaW5kZXRlcm1pbmF0ZT5cbiAqIDwvb25zLXByb2dyZXNzLWJhcj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHJvZ3Jlc3NCYXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DaGFuZ2UgdGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHByb2dyZXNzIGluZGljYXRvci5bL2VuXVxuICAgKiAgIFtqYV3jg5fjg63jgrDjg6zjgrnjgqTjg7PjgrjjgrHjg7zjgr/jga7opovjgZ/nm67jgpLlpInmm7TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB2YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBwcm9ncmVzcy4gU2hvdWxkIGJlIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxMDAuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu6YCy6KGM54q25rOB44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCMOOBi+OCiTEwMOOBrumWk+OBruWApOOCkuaMh+WumuOBl+OBpuS4i+OBleOBhOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNlY29uZGFyeS12YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBzZWNvbmRhcnkgcHJvZ3Jlc3MuIFNob3VsZCBiZSBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMTAwLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBru+8kueVquebruOBrumAsuihjOeKtuazgeOBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAgjDjgYvjgokxMDDjga7plpPjga7lgKTjgpLmjIflrprjgZfjgabkuIvjgZXjgYTjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbmRldGVybWluYXRlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQsIGFuIGluZmluaXRlIGxvb3BpbmcgYW5pbWF0aW9uIHdpbGwgYmUgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM6Kit5a6a44GV44KM44Gf5aC05ZCI44CB44Or44O844OX44GZ44KL44Ki44OL44Oh44O844K344On44Oz44GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgaWYgKCF0aGlzLl9pc0NvbXBpbGVkKCkpIHtcbiAgICAgIHRoaXMuX3RlbXBsYXRlID0gdGVtcGxhdGUuY2xvbmVOb2RlKHRydWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl90ZW1wbGF0ZSA9IHV0aWwuZmluZENoaWxkKHRoaXMsICcucHJvZ3Jlc3MtYmFyJyk7XG4gICAgfVxuXG4gICAgdGhpcy5fcHJpbWFyeSA9IHV0aWwuZmluZENoaWxkKHRoaXMuX3RlbXBsYXRlLCAnLnByb2dyZXNzLWJhcl9fcHJpbWFyeScpO1xuICAgIHRoaXMuX3NlY29uZGFyeSA9IHV0aWwuZmluZENoaWxkKHRoaXMuX3RlbXBsYXRlLCAnLnByb2dyZXNzLWJhcl9fc2Vjb25kYXJ5Jyk7XG5cbiAgICB0aGlzLl91cGRhdGVEZXRlcm1pbmF0ZSgpO1xuICAgIHRoaXMuX3VwZGF0ZVZhbHVlKCk7XG5cbiAgICB0aGlzLmFwcGVuZENoaWxkKHRoaXMuX3RlbXBsYXRlKTtcblxuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgfVxuXG4gIF9pc0NvbXBpbGVkKCkge1xuICAgIGlmICghdXRpbC5maW5kQ2hpbGQodGhpcywgJy5wcm9ncmVzcy1iYXInKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGJhckVsZW1lbnQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWJhcicpO1xuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZChiYXJFbGVtZW50LCAnLnByb2dyZXNzLWJhcl9fc2Vjb25kYXJ5JykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKGJhckVsZW1lbnQsICcucHJvZ3Jlc3MtYmFyX19wcmltYXJ5JykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ3ZhbHVlJywgJ3NlY29uZGFyeS12YWx1ZScsIElOREVUXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdtb2RpZmllcicpIHtcbiAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgICAgdGhpcy5oYXNBdHRyaWJ1dGUoSU5ERVQpICYmIHRoaXMuX3VwZGF0ZURldGVybWluYXRlKCk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSAndmFsdWUnIHx8IG5hbWUgPT09ICdzZWNvbmRhcnktdmFsdWUnKSB7XG4gICAgICB0aGlzLl91cGRhdGVWYWx1ZSgpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gSU5ERVQpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZURldGVybWluYXRlKCk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZURldGVybWluYXRlKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB1dGlsLnRvZ2dsZU1vZGlmaWVyKHRoaXMsIElOREVULCB7IGZvcmNlOiB0aGlzLmhhc0F0dHJpYnV0ZShJTkRFVCkgfSkpO1xuICB9XG5cbiAgX3VwZGF0ZVZhbHVlKCkge1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICB0aGlzLl9wcmltYXJ5LnN0eWxlLndpZHRoID0gKHRoaXMuaGFzQXR0cmlidXRlKCd2YWx1ZScpKSA/IHRoaXMuZ2V0QXR0cmlidXRlKCd2YWx1ZScpICsgJyUnIDogJzAlJztcbiAgICAgIHRoaXMuX3NlY29uZGFyeS5zdHlsZS53aWR0aCA9IHRoaXMuaGFzQXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSA/IHRoaXMuZ2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSArICclJyA6ICcwJSc7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DdXJyZW50IHByb2dyZXNzLiBTaG91bGQgYmUgYSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDEwMC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7pgLLooYznirbms4Hjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIIw44GL44KJMTAw44Gu6ZaT44Gu5YCk44KS5oyH5a6a44GX44Gm5LiL44GV44GE44CCWy9qYV1cbiAgICovXG4gIHNldCB2YWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDEwMCkge1xuICAgICAgdXRpbC50aHJvdygnSW52YWxpZCB2YWx1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCd2YWx1ZScsIE1hdGguZmxvb3IodmFsdWUpKTtcbiAgfVxuXG4gIGdldCB2YWx1ZSgpIHtcbiAgICByZXR1cm4gcGFyc2VJbnQodGhpcy5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykgfHwgJzAnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgc2Vjb25kYXJ5VmFsdWVcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgc2Vjb25kYXJ5IHByb2dyZXNzLiBTaG91bGQgYmUgYSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDEwMC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7vvJLnlarnm67jga7pgLLooYznirbms4Hjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIIw44GL44KJMTAw44Gu6ZaT44Gu5YCk44KS5oyH5a6a44GX44Gm5LiL44GV44GE44CCWy9qYV1cbiAgICovXG4gIHNldCBzZWNvbmRhcnlWYWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDEwMCkge1xuICAgICAgdXRpbC50aHJvdygnSW52YWxpZCB2YWx1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnLCBNYXRoLmZsb29yKHZhbHVlKSk7XG4gIH1cblxuICBnZXQgc2Vjb25kYXJ5VmFsdWUoKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSB8fCAnMCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBpbmRldGVybWluYXRlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAsIGFuIGluZmluaXRlIGxvb3BpbmcgYW5pbWF0aW9uIHdpbGwgYmUgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM6Kit5a6a44GV44KM44Gf5aC05ZCI44CB44Or44O844OX44GZ44KL44Ki44OL44Oh44O844K344On44Oz44GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHNldCBpbmRldGVybWluYXRlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZShJTkRFVCwgJycpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKElOREVUKTtcbiAgICB9XG4gIH1cblxuICBnZXQgaW5kZXRlcm1pbmF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoSU5ERVQpO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlByb2dyZXNzQmFyID0gUHJvZ3Jlc3NCYXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcHJvZ3Jlc3MtYmFyJywgUHJvZ3Jlc3NCYXJFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy5wcm9ncmVzcy1jaXJjdWxhcic6ICdwcm9ncmVzcy1jaXJjdWxhci0tKicsXG4gICcucHJvZ3Jlc3MtY2lyY3VsYXJfX2JhY2tncm91bmQnOiAncHJvZ3Jlc3MtY2lyY3VsYXItLSpfX2JhY2tncm91bmQnLFxuICAnLnByb2dyZXNzLWNpcmN1bGFyX19wcmltYXJ5JzogJ3Byb2dyZXNzLWNpcmN1bGFyLS0qX19wcmltYXJ5JyxcbiAgJy5wcm9ncmVzcy1jaXJjdWxhcl9fc2Vjb25kYXJ5JzogJ3Byb2dyZXNzLWNpcmN1bGFyLS0qX19zZWNvbmRhcnknXG59O1xuXG5jb25zdCB0ZW1wbGF0ZSA9IHV0aWwuY3JlYXRlRWxlbWVudChgXG4gIDxzdmcgY2xhc3M9XCJwcm9ncmVzcy1jaXJjdWxhclwiPlxuICAgIDxjaXJjbGUgY2xhc3M9XCJwcm9ncmVzcy1jaXJjdWxhcl9fYmFja2dyb3VuZFwiIC8+XG4gICAgPGNpcmNsZSBjbGFzcz1cInByb2dyZXNzLWNpcmN1bGFyX19zZWNvbmRhcnlcIiBjeD1cIjUwJVwiIGN5PVwiNTAlXCIgcj1cIjQwJVwiIC8+XG4gICAgPGNpcmNsZSBjbGFzcz1cInByb2dyZXNzLWNpcmN1bGFyX19wcmltYXJ5XCIgY3g9XCI1MCVcIiBjeT1cIjUwJVwiIHI9XCI0MCVcIiAvPlxuICA8L3N2Zz5cbmApO1xuXG5jb25zdCBJTkRFVCA9ICdpbmRldGVybWluYXRlJztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtcHJvZ3Jlc3MtY2lyY3VsYXJcbiAqIEBjYXRlZ29yeSB2aXN1YWxcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgVGhpcyBjb21wb25lbnQgZGlzcGxheXMgYSBjaXJjdWxhciBwcm9ncmVzcyBpbmRpY2F0b3IuIEl0IGNhbiBlaXRoZXIgYmUgdXNlZCB0byBzaG93IGhvdyBtdWNoIG9mIGEgdGFzayBoYXMgYmVlbiBjb21wbGV0ZWQgb3IgdG8gc2hvdyBhIGxvb3BpbmcgYW5pbWF0aW9uIHRvIGluZGljYXRlIHRoYXQgYW4gb3BlcmF0aW9uIGlzIGN1cnJlbnRseSBydW5uaW5nLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIEVWek1qUlxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3Byb2dyZXNzLWNpcmN1bGFyXG4gKiBAc2VlYWxzbyBvbnMtcHJvZ3Jlc3MtYmFyXG4gKiAgIFtlbl1UaGUgYDxvbnMtcHJvZ3Jlc3MtYmFyPmAgY29tcG9uZW50IGRpc3BsYXlzIGEgYmFyIHByb2dyZXNzIGluZGljYXRvci5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXByb2dyZXNzLWNpcmN1bGFyXG4gKiAgdmFsdWU9XCI1NVwiXG4gKiAgc2Vjb25kYXJ5LXZhbHVlPVwiODdcIj5cbiAqIDwvb25zLXByb2dyZXNzLWNpcmN1bGFyPlxuICpcbiAqIDxvbnMtcHJvZ3Jlc3MtY2lyY3VsYXJcbiAqICBpbmRldGVybWluYXRlPlxuICogPC9vbnMtcHJvZ3Jlc3MtY2lyY3VsYXI+XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFByb2dyZXNzQ2lyY3VsYXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DaGFuZ2UgdGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHByb2dyZXNzIGluZGljYXRvci5bL2VuXVxuICAgKiAgIFtqYV3jg5fjg63jgrDjg6zjgrnjgqTjg7PjgrjjgrHjg7zjgr/jga7opovjgZ/nm67jgpLlpInmm7TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB2YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBwcm9ncmVzcy4gU2hvdWxkIGJlIGEgdmFsdWUgYmV0d2VlbiAwIGFuZCAxMDAuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu6YCy6KGM54q25rOB44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCMOOBi+OCiTEwMOOBrumWk+OBruWApOOCkuaMh+WumuOBl+OBpuS4i+OBleOBhOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNlY29uZGFyeS12YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCBzZWNvbmRhcnkgcHJvZ3Jlc3MuIFNob3VsZCBiZSBhIHZhbHVlIGJldHdlZW4gMCBhbmQgMTAwLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBru+8kueVquebruOBrumAsuihjOeKtuazgeOBruWApOOCkuaMh+WumuOBl+OBvuOBmeOAgjDjgYvjgokxMDDjga7plpPjga7lgKTjgpLmjIflrprjgZfjgabkuIvjgZXjgYTjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbmRldGVybWluYXRlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQsIGFuIGluZmluaXRlIGxvb3BpbmcgYW5pbWF0aW9uIHdpbGwgYmUgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM6Kit5a6a44GV44KM44Gf5aC05ZCI44CB44Or44O844OX44GZ44KL44Ki44OL44Oh44O844K344On44Oz44GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAndmFsdWUnLCAnc2Vjb25kYXJ5LXZhbHVlJywgSU5ERVRdO1xuICB9XG5cbiAgYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpIHtcbiAgICBpZiAobmFtZSA9PT0gJ21vZGlmaWVyJykge1xuICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICB0aGlzLmhhc0F0dHJpYnV0ZShJTkRFVCkgJiYgdGhpcy5fdXBkYXRlRGV0ZXJtaW5hdGUoKTtcbiAgICB9IGVsc2UgaWYgKG5hbWUgPT09ICd2YWx1ZScgfHwgbmFtZSA9PT0gJ3NlY29uZGFyeS12YWx1ZScpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVZhbHVlKCk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSBJTkRFVCkge1xuICAgICAgdGhpcy5fdXBkYXRlRGV0ZXJtaW5hdGUoKTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlRGV0ZXJtaW5hdGUoKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHV0aWwudG9nZ2xlTW9kaWZpZXIodGhpcywgSU5ERVQsIHsgZm9yY2U6IHRoaXMuaGFzQXR0cmlidXRlKElOREVUKSB9KSk7XG4gIH1cblxuICBfdXBkYXRlVmFsdWUoKSB7XG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCd2YWx1ZScpKSB7XG4gICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICBjb25zdCBwZXIgPSBNYXRoLmNlaWwodGhpcy5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykgKiAyNTEuMzIgKiAwLjAxKTtcbiAgICAgICAgdGhpcy5fcHJpbWFyeS5zdHlsZVsnc3Ryb2tlLWRhc2hhcnJheSddID0gcGVyICsgJyUsIDI1MS4zMiUnO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZSgnc2Vjb25kYXJ5LXZhbHVlJykpIHtcbiAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHBlciA9ICBNYXRoLmNlaWwodGhpcy5nZXRBdHRyaWJ1dGUoJ3NlY29uZGFyeS12YWx1ZScpICogMjUxLjMyICogMC4wMSk7XG4gICAgICAgIHRoaXMuX3NlY29uZGFyeS5zdHlsZS5kaXNwbGF5ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fc2Vjb25kYXJ5LnN0eWxlWydzdHJva2UtZGFzaGFycmF5J10gPSBwZXIgKyAnJSwgMjUxLjMyJSc7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgdGhpcy5fc2Vjb25kYXJ5LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1DdXJyZW50IHByb2dyZXNzLiBTaG91bGQgYmUgYSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDEwMC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7pgLLooYznirbms4Hjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIIw44GL44KJMTAw44Gu6ZaT44Gu5YCk44KS5oyH5a6a44GX44Gm5LiL44GV44GE44CCWy9qYV1cbiAgICovXG4gIHNldCB2YWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDEwMCkge1xuICAgICAgdXRpbC50aHJvdygnSW52YWxpZCB2YWx1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCd2YWx1ZScsIE1hdGguZmxvb3IodmFsdWUpKTtcbiAgfVxuXG4gIGdldCB2YWx1ZSgpIHtcbiAgICByZXR1cm4gcGFyc2VJbnQodGhpcy5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykgfHwgJzAnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgc2Vjb25kYXJ5VmFsdWVcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgc2Vjb25kYXJ5IHByb2dyZXNzLiBTaG91bGQgYmUgYSB2YWx1ZSBiZXR3ZWVuIDAgYW5kIDEwMC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7vvJLnlarnm67jga7pgLLooYznirbms4Hjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIIw44GL44KJMTAw44Gu6ZaT44Gu5YCk44KS5oyH5a6a44GX44Gm5LiL44GV44GE44CCWy9qYV1cbiAgICovXG4gIHNldCBzZWNvbmRhcnlWYWx1ZSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlIDwgMCB8fCB2YWx1ZSA+IDEwMCkge1xuICAgICAgdXRpbC50aHJvdygnSW52YWxpZCB2YWx1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnLCBNYXRoLmZsb29yKHZhbHVlKSk7XG4gIH1cblxuICBnZXQgc2Vjb25kYXJ5VmFsdWUoKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCdzZWNvbmRhcnktdmFsdWUnKSB8fCAnMCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBpbmRldGVybWluYXRlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBwcm9wZXJ0eSBpcyBgdHJ1ZWAsIGFuIGluZmluaXRlIGxvb3BpbmcgYW5pbWF0aW9uIHdpbGwgYmUgc2hvd24uWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM6Kit5a6a44GV44KM44Gf5aC05ZCI44CB44Or44O844OX44GZ44KL44Ki44OL44Oh44O844K344On44Oz44GM6KGo56S644GV44KM44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHNldCBpbmRldGVybWluYXRlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlKSB7XG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZShJTkRFVCwgJycpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKElOREVUKTtcbiAgICB9XG4gIH1cblxuICBnZXQgaW5kZXRlcm1pbmF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoSU5ERVQpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgaWYgKHRoaXMuX2lzQ29tcGlsZWQoKSkge1xuICAgICAgdGhpcy5fdGVtcGxhdGUgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWNpcmN1bGFyJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX3RlbXBsYXRlID0gdGVtcGxhdGUuY2xvbmVOb2RlKHRydWUpO1xuICAgIH1cblxuICAgIHRoaXMuX3ByaW1hcnkgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLl90ZW1wbGF0ZSwgJy5wcm9ncmVzcy1jaXJjdWxhcl9fcHJpbWFyeScpO1xuICAgIHRoaXMuX3NlY29uZGFyeSA9IHV0aWwuZmluZENoaWxkKHRoaXMuX3RlbXBsYXRlLCAnLnByb2dyZXNzLWNpcmN1bGFyX19zZWNvbmRhcnknKTtcblxuICAgIHRoaXMuX3VwZGF0ZURldGVybWluYXRlKCk7XG4gICAgdGhpcy5fdXBkYXRlVmFsdWUoKTtcblxuICAgIHRoaXMuYXBwZW5kQ2hpbGQodGhpcy5fdGVtcGxhdGUpO1xuXG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgX2lzQ29tcGlsZWQoKSB7XG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWNpcmN1bGFyJykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBzdmcgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnByb2dyZXNzLWNpcmN1bGFyJyk7XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHN2ZywgJy5wcm9ncmVzcy1jaXJjdWxhcl9fc2Vjb25kYXJ5JykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXV0aWwuZmluZENoaWxkKHN2ZywgJy5wcm9ncmVzcy1jaXJjdWxhcl9fcHJpbWFyeScpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cblxub25zRWxlbWVudHMuUHJvZ3Jlc3NDaXJjdWxhciA9IFByb2dyZXNzQ2lyY3VsYXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcHJvZ3Jlc3MtY2lyY3VsYXInLCBQcm9ncmVzc0NpcmN1bGFyRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBzdHlsZXIgZnJvbSAnLi4vb25zL3N0eWxlcic7XG5pbXBvcnQgcGxhdGZvcm0gZnJvbSAnLi4vb25zL3BsYXRmb3JtJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBHZXN0dXJlRGV0ZWN0b3IgZnJvbSAnLi4vb25zL2dlc3R1cmUtZGV0ZWN0b3InO1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi9vbnMvYW5pbWl0JztcblxuY29uc3QgU1RBVEVfSU5JVElBTCA9ICdpbml0aWFsJztcbmNvbnN0IFNUQVRFX1BSRUFDVElPTiA9ICdwcmVhY3Rpb24nO1xuY29uc3QgU1RBVEVfQUNUSU9OID0gJ2FjdGlvbic7XG5cbmNvbnN0IHRocm93VHlwZSA9IChlbCwgdHlwZSkgPT4gdXRpbC50aHJvdyhgXCIke2VsfVwiIG11c3QgYmUgJHt0eXBlfWApO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1wdWxsLWhvb2tcbiAqIEBjYXRlZ29yeSBjb250cm9sXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIENvbXBvbmVudCB0aGF0IGFkZHMgKipQdWxsIHRvIHJlZnJlc2gqKiBmdW5jdGlvbmFsaXR5IHRvIGFuIGA8b25zLXBhZ2U+YCBlbGVtZW50LlxuICpcbiAqICAgICBJdCBjYW4gYmUgdXNlZCB0byBwZXJmb3JtIGEgdGFzayB3aGVuIHRoZSB1c2VyIHB1bGxzIGRvd24gYXQgdGhlIHRvcCBvZiB0aGUgcGFnZS4gQSBjb21tb24gdXNhZ2UgaXMgdG8gcmVmcmVzaCB0aGUgZGF0YSBkaXNwbGF5ZWQgaW4gYSBwYWdlLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIFdiSm9nTVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3B1bGwtaG9va1xuICogQGV4YW1wbGVcbiAqIDxvbnMtcGFnZT5cbiAqICAgPG9ucy1wdWxsLWhvb2s+XG4gKiAgICAgUmVsZWFzZSB0byByZWZyZXNoXG4gKiAgIDwvb25zLXB1bGwtaG9vaz5cbiAqIDwvb25zLXBhZ2U+XG4gKlxuICogPHNjcmlwdD5cbiAqICAgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignb25zLXB1bGwtaG9vaycpLm9uQWN0aW9uID0gZnVuY3Rpb24oZG9uZSkge1xuICogICAgIHNldFRpbWVvdXQoZG9uZSwgMTAwMCk7XG4gKiAgIH07XG4gKiA8L3NjcmlwdD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHVsbEhvb2tFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgY2hhbmdlc3RhdGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIHN0YXRlIGlzIGNoYW5nZWQuIFRoZSBzdGF0ZSBjYW4gYmUgZWl0aGVyIFwiaW5pdGlhbFwiLCBcInByZWFjdGlvblwiIG9yIFwiYWN0aW9uXCIuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI44Gu54q25oWL44GM5aSJ44KP44Gj44Gf5aC05ZCI44Gr55m654Gr44GX44G+44GZ44CC54q25oWL44Gv44CBXCJpbml0aWFsXCIsIFwicHJlYWN0aW9uXCIsIFwiYWN0aW9uXCLjga7jgYTjgZrjgozjgYvjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5wdWxsSG9va1xuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBldmVudC5zdGF0ZVxuICAgKiAgIFtlbl1DdXJyZW50IHN0YXRlLlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBrueKtuaFi+WQjeOCkuWPgueFp+OBp+OBjeOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIFwicHVsbC10by1yZWZyZXNoXCIgZnVuY3Rpb25hbGl0eSBpcyBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzjgYLjgovmmYLjgIFkaXNhYmxlZOeKtuaFi+OBq+OBquOCiuOCouOCr+OCt+ODp+ODs+OBjOWun+ihjOOBleOCjOOBquOBj+OBquOCiuOBvuOBmVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGhlaWdodFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgaGVpZ2h0IG9mIHRoZSBjb21wb25lbnQuIFdoZW4gcHVsbGVkIGRvd24gZnVydGhlciB0aGFuIHRoaXMgdmFsdWUgaXQgd2lsbCBzd2l0Y2ggdG8gdGhlIFwicHJlYWN0aW9uXCIgc3RhdGUuIFRoZSBkZWZhdWx0IHZhbHVlIGlzIFwiNjRweFwiLlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBrumrmOOBleOCkuaMh+WumuOBl+OBvuOBmeOAguOBk+OBrumrmOOBleS7peS4iuOBq3B1bGwgZG93buOBmeOCi+OBqFwicHJlYWN0aW9uXCLnirbmhYvjgavnp7vooYzjgZfjgb7jgZnjgILjg4fjg5Xjgqnjg6vjg4jjga7lgKTjga9cIjY0cHhcIuOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHRocmVzaG9sZC1oZWlnaHRcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIHRocmVzaG9sZCBoZWlnaHQuIFRoZSBjb21wb25lbnQgYXV0b21hdGljYWxseSBzd2l0Y2hlcyB0byB0aGUgXCJhY3Rpb25cIiBzdGF0ZSB3aGVuIHB1bGxlZCBmdXJ0aGVyIHRoYW4gdGhpcyB2YWx1ZS4gVGhlIGRlZmF1bHQgdmFsdWUgaXMgXCI5NnB4XCIuIEEgbmVnYXRpdmUgdmFsdWUgd2lsbCBkaXNhYmxlIHRoaXMgcHJvcGVydHkuIElmIHRoaXMgdmFsdWUgaXMgbG93ZXIgdGhhbiB0aGUgaGVpZ2h0LCBpdCB3aWxsIHNraXAgXCJwcmVhY3Rpb25cIiBzdGF0ZS5bL2VuXVxuICAgKiAgIFtqYV3plr7lgKTjgajjgarjgovpq5jjgZXjgpLmjIflrprjgZfjgb7jgZnjgILjgZPjga7lgKTjgafmjIflrprjgZfjgZ/pq5jjgZXjgojjgorjgoJwdWxsIGRvd27jgZnjgovjgajjgIHjgZPjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga/oh6rli5XnmoTjgatcImFjdGlvblwi54q25oWL44Gr56e76KGM44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZml4ZWQtY29udGVudFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRoZSBjb250ZW50IG9mIHRoZSBwYWdlIHdpbGwgbm90IG1vdmUgd2hlbiBwdWxsaW5nLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruWxnuaAp+OBjOOBguOCi+aZguOAgeODl+ODq+ODleODg+OCr+OBjOW8leOBjeWHuuOBleOCjOOBpuOBhOOCi+aZguOBq+OCguOCs+ODs+ODhuODs+ODhOOBr+WLleOBjeOBvuOBm+OCk+OAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9zaG91bGRGaXhTY3JvbGwgPSB1dGlsLmdsb2JhbHMuaXNVSVdlYlZpZXc7XG5cbiAgICB0aGlzLl9vbkRyYWcgPSB0aGlzLl9vbkRyYWcuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbkRyYWdTdGFydCA9IHRoaXMuX29uRHJhZ1N0YXJ0LmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25EcmFnRW5kID0gdGhpcy5fb25EcmFnRW5kLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25TY3JvbGwgPSB0aGlzLl9vblNjcm9sbC5iaW5kKHRoaXMpO1xuXG4gICAgdGhpcy5fc2V0U3RhdGUoU1RBVEVfSU5JVElBTCwgdHJ1ZSk7XG4gICAgdGhpcy5faGlkZSgpOyAvLyBGaXggZm9yIHRyYW5zcGFyZW50IHRvb2xiYXIgdHJhbnNpdGlvbnNcbiAgfVxuXG4gIF9zZXRTdHlsZSgpIHtcbiAgICBjb25zdCBoZWlnaHQgPSB0aGlzLmhlaWdodCArICdweCc7XG4gICAgc3R5bGVyKHRoaXMsIHsgaGVpZ2h0LCBsaW5lSGVpZ2h0OiBoZWlnaHQgfSk7XG4gICAgdGhpcy5zdHlsZS5kaXNwbGF5ID09PSAnJyAmJiB0aGlzLl9zaG93KCk7XG4gIH1cblxuICBfb25TY3JvbGwoZXZlbnQpIHtcbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5fcGFnZUVsZW1lbnQ7XG5cbiAgICBpZiAoZWxlbWVudC5zY3JvbGxUb3AgPCAwKSB7XG4gICAgICBlbGVtZW50LnNjcm9sbFRvcCA9IDA7XG4gICAgfVxuICB9XG5cbiAgX2NhbkNvbnN1bWVHZXN0dXJlKGdlc3R1cmUpIHtcbiAgICByZXR1cm4gZ2VzdHVyZS5kaXJlY3Rpb24gPT09ICd1cCcgfHwgZ2VzdHVyZS5kaXJlY3Rpb24gPT09ICdkb3duJztcbiAgfVxuXG4gIF9vbkRyYWdTdGFydChldmVudCkge1xuICAgIGlmICghZXZlbnQuZ2VzdHVyZSB8fCB0aGlzLmRpc2FibGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdGFwWSA9IGV2ZW50Lmdlc3R1cmUuY2VudGVyLmNsaWVudFkgKyB0aGlzLl9wYWdlRWxlbWVudC5zY3JvbGxUb3A7XG4gICAgY29uc3QgbWF4WSA9IHdpbmRvdy5pbm5lckhlaWdodDtcbiAgICAvLyBPbmx5IHVzZSBkcmFncyB0aGF0IHN0YXJ0IG5lYXIgdGhlIHB1bGxIb29rIHRvIHJlZHVjZSBmbGlja2VyaW5nc1xuICAgIGNvbnN0IGRyYWdnYWJsZUFyZWFSYXRpbyA9IHRoaXMuX3Nob3VsZEZpeFNjcm9sbCA/IC44IDogMTtcblxuICAgIHRoaXMuX2lnbm9yZURyYWcgPSBldmVudC5jb25zdW1lZCB8fCAodGFwWSA+IG1heFkgKiBkcmFnZ2FibGVBcmVhUmF0aW8pO1xuXG4gICAgaWYgKCF0aGlzLl9pZ25vcmVEcmFnKSB7XG4gICAgICBjb25zdCBjb25zdW1lID0gZXZlbnQuY29uc3VtZTtcbiAgICAgIGV2ZW50LmNvbnN1bWUgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN1bWUgJiYgY29uc3VtZSgpO1xuICAgICAgICB0aGlzLl9pZ25vcmVEcmFnID0gdHJ1ZTtcbiAgICAgICAgLy8gVGhpcyBlbGVtZW50cyByZXNpemVzIC5wYWdlX19jb250ZW50IHNvIGl0IGlzIHNhZmVyXG4gICAgICAgIC8vIHRvIGhpZGUgaXQgd2hlbiBvdGhlciBjb21wb25lbnRzIGFyZSBkcmFnZ2VkLlxuICAgICAgICB0aGlzLl9oaWRlKCk7XG4gICAgICB9O1xuXG4gICAgICBpZiAodGhpcy5fY2FuQ29uc3VtZUdlc3R1cmUoZXZlbnQuZ2VzdHVyZSkpIHtcbiAgICAgICAgY29uc3VtZSAmJiBjb25zdW1lKCk7XG4gICAgICAgIGV2ZW50LmNvbnN1bWVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5fc2hvdygpOyAvLyBOb3QgZW5vdWdoIGR1ZSB0byAnZHJhZ0xvY2tBeGlzJ1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX3N0YXJ0U2Nyb2xsID0gdGhpcy5fcGFnZUVsZW1lbnQuc2Nyb2xsVG9wO1xuICB9XG5cbiAgX29uRHJhZyhldmVudCkge1xuICAgIGlmICghZXZlbnQuZ2VzdHVyZSB8fCB0aGlzLmRpc2FibGVkIHx8IHRoaXMuX2lnbm9yZURyYWcgfHwgIXRoaXMuX2NhbkNvbnN1bWVHZXN0dXJlKGV2ZW50Lmdlc3R1cmUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gTmVjZXNzYXJ5IGR1ZSB0byAnZHJhZ0xvY2tBeGlzJyAoMjVweClcbiAgICBpZiAodGhpcy5zdHlsZS5kaXNwbGF5ID09PSAnbm9uZScpIHtcbiAgICAgIHRoaXMuX3Nob3coKTtcbiAgICB9XG5cbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIGNvbnN0IHRhcFkgPSBldmVudC5nZXN0dXJlLmNlbnRlci5jbGllbnRZICsgdGhpcy5fcGFnZUVsZW1lbnQuc2Nyb2xsVG9wO1xuICAgIGNvbnN0IG1heFkgPSB3aW5kb3cuaW5uZXJIZWlnaHQ7XG5cbiAgICAvLyBIYWNrIHRvIG1ha2UgaXQgd29yayBvbiBBbmRyb2lkIDQuNCBXZWJWaWV3IGFuZCBpT1MgVUlXZWJWaWV3LiBTY3JvbGxzIG1hbnVhbGx5XG4gICAgLy8gbmVhciB0aGUgdG9wIG9mIHRoZSBwYWdlIHNvIHRoZXJlIHdpbGwgYmUgbm8gaW5lcnRpYWwgc2Nyb2xsIHdoZW4gc2Nyb2xsaW5nIGRvd24uXG4gICAgLy8gQWxsb3dpbmcgZGVmYXVsdCBzY3JvbGxpbmcgd2lsbCBraWxsIGFsbCAndG91Y2htb3ZlJyBldmVudHMuXG4gICAgaWYgKHRoaXMuX3Nob3VsZEZpeFNjcm9sbCkge1xuICAgICAgdGhpcy5fcGFnZUVsZW1lbnQuc2Nyb2xsVG9wID0gdGhpcy5fc3RhcnRTY3JvbGwgLSBldmVudC5nZXN0dXJlLmRlbHRhWTtcbiAgICAgIC8vIEFsbG93IGluZXJ0aWEgd2hlbiBzY3JvbGxpbmcgZG93biBiZWxvdyA1MCUgb2YgdGhlIHZpZXcgdG8gcmVkdWNlIGZsaWNrZXJpbmdzXG4gICAgICBpZiAoZXZlbnQuZ2VzdHVyZS5pbnRlcmltRGlyZWN0aW9uICE9PSAndXAnIHx8ICh0YXBZIDw9IG1heFkgKiAuNSkpIHtcbiAgICAgICAgZXZlbnQuZ2VzdHVyZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHNjcm9sbCA9IE1hdGgubWF4KGV2ZW50Lmdlc3R1cmUuZGVsdGFZIC0gdGhpcy5fc3RhcnRTY3JvbGwsIDApO1xuICAgIGlmIChzY3JvbGwgIT09IHRoaXMuX2N1cnJlbnRUcmFuc2xhdGlvbikge1xuXG4gICAgICBjb25zdCB0aCA9IHRoaXMudGhyZXNob2xkSGVpZ2h0O1xuICAgICAgaWYgKHRoID4gMCAmJiBzY3JvbGwgPj0gdGgpIHtcbiAgICAgICAgZXZlbnQuZ2VzdHVyZS5zdG9wRGV0ZWN0KCk7XG4gICAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLl9maW5pc2goKSk7XG5cbiAgICAgIH0gZWxzZSBpZiAoc2Nyb2xsID49IHRoaXMuaGVpZ2h0KSB7XG4gICAgICAgIHRoaXMuX3NldFN0YXRlKFNUQVRFX1BSRUFDVElPTik7XG5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3NldFN0YXRlKFNUQVRFX0lOSVRJQUwpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl90cmFuc2xhdGVUbyhzY3JvbGwpO1xuICAgIH1cbiAgfVxuXG4gIF9vbkRyYWdFbmQoZXZlbnQpIHtcbiAgICBpZiAoIWV2ZW50Lmdlc3R1cmUgfHwgdGhpcy5kaXNhYmxlZCB8fCB0aGlzLl9pZ25vcmVEcmFnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICBpZiAodGhpcy5fY3VycmVudFRyYW5zbGF0aW9uID4gMCkge1xuICAgICAgY29uc3Qgc2Nyb2xsID0gdGhpcy5fY3VycmVudFRyYW5zbGF0aW9uO1xuXG4gICAgICBpZiAoc2Nyb2xsID4gdGhpcy5oZWlnaHQpIHtcbiAgICAgICAgdGhpcy5fZmluaXNoKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl90cmFuc2xhdGVUbygwLCB7YW5pbWF0ZTogdHJ1ZX0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25BY3Rpb25cbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhpcyB3aWxsIGJlIGNhbGxlZCBpbiB0aGUgYGFjdGlvbmAgc3RhdGUgaWYgaXQgZXhpc3RzLiBUaGUgZnVuY3Rpb24gd2lsbCBiZSBnaXZlbiBhIGBkb25lYCBjYWxsYmFjayBhcyBpdCdzIGZpcnN0IGFyZ3VtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgb25BY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX29uQWN0aW9uO1xuICB9XG5cbiAgc2V0IG9uQWN0aW9uKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHRocm93VHlwZSgnb25BY3Rpb24nLCAnZnVuY3Rpb24gb3IgbnVsbCcpO1xuICAgIH1cbiAgICB0aGlzLl9vbkFjdGlvbiA9IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvblB1bGxcbiAgICogQHR5cGUge0Z1bmN0aW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSG9vayBjYWxsZWQgd2hlbmV2ZXIgdGhlIHVzZXIgcHVsbHMgdGhlIGVsZW1lbnQuIEl0IGdldHMgdGhlIHB1bGxlZCBkaXN0YW5jZSByYXRpbyAoc2Nyb2xsIC8gaGVpZ2h0KSBhbmQgYW4gYW5pbWF0aW9uT3B0aW9ucyBvYmplY3QgYXMgYXJndW1lbnRzLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgb25QdWxsKCkge1xuICAgIHJldHVybiB0aGlzLl9vblB1bGw7XG4gIH1cblxuICBzZXQgb25QdWxsKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHRocm93VHlwZSgnb25QdWxsJywgJ2Z1bmN0aW9uIG9yIG51bGwnKTtcbiAgICB9XG4gICAgdGhpcy5fb25QdWxsID0gdmFsdWU7XG4gIH1cblxuICBfZmluaXNoKCkge1xuICAgIHRoaXMuX3NldFN0YXRlKFNUQVRFX0FDVElPTik7XG4gICAgdGhpcy5fdHJhbnNsYXRlVG8odGhpcy5oZWlnaHQsIHthbmltYXRlOiB0cnVlfSk7XG4gICAgY29uc3QgYWN0aW9uID0gdGhpcy5vbkFjdGlvbiB8fCAoZG9uZSA9PiBkb25lKCkpO1xuICAgIGFjdGlvbigoKSA9PiB7XG4gICAgICB0aGlzLl90cmFuc2xhdGVUbygwLCB7YW5pbWF0ZTogdHJ1ZX0pO1xuICAgICAgdGhpcy5fc2V0U3RhdGUoU1RBVEVfSU5JVElBTCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGhlaWdodFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGhlaWdodCBvZiB0aGUgcHVsbCBob29rIGluIHBpeGVscy4gVGhlIGRlZmF1bHQgdmFsdWUgaXMgYDY0cHhgLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBzZXQgaGVpZ2h0KHZhbHVlKSB7XG4gICAgaWYgKCF1dGlsLmlzSW50ZWdlcih2YWx1ZSkpIHtcbiAgICAgIHRocm93VHlwZSgnaGVpZ2h0JywgJ2ludGVnZXInKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldEF0dHJpYnV0ZSgnaGVpZ2h0JywgYCR7dmFsdWV9cHhgKTtcbiAgfVxuXG4gIGdldCBoZWlnaHQoKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKSB8fCAnNjQnLCAxMCk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHRocmVzaG9sZEhlaWdodFxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIHRocmVzaG9sZEhlaWdodCBvZiB0aGUgcHVsbCBob29rIGluIHBpeGVscy4gVGhlIGRlZmF1bHQgdmFsdWUgaXMgYDk2cHhgLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBzZXQgdGhyZXNob2xkSGVpZ2h0KHZhbHVlKSB7XG4gICAgaWYgKCF1dGlsLmlzSW50ZWdlcih2YWx1ZSkpIHtcbiAgICAgIHRocm93VHlwZSgndGhyZXNob2xkSGVpZ2h0JywgJ2ludGVnZXInKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldEF0dHJpYnV0ZSgndGhyZXNob2xkLWhlaWdodCcsIGAke3ZhbHVlfXB4YCk7XG4gIH1cblxuICBnZXQgdGhyZXNob2xkSGVpZ2h0KCkge1xuICAgIHJldHVybiBwYXJzZUludCh0aGlzLmdldEF0dHJpYnV0ZSgndGhyZXNob2xkLWhlaWdodCcpIHx8ICc5NicsIDEwKTtcbiAgfVxuXG4gIF9zZXRTdGF0ZShzdGF0ZSwgbm9FdmVudCkge1xuICAgIGNvbnN0IGxhc3RTdGF0ZSA9IHRoaXMuc3RhdGU7XG5cbiAgICB0aGlzLnNldEF0dHJpYnV0ZSgnc3RhdGUnLCBzdGF0ZSk7XG5cbiAgICBpZiAoIW5vRXZlbnQgJiYgbGFzdFN0YXRlICE9PSB0aGlzLnN0YXRlKSB7XG4gICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ2NoYW5nZXN0YXRlJywge1xuICAgICAgICBwdWxsSG9vazogdGhpcyxcbiAgICAgICAgc3RhdGU6IHN0YXRlLFxuICAgICAgICBsYXN0U3RhdGU6IGxhc3RTdGF0ZVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBzdGF0ZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgc3RhdGUgb2YgdGhlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBzdGF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUoJ3N0YXRlJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHB1bGxEaXN0YW5jZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBjdXJyZW50IG51bWJlciBvZiBwaXhlbHMgdGhlIHB1bGwgaG9vayBoYXMgbW92ZWQuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu44OX44Or44OV44OD44Kv44GM5byV44GN5Ye644GV44KM44Gf6Led6Zui44KS44OU44Kv44K744Or5pWw44CCWy9qYV1cbiAgICovXG4gIGdldCBwdWxsRGlzdGFuY2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2N1cnJlbnRUcmFuc2xhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgZGlzYWJsZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cbiAgc2V0IGRpc2FibGVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdkaXNhYmxlZCcsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gIH1cblxuICBfc2hvdygpIHtcbiAgICAvLyBSdW4gYXN5bmNyaG9ub3VzbHkgdG8gYXZvaWQgY29uZmxpY3RzIHdpdGggQW5pbWl0J3Mgc3R5bGUgY2xlYW5cbiAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJyc7XG4gICAgICBpZiAodGhpcy5fcGFnZUVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fcGFnZUVsZW1lbnQuc3R5bGUubWFyZ2luVG9wID0gYC0ke3RoaXMuaGVpZ2h0fXB4YDtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIF9oaWRlKCkge1xuICAgIHRoaXMuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICBpZiAodGhpcy5fcGFnZUVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX3BhZ2VFbGVtZW50LnN0eWxlLm1hcmdpblRvcCA9ICcnO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge051bWJlcn0gc2Nyb2xsXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKi9cbiAgX3RyYW5zbGF0ZVRvKHNjcm9sbCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKHRoaXMuX2N1cnJlbnRUcmFuc2xhdGlvbiA9PSAwICYmIHNjcm9sbCA9PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fY3VycmVudFRyYW5zbGF0aW9uID0gc2Nyb2xsO1xuICAgIGNvbnN0IG9wdCA9IG9wdGlvbnMuYW5pbWF0ZSA/IHsgZHVyYXRpb246IC4zLCB0aW1pbmc6ICdjdWJpYy1iZXppZXIoLjEsIC43LCAuMSwgMSknIH0gOiB7fTtcbiAgICB0aGlzLl9vblB1bGwgJiYgdGhpcy5fb25QdWxsKChzY3JvbGwgLyB0aGlzLmhlaWdodCkudG9GaXhlZCgyKSwgb3B0KTtcbiAgICBjb25zdCBzY3JvbGxFbGVtZW50ID0gIHRoaXMuaGFzQXR0cmlidXRlKCdmaXhlZC1jb250ZW50JykgPyB0aGlzIDogdGhpcy5fcGFnZUVsZW1lbnQ7XG5cbiAgICBhbmltaXQoc2Nyb2xsRWxlbWVudClcbiAgICAgIC5xdWV1ZSh7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDBweCwgJHtzY3JvbGx9cHgsIDBweClgIH0sIG9wdClcbiAgICAgIC5wbGF5KCgpID0+IHtcbiAgICAgICAgc2Nyb2xsID09PSAwICYmIHN0eWxlci5jbGVhcihzY3JvbGxFbGVtZW50LCAndHJhbnNpdGlvbiB0cmFuc2Zvcm0nKTtcbiAgICAgICAgb3B0aW9ucy5jYWxsYmFjayBpbnN0YW5jZW9mIEZ1bmN0aW9uICYmIG9wdGlvbnMuY2FsbGJhY2soKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9kaXNhYmxlRHJhZ0xvY2soKSB7IC8vIGUyZSB0ZXN0cyBuZWVkIGl0XG4gICAgdGhpcy5fZHJhZ0xvY2tEaXNhYmxlZCA9IHRydWU7XG4gICAgdGhpcy5fc2V0dXBMaXN0ZW5lcnModHJ1ZSk7XG4gIH1cblxuICBfc2V0dXBMaXN0ZW5lcnMoYWRkKSB7XG4gICAgY29uc3Qgc2Nyb2xsVG9nZ2xlID0gYWN0aW9uID0+IHRoaXMuX3BhZ2VFbGVtZW50W2Ake2FjdGlvbn1FdmVudExpc3RlbmVyYF0oJ3Njcm9sbCcsIHRoaXMuX29uU2Nyb2xsLCBmYWxzZSk7XG4gICAgY29uc3QgZ2RUb2dnbGUgPSBhY3Rpb24gPT4ge1xuICAgICAgY29uc3QgcGFzc2l2ZSA9IHsgcGFzc2l2ZTogdHJ1ZSB9O1xuICAgICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yW2FjdGlvbl0oJ2RyYWcnLCB0aGlzLl9vbkRyYWcsIHBhc3NpdmUpO1xuICAgICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yW2FjdGlvbl0oJ2RyYWdzdGFydCcsIHRoaXMuX29uRHJhZ1N0YXJ0LCBwYXNzaXZlKTtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvclthY3Rpb25dKCdkcmFnZW5kJywgdGhpcy5fb25EcmFnRW5kLCBwYXNzaXZlKTtcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMuX2dlc3R1cmVEZXRlY3Rvcikge1xuICAgICAgZ2RUb2dnbGUoJ29mZicpO1xuICAgICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yLmRpc3Bvc2UoKTtcbiAgICAgIHRoaXMuX2dlc3R1cmVEZXRlY3RvciA9IG51bGw7XG4gICAgfVxuICAgIHNjcm9sbFRvZ2dsZSgncmVtb3ZlJyk7XG5cbiAgICBpZiAoYWRkKSB7XG4gICAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3IgPSBuZXcgR2VzdHVyZURldGVjdG9yKHRoaXMuX3BhZ2VFbGVtZW50LCB7XG4gICAgICAgIGRyYWdNaW5EaXN0YW5jZTogMSxcbiAgICAgICAgZHJhZ0Rpc3RhbmNlQ29ycmVjdGlvbjogZmFsc2UsXG4gICAgICAgIGRyYWdMb2NrVG9BeGlzOiAhdGhpcy5fZHJhZ0xvY2tEaXNhYmxlZCxcbiAgICAgICAgcGFzc2l2ZTogIXRoaXMuX3Nob3VsZEZpeFNjcm9sbFxuICAgICAgfSk7XG5cbiAgICAgIGdkVG9nZ2xlKCdvbicpO1xuICAgICAgc2Nyb2xsVG9nZ2xlKCdhZGQnKTtcbiAgICB9XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9jdXJyZW50VHJhbnNsYXRpb24gPSAwO1xuICAgIHRoaXMuX3BhZ2VFbGVtZW50ID0gdGhpcy5wYXJlbnROb2RlO1xuXG4gICAgdGhpcy5fc2V0dXBMaXN0ZW5lcnModHJ1ZSk7XG4gICAgdGhpcy5fc2V0U3R5bGUoKTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuX2hpZGUoKTtcbiAgICB0aGlzLl9zZXR1cExpc3RlbmVycyhmYWxzZSk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydoZWlnaHQnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdoZWlnaHQnICYmIHRoaXMuX3BhZ2VFbGVtZW50KSB7XG4gICAgICB0aGlzLl9zZXRTdHlsZSgpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBnZXQgZXZlbnRzKCkge1xuICAgIHJldHVybiBbJ2NoYW5nZXN0YXRlJ11cbiAgfVxufVxuXG5vbnNFbGVtZW50cy5QdWxsSG9vayA9IFB1bGxIb29rRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXB1bGwtaG9vaycsIFB1bGxIb29rRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgQmFzZUlucHV0RWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1pbnB1dCc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJyc6ICdyYW5nZS0tKicsXG4gICcucmFuZ2VfX2lucHV0JzogJ3JhbmdlLS0qX19pbnB1dCcsXG4gICcucmFuZ2VfX2ZvY3VzLXJpbmcnOiAncmFuZ2UtLSpfX2ZvY3VzLXJpbmcnXG59O1xuXG5jb25zdCBhY3RpdmVDbGFzc1Rva2VuID0gJ3JhbmdlX19pbnB1dC0tYWN0aXZlJztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtcmFuZ2VcbiAqIEBjYXRlZ29yeSBmb3JtXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiBzbGlkZXJbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgUmFuZ2UgaW5wdXQgY29tcG9uZW50LiBVc2VkIHRvIGRpc3BsYXkgYSBkcmFnZ2FibGUgc2xpZGVyLlxuICpcbiAqICAgICBXb3JrcyB2ZXJ5IHNpbWlsYXIgdG8gdGhlIGA8aW5wdXQgdHlwZT1cInJhbmdlXCI+YCBlbGVtZW50LlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIHhaUW9tTVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3JhbmdlXG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI21vZGlmaWVycyBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1pbnB1dFxuICogICBbZW5dVGhlIGA8b25zLWlucHV0PmAgY29tcG9uZW50IGlzIHVzZWQgdG8gZGlzcGxheSB0ZXh0IGlucHV0cywgcmFkaW8gYnV0dG9ucyBhbmQgY2hlY2tib3hlcy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXJhbmdlIHZhbHVlPVwiMjBcIj48L29ucy1yYW5nZT5cbiAqIDxvbnMtcmFuZ2UgbW9kaWZpZXI9XCJtYXRlcmlhbFwiIHZhbHVlPVwiMTBcIj48L3JhbmdlPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJhbmdlRWxlbWVudCBleHRlbmRzIEJhc2VJbnB1dEVsZW1lbnQge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9vbk1vdXNlRG93biA9IHRoaXMuX29uTW91c2VEb3duLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Nb3VzZVVwID0gdGhpcy5fb25Nb3VzZVVwLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Ub3VjaFN0YXJ0ID0gdGhpcy5fb25Ub3VjaFN0YXJ0LmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25Ub3VjaEVuZCA9IHRoaXMuX29uVG91Y2hFbmQuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vbklucHV0ID0gdGhpcy5fdXBkYXRlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5fb25EcmFnc3RhcnQgPSB0aGlzLl9vbkRyYWdzdGFydC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX29uRHJhZ2VuZCA9IHRoaXMuX29uRHJhZ2VuZC5iaW5kKHRoaXMpO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgc3VwZXIuX2NvbXBpbGUoKTtcbiAgICB0aGlzLl91cGRhdGVEaXNhYmxlZCh0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKSk7XG4gIH1cblxuICAvKiBJbmhlcml0ZWQgcHJvcHMgKi9cblxuICBfdXBkYXRlKCkge1xuICAgIGNvbnN0IGlucHV0ID0gdGhpcy5faW5wdXQ7XG4gICAgY29uc3QgZm9jdXNSaW5nID0gdGhpcy5fZm9jdXNSaW5nO1xuXG4gICAgaW5wdXQuc3R5bGUuYmFja2dyb3VuZFNpemUgPSBgJHsxMDAgKiB0aGlzLl9yYXRpb30lIDJweGA7XG4gICAgZm9jdXNSaW5nLnZhbHVlID0gdGhpcy52YWx1ZTtcblxuICAgIC8vIE5PVEU6IFwiX3plcm9cIiBhdHRyaWJ1dGUgaXMgdXNlZCBmb3IgQ1NTIHN0eWxpbmcuXG4gICAgaWYgKChpbnB1dC5taW4gPT09ICcnICYmIGlucHV0LnZhbHVlID09PSAnMCcpIHx8IGlucHV0Lm1pbiA9PT0gaW5wdXQudmFsdWUpIHtcbiAgICAgIGlucHV0LnNldEF0dHJpYnV0ZSgnX3plcm8nLCAnJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlucHV0LnJlbW92ZUF0dHJpYnV0ZSgnX3plcm8nKTtcbiAgICB9XG5cbiAgICBbJ21pbicsICdtYXgnXS5mb3JFYWNoKGF0dHIgPT4gZm9jdXNSaW5nW2F0dHJdID0gaW5wdXRbYXR0cl0pO1xuICB9XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHNjaGVtZTtcbiAgfVxuXG4gIGdldCBfdGVtcGxhdGUoKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgIDxpbnB1dCB0eXBlPVwiJHt0aGlzLnR5cGV9XCIgY2xhc3M9XCIke3RoaXMuX2RlZmF1bHRDbGFzc05hbWV9X19pbnB1dFwiPlxuICAgICAgPGlucHV0IHR5cGU9XCJyYW5nZVwiIGNsYXNzPVwicmFuZ2VfX2ZvY3VzLXJpbmdcIiB0YWJJbmRleD1cIi0xXCI+XG4gICAgYDtcbiAgfVxuXG4gIGdldCBfZGVmYXVsdENsYXNzTmFtZSgpIHtcbiAgICByZXR1cm4gJ3JhbmdlJztcbiAgfVxuXG4gIGdldCB0eXBlKCkge1xuICAgIHJldHVybiAncmFuZ2UnO1xuICB9XG5cbiAgLyogT3duIHByb3BzICovXG5cbiAgX29uTW91c2VEb3duKGUpIHtcbiAgICB0aGlzLl9pbnB1dC5jbGFzc0xpc3QuYWRkKGFjdGl2ZUNsYXNzVG9rZW4pO1xuICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLl9pbnB1dC5mb2N1cygpKTtcbiAgfVxuXG4gIF9vblRvdWNoU3RhcnQoZSkge1xuICAgIHRoaXMuX29uTW91c2VEb3duKCk7XG4gIH1cblxuICBfb25Nb3VzZVVwKGUpIHtcbiAgICB0aGlzLl9pbnB1dC5jbGFzc0xpc3QucmVtb3ZlKGFjdGl2ZUNsYXNzVG9rZW4pO1xuICB9XG5cbiAgX29uVG91Y2hFbmQoZSkge1xuICAgIHRoaXMuX29uTW91c2VVcChlKTtcbiAgfVxuXG4gIF9vbkRyYWdzdGFydChlKSB7XG4gICAgZS5jb25zdW1lZCA9IHRydWU7XG4gICAgZS5nZXN0dXJlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIHRoaXMuX2lucHV0LmNsYXNzTGlzdC5hZGQoYWN0aXZlQ2xhc3NUb2tlbik7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdkcmFnJywgdGhpcy5fb25EcmFnKTtcbiAgfVxuXG4gIF9vbkRyYWcoZSkge1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICBfb25EcmFnZW5kKGUpIHtcbiAgICB0aGlzLl9pbnB1dC5jbGFzc0xpc3QucmVtb3ZlKGFjdGl2ZUNsYXNzVG9rZW4pO1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJhZycsIHRoaXMuX29uRHJhZyk7XG4gIH1cblxuICBnZXQgX2ZvY3VzUmluZygpIHtcbiAgICByZXR1cm4gdGhpcy5jaGlsZHJlblsxXTtcbiAgfVxuXG4gIGdldCBfcmF0aW8oKSB7XG4gICAgLy8gUmV0dXJucyB0aGUgY3VycmVudCByYXRpby5cbiAgICBjb25zdCBtaW4gPSB0aGlzLl9pbnB1dC5taW4gPT09ICcnID8gMCA6IHBhcnNlSW50KHRoaXMuX2lucHV0Lm1pbik7XG4gICAgY29uc3QgbWF4ID0gdGhpcy5faW5wdXQubWF4ID09PSAnJyA/IDEwMCA6IHBhcnNlSW50KHRoaXMuX2lucHV0Lm1heCk7XG5cbiAgICByZXR1cm4gKHRoaXMudmFsdWUgLSBtaW4pIC8gKG1heCAtIG1pbik7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydkaXNhYmxlZCcsIC4uLkJhc2VJbnB1dEVsZW1lbnQub2JzZXJ2ZWRBdHRyaWJ1dGVzXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgaWYgKG5hbWUgPT09ICdkaXNhYmxlZCcpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZURpc2FibGVkKGN1cnJlbnQpO1xuICAgIH1cbiAgICBzdXBlci5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtib29sZWFufSBkaXNhYmxlZFxuICAgKi9cbiAgX3VwZGF0ZURpc2FibGVkKGRpc2FibGVkKSB7XG4gICAgaWYgKGRpc2FibGVkKSB7XG4gICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ3JhbmdlLS1kaXNhYmxlZCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNsYXNzTGlzdC5yZW1vdmUoJ3JhbmdlLS1kaXNhYmxlZCcpO1xuICAgIH1cbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuX3NldHVwTGlzdGVuZXJzKHRydWUpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5fc2V0dXBMaXN0ZW5lcnMoZmFsc2UpO1xuICB9XG5cbiAgX3NldHVwTGlzdGVuZXJzKGFkZCkge1xuICAgIGNvbnN0IGFjdGlvbiA9IChhZGQgPyAnYWRkJyA6ICdyZW1vdmUnKSArICdFdmVudExpc3RlbmVyJztcbiAgICB1dGlsW2FjdGlvbl0odGhpcywgJ3RvdWNoc3RhcnQnLCB0aGlzLl9vblRvdWNoU3RhcnQsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcbiAgICB0aGlzW2FjdGlvbl0oJ21vdXNlZG93bicsIHRoaXMuX29uTW91c2VEb3duKTtcbiAgICB0aGlzW2FjdGlvbl0oJ21vdXNldXAnLCB0aGlzLl9vbk1vdXNlVXApO1xuICAgIHRoaXNbYWN0aW9uXSgndG91Y2hlbmQnLCB0aGlzLl9vblRvdWNoRW5kKTtcbiAgICB0aGlzW2FjdGlvbl0oJ2RyYWdzdGFydCcsIHRoaXMuX29uRHJhZ3N0YXJ0KTtcbiAgICB0aGlzW2FjdGlvbl0oJ2RyYWdlbmQnLCB0aGlzLl9vbkRyYWdlbmQpO1xuICAgIHRoaXNbYWN0aW9uXSgnaW5wdXQnLCB0aGlzLl9vbklucHV0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGRpc2FibGVkIG9yIG5vdC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZXjgozjgabjgYTjgovloLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB2YWx1ZVxuICAgKiBAdHlwZSB7TnVtYmVyfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ3VycmVudCB2YWx1ZS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbn1cblxub25zRWxlbWVudHMuUmFuZ2UgPSBSYW5nZUVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1yYW5nZScsIFJhbmdlRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNiBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgaW50ZXJuYWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsJztcblxuLyoqXG4gKiBAY2xhc3MgQW5pbWF0b3JDU1MgLSBpbXBsZW1lbnRhdGlvbiBvZiBBbmltYXRvciBjbGFzcyB1c2luZyBjc3MgdHJhbnNpdGlvbnNcbiAqL1xuY2xhc3MgQW5pbWF0b3JDU1Mge1xuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGFuaW1hdGVcbiAgICogQGRlc2MgbWFpbiBhbmltYXRpb24gZnVuY3Rpb25cbiAgICogQHBhcmFtIHtFbGVtZW50fSBlbGVtZW50XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBmaW5hbENTU1xuICAgKiBAcGFyYW0ge251bWJlcn0gW2R1cmF0aW9uPTIwMF0gLSBkdXJhdGlvbiBpbiBtaWxsaXNlY29uZHNcbiAgICogQHJldHVybiB7T2JqZWN0fSByZXN1bHRcbiAgICogQHJldHVybiB7RnVuY3Rpb259IHJlc3VsdC50aGVuKGNhbGxiYWNrKSAtIHNldHMgYSBjYWxsYmFjayB0byBiZSBleGVjdXRlZCBhZnRlciB0aGUgYW5pbWF0aW9uIGhhcyBzdG9wcGVkXG4gICAqIEByZXR1cm4ge0Z1bmN0aW9ufSByZXN1bHQuc3RvcChvcHRpb25zKSAtIHN0b3BzIHRoZSBhbmltYXRpb247IGlmIG9wdGlvbnMuc3RvcE5leHQgaXMgdHJ1ZSB0aGVuIGl0IGRvZXNuJ3QgY2FsbCB0aGUgY2FsbGJhY2tcbiAgICogQHJldHVybiB7RnVuY3Rpb259IHJlc3VsdC5maW5pc2gobXMpIC0gZmluaXNoZXMgdGhlIGFuaW1hdGlvbiBpbiB0aGUgc3BlY2lmaWVkIHRpbWUgaW4gbWlsbGlzZWNvbmRzXG4gICAqIEByZXR1cm4ge0Z1bmN0aW9ufSByZXN1bHQuc3BlZWQobXMpIC0gc2V0cyB0aGUgYW5pbWF0aW9uIHNwZWVkIHNvIHRoYXQgaXQgZmluaXNoZXMgYXMgaWYgdGhlIG9yaWdpbmFsIGR1cmF0aW9uIHdhcyB0aGUgb25lIHNwZWNpZmllZCBoZXJlXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYGBcbiAgICogIHZhciByZXN1bHQgPSBhbmltYXRvci5hbmltYXRlKGVsLCB7b3BhY2l0eTogMC41fSwgMTAwMCk7XG4gICAqXG4gICAqICBlbC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKGUpe1xuICAgKiAgICByZXN1bHQuc3BlZWQoMjAwKS50aGVuKGZ1bmN0aW9uKCl7XG4gICAqICAgICAgY29uc29sZS5sb2coJ2RvbmUnKTtcbiAgICogICAgfSk7XG4gICAqICB9LCAzMDApO1xuICAgKiBgYGBgXG4gICAqL1xuICBhbmltYXRlKGVsLCBmaW5hbCwgZHVyYXRpb24gPSAyMDApIHtcbiAgICB2YXIgc3RhcnQgPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpLFxuICAgICAgICBpbml0aWFsID0ge30sXG4gICAgICAgIHN0b3BwZWQgPSBmYWxzZSxcbiAgICAgICAgbmV4dCA9IGZhbHNlLFxuICAgICAgICB0aW1lb3V0ID0gZmFsc2UsXG4gICAgICAgIHByb3BlcnRpZXMgPSBPYmplY3Qua2V5cyhmaW5hbCk7XG5cbiAgICB2YXIgdXBkYXRlU3R5bGVzID0gKCkgPT4ge1xuICAgICAgbGV0IHMgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCk7XG4gICAgICBwcm9wZXJ0aWVzLmZvckVhY2gocy5nZXRQcm9wZXJ0eVZhbHVlLmJpbmQocykpO1xuICAgICAgcyA9IGVsLm9mZnNldEhlaWdodDtcbiAgICB9O1xuXG4gICAgdmFyIHJlc3VsdCA9IHtcbiAgICAgIHN0b3A6IChvcHRpb25zID0ge30pID0+IHtcbiAgICAgICAgdGltZW91dCAmJiBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgIHZhciBrID0gTWF0aC5taW4oMSwgKChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgLSBzdGFydCkgLyBkdXJhdGlvbik7XG4gICAgICAgIHByb3BlcnRpZXMuZm9yRWFjaChpID0+IHtcbiAgICAgICAgICBlbC5zdHlsZVtpXSA9ICgxIC0gaykgKiBpbml0aWFsW2ldICsgayAqIGZpbmFsW2ldICsgKGkgPT0gJ29wYWNpdHknID8gJycgOiAncHgnKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGVsLnN0eWxlLnRyYW5zaXRpb25EdXJhdGlvbiA9ICcwcyc7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuc3RvcE5leHQpIHtcbiAgICAgICAgICBuZXh0ID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAoIXN0b3BwZWQpIHtcbiAgICAgICAgICBzdG9wcGVkID0gdHJ1ZTtcbiAgICAgICAgICBuZXh0ICYmIG5leHQoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSxcbiAgICAgIHRoZW46IChjYikgPT4ge1xuICAgICAgICBuZXh0ID0gY2I7XG4gICAgICAgIGlmIChzdG9wcGVkKSB7XG4gICAgICAgICAgbmV4dCAmJiBuZXh0KCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0sXG4gICAgICBzcGVlZDogKG5ld0R1cmF0aW9uKSA9PiB7XG4gICAgICAgIGlmIChpbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkKSB7XG4gICAgICAgICAgbmV3RHVyYXRpb24gPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmICghc3RvcHBlZCkge1xuICAgICAgICAgIHRpbWVvdXQgJiYgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuXG4gICAgICAgICAgY29uc3QgcGFzc2VkID0gKG5ldyBEYXRlKCkpLmdldFRpbWUoKSAtIHN0YXJ0O1xuICAgICAgICAgIGNvbnN0ICBrID0gcGFzc2VkIC8gZHVyYXRpb247XG4gICAgICAgICAgY29uc3QgcmVtYWluaW5nID0gbmV3RHVyYXRpb24gKiAoMSAtIGspO1xuXG4gICAgICAgICAgcHJvcGVydGllcy5mb3JFYWNoKGkgPT4ge1xuICAgICAgICAgICAgZWwuc3R5bGVbaV0gPSAoMSAtIGspICogaW5pdGlhbFtpXSArIGsgKiBmaW5hbFtpXSArIChpID09ICdvcGFjaXR5JyA/ICcnIDogJ3B4Jyk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICB1cGRhdGVTdHlsZXMoKTtcblxuICAgICAgICAgIHN0YXJ0ID0gZWwuc3BlZWRVcFRpbWU7XG4gICAgICAgICAgZHVyYXRpb24gPSByZW1haW5pbmc7XG5cbiAgICAgICAgICBlbC5zdHlsZS50cmFuc2l0aW9uRHVyYXRpb24gPSBkdXJhdGlvbiAvIDEwMDAgKyAncyc7XG5cbiAgICAgICAgICBwcm9wZXJ0aWVzLmZvckVhY2goaSA9PiB7XG4gICAgICAgICAgICBlbC5zdHlsZVtpXSA9IGZpbmFsW2ldICsgKGkgPT0gJ29wYWNpdHknID8gJycgOiAncHgnKTtcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KHJlc3VsdC5zdG9wLCByZW1haW5pbmcpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9LFxuICAgICAgZmluaXNoOiAobWlsbGlzZWNvbmRzID0gNTApID0+IHtcbiAgICAgICAgdmFyIGsgPSAoKG5ldyBEYXRlKCkpLmdldFRpbWUoKSAtIHN0YXJ0KSAvIGR1cmF0aW9uO1xuXG4gICAgICAgIHJlc3VsdC5zcGVlZChtaWxsaXNlY29uZHMgLyAoMSAtIGspKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgaWYgKGVsLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKSB8fCBzdG9wcGVkIHx8IGludGVybmFsLmNvbmZpZy5hbmltYXRpb25zRGlzYWJsZWQpIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgdmFyIHN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWwpO1xuICAgIHByb3BlcnRpZXMuZm9yRWFjaChlID0+IHtcbiAgICAgIGNvbnN0IHYgPSBwYXJzZUZsb2F0KHN0eWxlLmdldFByb3BlcnR5VmFsdWUoZSkpO1xuICAgICAgaW5pdGlhbFtlXSA9IGlzTmFOKHYpID8gMCA6IHY7XG4gICAgfSk7XG5cblxuICAgIGlmICghc3RvcHBlZCkge1xuICAgICAgZWwuc3R5bGUudHJhbnNpdGlvblByb3BlcnR5ID0gcHJvcGVydGllcy5qb2luKCcsJyk7XG4gICAgICBlbC5zdHlsZS50cmFuc2l0aW9uRHVyYXRpb24gPSBkdXJhdGlvbiAvIDEwMDAgKyAncyc7XG5cbiAgICAgIHByb3BlcnRpZXMuZm9yRWFjaChlID0+IHtcbiAgICAgICAgZWwuc3R5bGVbZV0gPSBmaW5hbFtlXSArIChlID09ICdvcGFjaXR5JyA/ICcnIDogJ3B4Jyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aW1lb3V0ID0gc2V0VGltZW91dChyZXN1bHQuc3RvcCwgZHVyYXRpb24pO1xuICAgIHRoaXMuX29uU3RvcEFuaW1hdGlvbnMoZWwsIHJlc3VsdC5zdG9wKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLl9xdWV1ZSA9IFtdO1xuICAgIHRoaXMuX2luZGV4ID0gMDtcbiAgfVxuXG4gIF9vblN0b3BBbmltYXRpb25zKGVsLCBsaXN0ZW5lcikge1xuICAgIHZhciBxdWV1ZSA9IHRoaXMuX3F1ZXVlO1xuICAgIHZhciBpID0gdGhpcy5faW5kZXgrKztcbiAgICBxdWV1ZVtlbF0gPSBxdWV1ZVtlbF0gfHwgW107XG4gICAgcXVldWVbZWxdW2ldID0gKG9wdGlvbnMpID0+IHtcbiAgICAgIGRlbGV0ZSBxdWV1ZVtlbF1baV07XG4gICAgICBpZiAocXVldWVbZWxdICYmIHF1ZXVlW2VsXS5sZW5ndGggPT0gMCkge1xuICAgICAgICBkZWxldGUgcXVldWVbZWxdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxpc3RlbmVyKG9wdGlvbnMpO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgKiBAbWV0aG9kIHN0b3BBbmltYXRpb25zXG4gICogQGRlc2Mgc3RvcHMgYWN0aXZlIGFuaW1hdGlvbnMgb24gYSBzcGVjaWZpZWQgZWxlbWVudFxuICAqIEBwYXJhbSB7RWxlbWVudHxBcnJheX0gZWxlbWVudCAtIGVsZW1lbnQgb3IgYXJyYXkgb2YgZWxlbWVudHNcbiAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnM9e31dXG4gICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5zdG9wTmV4dF0gLSB0aGUgY2FsbGJhY2tzIGFmdGVyIHRoZSBhbmltYXRpb25zIHdvbid0IGJlIGNhbGxlZCBpZiB0aGlzIG9wdGlvbiBpcyB0cnVlXG4gICovXG4gIHN0b3BBbmltYXRpb25zKGVsLCBvcHRpb25zID0ge30pIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShlbCkpIHtcbiAgICAgIHJldHVybiBlbC5mb3JFYWNoKGVsID0+IHtcbiAgICAgICAgdGhpcy5zdG9wQW5pbWF0aW9ucyhlbCwgb3B0aW9ucyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAodGhpcy5fcXVldWVbZWxdIHx8IFtdKS5mb3JFYWNoKGUgPT4geyBlKG9wdGlvbnMgfHwge30pOyB9KTtcbiAgfVxuXG4gIC8qKlxuICAqIEBtZXRob2Qgc3RvcEFsbFxuICAqIEBkZXNjIHN0b3BzIGFsbCBhY3RpdmUgYW5pbWF0aW9uc1xuICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9ucz17fV1cbiAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLnN0b3BOZXh0XSAtIHRoZSBjYWxsYmFja3MgYWZ0ZXIgdGhlIGFuaW1hdGlvbnMgd29uJ3QgYmUgY2FsbGVkIGlmIHRoaXMgb3B0aW9uIGlzIHRydWVcbiAgKi9cbiAgc3RvcEFsbChvcHRpb25zID0ge30pIHtcbiAgICB0aGlzLnN0b3BBbmltYXRpb25zKE9iamVjdC5rZXlzKHRoaXMuX3F1ZXVlKSwgb3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgKiBAbWV0aG9kIGZhZGVcbiAgKiBAZGVzYyBmYWRlcyB0aGUgZWxlbWVudCAoc2hvcnQgdmVyc2lvbiBmb3IgYW5pbWF0ZShlbCwge29wYWNpdHk6IDB9KSlcbiAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAgKiBAcGFyYW0ge251bWJlcn0gW2R1cmF0aW9uPTIwMF1cbiAgKi9cbiAgZmFkZShlbCwgZHVyYXRpb24gPSAyMDApIHtcbiAgICByZXR1cm4gdGhpcy5hbmltYXRlKGVsLCB7b3BhY2l0eTogMH0sIGR1cmF0aW9uKTtcbiAgfVxuXG59XG5cbmV4cG9ydCBkZWZhdWx0IEFuaW1hdG9yQ1NTO1xuXG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBpbnRlcm5hbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4uL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yLWNzcyc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ3JpcHBsZSc7XG5jb25zdCBzY2hlbWUgPSB7XG4gICcnOiAncmlwcGxlLS0qJyxcbiAgJy5yaXBwbGVfX3dhdmUnOiAncmlwcGxlLS0qX193YXZlJyxcbiAgJy5yaXBwbGVfX2JhY2tncm91bmQnOiAncmlwcGxlLS0qX19iYWNrZ3JvdW5kJyxcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXJpcHBsZVxuICogQGNhdGVnb3J5IHZpc3VhbFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBBZGRzIGEgTWF0ZXJpYWwgRGVzaWduIFwicmlwcGxlXCIgZWZmZWN0IHRvIGFuIGVsZW1lbnQuIFRoZSByaXBwbGUgZWZmZWN0IHdpbGwgc3ByZWFkIGZyb20gdGhlIHBvc2l0aW9uIHdoZXJlIHRoZSB1c2VyIHRhcHMuXG4gKlxuICogICAgIFNvbWUgZWxlbWVudHMgc3VjaCBhcyBgPG9ucy1idXR0b24+YCBhbmQgYDxvbnMtZmFiPmAgIHN1cHBvcnQgYSBgcmlwcGxlYCBhdHRyaWJ1dGUuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV3jg57jg4bjg6rjgqLjg6vjg4fjgrbjgqTjg7Pjga7jg6rjg4Pjg5fjg6vlirnmnpzjgpJET03opoHntKDjgavov73liqDjgZfjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gd0tRV2RaXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvcmlwcGxlXG4gKiBAbW9kaWZpZXIgbGlnaHQtZ3JheVxuICogICBbZW5dQ2hhbmdlIHRoZSBjb2xvciBvZiBlZmZlY3RzIHRvIGxpZ2h0IGdyYXkuWy9lbl1cbiAqICAgW2phXeOCqOODleOCp+OCr+ODiOOBruiJsuOBjOaYjuOCi+OBhOeBsOiJsuOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI2Nyb3NzLXBsYXRmb3JtLXN0eWxpbmctYXV0b3N0eWxpbmdcbiAqICBbZW5dQ3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svZW5dXG4gKiAgW2phXUNyb3NzIHBsYXRmb3JtIHN0eWxpbmdbL2phXVxuICogQGV4YW1wbGVcbiAqIDxkaXYgY2xhc3M9XCJteS1kaXZcIj5cbiAqICA8b25zLXJpcHBsZT48L29ucy1yaXBwbGU+XG4gKiA8L2Rpdj5cbiAqXG4gKiBAZXhhbXBsZVxuICogPG9ucy1idXR0b24gcmlwcGxlPkNsaWNrIG1lITwvb25zLWJ1dHRvbj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmlwcGxlRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBjb2xvclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ29sb3Igb2YgdGhlIHJpcHBsZSBlZmZlY3QuWy9lbl1cbiAgICogICBbamFd44Oq44OD44OX44Or44Ko44OV44Kn44Kv44OI44Gu6Imy44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSByaXBwbGUgZWZmZWN0LlsvZW5dXG4gICAqICAgW2phXeOCqOODleOCp+OCr+ODiOOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGJhY2tncm91bmRcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUNvbG9yIG9mIHRoZSBiYWNrZ3JvdW5kLlsvZW5dXG4gICAqICAgW2phXeiDjOaZr+OBruiJsuOCkuioreWumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNpemVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNpemluZyBvZiB0aGUgd2F2ZSBvbiByaXBwbGUgZWZmZWN0LiBTZXQgXCJjb3ZlclwiIG9yIFwiY29udGFpblwiLiBEZWZhdWx0IGlzIFwiY292ZXJcIi5bL2VuXVxuICAgKiAgIFtqYV3jgqjjg5Xjgqfjgq/jg4jjga7jgrXjgqTjgrrjgpLmjIflrprjgZfjgb7jgZnjgIJcImNvdmVyXCLjgoLjgZfjgY/jga9cImNvbnRhaW5cIuOCkuaMh+WumuOBl+OBvuOBmeOAguODh+ODleOCqeODq+ODiOOBr1wiY292ZXJcIuOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGNlbnRlclxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIHByZXNlbnRzLCBjaGFuZ2UgdGhlIHBvc2l0aW9uIG9mIHdhdmUgZWZmZWN0IHRvIGNlbnRlciBvZiB0aGUgdGFyZ2V0IGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFd44GT44Gu6KaB57Sg44KS6Kit5a6a44GZ44KL44Go44CB44Ko44OV44Kn44Kv44OI44Gu5L2N572u44GM6KaB57Sg44Gu55yf44KT5Lit44GL44KJ5aeL44G+44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCwgdGhlIHJpcHBsZSBlZmZlY3Qgd2lsbCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7lsZ7mgKfjgYzoqK3lrprjgZXjgozjgZ/loLTlkIjjgIHjg6rjg4Pjg5fjg6vjgqjjg5Xjgqfjgq/jg4jjga/nhKHlirnjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fb25UYXAgPSB0aGlzLl9vblRhcC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX29uSG9sZCA9IHRoaXMuX29uSG9sZC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuX29uRHJhZ1N0YXJ0ID0gdGhpcy5fb25EcmFnU3RhcnQuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vblJlbGVhc2UgPSB0aGlzLl9vblJlbGVhc2UuYmluZCh0aGlzKTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuXG4gICAgdGhpcy5fYW5pbWF0b3IgPSBuZXcgQW5pbWF0b3IoKTtcblxuICAgIFsnY29sb3InLCAnY2VudGVyJywgJ3N0YXJ0LXJhZGl1cycsICdiYWNrZ3JvdW5kJywgJ21vZGlmaWVyJ10uZm9yRWFjaChlID0+IHtcbiAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKGUsIG51bGwsIHRoaXMuZ2V0QXR0cmlidXRlKGUpKTtcbiAgICB9KTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIHRoaXMuY2xhc3NMaXN0LmFkZChkZWZhdWx0Q2xhc3NOYW1lKTtcblxuICAgIHRoaXMuX3dhdmUgPSB0aGlzLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3JpcHBsZV9fd2F2ZScpWzBdO1xuICAgIHRoaXMuX2JhY2tncm91bmQgPSB0aGlzLmdldEVsZW1lbnRzQnlDbGFzc05hbWUoJ3JpcHBsZV9fYmFja2dyb3VuZCcpWzBdO1xuXG4gICAgaWYgKCEodGhpcy5fYmFja2dyb3VuZCAmJiB0aGlzLl93YXZlKSkge1xuICAgICAgdGhpcy5fd2F2ZSA9IHV0aWwuY3JlYXRlKCcucmlwcGxlX193YXZlJyk7XG4gICAgICB0aGlzLl9iYWNrZ3JvdW5kID0gdXRpbC5jcmVhdGUoJy5yaXBwbGVfX2JhY2tncm91bmQnKTtcblxuICAgICAgdGhpcy5hcHBlbmRDaGlsZCh0aGlzLl93YXZlKTtcbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQodGhpcy5fYmFja2dyb3VuZCk7XG4gICAgfVxuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgX2dldEVmZmVjdFNpemUoKSB7XG4gICAgY29uc3Qgc2l6ZXMgPSBbJ2NvdmVyJywgJ2NvbnRhaW4nXTtcbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ3NpemUnKSkge1xuICAgICAgY29uc3Qgc2l6ZSA9IHRoaXMuZ2V0QXR0cmlidXRlKCdzaXplJyk7XG4gICAgICBpZiAoc2l6ZXMuaW5kZXhPZihzaXplKSAhPT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIHNpemU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuICdjb3Zlcic7XG4gIH1cblxuICBfY2FsY3VsYXRlQ29vcmRzKGUpIHtcbiAgICBsZXQgeCwgeSwgaCwgdywgcjtcbiAgICBjb25zdCBiID0gdGhpcy5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBzaXplID0gdGhpcy5fZ2V0RWZmZWN0U2l6ZSgpO1xuICAgIGNvbnN0IGVycm9yID0gKCkgPT4gdXRpbC50aHJvdygnUmlwcGxlIGludmFsaWQgc3RhdGUnKTtcblxuICAgIGlmICh0aGlzLl9jZW50ZXIpIHtcbiAgICAgIHggPSBiLndpZHRoIC8gMjtcbiAgICAgIHkgPSBiLmhlaWdodCAvIDI7XG5cbiAgICAgIGlmIChzaXplID09PSAnY292ZXInKSB7XG4gICAgICAgIHIgPSBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSk7XG4gICAgICB9IGVsc2UgaWYgKHNpemUgPT09ICdjb250YWluJykge1xuICAgICAgICByID0gTWF0aC5taW4oeCwgeSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlcnJvcigpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB4ID0gKHR5cGVvZiBlLmNsaWVudFggPT09ICdudW1iZXInID8gZS5jbGllbnRYIDogZS5jaGFuZ2VkVG91Y2hlc1swXS5jbGllbnRYKSAtIGIubGVmdDtcbiAgICAgIHkgPSAodHlwZW9mIGUuY2xpZW50WSA9PT0gJ251bWJlcicgPyBlLmNsaWVudFkgOiBlLmNoYW5nZWRUb3VjaGVzWzBdLmNsaWVudFkpIC0gYi50b3A7XG4gICAgICBoID0gTWF0aC5tYXgoeSwgYi5oZWlnaHQgLSB5KTtcbiAgICAgIHcgPSBNYXRoLm1heCh4LCBiLndpZHRoIC0geCk7XG5cbiAgICAgIGlmIChzaXplID09PSAnY292ZXInKSB7XG4gICAgICAgIHIgPSBNYXRoLnNxcnQoaCAqIGggKyB3ICogdyk7XG4gICAgICB9IGVsc2UgaWYgKHNpemUgPT09ICdjb250YWluJykge1xuICAgICAgICByID0gTWF0aC5taW4oTWF0aC5yb3VuZChoIC8gMiksIE1hdGgucm91bmQodyAvIDIpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVycm9yKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHt4LCB5LCByfTtcbiAgfVxuXG4gIF9yaXBwbGVBbmltYXRpb24oZSwgZHVyYXRpb24gPSAzMDApIHtcbiAgICBjb25zdCB7X2FuaW1hdG9yLCBfd2F2ZSwgX2JhY2tncm91bmQsIF9taW5SfSA9IHRoaXM7XG4gICAgY29uc3Qge3gsIHksIHJ9ID0gdGhpcy5fY2FsY3VsYXRlQ29vcmRzKGUpO1xuXG4gICAgX2FuaW1hdG9yLnN0b3BBbGwoe3N0b3BOZXh0OiAxfSk7XG4gICAgX2FuaW1hdG9yLmFuaW1hdGUoX2JhY2tncm91bmQsIHtvcGFjaXR5OiAxfSwgZHVyYXRpb24pO1xuXG4gICAgdXRpbC5leHRlbmQoX3dhdmUuc3R5bGUsIHtcbiAgICAgIG9wYWNpdHk6IDEsXG4gICAgICB0b3A6IHkgLSBfbWluUiArICdweCcsXG4gICAgICBsZWZ0OiB4IC0gX21pblIgKyAncHgnLFxuICAgICAgd2lkdGg6IDIgKiBfbWluUiArICdweCcsXG4gICAgICBoZWlnaHQ6IDIgKiBfbWluUiArICdweCdcbiAgICB9KTtcblxuICAgIHJldHVybiBfYW5pbWF0b3IuYW5pbWF0ZShfd2F2ZSwge1xuICAgICAgdG9wOiB5IC0gcixcbiAgICAgIGxlZnQ6IHggLSByLFxuICAgICAgaGVpZ2h0OiAyICogcixcbiAgICAgIHdpZHRoOiAyICogclxuICAgIH0sIGR1cmF0aW9uKTtcbiAgfVxuXG4gIF91cGRhdGVQYXJlbnQoKSB7XG4gICAgaWYgKCF0aGlzLl9wYXJlbnRVcGRhdGVkICYmIHRoaXMucGFyZW50Tm9kZSkge1xuICAgICAgY29uc3QgY29tcHV0ZWRTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHRoaXMucGFyZW50Tm9kZSk7XG4gICAgICBpZiAoY29tcHV0ZWRTdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCdwb3NpdGlvbicpID09PSAnc3RhdGljJykge1xuICAgICAgICB0aGlzLnBhcmVudE5vZGUuc3R5bGUucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuICAgICAgfVxuICAgICAgdGhpcy5fcGFyZW50VXBkYXRlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgX29uVGFwKGUpIHtcbiAgICBpZiAoIXRoaXMuZGlzYWJsZWQgJiYgIWUucmlwcGxlKSB7XG4gICAgICBlLnJpcHBsZSA9IHRydWU7XG4gICAgICB0aGlzLl91cGRhdGVQYXJlbnQoKTtcbiAgICAgIHRoaXMuX3JpcHBsZUFuaW1hdGlvbihlLmdlc3R1cmUuc3JjRXZlbnQpLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLl9hbmltYXRvci5mYWRlKHRoaXMuX3dhdmUpO1xuICAgICAgICB0aGlzLl9hbmltYXRvci5mYWRlKHRoaXMuX2JhY2tncm91bmQpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgX29uSG9sZChlKSB7XG4gICAgaWYgKCF0aGlzLmRpc2FibGVkICYmICFlLnJpcHBsZSkge1xuICAgICAgZS5yaXBwbGUgPSB0cnVlO1xuICAgICAgdGhpcy5fdXBkYXRlUGFyZW50KCk7XG4gICAgICB0aGlzLl9ob2xkaW5nID0gdGhpcy5fcmlwcGxlQW5pbWF0aW9uKGUuZ2VzdHVyZS5zcmNFdmVudCwgMjAwMCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdyZWxlYXNlJywgdGhpcy5fb25SZWxlYXNlKTtcbiAgICB9XG4gIH1cblxuICBfb25SZWxlYXNlKGUpIHtcbiAgICBpZiAodGhpcy5faG9sZGluZyAmJiAhZS5yaXBwbGUpIHtcbiAgICAgIGUucmlwcGxlID0gdHJ1ZTtcbiAgICAgIHRoaXMuX2hvbGRpbmcuc3BlZWQoMzAwKS50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3Iuc3RvcEFsbCh7c3RvcE5leHQ6IHRydWV9KTtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3IuZmFkZSh0aGlzLl93YXZlKTtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3IuZmFkZSh0aGlzLl9iYWNrZ3JvdW5kKTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9ob2xkaW5nID0gZmFsc2U7XG4gICAgfVxuXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVsZWFzZScsIHRoaXMuX29uUmVsZWFzZSk7XG4gIH1cblxuICBfb25EcmFnU3RhcnQoZSkge1xuICAgIGlmICh0aGlzLl9ob2xkaW5nKSB7XG4gICAgICByZXR1cm4gdGhpcy5fb25SZWxlYXNlKGUpO1xuICAgIH1cbiAgICBpZiAoWydsZWZ0JywgJ3JpZ2h0J10uaW5kZXhPZihlLmdlc3R1cmUuZGlyZWN0aW9uKSAhPSAtMSkge1xuICAgICAgdGhpcy5fb25UYXAoZSk7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5fcGFyZW50Tm9kZSA9IHRoaXMucGFyZW50Tm9kZTtcblxuICAgIGlmIChpbnRlcm5hbC5jb25maWcuYW5pbWF0aW9uc0Rpc2FibGVkKSB7XG4gICAgICB0aGlzLmRpc2FibGVkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fcGFyZW50Tm9kZS5hZGRFdmVudExpc3RlbmVyKCd0YXAnLCB0aGlzLl9vblRhcCk7XG4gICAgICB0aGlzLl9wYXJlbnROb2RlLmFkZEV2ZW50TGlzdGVuZXIoJ2hvbGQnLCB0aGlzLl9vbkhvbGQpO1xuICAgICAgdGhpcy5fcGFyZW50Tm9kZS5hZGRFdmVudExpc3RlbmVyKCdkcmFnc3RhcnQnLCB0aGlzLl9vbkRyYWdTdGFydCk7XG4gICAgfVxuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgY29uc3QgcG4gPSB0aGlzLl9wYXJlbnROb2RlIHx8IHRoaXMucGFyZW50Tm9kZTtcbiAgICBwbi5yZW1vdmVFdmVudExpc3RlbmVyKCd0YXAnLCB0aGlzLl9vblRhcCk7XG4gICAgcG4ucmVtb3ZlRXZlbnRMaXN0ZW5lcignaG9sZCcsIHRoaXMuX29uSG9sZCk7XG4gICAgcG4ucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJhZ3N0YXJ0JywgdGhpcy5fb25EcmFnU3RhcnQpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnc3RhcnQtcmFkaXVzJywgJ2NvbG9yJywgJ2JhY2tncm91bmQnLCAnY2VudGVyJywgJ2NsYXNzJywgJ21vZGlmaWVyJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuXG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdtb2RpZmllcic6XG4gICAgICAgIE1vZGlmaWVyVXRpbC5vbk1vZGlmaWVyQ2hhbmdlZChsYXN0LCBjdXJyZW50LCB0aGlzLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnc3RhcnQtcmFkaXVzJzpcbiAgICAgICAgdGhpcy5fbWluUiA9IE1hdGgubWF4KDAsIHBhcnNlRmxvYXQoY3VycmVudCkgfHwgMCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdjb2xvcic6XG4gICAgICAgIGlmIChjdXJyZW50KSB7XG4gICAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3dhdmUuc3R5bGUuYmFja2dyb3VuZCA9IGN1cnJlbnQ7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaGFzQXR0cmlidXRlKCdiYWNrZ3JvdW5kJykpIHtcbiAgICAgICAgICAgICAgdGhpcy5fYmFja2dyb3VuZC5zdHlsZS5iYWNrZ3JvdW5kID0gY3VycmVudDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnYmFja2dyb3VuZCc6XG4gICAgICAgIGlmIChjdXJyZW50IHx8IGxhc3QpIHtcbiAgICAgICAgICBpZiAoY3VycmVudCA9PT0gJ25vbmUnKSB7XG4gICAgICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgICB0aGlzLl9iYWNrZ3JvdW5kLnNldEF0dHJpYnV0ZSgnZGlzYWJsZWQnLCAnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgdGhpcy5fYmFja2dyb3VuZC5zdHlsZS5iYWNrZ3JvdW5kID0gJ3RyYW5zcGFyZW50JztcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgICAgICAgICBpZiAodGhpcy5fYmFja2dyb3VuZC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9iYWNrZ3JvdW5kLnJlbW92ZUF0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB0aGlzLl9iYWNrZ3JvdW5kLnN0eWxlLmJhY2tncm91bmQgPSBjdXJyZW50O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdjZW50ZXInOlxuICAgICAgICBpZiAobmFtZSA9PT0gJ2NlbnRlcicpIHtcbiAgICAgICAgICB0aGlzLl9jZW50ZXIgPSBjdXJyZW50ICE9IG51bGwgJiYgY3VycmVudCAhPSAnZmFsc2UnO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdXRpbC50b2dnbGVBdHRyaWJ1dGUodGhpcywgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkKCkge1xuICAgIHJldHVybiB0aGlzLmhhc0F0dHJpYnV0ZSgnZGlzYWJsZWQnKTtcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5SaXBwbGUgPSBSaXBwbGVFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcmlwcGxlJywgUmlwcGxlRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtcm93XG4gKiBAY2F0ZWdvcnkgZ3JpZFxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1SZXByZXNlbnRzIGEgcm93IGluIHRoZSBncmlkIHN5c3RlbS4gVXNlIHdpdGggYDxvbnMtY29sPmAgdG8gbGF5b3V0IGNvbXBvbmVudHMuWy9lbl1cbiAqICAgW2phXeOCsOODquODg+ODieOCt+OCueODhuODoOOBq+OBpuihjOOCkuWumue+qeOBl+OBvuOBmeOAgm9ucy1jb2zjgajjgajjgoLjgavkvb/nlKjjgZfjgIHjgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7phY3nva7jgavkvb/nlKjjgZfjgb7jgZnjgIJbL2phXVxuICogQGNvZGVwZW4gR2d1akMge3dpZGV9XG4gKiBAZ3VpZGUgZmVhdHVyZXMuaHRtbFxuICogICBbZW5dTGF5b3V0aW5nIGd1aWRlWy9lbl1cbiAqICAgW2phXeODrOOCpOOCouOCpuODiOiqv+aVtFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtY29sXG4gKiAgIFtlbl1UaGUgYDxvbnMtY29sPmAgY29tcG9uZW50IGlzIHVzZWQgYXMgY2hpbGRyZW4gb2YgYDxvbnMtcm93PmAuWy9lbl1cbiAqICAgW2phXW9ucy1jb2zjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQG5vdGVcbiAqICAgW2VuXUZvciBBbmRyb2lkIDQuMyBhbmQgZWFybGllciwgYW5kIGlPUzYgYW5kIGVhcmxpZXIsIHdoZW4gdXNpbmcgbWl4ZWQgYWxpZ25tZW50IHdpdGggb25zLXJvdyBhbmQgb25zLWNvbCwgdGhleSBtYXkgbm90IGJlIGRpc3BsYXllZCBjb3JyZWN0bHkuIFlvdSBjYW4gdXNlIG9ubHkgb25lIHZlcnRpY2FsLWFsaWduLlsvZW5dXG4gKiAgIFtqYV1BbmRyb2lkIDQuM+S7peWJjeOAgeOCguOBl+OBj+OBr2lPUyA25Lul5YmN44GuT1Pjga7loLTlkIjjgIFvbnMtcm9344Gob25zLWNvbOOCkue1hOOBv+WQiOOCj+OBm+OBpuOBneOCjOOBnuOCjOOBrm9ucy1jb2zopoHntKDjga52ZXJ0aWNhbC1hbGlnbuWxnuaAp+OBruWApOOBq+WIpeOAheOBruWApOOCkuaMh+WumuOBmeOCi+OBqOOAgeaPj+eUu+OBjOW0qeOCjOOCi+WgtOWQiOOBjOOBguOCiuOBvuOBmeOAgnZlcnRpY2FsLWFsaWdu5bGe5oCn44Gu5YCk44Gr44Gv5LiA44Gk44Gu5YCk44Gg44GR44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXJvdz5cbiAqICAgPG9ucy1jb2wgd2lkdGg9XCI1MHB4XCI+PG9ucy1pY29uIGljb249XCJmYS10d2l0dGVyXCI+PC9vbnMtaWNvbj48L29ucy1jb2w+XG4gKiAgIDxvbnMtY29sPlRleHQ8L29ucy1jb2w+XG4gKiA8L29ucy1yb3c+XG4gKi9cblxuLyoqXG4gKiBAYXR0cmlidXRlIHZlcnRpY2FsLWFsaWduXG4gKiBAdHlwZSB7U3RyaW5nfVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1TaG9ydCBoYW5kIGF0dHJpYnV0ZSBmb3IgYWxpZ25pbmcgdmVydGljYWxseS4gVmFsaWQgdmFsdWVzIGFyZSB0b3AsIGJvdHRvbSwgYW5kIGNlbnRlci5bL2VuXVxuICogICBbamFd57im44Gr5pW05YiX44GZ44KL44Gf44KB44Gr5oyH5a6a44GX44G+44GZ44CCdG9w44CBYm90dG9t44CBY2VudGVy44Gu44GE44Ga44KM44GL44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAqL1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSb3dFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xufVxuXG5vbnNFbGVtZW50cy5Sb3cgPSBSb3dFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtcm93JywgUm93RWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ3NlZ21lbnQnO1xuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ3NlZ21lbnQtLSonLFxuICAnLnNlZ21lbnRfX2l0ZW0nOiAnc2VnbWVudC0tKl9faXRlbScsXG4gICcuc2VnbWVudF9faW5wdXQnOiAnc2VnbWVudC0tKl9faW5wdXQnLFxuICAnLnNlZ21lbnRfX2J1dHRvbic6ICdzZWdtZW50LS0qX19idXR0b24nXG59O1xuXG5jb25zdCBnZW5lcmF0ZUlkID0gKCgpID0+IHtcbiAgbGV0IGkgPSAwO1xuICByZXR1cm4gKCkgPT4gJ29ucy1zZWdtZW50LWdlbi0nICsgKGkrKyk7XG59KSgpO1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1zZWdtZW50XG4gKiBAY2F0ZWdvcnkgY29udHJvbFxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgIFtlbl1NYXRlcmlhbCBEZXNpZ24gc2VnbWVudFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBTZWdtZW50IGNvbXBvbmVudC4gVXNlIHRoaXMgY29tcG9uZW50IHRvIGhhdmUgYSBidXR0b24gYmFyIHdpdGggYXV0b21hdGljIHN0eWxlcyB0aGF0IHN3aXRjaCBvbiBjbGljayBvZiBhbm90aGVyIGJ1dHRvbi5cbiAqXG4gKiAgICAgV2lsbCBhdXRvbWF0aWNhbGx5IGRpc3BsYXkgYXMgYSBNYXRlcmlhbCBEZXNpZ24gc2VnbWVudCBvbiBBbmRyb2lkLlxuICogICBbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIGhMYXl4XG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvc2VnbWVudFxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNtb2RpZmllcnMgW2VuXU1vcmUgZGV0YWlscyBhYm91dCB0aGUgYG1vZGlmaWVyYCBhdHRyaWJ1dGVbL2VuXVtqYV1tb2RpZmllcuWxnuaAp+OBruS9v+OBhOaWuVsvamFdXG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI2Nyb3NzLXBsYXRmb3JtLXN0eWxpbmctYXV0b3N0eWxpbmcgW2VuXUluZm9ybWF0aW9uIGFib3V0IGNyb3NzIHBsYXRmb3JtIHN0eWxpbmdbL2VuXVtqYV1JbmZvcm1hdGlvbiBhYm91dCBjcm9zcyBwbGF0Zm9ybSBzdHlsaW5nWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXNlZ21lbnQ+XG4gKiAgIDxvbnMtYnV0dG9uPkxhYmVsIDE8L29ucy1idXR0b24+XG4gKiAgIDxvbnMtYnV0dG9uPkxhYmVsIDI8L29ucy1idXR0b24+XG4gKiAgIDxvbnMtYnV0dG9uPkxhYmVsIDM8L29ucy1idXR0b24+XG4gKiA8L29ucy1zZWdtZW50PlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNlZ21lbnRFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGNoYW5nZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZXMgYWZ0ZXIgdGhlIGFjdGl2ZSBidXR0b24gaXMgY2hhbmdlZC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBldmVudC5pbmRleFxuICAgKiAgIFtlbl1UYXBwZWQgYnV0dG9uIGluZGV4LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudC5zZWdtZW50SXRlbVxuICAgKiAgIFtlbl1TZWdtZW50IGl0ZW0gb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGlmaWVyXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBzZWdtZW50LlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgdGFiYmFyLWlkXG4gICAqIEBpbml0b25seVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JRCBvZiB0aGUgdGFiYmFyIGVsZW1lbnQgdG8gXCJjb25uZWN0XCIgdG8gdGhlIHNlZ21lbnQuIE11c3QgYmUgaW5zaWRlIHRoZSBzYW1lIHBhZ2UuWy9lbl1cbiAgICogIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhY3RpdmUtaW5kZXhcbiAgICogQGluaXRvbmx5XG4gICAqIEBkZWZhdWx0IDBcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSW5kZXggb2YgdGhlIGZpcnN0IGFjdGl2ZSBidXR0b24sIG9ubHkgd29ya3MgaWYgdGhlcmUgaXMgbm8gY29ubmVjdGVkIHRhYmJhciAoaW4gd2hpY2ggY2FzZSB0aGUgYWN0aXZlIHRhYiBzZXRzIHRoZSBhY3RpdmUgYnV0dG9uKS5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IGlmIHNlZ21lbnQgc2hvdWxkIGJlIGRpc2FibGVkLlsvZW5dXG4gICAqICAgW2phXeODnOOCv+ODs+OCkueEoeWKueWMluOBmeOCi+WgtOWQiOOBr+aMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX3NlZ21lbnRJZCA9IGdlbmVyYXRlSWQoKTtcbiAgICB0aGlzLl90YWJiYXIgPSBudWxsO1xuICAgIHRoaXMuX29uQ2hhbmdlID0gdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vblRhYmJhclByZUNoYW5nZSA9IHRoaXMuX29uVGFiYmFyUHJlQ2hhbmdlLmJpbmQodGhpcyk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29tcGlsZSgpXG4gICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGhpcy5fbGFzdEFjdGl2ZUluZGV4ID0gdGhpcy5fdGFiYmFyID8gdGhpcy5fdGFiYmFyLmdldEFjdGl2ZVRhYkluZGV4KCkgOiB0aGlzLmdldEFjdGl2ZUJ1dHRvbkluZGV4KCkpO1xuICAgIH0pO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSB0aGlzLmNoaWxkcmVuLmxlbmd0aCAtIDE7IGluZGV4ID49IDA7IGluZGV4LS0pIHtcbiAgICAgIGNvbnN0IGl0ZW0gPSB0aGlzLmNoaWxkcmVuW2luZGV4XTtcbiAgICAgIGl0ZW0uY2xhc3NMaXN0LmFkZCgnc2VnbWVudF9faXRlbScpO1xuXG4gICAgICBjb25zdCBpbnB1dCA9IHV0aWwuZmluZENoaWxkKGl0ZW0sICcuc2VnbWVudF9faW5wdXQnKSB8fCB1dGlsLmNyZWF0ZSgnaW5wdXQuc2VnbWVudF9faW5wdXQnKTtcbiAgICAgIGlucHV0LnR5cGUgPSAncmFkaW8nO1xuICAgICAgaW5wdXQudmFsdWUgPSBpbmRleDtcbiAgICAgIGlucHV0Lm5hbWUgPSBpbnB1dC5uYW1lIHx8IHRoaXMuX3NlZ21lbnRJZDtcbiAgICAgIGlucHV0LmNoZWNrZWQgPSAhdGhpcy5oYXNBdHRyaWJ1dGUoJ3RhYmJhci1pZCcpICYmIGluZGV4ID09PSAocGFyc2VJbnQodGhpcy5nZXRBdHRyaWJ1dGUoJ2FjdGl2ZS1pbmRleCcpKSB8fCAwKTtcblxuICAgICAgY29uc3QgYnV0dG9uID0gdXRpbC5maW5kQ2hpbGQoaXRlbSwgJy5zZWdtZW50X19idXR0b24nKSB8fCB1dGlsLmNyZWF0ZSgnLnNlZ21lbnRfX2J1dHRvbicpO1xuICAgICAgaWYgKGJ1dHRvbi5wYXJlbnRFbGVtZW50ICE9PSBpdGVtKSB7XG4gICAgICAgIHdoaWxlIChpdGVtLmZpcnN0Q2hpbGQpIHtcbiAgICAgICAgICBidXR0b24uYXBwZW5kQ2hpbGQoaXRlbS5maXJzdENoaWxkKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpdGVtLmFwcGVuZENoaWxkKGlucHV0KTtcbiAgICAgIGl0ZW0uYXBwZW5kQ2hpbGQoYnV0dG9uKTtcbiAgICB9XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCd0YWJiYXItaWQnKSkge1xuICAgICAgICBjb25zdCBwYWdlID0gdXRpbC5maW5kUGFyZW50KHRoaXMsICdvbnMtcGFnZScpO1xuICAgICAgICB0aGlzLl90YWJiYXIgPSBwYWdlICYmIHBhZ2UucXVlcnlTZWxlY3RvcignIycgKyB0aGlzLmdldEF0dHJpYnV0ZSgndGFiYmFyLWlkJykpO1xuICAgICAgICBpZiAoIXRoaXMuX3RhYmJhciB8fCB0aGlzLl90YWJiYXIudGFnTmFtZSAhPT0gJ09OUy1UQUJCQVInKSB7XG4gICAgICAgICAgdXRpbC50aHJvdyhgTm8gdGFiYmFyIHdpdGggaWQgJHt0aGlzLmdldEF0dHJpYnV0ZSgndGFiYmFyLWlkJyl9IHdhcyBmb3VuZC5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3RhYmJhci5zZXRBdHRyaWJ1dGUoJ2hpZGUtdGFicycsICcnKTtcbiAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHRoaXMuX3NldENoZWNrZWQodGhpcy5fdGFiYmFyLmdldEFjdGl2ZVRhYkluZGV4KCkpKTtcblxuICAgICAgICB0aGlzLl90YWJiYXIuYWRkRXZlbnRMaXN0ZW5lcigncHJlY2hhbmdlJywgdGhpcy5fb25UYWJiYXJQcmVDaGFuZ2UpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCB0aGlzLl9vbkNoYW5nZSk7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuX3RhYmJhcikge1xuICAgICAgICB0aGlzLl90YWJiYXIucmVtb3ZlRXZlbnRMaXN0ZW5lcigncHJlY2hhbmdlJywgdGhpcy5fb25UYWJiYXJQcmVDaGFuZ2UpO1xuICAgICAgICB0aGlzLl90YWJiYXIgPSBudWxsO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgdGhpcy5fb25DaGFuZ2UpO1xuICB9XG5cbiAgX3NldENoZWNrZWQoaW5kZXgpIHtcbiAgICB0aGlzLmNoaWxkcmVuW2luZGV4XS5maXJzdEVsZW1lbnRDaGlsZC5jaGVja2VkID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNldEFjdGl2ZUJ1dHRvblxuICAgKiBAc2lnbmF0dXJlIHNldEFjdGl2ZUJ1dHRvbihpbmRleCwgW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge051bWJlcn0gaW5kZXhcbiAgICogICBbZW5dQnV0dG9uIGluZGV4LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdCwgd29ya3Mgb25seSBpZiB0aGVyZSBpcyBhIGNvbm5lY3RlZCB0YWJiYXIuIFN1cHBvcnRzIHRoZSBzYW1lIG9wdGlvbnMgYXMgYG9ucy10YWJiYXJgJ3MgYHNldEFjdGl2ZVRhYmAgbWV0aG9kLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1NYWtlIGJ1dHRvbiB3aXRoIHRoZSBzcGVjaWZpZWQgaW5kZXggYWN0aXZlLiBJZiB0aGVyZSBpcyBhIGNvbm5lY3RlZCB0YWJiYXIgaXQgc2hvd3MgdGhlIGNvcnJlc3BvbmRpbmcgdGFiIHBhZ2UuIEluIHRoaXMgY2FzZSBhbmltYXRpb25zIGFuZCB0aGVpciBvcHRpb25zIGNhbiBiZSBzcGVjaWZpZWQgYnkgdGhlIHNlY29uZCBwYXJhbWV0ZXIuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIHNlbGVjdGVkIGluZGV4IG9yIHRvIHRoZSBuZXcgcGFnZSBlbGVtZW50IGlmIHRoZXJlIGlzIGEgY29ubmVjdGVkIHRhYmJhci5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgc2V0QWN0aXZlQnV0dG9uKGluZGV4LCBvcHRpb25zKSB7XG4gICAgaWYgKHRoaXMuX3RhYmJhcikge1xuICAgICAgcmV0dXJuIHRoaXMuX3RhYmJhci5zZXRBY3RpdmVUYWIoaW5kZXgsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIHRoaXMuX3NldENoZWNrZWQoaW5kZXgpO1xuICAgIHRoaXMuX3Bvc3RDaGFuZ2UoaW5kZXgpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoaW5kZXgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgZ2V0QWN0aXZlQnV0dG9uSW5kZXhcbiAgICogQHNpZ25hdHVyZSBnZXRBY3RpdmVCdXR0b25JbmRleCgpXG4gICAqIEByZXR1cm4ge051bWJlcn1cbiAgICogICBbZW5dVGhlIGluZGV4IG9mIHRoZSBjdXJyZW50bHkgYWN0aXZlIGJ1dHRvbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyBidXR0b24gaW5kZXggb2YgY3VycmVudCBhY3RpdmUgYnV0dG9uLiBJZiBhY3RpdmUgYnV0dG9uIGlzIG5vdCBmb3VuZCwgcmV0dXJucyAtMS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0QWN0aXZlQnV0dG9uSW5kZXgoKSB7XG4gICAgZm9yIChsZXQgaSA9IHRoaXMuY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHsgLy8gQXJyYXkuZmluZEluZGV4XG4gICAgICBpZiAodGhpcy5jaGlsZHJlbltpXS5maXJzdEVsZW1lbnRDaGlsZC5jaGVja2VkKSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICBfb25DaGFuZ2UoZXZlbnQpIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLl90YWJiYXJcbiAgICAgID8gdGhpcy5fdGFiYmFyLnNldEFjdGl2ZVRhYih0aGlzLmdldEFjdGl2ZUJ1dHRvbkluZGV4KCksIHsgcmVqZWN0OiBmYWxzZSB9KVxuICAgICAgOiB0aGlzLl9wb3N0Q2hhbmdlKHRoaXMuZ2V0QWN0aXZlQnV0dG9uSW5kZXgoKSk7XG4gIH1cblxuICBfb25UYWJiYXJQcmVDaGFuZ2UoZXZlbnQpIHtcbiAgICBzZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgaWYgKCFldmVudC5kZXRhaWwuY2FuY2VsZWQpIHtcbiAgICAgICAgdGhpcy5fc2V0Q2hlY2tlZChldmVudC5pbmRleCk7XG4gICAgICAgIHRoaXMuX3Bvc3RDaGFuZ2UoZXZlbnQuaW5kZXgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgX3Bvc3RDaGFuZ2UoaW5kZXgpIHtcbiAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ3Bvc3RjaGFuZ2UnLCB7XG4gICAgICBpbmRleCxcbiAgICAgIGFjdGl2ZUluZGV4OiBpbmRleCxcbiAgICAgIGxhc3RBY3RpdmVJbmRleDogdGhpcy5fbGFzdEFjdGl2ZUluZGV4LFxuICAgICAgc2VnbWVudEl0ZW06IHRoaXMuY2hpbGRyZW5baW5kZXhdXG4gICAgfSk7XG4gICAgdGhpcy5fbGFzdEFjdGl2ZUluZGV4ID0gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgc2VnbWVudCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIHNldCBkaXNhYmxlZCh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnZGlzYWJsZWQnLCB2YWx1ZSk7XG4gIH1cblxuICBnZXQgZGlzYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnY2xhc3MnLCAnbW9kaWZpZXInXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGdldCBldmVudHMoKSB7XG4gICAgcmV0dXJuIFsncG9zdGNoYW5nZSddO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlNlZ21lbnQgPSBTZWdtZW50RWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXNlZ21lbnQnLCBTZWdtZW50RWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcnOiAnc2VsZWN0LSogc2VsZWN0LS0qJyxcbiAgJy5zZWxlY3QtaW5wdXQnOiAnc2VsZWN0LWlucHV0LS0qJ1xufTtcblxuY29uc3QgZGVmYXVsdENsYXNzTmFtZSA9ICdzZWxlY3QnO1xuXG5jb25zdCBJTlBVVF9BVFRSSUJVVEVTID0gW1xuICAnYXV0b2ZvY3VzJyxcbiAgJ2Rpc2FibGVkJyxcbiAgJ2Zvcm0nLFxuICAnbXVsdGlwbGUnLFxuICAnbmFtZScsXG4gICdyZXF1aXJlZCcsXG4gICdzaXplJ1xuXTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc2VsZWN0XG4gKiBAY2F0ZWdvcnkgZm9ybVxuICogQG1vZGlmaWVyIG1hdGVyaWFsXG4gKiAgW2VuXURpc3BsYXlzIGEgTWF0ZXJpYWwgRGVzaWduIHNlbGVjdCBpbnB1dC5bL2VuXVxuICogIFtqYV1bL2phXVxuICogQG1vZGlmaWVyIHVuZGVyYmFyXG4gKiAgW2VuXURpc3BsYXlzIGEgaG9yaXpvbnRhbCBsaW5lIHVuZGVybmVhdGggYSBzZWxlY3QgaW5wdXQuWy9lbl1cbiAqICBbamFdWy9qYV1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgU2VsZWN0IGNvbXBvbmVudC4gSWYgeW91IHdhbnQgdG8gcGxhY2UgYSBzZWxlY3Qgd2l0aCBhbiBJRCBvZiBgbXktaWRgIG9uIGEgcGFnZSwgdXNlIGA8b25zLXNlbGVjdCBzZWxlY3QtaWQ9XCJteS1pZFwiPmAuXG4gKlxuICogICAgIFRoZSBjb21wb25lbnQgd2lsbCBhdXRvbWF0aWNhbGx5IGRpc3BsYXkgYXMgYSBNYXRlcmlhbCBEZXNpZ24gc2VsZWN0IG9uIEFuZHJvaWQuXG4gKlxuICogICAgIE1vc3QgYXR0cmlidXRlcyB0aGF0IGNhbiBiZSB1c2VkIGZvciBhIG5vcm1hbCBgPHNlbGVjdD5gIGVsZW1lbnQgY2FuIGFsc28gYmUgdXNlZCBvbiB0aGUgYDxvbnMtc2VsZWN0PmAgZWxlbWVudC5cbiAqICAgWy9lbl1cbiAqICAgW2phXeOCu+ODrOOCr+ODiOODnOODg+OCr+OCueOCkuihqOekuuOBmeOCi+OCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAgmBzZWxlY3RgIOimgee0oOOBq+S9v+eUqOOBp+OBjeOCi+WxnuaAp+OBruWkmuOBj+OBjCBgb25zLXNlbGVjdGAg6KaB57Sg44Gn44KC5Yip55So44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIGhMYXl4XG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvc2VsZWN0XG4gKiBAZ3VpZGUgdGhlbWluZy5odG1sI21vZGlmaWVycyBbZW5dTW9yZSBkZXRhaWxzIGFib3V0IHRoZSBgbW9kaWZpZXJgIGF0dHJpYnV0ZVsvZW5dW2phXW1vZGlmaWVy5bGe5oCn44Gu5L2/44GE5pa5Wy9qYV1cbiAqIEBndWlkZSB0aGVtaW5nLmh0bWwjY3Jvc3MtcGxhdGZvcm0tc3R5bGluZy1hdXRvc3R5bGluZyBbZW5dSW5mb3JtYXRpb24gYWJvdXQgY3Jvc3MgcGxhdGZvcm0gc3R5bGluZ1svZW5dW2phXUluZm9ybWF0aW9uIGFib3V0IGNyb3NzIHBsYXRmb3JtIHN0eWxpbmdbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtc2VsZWN0PlxuICogICA8b3B0aW9uIHZhbHVlPVwiMVwiPjE8L29wdGlvbj5cbiAqICAgPG9wdGlvbiB2YWx1ZT1cIjJcIj4ybmQ8L29wdGlvbj5cbiAqICAgPG9wdGlvbiB2YWx1ZT1cIjNcIj4zcmQgb3B0aW9uPC9vcHRpb24+XG4gKiA8L29ucy1zZWxlY3Q+XG4gKi9cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2VsZWN0RWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhdXRvZm9jdXNcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXUVsZW1lbnQgYXV0b21hdGljYWxseSBnYWlucyBmb2N1cyBvbiBwYWdlIGxvYWQuWy9lbl1cbiAgICogIFtqYV3jg5rjg7zjgrjjg63jg7zjg4nmmYLjgavjgZPjga7jgrvjg6zjgq/jg4jjg5zjg4Pjgq/jgrnjgavjg5Xjgqnjg7zjgqvjgrnjgYznp7vjgovjgojjgYbjgavjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgc2VsZWN0IGlucHV0IHNob3VsZCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jgrvjg6zjgq/jg4jjg5zjg4Pjgq/jgrnjgpLnhKHlirnljJbjgZnjgovloLTlkIjjgavmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBmb3JtXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Bc3NvY2lhdGUgYSBzZWxlY3QgZWxlbWVudCB0byBhbiBleGlzdGluZyBmb3JtIG9uIHRoZSBwYWdlLCBldmVuIGlmIG5vdCBuZXN0ZWQuWy9lbl1cbiAgICogICBbamFd44GT44Gu44K744Os44Kv44OI44Oc44OD44Kv44K544KS44CB5oyH5a6a44GX44GfIGBmb3JtYCDopoHntKDjgavntJDku5jjgZHjgb7jgZnjgILjgrvjg6zjgq/jg4jjg5zjg4Pjgq/jgrnjgpIgYGZvcm1gIOimgee0oOOBruWkluWBtOOBq+mFjee9ruOBmeOCi+mam+OBq+S9v+eUqOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG11bHRpcGxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBkZWZpbmVkLCBtdWx0aXBsZSBvcHRpb25zIGNhbiBiZSBzZWxlY3RlZCBhdCBvbmNlLlsvZW5dXG4gICAqICBbamFd6YG45oqe6IKi44Gu6KSH5pWw6YG45oqe44KS5pyJ5Yq544Gr44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbmFtZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dTmFtZSB0aGUgc2VsZWN0IGVsZW1lbnQsIHVzZWZ1bCBmb3IgaW5zdGFuY2UgaWYgaXQgaXMgcGFydCBvZiBhIGZvcm0uWy9lbl1cbiAgICogICBbamFd44GT44Gu44K744Os44Kv44OI44Oc44OD44Kv44K544Gu5ZCN5YmN44KS5oyH5a6a44GX44G+44GZ44CC6YCa5bi4IGBmb3JtYCDopoHntKDjgajlhbHjgavkvb/nlKjjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSByZXF1aXJlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXU1ha2UgdGhlIHNlbGVjdCBpbnB1dCByZXF1aXJlZCBmb3Igc3VibWl0dGluZyB0aGUgZm9ybSBpdCBpcyBwYXJ0IG9mLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruOCu+ODrOOCr+ODiOODnOODg+OCr+OCueOCkuWFpeWKm+W/hemgiOOBq+OBmeOCi+WgtOWQiOOBq+aMh+WumuOBl+OBvuOBmeOAgumAmuW4uCBgZm9ybWAg6KaB57Sg44Go5YWx44Gr5L2/55So44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc2VsZWN0LWlkXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JRCBnaXZlbiB0byB0aGUgaW5uZXIgc2VsZWN0LCB1c2VmdWwgZm9yIGR5bmFtaWMgbWFuaXB1bGF0aW9uLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruOCu+ODrOOCr+ODiOODnOODg+OCr+OCueOBjOWGhemDqOOBq+aMgeOBpCBzZWxlY3Qg6KaB57Sg44Gr5LiO44GI44KLIElEIOOCkuaMh+WumuOBl+OBvuOBmeOAguOCu+ODrOOCr+ODiOODnOODg+OCr+OCueOBruWGheWuueOCkuWLleeahOOBq+WkieabtOOBmeOCi+W/heimgeOBjOOBguOCi+WgtOWQiOOBq+S9v+eUqOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHNpemVcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgMVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSG93IG1hbnkgb3B0aW9ucyBhcmUgZGlzcGxheWVkOyBpZiB0aGVyZSBhcmUgbW9yZSB0aGFuIHRoZSBzaXplIHRoZW4gYSBzY3JvbGwgYXBwZWFycyB0byBuYXZpZ2F0ZSB0aGVtLlsvZW5dXG4gICAqICAgW2phXeS4gOW6puOBq+ihqOekuuOBmeOCi+mBuOaKnuiCouOBruWAi+aVsOOCkuaMh+WumuOBl+OBvuOBmeOAgumBuOaKnuiCouOBjOOBk+OBruWxnuaAp+OBp+aMh+WumuOBl+OBn+WAi+aVsOOCiOOCiuOCguWkmuOBhOWgtOWQiOOAgeOCueOCr+ODreODvOODq+OBjOacieWKueOBq+OBquOCiuOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fY29tcGlsZSgpKTtcblxuICAgIHRoaXMuX2Rlcml2ZUdldHRlcnMoKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ2NsYXNzJywgLi4uSU5QVVRfQVRUUklCVVRFU107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICB1dGlsLnJlc3RvcmVDbGFzcyh0aGlzLCBkZWZhdWx0Q2xhc3NOYW1lLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21vZGlmaWVyJzpcbiAgICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGlmIChJTlBVVF9BVFRSSUJVVEVTLmluZGV4T2YobmFtZSkgPj0gMCkge1xuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3VwZGF0ZUJvdW5kQXR0cmlidXRlcygpKTtcbiAgICB9XG4gIH1cblxuICBnZXQgX3NlbGVjdCgpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKCdzZWxlY3QnKTtcbiAgfVxuXG4gIF91cGRhdGVCb3VuZEF0dHJpYnV0ZXMoKSB7XG4gICAgSU5QVVRfQVRUUklCVVRFUy5mb3JFYWNoKChhdHRyKSA9PiB7XG4gICAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoYXR0cikpIHtcbiAgICAgICAgdGhpcy5fc2VsZWN0LnNldEF0dHJpYnV0ZShhdHRyLCB0aGlzLmdldEF0dHJpYnV0ZShhdHRyKSk7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5fc2VsZWN0LnJlbW92ZUF0dHJpYnV0ZShhdHRyKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgbGVuZ3RoXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1OdW1iZXIgb2Ygb3B0aW9ucyBpbiB0aGUgc2VsZWN0IGJveC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jgrvjg6zjgq/jg4jjg5zjg4Pjgq/jgrnjgavlkKvjgb7jgozjgovpgbjmip7ogqLjga7lgIvmlbDjgpLov5TjgZfjgb7jgZnjgIIgYHNlbGVjdGAg6KaB57SgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvcHRpb25zXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TZXZlcmFsIG9wdGlvbnMgZm9yIGhhbmRsaW5nIHRoZSBzZWxlY3QgRE9NIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jgrvjg6zjgq/jg4jjg5zjg4Pjgq/jgrnjgavlkKvjgb7jgozjgosgYG9wdGlvbmAg6KaB57Sg44Gu6YWN5YiX44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBzZWxlY3RlZEluZGV4XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JbmRleCBvZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIG9wdGlvbi5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjpgbjmip7jgZXjgozjgabjgYTjgovpgbjmip7ogqLjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1WYWx1ZSBvZiB0aGUgY3VycmVudGx5IHNlbGVjdGVkIG9wdGlvbi5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjpgbjmip7jgZXjgozjgabjgYTjgovpgbjmip7ogqLjga7lgKTjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG5cbiAgICB0aGlzLmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgY29uc3Qgc2VsID0gdGhpcy5fc2VsZWN0IHx8IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NlbGVjdCcpO1xuICAgIGlmICghc2VsLmlkICYmIHRoaXMuaGFzQXR0cmlidXRlKCdzZWxlY3QtaWQnKSkge1xuICAgICAgc2VsLmlkID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3NlbGVjdC1pZCcpO1xuICAgIH1cbiAgICBzZWwuY2xhc3NMaXN0LmFkZCgnc2VsZWN0LWlucHV0Jyk7XG4gICAgaWYgKCF0aGlzLl9zZWxlY3QpIHtcbiAgICAgIHV0aWwuYXJyYXlGcm9tKHRoaXMuY2hpbGROb2RlcykuZm9yRWFjaChlbGVtZW50ID0+IHNlbC5hcHBlbmRDaGlsZChlbGVtZW50KSk7XG4gICAgICB0aGlzLmFwcGVuZENoaWxkKHNlbCk7XG4gICAgfVxuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgX2Rlcml2ZUdldHRlcnMoKSB7XG4gICAgWydkaXNhYmxlZCcsICdsZW5ndGgnLCAnbXVsdGlwbGUnLCAnbmFtZScsICdvcHRpb25zJywgJ3NlbGVjdGVkSW5kZXgnLCAnc2l6ZScsICd2YWx1ZScsICdmb3JtJywgJ3R5cGUnXVxuICAgICAgLmZvckVhY2goa2V5ID0+IHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIGtleSwge1xuICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgIGdldDogKCkgPT4gdGhpcy5fc2VsZWN0W2tleV0sXG4gICAgICAgICAgc2V0OiBbJ2Zvcm0nLCAndHlwZSddLmluZGV4T2Yoa2V5KSA9PT0gLTFcbiAgICAgICAgICAgID8gdmFsdWUgPT4gY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3NlbGVjdFtrZXldID0gdmFsdWUpXG4gICAgICAgICAgICA6IHVuZGVmaW5lZFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgYWRkKG9wdGlvbiwgaW5kZXggPSBudWxsKSB7XG4gICAgdGhpcy5fc2VsZWN0LmFkZChvcHRpb24sIGluZGV4KTtcbiAgfVxuXG4gIHJlbW92ZShpbmRleCkge1xuICAgIHRoaXMuX3NlbGVjdC5yZW1vdmUoaW5kZXgpO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlNlbGVjdCA9IFNlbGVjdEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1zZWxlY3QnLCBTZWxlY3RFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBhdXRvU3R5bGUgZnJvbSAnLi4vb25zL2F1dG9zdHlsZSc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcblxuY29uc3QgZGVmYXVsdENsYXNzTmFtZSA9ICdmYWIgZmFiLS1taW5pIHNwZWVkLWRpYWxfX2l0ZW0nO1xuXG5jb25zdCBzY2hlbWUgPSB7XG4gICcnOiAnZmFiLS0qIHNwZWVkLWRpYWxfX2l0ZW0tLSonXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy1zcGVlZC1kaWFsLWl0ZW1cbiAqIEBjYXRlZ29yeSBjb250cm9sXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVxuICogICAgIFRoaXMgY29tcG9uZW50IGRpc3BsYXlzIHRoZSBjaGlsZCBlbGVtZW50cyBvZiB0aGUgTWF0ZXJpYWwgRGVzaWduIFNwZWVkIGRpYWwgY29tcG9uZW50LlxuICogICBbL2VuXVxuICogICBbamFdXG4gKiAgICAgTWF0ZXJpYWwgRGVzaWdu44GuU3BlZWQgZGlhbOOBruWtkOimgee0oOOCkuihqOePvuOBmeOCi+imgee0oOOBp+OBmeOAglxuICogICBbL2phXVxuICogQGNvZGVwZW4gZFlRWUxnXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvc3BlZWQtZGlhbFxuICogQHNlZWFsc28gb25zLXNwZWVkLWRpYWxcbiAqICAgW2VuXVRoZSBgPG9ucy1zcGVlZC1kaWFsPmAgY29tcG9uZW50LlsvZW5dXG4gKiAgIFtqYV1vbnMtc3BlZWQtZGlhbOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtZmFiXG4gKiAgIFtlbl1vbnMtZmFiIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtZmFi44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXNwZWVkLWRpYWwgcG9zaXRpb249XCJsZWZ0IGJvdHRvbVwiPlxuICogICA8b25zLWZhYj5cbiAqICAgICA8b25zLWljb24gaWNvbj1cImZhLXR3aXR0ZXJcIj48L29ucy1pY29uPlxuICogICA8L29ucy1mYWI+XG4gKiAgIDxvbnMtc3BlZWQtZGlhbC1pdGVtPkE8L29ucy1zcGVlZC1kaWFsLWl0ZW0+XG4gKiAgIDxvbnMtc3BlZWQtZGlhbC1pdGVtPkI8L29ucy1zcGVlZC1kaWFsLWl0ZW0+XG4gKiAgIDxvbnMtc3BlZWQtZGlhbC1pdGVtPkM8L29ucy1zcGVlZC1kaWFsLWl0ZW0+XG4gKiA8L29ucy1zcGVlZC1kaWFsPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGVlZERpYWxJdGVtRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGNvbXBvbmVudC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSByaXBwbGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgZGVmaW5lZCwgdGhlIGJ1dHRvbiB3aWxsIGhhdmUgYSByaXBwbGUgZWZmZWN0IHdoZW4gdGFwcGVkLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB0aGlzLl9ib3VuZE9uQ2xpY2sgPSB0aGlzLl9vbkNsaWNrLmJpbmQodGhpcyk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydtb2RpZmllcicsICdyaXBwbGUnLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgICAgdXRpbC5hZGRNb2RpZmllcih0aGlzLCAnbWluaScpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3JpcHBsZSc6XG4gICAgICAgIHRoaXMuX3VwZGF0ZVJpcHBsZSgpO1xuICAgIH1cbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9ib3VuZE9uQ2xpY2ssIGZhbHNlKTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9ib3VuZE9uQ2xpY2ssIGZhbHNlKTtcbiAgfVxuXG4gIF91cGRhdGVSaXBwbGUoKSB7XG4gICAgdXRpbC51cGRhdGVSaXBwbGUodGhpcyk7XG4gIH1cblxuICBfb25DbGljayhlKSB7XG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuXG4gICAgZGVmYXVsdENsYXNzTmFtZS5zcGxpdCgvXFxzKy8pLmZvckVhY2godG9rZW4gPT4gdGhpcy5jbGFzc0xpc3QuYWRkKHRva2VuKSk7XG5cbiAgICB1dGlsLmFkZE1vZGlmaWVyKHRoaXMsICdtaW5pJyk7XG4gICAgdGhpcy5fdXBkYXRlUmlwcGxlKCk7XG5cbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG4gIH1cbn1cblxub25zRWxlbWVudHMuU3BlZWREaWFsSXRlbSA9IFNwZWVkRGlhbEl0ZW1FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc3BlZWQtZGlhbC1pdGVtJywgU3BlZWREaWFsSXRlbUVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgc3R5bGVyIGZyb20gJy4uL29ucy9zdHlsZXInO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ3NwZWVkLWRpYWwnO1xuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ3NwZWVkLWRpYWwtLSonLFxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc3BlZWQtZGlhbFxuICogQGNhdGVnb3J5IGNvbnRyb2xcbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgRWxlbWVudCB0aGF0IGRpc3BsYXlzIGEgTWF0ZXJpYWwgRGVzaWduIFNwZWVkIERpYWxvZyBjb21wb25lbnQuIEl0IGlzIHVzZWZ1bCB3aGVuIHRoZXJlIGFyZSBtb3JlIHRoYW4gb25lIHByaW1hcnkgYWN0aW9uIHRoYXQgY2FuIGJlIHBlcmZvcm1lZCBpbiBhIHBhZ2UuXG4gKlxuICogICAgIFRoZSBTcGVlZCBkaWFsIGxvb2tzIGxpa2UgYSBgPG9ucy1mYWI+YCBlbGVtZW50IGJ1dCB3aWxsIGV4cGFuZCBhIG1lbnUgd2hlbiB0YXBwZWQuXG4gKiAgIFsvZW5dXG4gKiAgIFtqYV1bL2phXVxuICogQGNvZGVwZW4gZFlRWUxnXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2Uvc3BlZWQtZGlhbFxuICogQHNlZWFsc28gb25zLXNwZWVkLWRpYWwtaXRlbVxuICogICBbZW5dVGhlIGA8b25zLXNwZWVkLWRpYWwtaXRlbT5gIHJlcHJlc2VudHMgYSBtZW51IGl0ZW0uWy9lbl1cbiAqICAgW2phXW9ucy1zcGVlZC1kaWFsLWl0ZW3jgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLWZhYlxuICogICBbZW5db25zLWZhYiBjb21wb25lbnRbL2VuXVxuICogICBbamFdb25zLWZhYuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zcGVlZC1kaWFsIHBvc2l0aW9uPVwibGVmdCBib3R0b21cIj5cbiAqICAgPG9ucy1mYWI+XG4gKiAgICAgPG9ucy1pY29uIGljb249XCJmYS10d2l0dGVyXCI+PC9vbnMtaWNvbj5cbiAqICAgPC9vbnMtZmFiPlxuICogICA8b25zLXNwZWVkLWRpYWwtaXRlbT5BPC9vbnMtc3BlZWQtZGlhbC1pdGVtPlxuICogICA8b25zLXNwZWVkLWRpYWwtaXRlbT5CPC9vbnMtc3BlZWQtZGlhbC1pdGVtPlxuICogICA8b25zLXNwZWVkLWRpYWwtaXRlbT5DPC9vbnMtc3BlZWQtZGlhbC1pdGVtPlxuICogPC9vbnMtc3BlZWQtZGlhbD5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU3BlZWREaWFsRWxlbWVudCBleHRlbmRzIEJhc2VFbGVtZW50IHtcblxuICAvKipcbiAgICogQGV2ZW50IG9wZW5cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIG1lbnUgaXRlbXMgYXJlIHNob3duLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgY2xvc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIG1lbnUgaXRlbXMgYXJlIGhpZGRlbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBtb2RpZmllclxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIGNvbXBvbmVudC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7ooajnj77jgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSByaXBwbGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgZGVmaW5lZCwgdGhlIGJ1dHRvbiB3aWxsIGhhdmUgYSByaXBwbGUgZWZmZWN0IHdoZW4gdGFwcGVkLlsvZW5dXG4gICAqICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgcG9zaXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgU3BlY2lmeSB0aGUgdmVydGljYWwgYW5kIGhvcml6b250YWwgcG9zaXRpb24gb2YgdGhlIGNvbXBvbmVudC5cbiAgICogICAgIEkuZS4gdG8gZGlzcGxheSBpdCBpbiB0aGUgdG9wIHJpZ2h0IGNvcm5lciBzcGVjaWZ5IFwicmlnaHQgdG9wXCIuXG4gICAqICAgICBDaG9vc2UgZnJvbSBcInJpZ2h0XCIsIFwibGVmdFwiLCBcInRvcFwiIGFuZCBcImJvdHRvbVwiLlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXVxuICAgKiAgICAg44GT44Gu6KaB57Sg44KS6KGo56S644GZ44KL5bem5Y+z44Go5LiK5LiL44Gu5L2N572u44KS5oyH5a6a44GX44G+44GZ44CCXG4gICAqICAgICDkvovjgYjjgbDjgIHlj7PkuIrjgavooajnpLrjgZnjgovloLTlkIjjgavjga9cInJpZ2h0IHRvcFwi44KS5oyH5a6a44GX44G+44GZ44CCXG4gICAqICAgICDlt6blj7PjgajkuIrkuIvjga7kvY3nva7jga7mjIflrprjgavjga/jgIFyaWdodOOBqGxlZnTjgIF0b3Djgahib3R0b23jgYzjgZ3jgozjgZ7jgozmjIflrprjgafjgY3jgb7jgZnjgIJcbiAgICogICBbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBkaXJlY3Rpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGRpcmVjdGlvbiB0aGUgaXRlbXMgYXJlIGRpc3BsYXllZC4gUG9zc2libGUgdmFsdWVzIGFyZSBcInVwXCIsIFwiZG93blwiLCBcImxlZnRcIiBhbmQgXCJyaWdodFwiLlsvZW5dXG4gICAqICAgW2phXVxuICAgKiAgICAg6KaB57Sg44GM6KGo56S644GZ44KL5pa55ZCR44KS5oyH5a6a44GX44G+44GZ44CCdXAsIGRvd24sIGxlZnQsIHJpZ2h044GM5oyH5a6a44Gn44GN44G+44GZ44CCXG4gICAqICAgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgYnV0dG9uIHNob3VsZCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3nhKHlirnljJbjgZnjgovloLTlkIjjgavmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX2l0ZW1TaG93biA9IGZhbHNlO1xuICAgIHRoaXMuX2JvdW5kT25DbGljayA9IHRoaXMuX29uQ2xpY2suYmluZCh0aGlzKTtcbiAgfVxuXG4gIF9jb21waWxlKCkge1xuICAgIHRoaXMuY2xhc3NMaXN0LmFkZChkZWZhdWx0Q2xhc3NOYW1lKTtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcbiAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcbiAgICBNb2RpZmllclV0aWwuaW5pdE1vZGlmaWVyKHRoaXMsIHNjaGVtZSk7XG5cbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ2RpcmVjdGlvbicpKSB7XG4gICAgICB0aGlzLl91cGRhdGVEaXJlY3Rpb24odGhpcy5nZXRBdHRyaWJ1dGUoJ2RpcmVjdGlvbicpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fdXBkYXRlRGlyZWN0aW9uKCd1cCcpO1xuICAgIH1cblxuICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydjbGFzcycsICdtb2RpZmllcicsICdyaXBwbGUnLCAnZGlyZWN0aW9uJywgJ3Bvc2l0aW9uJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnY2xhc3MnOlxuICAgICAgICB1dGlsLnJlc3RvcmVDbGFzcyh0aGlzLCBkZWZhdWx0Q2xhc3NOYW1lLCBzY2hlbWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21vZGlmaWVyJzpcbiAgICAgICAgTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncmlwcGxlJzpcbiAgICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX3VwZGF0ZVJpcHBsZSgpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdkaXJlY3Rpb24nOlxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gdGhpcy5fdXBkYXRlRGlyZWN0aW9uKGN1cnJlbnQpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdwb3NpdGlvbic6XG4gICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVQb3NpdGlvbigpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljaywgZmFsc2UpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljaywgZmFsc2UpO1xuICB9XG5cbiAgZ2V0IGl0ZW1zKCkge1xuICAgIHJldHVybiB1dGlsLmFycmF5RnJvbSh0aGlzLnF1ZXJ5U2VsZWN0b3JBbGwoJ29ucy1zcGVlZC1kaWFsLWl0ZW0nKSk7XG4gIH1cblxuICBnZXQgX2ZhYigpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJ29ucy1mYWInKTtcbiAgfVxuXG4gIF9vbkNsaWNrKGUpIHtcbiAgICBpZiAodGhpcy5vbkNsaWNrKSB7XG4gICAgICB0aGlzLm9uQ2xpY2suYXBwbHkodGhpcyk7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfSBlbHNlIGlmICghdGhpcy5kaXNhYmxlZCAmJiB0aGlzLnZpc2libGUpIHtcbiAgICAgIHJldHVybiB0aGlzLnRvZ2dsZUl0ZW1zKCk7XG4gICAgfVxuICB9XG5cbiAgX3Nob3coKSB7XG4gICAgaWYgKCF0aGlzLmlubGluZSkge1xuICAgICAgcmV0dXJuIHRoaXMuc2hvdygpO1xuICAgIH1cbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICBfaGlkZSgpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBpZiAoIXRoaXMuaW5saW5lKSB7XG4gICAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB0aGlzLmhpZGUoKS50aGVuKHJlc29sdmUpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgX3VwZGF0ZVJpcHBsZSgpIHtcbiAgICBpZiAodGhpcy5fZmFiKSB7XG4gICAgICB0aGlzLmhhc0F0dHJpYnV0ZSgncmlwcGxlJykgPyB0aGlzLl9mYWIuc2V0QXR0cmlidXRlKCdyaXBwbGUnLCAnJykgOiB0aGlzLl9mYWIucmVtb3ZlQXR0cmlidXRlKCdyaXBwbGUnKTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlRGlyZWN0aW9uKGRpcmVjdGlvbikge1xuICAgIGNvbnN0IGNoaWxkcmVuID0gdGhpcy5pdGVtcztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICBzdHlsZXIoY2hpbGRyZW5baV0sIHtcbiAgICAgICAgdHJhbnNpdGlvbkRlbGF5OiAyNSAqIGkgKyAnbXMnLFxuICAgICAgICBib3R0b206ICdhdXRvJyxcbiAgICAgICAgcmlnaHQ6ICdhdXRvJyxcbiAgICAgICAgdG9wOiAnYXV0bycsXG4gICAgICAgIGxlZnQ6ICdhdXRvJ1xuICAgICAgfSk7XG4gICAgfVxuICAgIHN3aXRjaCAoZGlyZWN0aW9uKSB7XG4gICAgICBjYXNlICd1cCc6XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBjaGlsZHJlbltpXS5zdHlsZS5ib3R0b20gPSA3MiArIDU2ICogaSArICdweCc7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUucmlnaHQgPSAnOHB4JztcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2Rvd24nOlxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUudG9wID0gNzIgKyA1NiAqIGkgKyAncHgnO1xuICAgICAgICAgIGNoaWxkcmVuW2ldLnN0eWxlLmxlZnQgPSAnOHB4JztcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2xlZnQnOlxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUudG9wID0gJzhweCc7XG4gICAgICAgICAgY2hpbGRyZW5baV0uc3R5bGUucmlnaHQgPSA3MiArIDU2ICogaSArICdweCc7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdyaWdodCc6XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBjaGlsZHJlbltpXS5zdHlsZS50b3AgPSAnOHB4JztcbiAgICAgICAgICBjaGlsZHJlbltpXS5zdHlsZS5sZWZ0ID0gNzIgKyA1NiAqIGkgKyAncHgnO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdXRpbC50aHJvdygnQXJndW1lbnQgbXVzdCBiZSBvbmUgb2YgdXAsIGRvd24sIGxlZnQgb3IgcmlnaHQuJyk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZVBvc2l0aW9uKCkge1xuICAgIGNvbnN0IHBvc2l0aW9uID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3Bvc2l0aW9uJyk7XG4gICAgdGhpcy5jbGFzc0xpc3QucmVtb3ZlKFxuICAgICAgJ2ZhYi0tdG9wX19sZWZ0JyxcbiAgICAgICdmYWItLWJvdHRvbV9fcmlnaHQnLFxuICAgICAgJ2ZhYi0tYm90dG9tX19sZWZ0JyxcbiAgICAgICdmYWItLXRvcF9fcmlnaHQnLFxuICAgICAgJ2ZhYi0tdG9wX19jZW50ZXInLFxuICAgICAgJ2ZhYi0tYm90dG9tX19jZW50ZXInKTtcbiAgICBzd2l0Y2ggKHBvc2l0aW9uKSB7XG4gICAgICBjYXNlICd0b3AgcmlnaHQnOlxuICAgICAgY2FzZSAncmlnaHQgdG9wJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLXRvcF9fcmlnaHQnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0b3AgbGVmdCc6XG4gICAgICBjYXNlICdsZWZ0IHRvcCc6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS10b3BfX2xlZnQnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdib3R0b20gcmlnaHQnOlxuICAgICAgY2FzZSAncmlnaHQgYm90dG9tJzpcbiAgICAgICAgdGhpcy5jbGFzc0xpc3QuYWRkKCdmYWItLWJvdHRvbV9fcmlnaHQnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdib3R0b20gbGVmdCc6XG4gICAgICBjYXNlICdsZWZ0IGJvdHRvbSc6XG4gICAgICAgIHRoaXMuY2xhc3NMaXN0LmFkZCgnZmFiLS1ib3R0b21fX2xlZnQnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdjZW50ZXIgdG9wJzpcbiAgICAgIGNhc2UgJ3RvcCBjZW50ZXInOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tdG9wX19jZW50ZXInKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdjZW50ZXIgYm90dG9tJzpcbiAgICAgIGNhc2UgJ2JvdHRvbSBjZW50ZXInOlxuICAgICAgICB0aGlzLmNsYXNzTGlzdC5hZGQoJ2ZhYi0tYm90dG9tX19jZW50ZXInKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBfZ2V0VHJhbnNsYXRlKCkge1xuICAgIGNvbnN0IGlzQm90dG9tID0gKHRoaXMuZ2V0QXR0cmlidXRlKCdwb3NpdGlvbicpIHx8ICcnKS5pbmRleE9mKCdib3R0b20nKSA+PSAwO1xuICAgIGNvbnN0IHRyYW5zbGF0ZSA9IGlzQm90dG9tID8gYHRyYW5zbGF0ZTNkKDBweCwgLSR7dXRpbC5nbG9iYWxzLmZhYk9mZnNldCB8fCAwfXB4LCAwcHgpIGAgOiAnJztcbiAgICByZXR1cm4gdHJhbnNsYXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgc2hvd1xuICAgKiBAc2lnbmF0dXJlIHNob3coKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgc3BlZWQgZGlhbC5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHNob3coKSB7XG4gICAgdGhpcy5fZmFiLnNob3coKTtcbiAgICBzdHlsZXIodGhpcywgeyB0cmFuc2Zvcm06IHRoaXMuX2dldFRyYW5zbGF0ZSB9KTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1IaWRlIHRoZSBzcGVlZCBkaWFsLlsvZW5dXG4gICAqICAgW2phXVNwZWVkIGRpYWzjgpLpnZ7ooajnpLrjgavjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgaGlkZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oaWRlSXRlbXMoKS50aGVuKCgpPT4gdGhpcy5fZmFiLmhpZGUoKSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzaG93SXRlbXNcbiAgICogQHNpZ25hdHVyZSBzaG93SXRlbXMoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgc3BlZWQgZGlhbCBpdGVtcy5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44Gu5a2Q6KaB57Sg44KS6KGo56S644GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHNob3dJdGVtcygpIHtcbiAgICBpZiAodGhpcy5oYXNBdHRyaWJ1dGUoJ2RpcmVjdGlvbicpKSB7XG4gICAgICB0aGlzLl91cGRhdGVEaXJlY3Rpb24odGhpcy5nZXRBdHRyaWJ1dGUoJ2RpcmVjdGlvbicpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fdXBkYXRlRGlyZWN0aW9uKCd1cCcpO1xuICAgIH1cblxuICAgIGxldCB0b3RhbERlbGF5ID0gMDtcbiAgICBpZiAoIXRoaXMuX2l0ZW1TaG93bikge1xuICAgICAgY29uc3QgY2hpbGRyZW4gPSB0aGlzLml0ZW1zO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBkZWxheSA9IDI1ICogaTtcbiAgICAgICAgdG90YWxEZWxheSArPSBkZWxheTtcbiAgICAgICAgc3R5bGVyKGNoaWxkcmVuW2ldLCB7XG4gICAgICAgICAgdHJhbnNmb3JtOiAnc2NhbGUoMSknLFxuICAgICAgICAgIHRyYW5zaXRpb25EZWxheTogZGVsYXkgKyAnbXMnXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgdG90YWxEZWxheSArPSA1MDtcblxuICAgICAgdGhpcy5faXRlbVNob3duID0gdHJ1ZTtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnb3BlbicpO1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmVycmVkID0gdXRpbC5kZWZlcigpO1xuICAgIHNldFRpbWVvdXQoZGVmZXJyZWQucmVzb2x2ZSwgdG90YWxEZWxheSk7XG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlSXRlbXNcbiAgICogQHNpZ25hdHVyZSBoaWRlSXRlbXMoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSGlkZSB0aGUgc3BlZWQgZGlhbCBpdGVtcy5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44Gu5a2Q6KaB57Sg44KS6Z2e6KGo56S644Gr44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGhpZGVJdGVtcygpIHtcbiAgICBsZXQgdG90YWxEZWxheSA9IDA7XG4gICAgaWYgKHRoaXMuX2l0ZW1TaG93bikge1xuICAgICAgY29uc3QgY2hpbGRyZW4gPSB0aGlzLml0ZW1zO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBkZWxheSA9IDI1ICogKGNoaWxkcmVuLmxlbmd0aCAtIGkpO1xuICAgICAgICB0b3RhbERlbGF5ICs9IGRlbGF5O1xuICAgICAgICBzdHlsZXIoY2hpbGRyZW5baV0sIHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICdzY2FsZSgwKScsXG4gICAgICAgICAgdHJhbnNpdGlvbkRlbGF5OiBkZWxheSArICdtcydcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICB0b3RhbERlbGF5ICs9IDUwO1xuXG4gICAgICB0aGlzLl9pdGVtU2hvd24gPSBmYWxzZTtcbiAgICAgIHV0aWwudHJpZ2dlckVsZW1lbnRFdmVudCh0aGlzLCAnY2xvc2UnKTtcbiAgICB9XG5cbiAgICBjb25zdCBkZWZlcnJlZCA9IHV0aWwuZGVmZXIoKTtcbiAgICBzZXRUaW1lb3V0KGRlZmVycmVkLnJlc29sdmUsIHRvdGFsRGVsYXkpO1xuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBzZXQgZGlzYWJsZWQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUpIHtcbiAgICAgIHRoaXMuaGlkZUl0ZW1zKCk7XG4gICAgfVxuICAgIHV0aWwuYXJyYXlGcm9tKHRoaXMuY2hpbGRyZW4pLmZvckVhY2goZSA9PiB7XG4gICAgICB1dGlsLm1hdGNoKGUsICcuZmFiJykgJiYgdXRpbC50b2dnbGVBdHRyaWJ1dGUoZSwgJ2Rpc2FibGVkJywgdmFsdWUpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdkaXNhYmxlZCcsIHZhbHVlKTtcbiAgfVxuXG4gIGdldCBkaXNhYmxlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGlubGluZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIGlubGluZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd44Kk44Oz44Op44Kk44Oz6KaB57Sg44Gu5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIGdldCBpbmxpbmUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaGFzQXR0cmlidXRlKCdpbmxpbmUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIHZpc2libGUgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeimgee0oOOBjOimi+OBiOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuICBnZXQgdmlzaWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fZmFiLnZpc2libGUgJiYgdGhpcy5zdHlsZS5kaXNwbGF5ICE9PSAnbm9uZSc7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBpc09wZW5cbiAgICogQHNpZ25hdHVyZSBpc09wZW4oKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmV0dXJucyB3aGV0aGVyIHRoZSBtZW51IGlzIG9wZW4gb3Igbm90LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBpc09wZW4oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2l0ZW1TaG93bjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHRvZ2dsZVxuICAgKiBAc2lnbmF0dXJlIHRvZ2dsZSgpXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Ub2dnbGUgdmlzaWJpbGl0eS5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44Gu6KGo56S66Z2e6KGo56S644KS5YiH44KK5pu/44GI44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHRvZ2dsZSgpIHtcbiAgICByZXR1cm4gdGhpcy52aXNpYmxlID8gdGhpcy5oaWRlKCkgOiB0aGlzLnNob3coKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHRvZ2dsZUl0ZW1zXG4gICAqIEBzaWduYXR1cmUgdG9nZ2xlSXRlbXMoKVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVG9nZ2xlIGl0ZW0gdmlzaWJpbGl0eS5bL2VuXVxuICAgKiAgIFtqYV1TcGVlZCBkaWFs44Gu5a2Q6KaB57Sg44Gu6KGo56S66Z2e6KGo56S644KS5YiH44KK5pu/44GI44G+44GZ44CCWy9qYV1cbiAgICovXG4gIHRvZ2dsZUl0ZW1zKCkge1xuICAgIHJldHVybiB0aGlzLmlzT3BlbigpID8gdGhpcy5oaWRlSXRlbXMoKSA6IHRoaXMuc2hvd0l0ZW1zKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IGV2ZW50cygpIHtcbiAgICByZXR1cm4gWydvcGVuJywgJ2Nsb3NlJ107XG4gIH1cbn1cblxub25zRWxlbWVudHMuU3BlZWREaWFsID0gU3BlZWREaWFsRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXNwZWVkLWRpYWwnLCBTcGVlZERpYWxFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCB7UGFnZUxvYWRlciwgZGVmYXVsdFBhZ2VMb2FkZXJ9IGZyb20gJy4uL29ucy9wYWdlLWxvYWRlcic7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3QgcmV3cml0YWJsZXMgPSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IGVsZW1lbnRcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHJlYWR5KGVsZW1lbnQsIGNhbGxiYWNrKSB7XG4gICAgc2V0SW1tZWRpYXRlKGNhbGxiYWNrKTtcbiAgfVxufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtc3BsaXR0ZXItY29udGVudFxuICogQGNhdGVnb3J5IG1lbnVcbiAqIEBkZXNjcmlwdGlvblxuICogIFtlbl1cbiAqICAgIFRoZSBgPG9ucy1zcGxpdHRlci1jb250ZW50PmAgZWxlbWVudCBpcyB1c2VkIGFzIGEgY2hpbGQgZWxlbWVudCBvZiBgPG9ucy1zcGxpdHRlcj5gLlxuICpcbiAqICAgIEl0IGNvbnRhaW5zIHRoZSBtYWluIGNvbnRlbnQgb2YgdGhlIHBhZ2Ugd2hpbGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGNvbnRhaW5zIHRoZSBsaXN0LlxuICogIFsvZW5dXG4gKiAgW2phXW9ucy1zcGxpdHRlci1jb250ZW506KaB57Sg44Gv44CBb25zLXNwbGl0dGVy6KaB57Sg44Gu5a2Q6KaB57Sg44Go44GX44Gm5Yip55So44GX44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIHJPUU9NTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3NwbGl0dGVyXG4gKiBAZ3VpZGUgZnVuZGFtZW50YWxzLmh0bWwjbWFuYWdpbmctcGFnZXNcbiAqICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXMuWy9lbl1cbiAqICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zcGxpdHRlclxuICogIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXI+YCBjb21wb25lbnQgaXMgdGhlIHBhcmVudCBlbGVtZW50LlsvZW5dXG4gKiAgW2phXW9ucy1zcGxpdHRlcuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtc3BsaXR0ZXItc2lkZVxuICogIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGNvbXBvbmVudCBjb250YWlucyB0aGUgbWVudS5bL2VuXVxuICogIFtqYV1vbnMtc3BsaXR0ZXItc2lkZeOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zcGxpdHRlcj5cbiAqICAgPG9ucy1zcGxpdHRlci1jb250ZW50PlxuICogICAgIC4uLlxuICogICA8L29ucy1zcGxpdHRlci1jb250ZW50PlxuICpcbiAqICAgPG9ucy1zcGxpdHRlci1zaWRlIHNpZGU9XCJsZWZ0XCIgd2lkdGg9XCI4MCVcIiBjb2xsYXBzZT5cbiAqICAgICAuLi5cbiAqICAgPC9vbnMtc3BsaXR0ZXItc2lkZT5cbiAqIDwvb25zLXNwbGl0dGVyPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGxpdHRlckNvbnRlbnRFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHBhZ2VcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhlIHVybCBvZiB0aGUgY29udGVudCBwYWdlLiBJZiB0aGlzIGF0dHJpYnV0ZSBpcyB1c2VkIHRoZSBjb250ZW50IHdpbGwgYmUgbG9hZGVkIGZyb20gYSBgPHRlbXBsYXRlPmAgdGFnIG9yIGEgcmVtb3RlIGZpbGUuXG4gICAqXG4gICAqICAgICBJdCBpcyBhbHNvIHBvc3NpYmxlIHRvIHB1dCBgPG9ucy1wYWdlPmAgZWxlbWVudCBhcyBhIGNoaWxkIG9mIHRoZSBlbGVtZW50LlxuICAgKiAgIFsvZW5dXG4gICAqICAgW2phXW9ucy1zcGxpdHRlci1jb250ZW506KaB57Sg44Gr6KGo56S644GZ44KL44Oa44O844K444GuVVJM44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX3BhZ2UgPSBudWxsO1xuICAgIHRoaXMuX3BhZ2VMb2FkZXIgPSBkZWZhdWx0UGFnZUxvYWRlcjtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICByZXdyaXRhYmxlcy5yZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHBhZ2UgPSB0aGlzLl9nZXRQYWdlVGFyZ2V0KCk7XG5cbiAgICAgICAgaWYgKHBhZ2UpIHtcbiAgICAgICAgICB0aGlzLmxvYWQocGFnZSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgaWYgKCF1dGlsLm1hdGNoKHRoaXMucGFyZW50Tm9kZSwgJ29ucy1zcGxpdHRlcicpKSB7XG4gICAgICB1dGlsLnRocm93KCdcIm9ucy1zcGxpdHRlci1jb250ZW50XCIgbXVzdCBoYXZlIFwib25zLXNwbGl0dGVyXCIgYXMgcGFyZW50Jyk7XG4gICAgfVxuICB9XG5cbiAgX2dldFBhZ2VUYXJnZXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhZ2UgfHwgdGhpcy5nZXRBdHRyaWJ1dGUoJ3BhZ2UnKTtcbiAgfVxuXG4gIGRpc2Nvbm5lY3RlZENhbGxiYWNrKCkge31cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBwYWdlXG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBwYWdlIHRvIGxvYWQgaW4gdGhlIHNwbGl0dGVyIGNvbnRlbnQuWy9lbl1cbiAgICogICBbamFd44GT44Gu6KaB57Sg5YaF44Gr6KGo56S644GZ44KL44Oa44O844K444KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldCBwYWdlKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7Kn0gcGFnZVxuICAgKi9cbiAgc2V0IHBhZ2UocGFnZSkge1xuICAgIHRoaXMuX3BhZ2UgPSBwYWdlO1xuICB9XG5cbiAgZ2V0IF9jb250ZW50KCkge1xuICAgIHJldHVybiB0aGlzLmNoaWxkcmVuWzBdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBwYWdlTG9hZGVyXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVBhZ2UgZWxlbWVudCBsb2FkZWQgaW4gdGhlIHNwbGl0dGVyIGNvbnRlbnQuWy9lbl1cbiAgICogICBbamFd44GT44Gu6KaB57Sg5YaF44Gr6KGo56S644GZ44KL44Oa44O844K444KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldCBwYWdlTG9hZGVyKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlTG9hZGVyO1xuICB9XG5cbiAgc2V0IHBhZ2VMb2FkZXIobG9hZGVyKSB7XG4gICAgaWYgKCEobG9hZGVyIGluc3RhbmNlb2YgUGFnZUxvYWRlcikpIHtcbiAgICAgIHV0aWwudGhyb3dQYWdlTG9hZGVyKCk7XG4gICAgfVxuICAgIHRoaXMuX3BhZ2VMb2FkZXIgPSBsb2FkZXI7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBsb2FkXG4gICAqIEBzaWduYXR1cmUgbG9hZChwYWdlLCBbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwYWdlLCBbb3B0aW9uc11cbiAgICogICBbZW5dUGFnZSBVUkwuIENhbiBiZSBlaXRoZXIgYW4gSFRNTCBkb2N1bWVudCBvciBhbiBgPHRlbXBsYXRlPmAgaWQuWy9lbl1cbiAgICogICBbamFdcGFnZeOBrlVSTOOBi+OAgWA8dGVtcGxhdGU+YOOBp+Wuo+iogOOBl+OBn+ODhuODs+ODl+ODrOODvOODiOOBrmlk5bGe5oCn44Gu5YCk44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5jYWxsYmFja11cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgdGhlIHBhZ2Ugc3BlY2lmaWVkIGluIGBwYWdlYCBpbiB0aGUgY29udGVudC5bL2VuXVxuICAgKiAgIFtqYV3mjIflrprjgZfjgZ9VUkzjgpLjg6HjgqTjg7Pjg5rjg7zjgrjjgpLoqq3jgb/ovrzjgb/jgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgbmV3IGA8b25zLXBhZ2U+YCBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdYDxvbnMtcGFnZT5g6KaB57Sg44KS6Kej5rG644GZ44KLUHJvbWlzZeOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuICBsb2FkKHBhZ2UsIG9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMuX3BhZ2UgPSBwYWdlO1xuICAgIGNvbnN0IGNhbGxiYWNrID0gb3B0aW9ucy5jYWxsYmFjayB8fCBmdW5jdGlvbigpIHt9O1xuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgbGV0IG9sZENvbnRlbnQgPSB0aGlzLl9jb250ZW50IHx8IG51bGw7XG5cbiAgICAgIHRoaXMuX3BhZ2VMb2FkZXIubG9hZCh7cGFnZSwgcGFyZW50OiB0aGlzfSwgcGFnZUVsZW1lbnQgPT4ge1xuICAgICAgICBpZiAob2xkQ29udGVudCkge1xuICAgICAgICAgIHRoaXMuX3BhZ2VMb2FkZXIudW5sb2FkKG9sZENvbnRlbnQpO1xuICAgICAgICAgIG9sZENvbnRlbnQgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHRoaXMuX3Nob3coKSk7XG5cbiAgICAgICAgY2FsbGJhY2socGFnZUVsZW1lbnQpO1xuICAgICAgICByZXNvbHZlKHBhZ2VFbGVtZW50KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgX3Nob3coKSB7XG4gICAgaWYgKHRoaXMuX2NvbnRlbnQpIHtcbiAgICAgIHRoaXMuX2NvbnRlbnQuX3Nob3coKTtcbiAgICB9XG4gIH1cblxuICBfaGlkZSgpIHtcbiAgICBpZiAodGhpcy5fY29udGVudCkge1xuICAgICAgdGhpcy5fY29udGVudC5faGlkZSgpO1xuICAgIH1cbiAgfVxuXG4gIF9kZXN0cm95KCkge1xuICAgIGlmICh0aGlzLl9jb250ZW50KSB7XG4gICAgICB0aGlzLl9wYWdlTG9hZGVyLnVubG9hZCh0aGlzLl9jb250ZW50KTtcbiAgICB9XG4gICAgdGhpcy5yZW1vdmUoKTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgcmV3cml0YWJsZXMoKSB7XG4gICAgcmV0dXJuIHJld3JpdGFibGVzO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlNwbGl0dGVyQ29udGVudCA9IFNwbGl0dGVyQ29udGVudEVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy1zcGxpdHRlci1jb250ZW50JywgU3BsaXR0ZXJDb250ZW50RWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCB1dGlsIGZyb20gJy4uL29ucy91dGlsJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGxpdHRlck1hc2tFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9ib3VuZE9uQ2xpY2sgPSB0aGlzLl9vbkNsaWNrLmJpbmQodGhpcyk7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIGlmICh0aGlzLnBhcmVudE5vZGUuX3NpZGVzLmV2ZXJ5KHNpZGUgPT4gc2lkZS5tb2RlID09PSAnc3BsaXQnKSkge1xuICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnc3R5bGUnLCAnZGlzcGxheTogbm9uZSAhaW1wb3J0YW50Jyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBfb25DbGljayhldmVudCkge1xuICAgIGlmICh0aGlzLm9uQ2xpY2sgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgdGhpcy5vbkNsaWNrKCk7XG4gICAgfSBlbHNlIGlmICh1dGlsLm1hdGNoKHRoaXMucGFyZW50Tm9kZSwgJ29ucy1zcGxpdHRlcicpKSB7XG4gICAgICB0aGlzLnBhcmVudE5vZGUuX3NpZGVzLmZvckVhY2goc2lkZSA9PiBzaWRlLmNsb3NlKCdsZWZ0JykuY2F0Y2goKCkgPT4ge30pKTtcbiAgICB9XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljayk7XG4gICAgdXRpbC5pb3NNYXNrU2Nyb2xsRml4KHRoaXMsIHRydWUpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX2JvdW5kT25DbGljayk7XG4gICAgdXRpbC5pb3NNYXNrU2Nyb2xsRml4KHRoaXMsIGZhbHNlKTtcbiAgfVxufVxuXG5vbnNFbGVtZW50cy5TcGxpdHRlck1hc2sgPSBTcGxpdHRlck1hc2tFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc3BsaXR0ZXItbWFzaycsIFNwbGl0dGVyTWFza0VsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IHN0eWxlciBmcm9tICcuLi8uLi9vbnMvc3R5bGVyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuaW1wb3J0IEJhc2VBbmltYXRvciBmcm9tICcuLi8uLi9vbnMvYmFzZS1hbmltYXRvcic7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNwbGl0dGVyQW5pbWF0b3IgZXh0ZW5kcyBCYXNlQW5pbWF0b3Ige1xuXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnY3ViaWMtYmV6aWVyKC4xLCAuNywgLjEsIDEpJywgZHVyYXRpb24gPSAwLjMsIGRlbGF5ID0gMH0gPSB7fSkge1xuICAgIHN1cGVyKHsgdGltaW5nLCBkdXJhdGlvbiwgZGVsYXkgfSk7XG4gIH1cblxuICB1cGRhdGVPcHRpb25zKG9wdGlvbnMgPSB7fSkge1xuICAgIHV0aWwuZXh0ZW5kKHRoaXMsIHtcbiAgICAgIHRpbWluZzogdGhpcy50aW1pbmcsIGR1cmF0aW9uOiB0aGlzLmR1cmF0aW9uLCBkZWxheTogdGhpcy5kZWxheVxuICAgIH0sIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gc2lkZUVsZW1lbnRcbiAgICovXG4gIGFjdGl2YXRlKHNpZGVFbGVtZW50KSB7XG4gICAgY29uc3Qgc3BsaXR0ZXIgPSBzaWRlRWxlbWVudC5wYXJlbnROb2RlO1xuXG4gICAgY29udGVudFJlYWR5KHNwbGl0dGVyLCAoKSA9PiB7XG4gICAgICB0aGlzLl9zaWRlID0gc2lkZUVsZW1lbnQ7XG4gICAgICB0aGlzLl9vcHBvc2l0ZVNpZGUgPSBzcGxpdHRlci5yaWdodCAhPT0gc2lkZUVsZW1lbnQgJiYgc3BsaXR0ZXIucmlnaHQgfHwgc3BsaXR0ZXIubGVmdCAhPT0gc2lkZUVsZW1lbnQgJiYgc3BsaXR0ZXIubGVmdDtcbiAgICAgIHRoaXMuX2NvbnRlbnQgPSBzcGxpdHRlci5jb250ZW50O1xuICAgICAgdGhpcy5fbWFzayA9IHNwbGl0dGVyLm1hc2s7XG4gICAgfSk7XG4gIH1cblxuICBkZWFjdGl2YXRlKCkge1xuICAgIHRoaXMuY2xlYXJUcmFuc2l0aW9uKCk7XG4gICAgdGhpcy5fbWFzayAmJiB0aGlzLmNsZWFyTWFzaygpO1xuICAgIHRoaXMuX2NvbnRlbnQgPSB0aGlzLl9zaWRlID0gdGhpcy5fb3Bwb3NpdGVTaWRlID0gdGhpcy5fbWFzayA9IG51bGw7XG4gIH1cblxuICBnZXQgbWludXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3NpZGUuc2lkZSA9PT0gJ3JpZ2h0JyA/ICctJyA6ICcnO1xuICB9XG5cbiAgY2xlYXJUcmFuc2l0aW9uKCkge1xuICAgICdzaWRlIG1hc2sgY29udGVudCcuc3BsaXQoL1xccysvKVxuICAgICAgLmZvckVhY2goZSA9PiB0aGlzWydfJyArIGVdICYmIHN0eWxlci5jbGVhcih0aGlzWydfJyArIGVdLCAndHJhbnNmb3JtIHRyYW5zaXRpb24nKSlcbiAgfVxuXG4gIGNsZWFyTWFzaygpIHtcbiAgICAvLyBDaGVjayBpZiB0aGUgb3RoZXIgc2lkZSBuZWVkcyB0aGUgbWFzayBiZWZvcmUgY2xlYXJpbmdcbiAgICBpZiAoIXRoaXMuX29wcG9zaXRlU2lkZSB8fCB0aGlzLl9vcHBvc2l0ZVNpZGUubW9kZSA9PT0gJ3NwbGl0JyB8fCAhdGhpcy5fb3Bwb3NpdGVTaWRlLmlzT3Blbikge1xuICAgICAgdGhpcy5fbWFzay5zdHlsZS5vcGFjaXR5ID0gJyc7XG4gICAgICB0aGlzLl9tYXNrLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkaXN0YW5jZVxuICAgKi9cbiAgdHJhbnNsYXRlKGRpc3RhbmNlKSB7XG5cbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBvcGVuKGRvbmUpIHtcbiAgICBkb25lKCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgY2xvc2UoZG9uZSkge1xuICAgIGRvbmUoKTtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcbmltcG9ydCBTcGxpdHRlckFuaW1hdG9yIGZyb20gJy4vYW5pbWF0b3IuanMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBPdmVybGF5U3BsaXR0ZXJBbmltYXRvciBleHRlbmRzIFNwbGl0dGVyQW5pbWF0b3Ige1xuXG4gIHRyYW5zbGF0ZShkaXN0YW5jZSkge1xuICAgIHRoaXMuX21hc2suc3R5bGUuZGlzcGxheSA9ICdibG9jayc7IC8vIEF2b2lkIGNvbnRlbnQgY2xpY2tzXG5cbiAgICBhbmltaXQodGhpcy5fc2lkZSlcbiAgICAgIC5xdWV1ZSh7XG4gICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKCR7dGhpcy5taW51cyArIGRpc3RhbmNlfXB4LCAwLCAwKWBcbiAgICAgIH0pXG4gICAgICAucGxheSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGRvbmVcbiAgICovXG4gIG9wZW4oZG9uZSkge1xuICAgIGFuaW1pdC5ydW5BbGwoXG4gICAgICBhbmltaXQodGhpcy5fc2lkZSlcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3RoaXMubWludXN9MTAwJSwgMCwgMClgXG4gICAgICAgIH0sIHRoaXMuZGVmKVxuICAgICAgICAucXVldWUoY2FsbGJhY2sgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSAmJiBkb25lKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQodGhpcy5fbWFzaylcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBkaXNwbGF5OiAnYmxvY2snXG4gICAgICAgIH0pXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogJzEnXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6ICdsaW5lYXInLFxuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgY2xvc2UoZG9uZSkge1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0aGlzLl9zaWRlKVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIHRyYW5zZm9ybTogJ3RyYW5zbGF0ZTNkKDAsIDAsIDApJ1xuICAgICAgICB9LCB0aGlzLmRlZilcbiAgICAgICAgLnF1ZXVlKGNhbGxiYWNrID0+IHtcbiAgICAgICAgICBkb25lICYmIGRvbmUoKTtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KHRoaXMuX21hc2spXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgb3BhY2l0eTogJzAnXG4gICAgICAgIH0sIHtcbiAgICAgICAgICBkdXJhdGlvbjogdGhpcy5kdXJhdGlvbixcbiAgICAgICAgICB0aW1pbmc6ICdsaW5lYXInLFxuICAgICAgICB9KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGRpc3BsYXk6ICdub25lJ1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5pbXBvcnQgU3BsaXR0ZXJBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yLmpzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUHVzaFNwbGl0dGVyQW5pbWF0b3IgZXh0ZW5kcyBTcGxpdHRlckFuaW1hdG9yIHtcblxuICBfZ2V0U2xpZGluZ0VsZW1lbnRzKCkge1xuICAgIGNvbnN0IHNsaWRpbmdFbGVtZW50cyA9IFt0aGlzLl9zaWRlLCB0aGlzLl9jb250ZW50XTtcbiAgICBpZiAodGhpcy5fb3Bwb3NpdGVTaWRlICYmIHRoaXMuX29wcG9zaXRlU2lkZS5tb2RlID09PSAnc3BsaXQnKSB7XG4gICAgICBzbGlkaW5nRWxlbWVudHMucHVzaCh0aGlzLl9vcHBvc2l0ZVNpZGUpO1xuICAgIH1cblxuICAgIHJldHVybiBzbGlkaW5nRWxlbWVudHM7XG4gIH1cblxuICB0cmFuc2xhdGUoZGlzdGFuY2UpIHtcbiAgICBpZiAoIXRoaXMuX3NsaWRpbmdFbGVtZW50cykge1xuICAgICAgdGhpcy5fc2xpZGluZ0VsZW1lbnRzID0gdGhpcy5fZ2V0U2xpZGluZ0VsZW1lbnRzKCk7XG4gICAgfVxuXG4gICAgdGhpcy5fbWFzay5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJzsgLy8gQXZvaWQgY29udGVudCBjbGlja3NcblxuICAgIGFuaW1pdCh0aGlzLl9zbGlkaW5nRWxlbWVudHMpXG4gICAgICAucXVldWUoe1xuICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3RoaXMubWludXMgKyBkaXN0YW5jZX1weCwgMCwgMClgXG4gICAgICB9KVxuICAgICAgLnBsYXkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBvcGVuKGRvbmUpIHtcbiAgICBjb25zdCBtYXggPSB0aGlzLl9zaWRlLm9mZnNldFdpZHRoO1xuICAgIHRoaXMuX3NsaWRpbmdFbGVtZW50cyA9IHRoaXMuX2dldFNsaWRpbmdFbGVtZW50cygpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0aGlzLl9zbGlkaW5nRWxlbWVudHMpXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoJHt0aGlzLm1pbnVzICsgbWF4fXB4LCAwLCAwKWBcbiAgICAgICAgfSwgdGhpcy5kZWYpXG4gICAgICAgIC5xdWV1ZShjYWxsYmFjayA9PiB7XG4gICAgICAgICAgdGhpcy5fc2xpZGluZ0VsZW1lbnRzID0gbnVsbDtcbiAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUgJiYgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KHRoaXMuX21hc2spXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgZGlzcGxheTogJ2Jsb2NrJ1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZG9uZVxuICAgKi9cbiAgY2xvc2UoZG9uZSkge1xuICAgIHRoaXMuX3NsaWRpbmdFbGVtZW50cyA9IHRoaXMuX2dldFNsaWRpbmdFbGVtZW50cygpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0aGlzLl9zbGlkaW5nRWxlbWVudHMpXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7XG4gICAgICAgICAgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknXG4gICAgICAgIH0sIHRoaXMuZGVmKVxuICAgICAgICAucXVldWUoY2FsbGJhY2sgPT4ge1xuICAgICAgICAgIHRoaXMuX3NsaWRpbmdFbGVtZW50cyA9IG51bGw7XG4gICAgICAgICAgc3VwZXIuY2xlYXJUcmFuc2l0aW9uKCk7XG4gICAgICAgICAgZG9uZSAmJiBkb25lKCk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdCh0aGlzLl9tYXNrKVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoe1xuICAgICAgICAgIGRpc3BsYXk6ICdub25lJ1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuaW1wb3J0IHN0eWxlciBmcm9tICcuLi8uLi9vbnMvc3R5bGVyJztcbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5pbXBvcnQgU3BsaXR0ZXJBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yLmpzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgUmV2ZWFsU3BsaXR0ZXJBbmltYXRvciBleHRlbmRzIFNwbGl0dGVyQW5pbWF0b3Ige1xuXG4gIF9nZXRTbGlkaW5nRWxlbWVudHMoKSB7XG4gICAgY29uc3Qgc2xpZGluZ0VsZW1lbnRzID0gW3RoaXMuX2NvbnRlbnQsIHRoaXMuX21hc2tdO1xuICAgIGlmICh0aGlzLl9vcHBvc2l0ZVNpZGUgJiYgdGhpcy5fb3Bwb3NpdGVTaWRlLm1vZGUgPT09ICdzcGxpdCcpIHtcbiAgICAgIHNsaWRpbmdFbGVtZW50cy5wdXNoKHRoaXMuX29wcG9zaXRlU2lkZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNsaWRpbmdFbGVtZW50cztcbiAgfVxuXG4gIGFjdGl2YXRlKHNpZGVFbGVtZW50KSB7XG4gICAgc3VwZXIuYWN0aXZhdGUoc2lkZUVsZW1lbnQpO1xuICAgIGlmIChzaWRlRWxlbWVudC5tb2RlID09PSAnY29sbGFwc2UnKSB7XG4gICAgICB0aGlzLl9zZXRTdHlsZXMoc2lkZUVsZW1lbnQpO1xuICAgIH1cbiAgfVxuXG4gIGRlYWN0aXZhdGUoKSB7XG4gICAgdGhpcy5fc2lkZSAmJiB0aGlzLl91bnNldFN0eWxlcyh0aGlzLl9zaWRlKTtcbiAgICBzdXBlci5kZWFjdGl2YXRlKCk7XG4gIH1cblxuICBfc2V0U3R5bGVzKHNpZGVFbGVtZW50KSB7XG4gICAgc3R5bGVyKHNpZGVFbGVtZW50LCB7XG4gICAgICBsZWZ0OiBzaWRlRWxlbWVudC5zaWRlID09PSAncmlnaHQnID8gJ2F1dG8nIDogMCxcbiAgICAgIHJpZ2h0OiBzaWRlRWxlbWVudC5zaWRlID09PSAncmlnaHQnICA/IDAgOiAnYXV0bycsXG4gICAgICB6SW5kZXg6IDAsXG4gICAgICBiYWNrZ3JvdW5kQ29sb3I6ICdibGFjaycsXG4gICAgICB0cmFuc2Zvcm06IHRoaXMuX2dlbmVyYXRlQmVoaW5kUGFnZVN0eWxlKDApLmNvbnRhaW5lci50cmFuc2Zvcm0sXG4gICAgICBkaXNwbGF5OiAnbm9uZSdcbiAgICB9KTtcblxuICAgIGNvbnN0IHNwbGl0dGVyID0gc2lkZUVsZW1lbnQucGFyZW50RWxlbWVudDtcbiAgICBjb250ZW50UmVhZHkoc3BsaXR0ZXIsICgpID0+IHNwbGl0dGVyLmNvbnRlbnQgJiYgc3R5bGVyKHNwbGl0dGVyLmNvbnRlbnQsIHsgYm94U2hhZG93OiAnMCAwIDEycHggMCByZ2JhKDAsIDAsIDAsIDAuMiknIH0pKTtcbiAgfVxuXG4gIF91bnNldFN0eWxlcyhzaWRlRWxlbWVudCkge1xuICAgIHN0eWxlci5jbGVhcihzaWRlRWxlbWVudCwgJ2xlZnQgcmlnaHQgekluZGV4IGJhY2tncm91bmRDb2xvciBkaXNwbGF5Jyk7XG4gICAgaWYgKHNpZGVFbGVtZW50Ll9jb250ZW50KSB7XG4gICAgICBzaWRlRWxlbWVudC5fY29udGVudC5zdHlsZS5vcGFjaXR5ID0gJyc7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIG90aGVyIHNpZGUgbmVlZHMgdGhlIGNvbW1vbiBzdHlsZXNcbiAgICBpZiAoIXRoaXMuX29wcG9zaXRlU2lkZSB8fCB0aGlzLl9vcHBvc2l0ZVNpZGUubW9kZSA9PT0gJ3NwbGl0Jykge1xuICAgICAgc2lkZUVsZW1lbnQucGFyZW50RWxlbWVudC5jb250ZW50ICYmIHN0eWxlci5jbGVhcihzaWRlRWxlbWVudC5wYXJlbnRFbGVtZW50LmNvbnRlbnQsICdib3hTaGFkb3cnKTtcbiAgICB9XG4gIH1cblxuICBfZ2VuZXJhdGVCZWhpbmRQYWdlU3R5bGUoZGlzdGFuY2UpIHtcbiAgICBjb25zdCBtYXggPSB0aGlzLm1heFdpZHRoO1xuXG4gICAgbGV0IGJlaGluZERpc3RhbmNlID0gKGRpc3RhbmNlIC0gbWF4KSAvIG1heCAqIDEwO1xuICAgIGJlaGluZERpc3RhbmNlID0gaXNOYU4oYmVoaW5kRGlzdGFuY2UpID8gMCA6IE1hdGgubWF4KE1hdGgubWluKGJlaGluZERpc3RhbmNlLCAwKSwgLTEwKTtcblxuICAgIGNvbnN0IGJlaGluZFRyYW5zZm9ybSA9IGB0cmFuc2xhdGUzZCgkeyh0aGlzLm1pbnVzID8gLTEgOiAxKSAqIGJlaGluZERpc3RhbmNlfSUsIDAsIDApYDtcbiAgICBjb25zdCBvcGFjaXR5ID0gMSArIGJlaGluZERpc3RhbmNlIC8gMTAwO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbnRlbnQ6IHtcbiAgICAgICAgb3BhY2l0eVxuICAgICAgfSxcbiAgICAgIGNvbnRhaW5lcjoge1xuICAgICAgICB0cmFuc2Zvcm06IGJlaGluZFRyYW5zZm9ybVxuICAgICAgfVxuICAgIH07XG4gIH1cblxuICB0cmFuc2xhdGUoZGlzdGFuY2UpIHtcbiAgICB0aGlzLl9zaWRlLnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICB0aGlzLl9zaWRlLnN0eWxlLnpJbmRleCA9IDE7XG4gICAgdGhpcy5tYXhXaWR0aCA9IHRoaXMubWF4V2lkdGggfHwgdGhpcy5fZ2V0TWF4V2lkdGgoKTtcbiAgICBjb25zdCBtZW51U3R5bGUgPSB0aGlzLl9nZW5lcmF0ZUJlaGluZFBhZ2VTdHlsZShNYXRoLm1pbihkaXN0YW5jZSwgdGhpcy5tYXhXaWR0aCkpO1xuXG4gICAgaWYgKCF0aGlzLl9zbGlkaW5nRWxlbWVudHMpIHtcbiAgICAgIHRoaXMuX3NsaWRpbmdFbGVtZW50cyA9IHRoaXMuX2dldFNsaWRpbmdFbGVtZW50cygpO1xuICAgIH1cblxuICAgIHRoaXMuX21hc2suc3R5bGUuZGlzcGxheSA9ICdibG9jayc7IC8vIEF2b2lkIGNvbnRlbnQgY2xpY2tzXG5cbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KHRoaXMuX3NsaWRpbmdFbGVtZW50cylcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgke3RoaXMubWludXMgKyBkaXN0YW5jZX1weCwgMCwgMClgXG4gICAgICAgIH0pLFxuICAgICAgYW5pbWl0KHRoaXMuX3NpZGUuX2NvbnRlbnQpXG4gICAgICAgIC5xdWV1ZShtZW51U3R5bGUuY29udGVudCksXG4gICAgICBhbmltaXQodGhpcy5fc2lkZSlcbiAgICAgICAgLnF1ZXVlKG1lbnVTdHlsZS5jb250YWluZXIpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBvcGVuKGRvbmUpIHtcbiAgICB0aGlzLl9zaWRlLnN0eWxlLmRpc3BsYXkgPSAnJztcbiAgICB0aGlzLl9zaWRlLnN0eWxlLnpJbmRleCA9IDE7XG4gICAgdGhpcy5tYXhXaWR0aCA9IHRoaXMubWF4V2lkdGggfHwgdGhpcy5fZ2V0TWF4V2lkdGgoKTtcbiAgICBjb25zdCBtZW51U3R5bGUgPSB0aGlzLl9nZW5lcmF0ZUJlaGluZFBhZ2VTdHlsZSh0aGlzLm1heFdpZHRoKTtcbiAgICB0aGlzLl9zbGlkaW5nRWxlbWVudHMgPSB0aGlzLl9nZXRTbGlkaW5nRWxlbWVudHMoKTtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4geyAvLyBGaXg6IFRpbWUgdG8gdXBkYXRlIHByZXZpb3VzIHRyYW5zbGF0ZTNkIGFmdGVyIGNoYW5naW5nIHN0eWxlLmRpc3BsYXlcbiAgICAgIGFuaW1pdC5ydW5BbGwoXG4gICAgICAgIGFuaW1pdCh0aGlzLl9zbGlkaW5nRWxlbWVudHMpXG4gICAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgICAucXVldWUoe1xuICAgICAgICAgICAgdHJhbnNmb3JtOiBgdHJhbnNsYXRlM2QoJHt0aGlzLm1pbnVzICsgdGhpcy5tYXhXaWR0aH1weCwgMCwgMClgXG4gICAgICAgICAgfSwgdGhpcy5kZWYpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLl9tYXNrKVxuICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICAgIGRpc3BsYXk6ICdibG9jaydcbiAgICAgICAgICB9KSxcblxuICAgICAgICBhbmltaXQodGhpcy5fc2lkZS5fY29udGVudClcbiAgICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAgIC5xdWV1ZShtZW51U3R5bGUuY29udGVudCwgdGhpcy5kZWYpLFxuXG4gICAgICAgIGFuaW1pdCh0aGlzLl9zaWRlKVxuICAgICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgICAgLnF1ZXVlKG1lbnVTdHlsZS5jb250YWluZXIsIHRoaXMuZGVmKVxuICAgICAgICAgIC5xdWV1ZShjYWxsYmFjayA9PiB7XG4gICAgICAgICAgICB0aGlzLl9zbGlkaW5nRWxlbWVudHMgPSBudWxsO1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIGRvbmUgJiYgZG9uZSgpO1xuICAgICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9LCAxMDAwLzYwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBkb25lXG4gICAqL1xuICBjbG9zZShkb25lKSB7XG4gICAgY29uc3QgbWVudVN0eWxlID0gdGhpcy5fZ2VuZXJhdGVCZWhpbmRQYWdlU3R5bGUoMCk7XG4gICAgdGhpcy5fc2xpZGluZ0VsZW1lbnRzID0gdGhpcy5fZ2V0U2xpZGluZ0VsZW1lbnRzKCk7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KHRoaXMuX3NsaWRpbmdFbGVtZW50cylcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKSdcbiAgICAgICAgfSwgdGhpcy5kZWYpLFxuXG4gICAgICBhbmltaXQodGhpcy5fbWFzaylcbiAgICAgICAgLndhaXQodGhpcy5kZWxheSlcbiAgICAgICAgLnF1ZXVlKHtcbiAgICAgICAgICBkaXNwbGF5OiAnbm9uZSdcbiAgICAgICAgfSksXG5cbiAgICAgIGFuaW1pdCh0aGlzLl9zaWRlLl9jb250ZW50KVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUobWVudVN0eWxlLmNvbnRlbnQsIHRoaXMuZGVmKSxcblxuICAgICAgYW5pbWl0KHRoaXMuX3NpZGUpXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZShtZW51U3R5bGUuY29udGFpbmVyLCB0aGlzLmRlZilcbiAgICAgICAgLnF1ZXVlKGNhbGxiYWNrID0+IHtcbiAgICAgICAgICB0aGlzLl9zbGlkaW5nRWxlbWVudHMgPSBudWxsO1xuICAgICAgICAgIHRoaXMuX3NpZGUuc3R5bGUuekluZGV4ID0gMDtcbiAgICAgICAgICB0aGlzLl9zaWRlLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgdGhpcy5fc2lkZS5fY29udGVudC5zdHlsZS5vcGFjaXR5ID0gJyc7XG4gICAgICAgICAgZG9uZSAmJiBkb25lKCk7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIF9nZXRNYXhXaWR0aCgpIHtcbiAgICByZXR1cm4gdGhpcy5fc2lkZS5vZmZzZXRXaWR0aDtcbiAgfVxufVxuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uLy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBBbmltYXRvckZhY3RvcnkgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2FuaW1hdG9yLWZhY3RvcnknO1xuaW1wb3J0IE92ZXJsYXlTcGxpdHRlckFuaW1hdG9yIGZyb20gJy4vb3ZlcmxheS1hbmltYXRvcic7XG5pbXBvcnQgUHVzaFNwbGl0dGVyQW5pbWF0b3IgZnJvbSAnLi9wdXNoLWFuaW1hdG9yJztcbmltcG9ydCBSZXZlYWxTcGxpdHRlckFuaW1hdG9yIGZyb20gJy4vcmV2ZWFsLWFuaW1hdG9yJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL2RldmljZS1iYWNrLWJ1dHRvbi1kaXNwYXRjaGVyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuXG5jb25zdCBfYW5pbWF0b3JEaWN0ID0ge1xuICBkZWZhdWx0OiBPdmVybGF5U3BsaXR0ZXJBbmltYXRvcixcbiAgb3ZlcmxheTogT3ZlcmxheVNwbGl0dGVyQW5pbWF0b3IsXG4gIHB1c2g6IFB1c2hTcGxpdHRlckFuaW1hdG9yLFxuICByZXZlYWw6IFJldmVhbFNwbGl0dGVyQW5pbWF0b3Jcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXNwbGl0dGVyXG4gKiBAY2F0ZWdvcnkgbWVudVxuICogQGRlc2NyaXB0aW9uXG4gKiAgW2VuXVxuICogICAgQSBjb21wb25lbnQgdGhhdCBlbmFibGVzIHJlc3BvbnNpdmUgbGF5b3V0IGJ5IGltcGxlbWVudGluZyBib3RoIGEgdHdvLWNvbHVtbiBsYXlvdXQgYW5kIGEgc2xpZGluZyBtZW51IGxheW91dC5cbiAqXG4gKiAgICBJdCBjYW4gYmUgY29uZmlndXJlZCB0byBhdXRvbWF0aWNhbGx5IGV4cGFuZCBpbnRvIGEgY29sdW1uIGxheW91dCBvbiBsYXJnZSBzY3JlZW5zIGFuZCBjb2xsYXBzZSB0aGUgbWVudSBvbiBzbWFsbGVyIHNjcmVlbnMuIFdoZW4gdGhlIG1lbnUgaXMgY29sbGFwc2VkIHRoZSB1c2VyIGNhbiBvcGVuIGl0IGJ5IHN3aXBpbmcuXG4gKiAgWy9lbl1cbiAqICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIHJPUU9NTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3NwbGl0dGVyXG4gKiBAZ3VpZGUgZnVuZGFtZW50YWxzLmh0bWwjbWFuYWdpbmctcGFnZXNcbiAqICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXMuWy9lbl1cbiAqICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zcGxpdHRlci1jb250ZW50XG4gKiAgW2VuXVRoZSBgPG9ucy1zcGxpdHRlci1jb250ZW50PmAgY29tcG9uZW50IGNvbnRhaW5zIHRoZSBtYWluIGNvbnRlbnQgb2YgdGhlIHBhZ2UuWy9lbl1cbiAqICBbamFdb25zLXNwbGl0dGVyLWNvbnRlbnTjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLXNwbGl0dGVyLXNpZGVcbiAqICBbZW5dVGhlIGA8b25zLXNwbGl0dGVyLXNpZGU+YCBjb21wb25lbnQgY29udGFpbnMgdGhlIG1lbnUuWy9lbl1cbiAqICBbamFdb25zLXNwbGl0dGVyLXNpZGXjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQGV4YW1wbGVcbiAqIDxvbnMtc3BsaXR0ZXIgaWQ9XCJzcGxpdHRlclwiPlxuICogICA8b25zLXNwbGl0dGVyLWNvbnRlbnQ+XG4gKiAgICAgLi4uXG4gKiAgIDwvb25zLXNwbGl0dGVyLWNvbnRlbnQ+XG4gKlxuICogICA8b25zLXNwbGl0dGVyLXNpZGUgc2lkZT1cImxlZnRcIiB3aWR0aD1cIjgwJVwiIGNvbGxhcHNlIHN3aXBlYWJsZT5cbiAqICAgICAuLi5cbiAqICAgPC9vbnMtc3BsaXR0ZXItc2lkZT5cbiAqIDwvb25zLXNwbGl0dGVyPlxuICpcbiAqIDxzY3JpcHQ+XG4gKiAgIHZhciBzcGxpdHRlciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzcGxpdHRlcicpO1xuICogICBzcGxpdHRlci5sZWZ0Lm9wZW4oKTtcbiAqIDwvc2NyaXB0PlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGxpdHRlckVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgX2dldFNpZGUoc2lkZSkge1xuICAgIGNvbnN0IGVsZW1lbnQgPSB1dGlsLmZpbmRDaGlsZCh0aGlzLCBlID0+IHtcbiAgICAgIHJldHVybiB1dGlsLm1hdGNoKGUsICdvbnMtc3BsaXR0ZXItc2lkZScpICYmIGUuZ2V0QXR0cmlidXRlKCdzaWRlJykgPT09IHNpZGU7XG4gICAgfSk7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IGxlZnRcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUxlZnQgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBsZWZ0KCkge1xuICAgIHJldHVybiB0aGlzLl9nZXRTaWRlKCdsZWZ0Jyk7XG4gIH1cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSByaWdodFxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dUmlnaHQgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCByaWdodCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZ2V0U2lkZSgncmlnaHQnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgc2lkZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyc3QgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQgcmVnYXJkbGVzcyB0aGUgYWN0dWFsIHNpZGUuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGdldCBzaWRlKCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnb25zLXNwbGl0dGVyLXNpZGUnKTtcbiAgfVxuXG4gIGdldCBfc2lkZXMoKSB7XG4gICAgcmV0dXJuIFt0aGlzLmxlZnQsIHRoaXMucmlnaHRdLmZpbHRlcihlID0+IGUpO1xuICB9XG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY29udGVudFxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0hUTUxFbGVtZW50fVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIGA8b25zLXNwbGl0dGVyLWNvbnRlbnQ+YCBlbGVtZW50LlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgY29udGVudCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJ29ucy1zcGxpdHRlci1jb250ZW50Jyk7XG4gIH1cblxuICBnZXQgdG9wUGFnZSgpIHtcbiAgICByZXR1cm4gdGhpcy5jb250ZW50Ll9jb250ZW50O1xuICB9XG5cbiAgZ2V0IG1hc2soKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICdvbnMtc3BsaXR0ZXItbWFzaycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvbkRldmljZUJhY2tCdXR0b25cbiAgICogQHR5cGUge09iamVjdH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUJhY2stYnV0dG9uIGhhbmRsZXIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44Kv44Oc44K/44Oz44OP44Oz44OJ44Op44CCWy9qYV1cbiAgICovXG4gIGdldCBvbkRldmljZUJhY2tCdXR0b24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyO1xuICB9XG5cbiAgc2V0IG9uRGV2aWNlQmFja0J1dHRvbihjYWxsYmFjaykge1xuICAgIGlmICh0aGlzLl9iYWNrQnV0dG9uSGFuZGxlcikge1xuICAgICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyID0gZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIuY3JlYXRlSGFuZGxlcih0aGlzLCBjYWxsYmFjayk7XG4gIH1cblxuICBfb25EZXZpY2VCYWNrQnV0dG9uKGV2ZW50KSB7XG4gICAgdGhpcy5fc2lkZXMuc29tZShzID0+IHMuaXNPcGVuID8gcy5jbG9zZSgpIDogZmFsc2UpIHx8IGV2ZW50LmNhbGxQYXJlbnRIYW5kbGVyKCk7XG4gIH1cblxuICBfb25Nb2RlQ2hhbmdlKGUpIHtcbiAgICBpZiAoZS50YXJnZXQucGFyZW50Tm9kZSkge1xuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgdGhpcy5fbGF5b3V0KCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBfbGF5b3V0KCkge1xuICAgIHRoaXMuX3NpZGVzLmZvckVhY2goc2lkZSA9PiB7XG4gICAgICBpZiAodGhpcy5jb250ZW50KSB7XG4gICAgICAgIHRoaXMuY29udGVudC5zdHlsZVtzaWRlLnNpZGVdID0gc2lkZS5tb2RlID09PSAnc3BsaXQnID8gc2lkZS5zdHlsZS53aWR0aCA6IDA7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fb25Nb2RlQ2hhbmdlID0gdGhpcy5fb25Nb2RlQ2hhbmdlLmJpbmQodGhpcyk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgIXRoaXMubWFzayAmJiB0aGlzLmFwcGVuZENoaWxkKGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29ucy1zcGxpdHRlci1tYXNrJykpO1xuICAgICAgdGhpcy5fbGF5b3V0KCk7XG4gICAgfSk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLm9uRGV2aWNlQmFja0J1dHRvbiA9IHRoaXMuX29uRGV2aWNlQmFja0J1dHRvbi5iaW5kKHRoaXMpO1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignbW9kZWNoYW5nZScsIHRoaXMuX29uTW9kZUNoYW5nZSwgZmFsc2UpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5fYmFja0J1dHRvbkhhbmRsZXIuZGVzdHJveSgpO1xuICAgIHRoaXMuX2JhY2tCdXR0b25IYW5kbGVyID0gbnVsbDtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vZGVjaGFuZ2UnLCB0aGlzLl9vbk1vZGVDaGFuZ2UsIGZhbHNlKTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7fVxuXG4gIF9zaG93KCkge1xuICAgIHV0aWwucHJvcGFnYXRlQWN0aW9uKHRoaXMsICdfc2hvdycpO1xuICB9XG5cbiAgX2hpZGUoKSB7XG4gICAgdXRpbC5wcm9wYWdhdGVBY3Rpb24odGhpcywgJ19oaWRlJyk7XG4gIH1cblxuICBfZGVzdHJveSgpIHtcbiAgICB1dGlsLnByb3BhZ2F0ZUFjdGlvbih0aGlzLCAnX2Rlc3Ryb3knKTtcbiAgICB0aGlzLnJlbW92ZSgpO1xuICB9XG5cbiAgc3RhdGljIHJlZ2lzdGVyQW5pbWF0b3IobmFtZSwgQW5pbWF0b3IpIHtcbiAgICBpZiAoIShBbmltYXRvciBpbnN0YW5jZW9mIFNwbGl0dGVyQW5pbWF0b3IpKSB7XG4gICAgICB1dGlsLnRocm93QW5pbWF0b3IoJ1NwbGl0dGVyJyk7XG4gICAgfVxuICAgIF9hbmltYXRvckRpY3RbbmFtZV0gPSBBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgU3BsaXR0ZXJBbmltYXRvcigpIHtcbiAgICByZXR1cm4gU3BsaXR0ZXJBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgYW5pbWF0b3JzKCkge1xuICAgIHJldHVybiBfYW5pbWF0b3JEaWN0O1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlNwbGl0dGVyID0gU3BsaXR0ZXJFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc3BsaXR0ZXInLCBTcGxpdHRlckVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgdXRpbCBmcm9tICcuLi9vbnMvdXRpbCc7XG5pbXBvcnQgQW5pbWF0b3JGYWN0b3J5IGZyb20gJy4uL29ucy9pbnRlcm5hbC9hbmltYXRvci1mYWN0b3J5JztcbmltcG9ydCBvcmllbnRhdGlvbiBmcm9tICcuLi9vbnMvb3JpZW50YXRpb24nO1xuaW1wb3J0IGludGVybmFsIGZyb20gJy4uL29ucy9pbnRlcm5hbCc7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuL2Jhc2UvYmFzZS1lbGVtZW50JztcbmltcG9ydCBTcGxpdHRlckFuaW1hdG9yIGZyb20gJy4vb25zLXNwbGl0dGVyL2FuaW1hdG9yJztcbmltcG9ydCBTd2lwZVJldmVhbCBmcm9tICcuLi9vbnMvaW50ZXJuYWwvc3dpcGUtcmV2ZWFsJztcbmltcG9ydCBEb29yTG9jayBmcm9tICcuLi9vbnMvZG9vcmxvY2snO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgeyBQYWdlTG9hZGVyLCBkZWZhdWx0UGFnZUxvYWRlcn0gZnJvbSAnLi4vb25zL3BhZ2UtbG9hZGVyJztcbmltcG9ydCBTcGxpdHRlckVsZW1lbnQgZnJvbSAnLi9vbnMtc3BsaXR0ZXInO1xuXG5jb25zdCBTUExJVF9NT0RFID0gJ3NwbGl0JztcbmNvbnN0IENPTExBUFNFX01PREUgPSAnY29sbGFwc2UnO1xuY29uc3QgQ0xPU0VEX1NUQVRFID0gJ2Nsb3NlZCc7XG5jb25zdCBPUEVOX1NUQVRFID0gJ29wZW4nO1xuY29uc3QgQ0hBTkdJTkdfU1RBVEUgPSAnY2hhbmdpbmcnO1xuXG5jb25zdCByZXdyaXRhYmxlcyA9IHtcbiAgLyoqXG4gICAqIEBwYXJhbSB7RWxlbWVudH0gc3BsaXR0ZXJTaWRlRWxlbWVudFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgcmVhZHkoc3BsaXR0ZXJTaWRlRWxlbWVudCwgY2FsbGJhY2spIHtcbiAgICBzZXRJbW1lZGlhdGUoY2FsbGJhY2spO1xuICB9XG59O1xuXG5jbGFzcyBDb2xsYXBzZURldGVjdGlvbiB7XG4gIGNvbnN0cnVjdG9yKGVsZW1lbnQsIHRhcmdldCkge1xuICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgIHRoaXMuX29uQ2hhbmdlID0gdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzKTtcbiAgICB0YXJnZXQgJiYgdGhpcy5jaGFuZ2VUYXJnZXQodGFyZ2V0KTtcbiAgfVxuXG4gIGNoYW5nZVRhcmdldCh0YXJnZXQpIHtcbiAgICB0aGlzLmRpc2FibGUoKTtcbiAgICB0aGlzLl90YXJnZXQgPSB0YXJnZXQ7XG4gICAgaWYgKHRhcmdldCkge1xuICAgICAgdGhpcy5fb3JpZW50YXRpb24gPSBbJ3BvcnRyYWl0JywgJ2xhbmRzY2FwZSddLmluZGV4T2YodGFyZ2V0KSAhPT0gLTE7XG4gICAgICB0aGlzLmFjdGl2YXRlKCk7XG4gICAgfVxuICB9XG5cbiAgX21hdGNoKHZhbHVlKSB7XG4gICAgaWYgKHRoaXMuX29yaWVudGF0aW9uKSB7XG4gICAgICByZXR1cm4gdGhpcy5fdGFyZ2V0ID09PSAodmFsdWUuaXNQb3J0cmFpdCA/ICdwb3J0cmFpdCcgOiAnbGFuZHNjYXBlJyk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZS5tYXRjaGVzO1xuICB9XG5cbiAgX29uQ2hhbmdlKHZhbHVlKSB7XG4gICAgdGhpcy5fZWxlbWVudC5fdXBkYXRlTW9kZSh0aGlzLl9tYXRjaCh2YWx1ZSkgPyBDT0xMQVBTRV9NT0RFIDogU1BMSVRfTU9ERSk7XG4gIH1cblxuICBhY3RpdmF0ZSgpIHtcbiAgICBpZiAodGhpcy5fb3JpZW50YXRpb24pIHtcbiAgICAgIG9yaWVudGF0aW9uLm9uKCdjaGFuZ2UnLCB0aGlzLl9vbkNoYW5nZSk7XG4gICAgICB0aGlzLl9vbkNoYW5nZSh7aXNQb3J0cmFpdDogb3JpZW50YXRpb24uaXNQb3J0cmFpdCgpfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX3F1ZXJ5UmVzdWx0ID0gd2luZG93Lm1hdGNoTWVkaWEodGhpcy5fdGFyZ2V0KTtcbiAgICAgIHRoaXMuX3F1ZXJ5UmVzdWx0LmFkZExpc3RlbmVyKHRoaXMuX29uQ2hhbmdlKTtcbiAgICAgIHRoaXMuX29uQ2hhbmdlKHRoaXMuX3F1ZXJ5UmVzdWx0KTtcbiAgICB9XG4gIH1cblxuICBkaXNhYmxlKCkge1xuICAgIGlmICh0aGlzLl9vcmllbnRhdGlvbikge1xuICAgICAgb3JpZW50YXRpb24ub2ZmKCdjaGFuZ2UnLCB0aGlzLl9vbkNoYW5nZSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLl9xdWVyeVJlc3VsdCkge1xuICAgICAgdGhpcy5fcXVlcnlSZXN1bHQucmVtb3ZlTGlzdGVuZXIodGhpcy5fb25DaGFuZ2UpO1xuICAgICAgdGhpcy5fcXVlcnlSZXN1bHQgPSBudWxsO1xuICAgIH1cbiAgfVxufVxuXG5jb25zdCB3aWR0aFRvUHggPSAod2lkdGgsIHBhcmVudCkgPT4ge1xuICBjb25zdCBbdmFsdWUsIHB4XSA9IFtwYXJzZUludCh3aWR0aCwgMTApLCAvcHgvLnRlc3Qod2lkdGgpXTtcbiAgcmV0dXJuIHB4ID8gdmFsdWUgOiBNYXRoLnJvdW5kKHBhcmVudC5vZmZzZXRXaWR0aCAqIHZhbHVlIC8gMTAwKTtcbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXNwbGl0dGVyLXNpZGVcbiAqIEBjYXRlZ29yeSBtZW51XG4gKiBAZGVzY3JpcHRpb25cbiAqICBbZW5dXG4gKiAgICBUaGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQgaXMgdXNlZCBhcyBhIGNoaWxkIGVsZW1lbnQgb2YgYDxvbnMtc3BsaXR0ZXI+YC5cbiAqXG4gKiAgICBJdCB3aWxsIGJlIGRpc3BsYXllZCBvbiBlaXRoZXIgdGhlIGxlZnQgb3IgcmlnaHQgc2lkZSBvZiB0aGUgYDxvbnMtc3BsaXR0ZXItY29udGVudD5gIGVsZW1lbnQuXG4gKlxuICogICAgSXQgc3VwcG9ydHMgdHdvIG1vZGVzOiBjb2xsYXBzZWQgYW5kIHNwbGl0LiBXaGVuIGl0J3MgaW4gY29sbGFwc2VkIG1vZGUgaXQgd2lsbCBiZSBoaWRkZW4gZnJvbSB2aWV3IGFuZCBjYW4gYmUgZGlzcGxheWVkIHdoZW4gdGhlIHVzZXIgc3dpcGVzIHRoZSBzY3JlZW4gb3IgdGFwcyBhIGJ1dHRvbi4gSW4gc3BsaXQgbW9kZSB0aGUgZWxlbWVudCBpcyBhbHdheXMgc2hvd24uIEl0IGNhbiBiZSBjb25maWd1cmVkIHRvIGF1dG9tYXRpY2FsbHkgc3dpdGNoIGJldHdlZW4gdGhlIHR3byBtb2RlcyBkZXBlbmRpbmcgb24gdGhlIHNjcmVlbiBzaXplLlxuICogIFsvZW5dXG4gKiAgW2phXW9ucy1zcGxpdHRlci1zaWRl6KaB57Sg44Gv44CBb25zLXNwbGl0dGVy6KaB57Sg44Gu5a2Q6KaB57Sg44Go44GX44Gm5Yip55So44GX44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIHJPUU9NTFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3NwbGl0dGVyXG4gKiBAZ3VpZGUgZnVuZGFtZW50YWxzLmh0bWwjbWFuYWdpbmctcGFnZXNcbiAqICBbZW5dTWFuYWdpbmcgbXVsdGlwbGUgcGFnZXMuWy9lbl1cbiAqICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1zcGxpdHRlclxuICogIFtlbl1UaGUgYDxvbnMtc3BsaXR0ZXI+YCBpcyB0aGUgcGFyZW50IGNvbXBvbmVudC5bL2VuXVxuICogIFtqYV1vbnMtc3BsaXR0ZXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLXNwbGl0dGVyLWNvbnRlbnRcbiAqICBbZW5dVGhlIGA8b25zLXNwbGl0dGVyLWNvbnRlbnQ+YCBjb21wb25lbnQgY29udGFpbnMgdGhlIG1haW4gY29udGVudCBvZiB0aGUgcGFnZS5bL2VuXVxuICogIFtqYV1vbnMtc3BsaXR0ZXItY29udGVudOOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zcGxpdHRlcj5cbiAqICAgPG9ucy1zcGxpdHRlci1jb250ZW50PlxuICogICAgIC4uLlxuICogICA8L29ucy1zcGxpdHRlci1jb250ZW50PlxuICpcbiAqICAgPG9ucy1zcGxpdHRlci1zaWRlIHNpZGU9XCJsZWZ0XCIgd2lkdGg9XCI4MCVcIiBjb2xsYXBzZT5cbiAqICAgICAuLi5cbiAqICAgPC9vbnMtc3BsaXR0ZXItc2lkZT5cbiAqIDwvb25zLXNwbGl0dGVyPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTcGxpdHRlclNpZGVFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgbW9kZWNoYW5nZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZWQganVzdCBhZnRlciB0aGUgY29tcG9uZW50J3MgbW9kZSBjaGFuZ2VzLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruimgee0oOOBruODouODvOODieOBjOWkieWMluOBl+OBn+mam+OBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnNpZGVcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gZXZlbnQubW9kZVxuICAgKiAgIFtlbl1SZXR1cm5zIHRoZSBjdXJyZW50IG1vZGUuIENhbiBiZSBlaXRoZXIgYFwiY29sbGFwc2VcImAgb3IgYFwic3BsaXRcImAuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Gu44Oi44O844OJ44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwcmVvcGVuXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlZCBqdXN0IGJlZm9yZSB0aGUgc2xpZGluZyBtZW51IGlzIG9wZW5lZC5bL2VuXVxuICAgKiAgIFtqYV3jgrnjg6njgqTjg4fjgqPjg7PjgrDjg6Hjg4vjg6Xjg7zjgYzplovjgY/liY3jgavnmbrngavjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnRcbiAgICogICBbZW5dRXZlbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOCquODluOCuOOCp+OCr+ODiOOBp+OBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGV2ZW50LmNhbmNlbFxuICAgKiAgIFtlbl1DYWxsIHRvIGNhbmNlbCBvcGVuaW5nIHNsaWRpbmcgbWVudS5bL2VuXVxuICAgKiAgIFtqYV3jgrnjg6njgqTjg4fjgqPjg7PjgrDjg6Hjg4vjg6Xjg7zjgYzplovjgY/jga7jgpLjgq3jg6Pjg7Pjgrvjg6vjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuc2lkZVxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdG9wZW5cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIHNsaWRpbmcgbWVudSBpcyBvcGVuZWQuWy9lbl1cbiAgICogICBbamFd44K544Op44Kk44OH44Kj44Oz44Kw44Oh44OL44Ol44O844GM6ZaL44GE44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuc2lkZVxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlY2xvc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYmVmb3JlIHRoZSBzbGlkaW5nIG1lbnUgaXMgY2xvc2VkLlsvZW5dXG4gICAqICAgW2phXeOCueODqeOCpOODh+OCo+ODs+OCsOODoeODi+ODpeODvOOBjOmWieOBmOOCi+WJjeOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44Gn44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnNpZGVcbiAgICogICBbZW5dQ29tcG9uZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgrPjg7Pjg53jg7zjg43jg7Pjg4jjga7jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0byBjYW5jZWwgb3BlbmluZyBzbGlkaW5nLW1lbnUuWy9lbl1cbiAgICogICBbamFd44K544Op44Kk44OH44Kj44Oz44Kw44Oh44OL44Ol44O844GM6ZaJ44GY44KL44Gu44KS44Kt44Oj44Oz44K744Or44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBldmVudCBwb3N0Y2xvc2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIGp1c3QgYWZ0ZXIgdGhlIHNsaWRpbmcgbWVudSBpcyBjbG9zZWQuWy9lbl1cbiAgICogICBbamFd44K544Op44Kk44OH44Kj44Oz44Kw44Oh44OL44Ol44O844GM6ZaJ44GY44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgafjgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gZXZlbnQuc2lkZVxuICAgKiAgIFtlbl1Db21wb25lbnQgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCs+ODs+ODneODvOODjeODs+ODiOOBruOCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCAgZGVmYXVsdFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24uIFVzZSBvbmUgb2YgYG92ZXJsYXlgLCBgcHVzaGAsIGByZXZlYWxgIG9yICBgZGVmYXVsdGAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PjgpLmjIflrprjgZfjgb7jgZnjgIJcIm92ZXJsYXlcIiwgXCJwdXNoXCIsIFwicmV2ZWFsXCIsIFwiZGVmYXVsdFwi44Gu44GE44Ga44KM44GL44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYW5pbWF0aW9uLW9wdGlvbnNcbiAgICogQHR5cGUge0V4cHJlc3Npb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCB0aW1pbmcgYW5kIGRlbGF5IHdpdGggYW4gb2JqZWN0IGxpdGVyYWwuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMSwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCB0aW1pbmcsIGRlbGF544KS44Kq44OW44K444Kn44Kv44OI44Oq44OG44Op44Or44Gn5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG9wZW4tdGhyZXNob2xkXG4gICAqIEB0eXBlIHtOdW1iZXJ9XG4gICAqIEBkZWZhdWx0ICAwLjNcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dU3BlY2lmeSBob3cgbXVjaCB0aGUgbWVudSBuZWVkcyB0byBiZSBzd2lwZWQgYmVmb3JlIG9wZW5pbmcuIEEgdmFsdWUgYmV0d2VlbiBgMGAgYW5kIGAxYC5bL2VuXVxuICAgKiAgW2phXeOBqeOBruOBj+OCieOBhOOCueODr+OCpOODl+OBmeOCjOOBsOOCueODqeOCpOODh+OCo+ODs+OCsOODoeODi+ODpeODvOOCkumWi+OBj+OBi+OBqeOBhuOBi+OBruWJsuWQiOOCkuaMh+WumuOBl+OBvuOBmeOAgjDjgYvjgokx44Gu6ZaT44Gu5pWw5YCk44KS5oyH5a6a44GX44G+44GZ44CC44K544Ov44Kk44OX44Gu6Led6Zui44GM44GT44GT44Gn5oyH5a6a44GX44Gf5pWw5YCk5o6b44GR44KL44GT44Gu6KaB57Sg44Gu5bmF44KI44KK44KC5aSn44GN44GR44KM44Gw44CB44K544Ov44Kk44OX44GM57WC44KP44Gj44Gf5pmC44Gr44GT44Gu6KaB57Sg44KS6ZaL44GN44G+44GZ44CC44OH44OV44Kp44Or44OI44GvMC4z44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY29sbGFwc2VcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgU3BlY2lmeSB0aGUgY29sbGFwc2UgYmVoYXZpb3IuIFZhbGlkIHZhbHVlcyBhcmUgYFwicG9ydHJhaXRcImAsIGBcImxhbmRzY2FwZVwiYCBvciBhIG1lZGlhIHF1ZXJ5LlxuICAgKiAgICAgVGhlIHN0cmluZ3MgYFwicG9ydHJhaXRcImAgYW5kIGBcImxhbmRzY2FwZVwiYCBtZWFucyB0aGUgdmlldyB3aWxsIGNvbGxhcHNlIHdoZW4gZGV2aWNlIGlzIGluIGxhbmRzY2FwZSBvciBwb3J0cmFpdCBvcmllbnRhdGlvbi5cbiAgICogICAgIElmIHRoZSB2YWx1ZSBpcyBhIG1lZGlhIHF1ZXJ5LCB0aGUgdmlldyB3aWxsIGNvbGxhcHNlIHdoZW4gdGhlIG1lZGlhIHF1ZXJ5IHJlc29sdmVzIHRvIGB0cnVlYC5cbiAgICogICAgIElmIHRoZSB2YWx1ZSBpcyBub3QgZGVmaW5lZCwgdGhlIHZpZXcgYWx3YXlzIGJlIGluIGBcImNvbGxhcHNlXCJgIG1vZGUuXG4gICAqICAgWy9lbl1cbiAgICogICBbamFdXG4gICAqICAgICDlt6blgbTjga7jg5rjg7zjgrjjgpLpnZ7ooajnpLrjgavjgZnjgovmnaHku7bjgpLmjIflrprjgZfjgb7jgZnjgIJwb3J0cmFpdCwgbGFuZHNjYXBl44CBd2lkdGggI3B444KC44GX44GP44Gv44Oh44OH44Kj44Ki44Kv44Ko44Oq44Gu5oyH5a6a44GM5Y+v6IO944Gn44GZ44CCXG4gICAqICAgICBwb3J0cmFpdOOCguOBl+OBj+OBr2xhbmRzY2FwZeOCkuaMh+WumuOBmeOCi+OBqOOAgeODh+ODkOOCpOOCueOBrueUu+mdouOBjOe4puWQkeOBjeOCguOBl+OBj+OBr+aoquWQkeOBjeOBq+OBquOBo+OBn+aZguOBq+mBqeeUqOOBleOCjOOBvuOBmeOAglxuICAgKiAgICAg44Oh44OH44Kj44Ki44Kv44Ko44Oq44KS5oyH5a6a44GZ44KL44Go44CB5oyH5a6a44GX44Gf44Kv44Ko44Oq44Gr6YGp5ZCI44GX44Gm44GE44KL5aC05ZCI44Gr6YGp55So44GV44KM44G+44GZ44CCXG4gICAqICAgICDlgKTjgavkvZXjgoLmjIflrprjgZfjgarjgYTloLTlkIjjgavjga/jgIHluLjjgatjb2xsYXBzZeODouODvOODieOBq+OBquOCiuOBvuOBmeOAglxuICAgKiAgIFsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHN3aXBlLXRhcmdldC13aWR0aFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dVGhlIHdpZHRoIG9mIHN3aXBlYWJsZSBhcmVhIGNhbGN1bGF0ZWQgZnJvbSB0aGUgZWRnZSAoaW4gcGl4ZWxzKS4gVXNlIHRoaXMgdG8gZW5hYmxlIHN3aXBlIG9ubHkgd2hlbiB0aGUgZmluZ2VyIHRvdWNoIG9uIHRoZSBzY3JlZW4gZWRnZS5bL2VuXVxuICAgKiAgIFtqYV3jgrnjg6/jgqTjg5fjga7liKTlrprpoJjln5/jgpLjg5Tjgq/jgrvjg6vljZjkvY3jgafmjIflrprjgZfjgb7jgZnjgILnlLvpnaLjga7nq6/jgYvjgonmjIflrprjgZfjgZ/ot53pm6LjgavpgZTjgZnjgovjgajjg5rjg7zjgrjjgYzooajnpLrjgZXjgozjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSB3aWR0aFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ2FuIGJlIHNwZWNpZmllZCBpbiBlaXRoZXIgcGl4ZWxzIG9yIGFzIGEgcGVyY2VudGFnZSwgZS5nLiBgOTAlYCBvciBgMjAwcHhgLlsvZW5dXG4gICAqICAgW2phXeOBk+OBruimgee0oOOBruaoquW5heOCkuaMh+WumuOBl+OBvuOBmeOAgnB444GoJeOBp+OBruaMh+WumuOBjOWPr+iDveOBp+OBmeOAgmVnLiA5MCUsIDIwMHB4Wy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc2lkZVxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVmYXVsdCBsZWZ0XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1TcGVjaWZ5IHdoaWNoIHNpZGUgb2YgdGhlIHNjcmVlbiB0aGUgYDxvbnMtc3BsaXR0ZXItc2lkZT5gIGVsZW1lbnQgaXMgbG9jYXRlZC4gUG9zc2libGUgdmFsdWVzIGFyZSBgXCJsZWZ0XCJgIGFuZCBgXCJyaWdodFwiYC5bL2VuXVxuICAgKiAgIFtqYV3jgZPjga7opoHntKDjgYzlt6bjgYvlj7PjgYvjgpLmjIflrprjgZfjgb7jgZnjgILmjIflrprjgafjgY3jgovlgKTjga9cImxlZnRcIuOBi1wicmlnaHRcIuOBruOBv+OBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIG1vZGVcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgbW9kZS4gUG9zc2libGUgdmFsdWVzIGFyZSBgXCJjb2xsYXBzZVwiYCBvciBgXCJzcGxpdFwiYC4gVGhpcyBhdHRyaWJ1dGUgaXMgcmVhZCBvbmx5LlsvZW5dXG4gICAqICAgW2phXeePvuWcqOOBruODouODvOODieOBjOioreWumuOBleOCjOOBvuOBmeOAglwiY29sbGFwc2VcIuOCguOBl+OBj+OBr1wic3BsaXRcIuOBjOaMh+WumuOBleOCjOOBvuOBmeOAguOBk+OBruWxnuaAp+OBr+iqreOBv+i+vOOBv+WwgueUqOOBp+OBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHBhZ2VcbiAgICogQGluaXRvbmx5XG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgVVJMIG9mIHRoZSBtZW51IHBhZ2UuWy9lbl1cbiAgICogICBbamFdb25zLXNwbGl0dGVyLXNpZGXopoHntKDjgavooajnpLrjgZnjgovjg5rjg7zjgrjjga5VUkzjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBzd2lwZWFibGVcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRvIGVuYWJsZSBzd2lwZSBpbnRlcmFjdGlvbiBvbiBjb2xsYXBzZSBtb2RlLlsvZW5dXG4gICAqICAgW2phXWNvbGxhcHNl44Oi44O844OJ5pmC44Gr44K544Ov44Kk44OX5pON5L2c44KS5pyJ5Yq544Gr44GZ44KL5aC05ZCI44Gr5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX3BhZ2UgPSBudWxsO1xuICAgIHRoaXMuX3N0YXRlID0gQ0xPU0VEX1NUQVRFO1xuICAgIHRoaXMuX2xvY2sgPSBuZXcgRG9vckxvY2soKTtcbiAgICB0aGlzLl9wYWdlTG9hZGVyID0gZGVmYXVsdFBhZ2VMb2FkZXI7XG4gICAgdGhpcy5fY29sbGFwc2VEZXRlY3Rpb24gPSBuZXcgQ29sbGFwc2VEZXRlY3Rpb24odGhpcyk7XG5cbiAgICB0aGlzLl9hbmltYXRvckZhY3RvcnkgPSBuZXcgQW5pbWF0b3JGYWN0b3J5KHtcbiAgICAgIGFuaW1hdG9yczogU3BsaXR0ZXJFbGVtZW50LmFuaW1hdG9ycyxcbiAgICAgIGJhc2VDbGFzczogU3BsaXR0ZXJBbmltYXRvcixcbiAgICAgIGJhc2VDbGFzc05hbWU6ICdTcGxpdHRlckFuaW1hdG9yJyxcbiAgICAgIGRlZmF1bHRBbmltYXRpb246IHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24nKVxuICAgIH0pO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIC8vIFRoZXNlIGF0dHJpYnV0ZXMgYXJlIHVzZWQgZWFybHkgYnkgdGhlIHBhcmVudCBlbGVtZW50XG4gICAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnd2lkdGgnKTtcbiAgICAgIGlmICghdGhpcy5oYXNBdHRyaWJ1dGUoJ3NpZGUnKSkge1xuICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnc2lkZScsICdsZWZ0Jyk7XG4gICAgICB9XG5cbiAgICAgIHJld3JpdGFibGVzLnJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgY29uc3QgcGFnZSA9IHRoaXMuX3BhZ2UgfHwgdGhpcy5nZXRBdHRyaWJ1dGUoJ3BhZ2UnKTtcbiAgICAgICAgcGFnZSAmJiB0aGlzLmxvYWQocGFnZSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGNvbm5lY3RlZENhbGxiYWNrKCkge1xuICAgIGlmICghdXRpbC5tYXRjaCh0aGlzLnBhcmVudE5vZGUsICdvbnMtc3BsaXR0ZXInKSkge1xuICAgICAgdXRpbC50aHJvdygnUGFyZW50IG11c3QgYmUgYW4gb25zLXNwbGl0dGVyIGVsZW1lbnQnKTtcbiAgICB9XG5cbiAgICB0aGlzLl9zd2lwZSA9IG5ldyBTd2lwZVJldmVhbCh7XG4gICAgICBlbGVtZW50OiB0aGlzLFxuICAgICAgZWxlbWVudEhhbmRsZXI6IHRoaXMucGFyZW50RWxlbWVudCxcbiAgICAgIHN3aXBlTWF4OiAoKSA9PiB7XG4gICAgICAgIHRoaXMuX29uU3dpcGUgJiYgdGhpcy5fb25Td2lwZSgxLCB0aGlzLl9hbmltYXRpb25PcHQpO1xuICAgICAgICB0aGlzLm9wZW4oKTtcbiAgICAgIH0sXG4gICAgICBzd2lwZU1pZDogKGRpc3RhbmNlLCB3aWR0aCkgPT4ge1xuICAgICAgICB0aGlzLl9vblN3aXBlICYmIHRoaXMuX29uU3dpcGUoZGlzdGFuY2Uvd2lkdGgpO1xuICAgICAgICB0aGlzLl9hbmltYXRvci50cmFuc2xhdGUoZGlzdGFuY2UpO1xuICAgICAgfSxcbiAgICAgIHN3aXBlTWluOiAoKSA9PiB7XG4gICAgICAgIHRoaXMuX29uU3dpcGUgJiYgdGhpcy5fb25Td2lwZSgwLCB0aGlzLl9hbmltYXRpb25PcHQpO1xuICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICB9LFxuICAgICAgZ2V0VGhyZXNob2xkOiAoKSA9PiBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBwYXJzZUZsb2F0KHRoaXMuZ2V0QXR0cmlidXRlKCdvcGVuLXRocmVzaG9sZCcpKSB8fCAwLjMpKSxcbiAgICAgIGdldFNpZGU6ICgpID0+IHRoaXMuc2lkZSxcbiAgICAgIGlzSW5pdGlhbFN0YXRlOiAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGNsb3NlZCA9IHRoaXMuX3N0YXRlID09PSBDTE9TRURfU1RBVEU7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gQ0hBTkdJTkdfU1RBVEU7XG4gICAgICAgIHJldHVybiBjbG9zZWQ7XG4gICAgICB9LFxuICAgICAgaWdub3JlU3dpcGU6IChldmVudCwgZGlzdGFuY2UpID0+IHtcbiAgICAgICAgY29uc3QgaXNPcGVuID0gdGhpcy5pc09wZW47XG4gICAgICAgIGNvbnN0IHZhbGlkRHJhZyA9IGQgPT4gdGhpcy5zaWRlID09PSAnbGVmdCdcbiAgICAgICAgICA/ICgoZCA9PT0gJ2xlZnQnICYmIGlzT3BlbikgfHwgKGQgPT09ICdyaWdodCcgJiYgIWlzT3BlbikpXG4gICAgICAgICAgOiAoKGQgPT09ICdsZWZ0JyAmJiAhaXNPcGVuKSB8fCAoZCA9PT0gJ3JpZ2h0JyAmJiBpc09wZW4pKTtcblxuICAgICAgICBjb25zdCBhcmVhID0gTWF0aC5tYXgoMCwgcGFyc2VJbnQodGhpcy5nZXRBdHRyaWJ1dGUoJ3N3aXBlLXRhcmdldC13aWR0aCcpLCAxMCkgfHwgMCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX21vZGUgPT09IFNQTElUX01PREUgfHwgdGhpcy5fbG9jay5pc0xvY2tlZCgpIHx8IHRoaXMuX2lzT3RoZXJTaWRlT3BlbigpXG4gICAgICAgICAgfHwgIXZhbGlkRHJhZyhldmVudC5nZXN0dXJlLmRpcmVjdGlvbilcbiAgICAgICAgICB8fCAoIWlzT3BlbiAmJiBhcmVhICE9PSAwICYmIGRpc3RhbmNlID4gYXJlYSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnc3dpcGVhYmxlJyk7XG5cbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5vYnNlcnZlZEF0dHJpYnV0ZXMuZm9yRWFjaChhdHRyID0+IHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKGF0dHIsIG51bGwsIHRoaXMuZ2V0QXR0cmlidXRlKGF0dHIpKSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgc2lkZSgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRBdHRyaWJ1dGUoJ3NpZGUnKSA9PT0gJ3JpZ2h0JyA/ICdyaWdodCcgOiAnbGVmdCc7XG4gIH1cblxuICBkaXNjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICB0aGlzLl9zd2lwZSAmJiB0aGlzLl9zd2lwZS5kaXNwb3NlKCk7XG4gICAgdGhpcy5fYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRpb25PcHQgPSB0aGlzLl9zd2lwZSA9IG51bGw7XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWydhbmltYXRpb24nLCAnd2lkdGgnLCAnY29sbGFwc2UnLCAnc3dpcGVhYmxlJywgJ2FuaW1hdGlvbi1vcHRpb25zJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIHN3aXRjaCAobmFtZSkge1xuICAgICAgY2FzZSAnc3dpcGVhYmxlJzpcbiAgICAgICAgdGhpcy5fc3dpcGUgJiYgdGhpcy5fc3dpcGUudXBkYXRlKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnd2lkdGgnOlxuICAgICAgICBjdXJyZW50ID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3dpZHRoJyk7IC8vIFNvbWV0aW1lcyB1bmRlZmluZWQuIENFIGJ1Zz9cbiAgICAgICAgdGhpcy5zdHlsZS53aWR0aCA9IC9eXFxkKyhweHwlKSQvLnRlc3QoY3VycmVudCkgPyBjdXJyZW50IDogJzgwJSc7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhpc1t1dGlsLmNhbWVsaXplKGBfdXBkYXRlLSR7bmFtZX1gKV0oY3VycmVudCk7XG4gICAgfVxuICB9XG5cbiAgX2VtaXRFdmVudChuYW1lKSB7XG4gICAgaWYgKG5hbWUuc2xpY2UoMCwgMykgIT09ICdwcmUnKSB7XG4gICAgICByZXR1cm4gdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsIG5hbWUsIHtzaWRlOiB0aGlzfSk7XG4gICAgfVxuICAgIGxldCBpc0NhbmNlbGVkID0gZmFsc2U7XG5cbiAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgbmFtZSwge1xuICAgICAgc2lkZTogdGhpcyxcbiAgICAgIGNhbmNlbDogKCkgPT4gaXNDYW5jZWxlZCA9IHRydWVcbiAgICB9KTtcblxuICAgIHJldHVybiBpc0NhbmNlbGVkO1xuICB9XG5cbiAgX2lzT3RoZXJTaWRlT3BlbigpIHtcbiAgICByZXR1cm4gISF1dGlsLmZpbmRDaGlsZCh0aGlzLnBhcmVudEVsZW1lbnQsXG4gICAgICBlbCA9PiBlbCBpbnN0YW5jZW9mIHRoaXMuY29uc3RydWN0b3IgJiYgZWwgIT09IHRoaXMgJiYgZWwuX21vZGUgPT09IENPTExBUFNFX01PREUgJiYgZWwuaXNPcGVuXG4gICAgKTtcbiAgfVxuXG4gIF91cGRhdGVDb2xsYXBzZSh2YWx1ZSA9IHRoaXMuZ2V0QXR0cmlidXRlKCdjb2xsYXBzZScpKSB7XG4gICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSAnc3BsaXQnKSB7XG4gICAgICB0aGlzLl9jb2xsYXBzZURldGVjdGlvbi5kaXNhYmxlKCk7XG4gICAgICByZXR1cm4gdGhpcy5fdXBkYXRlTW9kZShTUExJVF9NT0RFKTtcbiAgICB9XG4gICAgaWYgKHZhbHVlID09PSAnJyB8fCB2YWx1ZSA9PT0gJ2NvbGxhcHNlJykge1xuICAgICAgdGhpcy5fY29sbGFwc2VEZXRlY3Rpb24uZGlzYWJsZSgpO1xuICAgICAgcmV0dXJuIHRoaXMuX3VwZGF0ZU1vZGUoQ09MTEFQU0VfTU9ERSk7XG4gICAgfVxuXG4gICAgdGhpcy5fY29sbGFwc2VEZXRlY3Rpb24uY2hhbmdlVGFyZ2V0KHZhbHVlKTtcbiAgfVxuXG4gIF91cGRhdGVNb2RlKG1vZGUpIHtcbiAgICBpZiAobW9kZSAhPT0gdGhpcy5fbW9kZSkge1xuICAgICAgdGhpcy5fbW9kZSA9IG1vZGU7XG4gICAgICB0aGlzLnNldEF0dHJpYnV0ZSgnbW9kZScsIG1vZGUpOyAvLyByZWFkb25seSBhdHRyaWJ1dGUgZm9yIHRoZSB1c2Vyc1xuXG4gICAgICBpZiAobW9kZSA9PT0gU1BMSVRfTU9ERSkge1xuICAgICAgICB0aGlzLl9hbmltYXRvciAmJiB0aGlzLl9hbmltYXRvci5kZWFjdGl2YXRlKCk7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gQ0xPU0VEX1NUQVRFO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fYW5pbWF0b3IgJiYgdGhpcy5fYW5pbWF0b3IuYWN0aXZhdGUodGhpcyk7XG4gICAgICAgIHRoaXMuX3N0YXRlID09PSBPUEVOX1NUQVRFICYmIHRoaXMuX2FuaW1hdG9yLm9wZW4oKTtcbiAgICAgIH1cblxuICAgICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdtb2RlY2hhbmdlJywgeyBzaWRlOiB0aGlzLCBtb2RlIH0pO1xuICAgIH1cbiAgfVxuXG4gIF91cGRhdGVBbmltYXRpb24oYW5pbWF0aW9uID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ2FuaW1hdGlvbicpKSB7XG4gICAgaWYgKHRoaXMucGFyZW50Tm9kZSkge1xuICAgICAgdGhpcy5fYW5pbWF0b3IgJiYgdGhpcy5fYW5pbWF0b3IuZGVhY3RpdmF0ZSgpO1xuICAgICAgdGhpcy5fYW5pbWF0b3IgPSB0aGlzLl9hbmltYXRvckZhY3RvcnkubmV3QW5pbWF0b3Ioe2FuaW1hdGlvbn0pO1xuICAgICAgdGhpcy5fYW5pbWF0b3IuYWN0aXZhdGUodGhpcyk7XG4gICAgICB0aGlzLl9hbmltYXRpb25PcHQgPSB7XG4gICAgICAgIHRpbWluZzogdGhpcy5fYW5pbWF0b3IuZHVyYXRpb24sXG4gICAgICAgIGR1cmF0aW9uOiB0aGlzLl9hbmltYXRvci5kdXJhdGlvblxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlQW5pbWF0aW9uT3B0aW9ucyh2YWx1ZSA9IHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKSB7XG4gICAgdGhpcy5fYW5pbWF0b3IudXBkYXRlT3B0aW9ucyhBbmltYXRvckZhY3RvcnkucGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nKHZhbHVlKSk7XG4gIH1cblxuICAvKipcbiAgICogQHByb3BlcnR5IHBhZ2VcbiAgICogQHR5cGUgeyp9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1QYWdlIGxvY2F0aW9uIHRvIGxvYWQgaW4gdGhlIHNwbGl0dGVyIHNpZGUuWy9lbl1cbiAgICogICBbamFd44GT44Gu6KaB57Sg5YaF44Gr6KGo56S644GZ44KL44Oa44O844K444KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG4gIGdldCBwYWdlKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7Kn0gcGFnZVxuICAgKi9cbiAgc2V0IHBhZ2UocGFnZSkge1xuICAgIHRoaXMuX3BhZ2UgPSBwYWdlO1xuICB9XG5cbiAgZ2V0IF9jb250ZW50KCkge1xuICAgIHJldHVybiB0aGlzLmNoaWxkcmVuWzBdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBwYWdlTG9hZGVyXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0IHBhZ2VMb2FkZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhZ2VMb2FkZXI7XG4gIH1cblxuICBzZXQgcGFnZUxvYWRlcihsb2FkZXIpIHtcbiAgICBpZiAoIShsb2FkZXIgaW5zdGFuY2VvZiBQYWdlTG9hZGVyKSkge1xuICAgICAgdXRpbC50aHJvd1BhZ2VMb2FkZXIoKTtcbiAgICB9XG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IGxvYWRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgbW9kZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUN1cnJlbnQgbW9kZS4gUG9zc2libGUgdmFsdWVzIGFyZSBcInNwbGl0XCIsIFwiY29sbGFwc2VcIiwgXCJjbG9zZWRcIiwgXCJvcGVuXCIgb3IgXCJjaGFuZ2luZ1wiLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgbW9kZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25Td2lwZVxuICAgKiBAdHlwZSB7RnVuY3Rpb259XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Ib29rIGNhbGxlZCB3aGVuZXZlciB0aGUgdXNlciBzbGlkZXMgdGhlIHNwbGl0dGVyLiBJdCBnZXRzIGEgZGVjaW1hbCByYXRpbyAoMC0xKSBhbmQgYW4gYW5pbWF0aW9uT3B0aW9ucyBvYmplY3QgYXMgYXJndW1lbnRzLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgb25Td2lwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fb25Td2lwZTtcbiAgfVxuXG4gIHNldCBvblN3aXBlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHV0aWwudGhyb3coJ1wib25Td2lwZVwiIG11c3QgYmUgYSBmdW5jdGlvbicpXG4gICAgfVxuICAgIHRoaXMuX29uU3dpcGUgPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgaXNPcGVuXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAcmVhZG9ubHlcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoaXMgdmFsdWUgaXMgYHRydWVgIHdoZW4gdGhlIG1lbnUgaXMgb3Blbi5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cbiAgZ2V0IGlzT3BlbigpIHtcbiAgICByZXR1cm4gdGhpcy5fbW9kZSA9PT0gQ09MTEFQU0VfTU9ERSAmJiB0aGlzLl9zdGF0ZSAhPT0gQ0xPU0VEX1NUQVRFO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2Qgb3BlblxuICAgKiBAc2lnbmF0dXJlIG9wZW4oW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXVRoaXMgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgdGhlIG1lbnUgaGFzIGJlZW4gb3BlbmVkLlsvZW5dXG4gICAqICAgW2phXeODoeODi+ODpeODvOOBjOmWi+OBhOOBn+W+jOOBq+WRvOOBs+WHuuOBleOCjOOCi+mWouaVsOOCquODluOCuOOCp+OCr+ODiOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1PcGVuIG1lbnUgaW4gY29sbGFwc2UgbW9kZS5bL2VuXVxuICAgKiAgIFtqYV1jb2xsYXBzZeODouODvOODieOBq+OBquOBo+OBpuOBhOOCi29ucy1zcGxpdHRlci1zaWRl6KaB57Sg44KS6ZaL44GN44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIHNwbGl0dGVyIHNpZGUgZWxlbWVudCBvciBmYWxzZSBpZiBub3QgaW4gY29sbGFwc2UgbW9kZVsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBvcGVuKG9wdGlvbnMpIHtcbiAgICByZXR1cm4gdGhpcy50b2dnbGUob3B0aW9ucywgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBjbG9zZVxuICAgKiBAc2lnbmF0dXJlIGNsb3NlKFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiAgIFtlbl1UaGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGFmdGVyIHRoZSBtZW51IGhhcyBiZWVuIGNsb3NlZC5bL2VuXVxuICAgKiAgIFtqYV3jg6Hjg4vjg6Xjg7zjgYzplonjgZjjgZ/lvozjgavlkbzjgbPlh7rjgZXjgozjgovplqLmlbDjgqrjg5bjgrjjgqfjgq/jg4jjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dQ2xvc2UgbWVudSBpbiBjb2xsYXBzZSBtb2RlLlsvZW5dXG4gICAqICAgW2phXWNvbGxhcHNl44Oi44O844OJ44Gr44Gq44Gj44Gm44GE44KLb25zLXNwbGl0dGVyLXNpZGXopoHntKDjgpLplonjgZjjgb7jgZnjgIJbL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgc3BsaXR0ZXIgc2lkZSBlbGVtZW50IG9yIGZhbHNlIGlmIG5vdCBpbiBjb2xsYXBzZSBtb2RlWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGNsb3NlKG9wdGlvbnMpIHtcbiAgICByZXR1cm4gdGhpcy50b2dnbGUob3B0aW9ucywgZmFsc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBtZXRob2QgdG9nZ2xlXG4gICAqIEBzaWduYXR1cmUgdG9nZ2xlKFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dT3BlbnMgaWYgaXQncyBjbG9zZWQuIENsb3NlcyBpZiBpdCdzIG9wZW4uWy9lbl1cbiAgICogICBbamFd6ZaL44GR44Gm44GE44KL5aC05ZCI44Gv6KaB57Sg44KS6ZaJ44GY44G+44GZ44Gd44GX44Gm6ZaL44GR44Gm44GE44KL5aC05ZCI44Gv6KaB57Sg44KS6ZaL44GN44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIHNwbGl0dGVyIHNpZGUgZWxlbWVudCBvciBmYWxzZSBpZiBub3QgaW4gY29sbGFwc2UgbW9kZVsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICB0b2dnbGUob3B0aW9ucyA9IHt9LCBmb3JjZSkge1xuICAgIGNvbnN0IHNob3VsZE9wZW4gPSB0eXBlb2YgZm9yY2UgPT09ICdib29sZWFuJyA/IGZvcmNlIDogIXRoaXMuaXNPcGVuO1xuICAgIGNvbnN0IGFjdGlvbiA9IHNob3VsZE9wZW4gPyAnb3BlbicgOiAnY2xvc2UnO1xuICAgIGNvbnN0IEZJTkFMX1NUQVRFID0gc2hvdWxkT3BlbiA/IE9QRU5fU1RBVEUgOiBDTE9TRURfU1RBVEU7XG5cbiAgICBpZiAodGhpcy5fbW9kZSA9PT0gU1BMSVRfTU9ERSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gRklOQUxfU1RBVEUpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcyk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9sb2NrLmlzTG9ja2VkKCkpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnQW5vdGhlciBzcGxpdHRlci1zaWRlIGFjdGlvbiBpcyBhbHJlYWR5IHJ1bm5pbmcuJyk7XG4gICAgfVxuICAgIGlmIChzaG91bGRPcGVuICYmIHRoaXMuX2lzT3RoZXJTaWRlT3BlbigpKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0Fub3RoZXIgbWVudSBpcyBhbHJlYWR5IG9wZW4uJyk7XG4gICAgfVxuICAgIGlmICh0aGlzLl9lbWl0RXZlbnQoYHByZSR7YWN0aW9ufWApKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoYENhbmNlbGVkIGluIHByZSR7YWN0aW9ufSBldmVudC5gKTtcbiAgICB9XG5cbiAgICBjb25zdCB1bmxvY2sgPSB0aGlzLl9sb2NrLmxvY2soKTtcbiAgICB0aGlzLl9zdGF0ZSA9IENIQU5HSU5HX1NUQVRFO1xuXG4gICAgaWYgKG9wdGlvbnMuYW5pbWF0aW9uKSB7XG4gICAgICB0aGlzLl91cGRhdGVBbmltYXRpb24ob3B0aW9ucy5hbmltYXRpb24pO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHRoaXMuX2FuaW1hdG9yW2FjdGlvbl0oKCkgPT4ge1xuICAgICAgICB1dGlsLmlvc1BhZ2VTY3JvbGxGaXgoc2hvdWxkT3Blbik7XG4gICAgICAgIHRoaXMuX3N0YXRlID0gRklOQUxfU1RBVEU7XG4gICAgICAgIHVubG9jaygpO1xuICAgICAgICB0aGlzLl9lbWl0RXZlbnQoYHBvc3Qke2FjdGlvbn1gKTtcbiAgICAgICAgb3B0aW9ucy5jYWxsYmFjayBpbnN0YW5jZW9mIEZ1bmN0aW9uICYmIG9wdGlvbnMuY2FsbGJhY2sodGhpcyk7XG4gICAgICAgIHJlc29sdmUodGhpcyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGxvYWRcbiAgICogQHNpZ25hdHVyZSBsb2FkKHBhZ2UsIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtTdHJpbmd9IHBhZ2VcbiAgICogICBbZW5dUGFnZSBVUkwuIENhbiBiZSBlaXRoZXIgYW4gSFRNTCBkb2N1bWVudCBvciBhIGA8dGVtcGxhdGU+YC5bL2VuXVxuICAgKiAgIFtqYV1wYWdl44GuVVJM44GL44CBYDx0ZW1wbGF0ZT5g44Gn5a6j6KiA44GX44Gf44OG44Oz44OX44Os44O844OI44GuaWTlsZ7mgKfjga7lgKTjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IFtvcHRpb25zLmNhbGxiYWNrXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgcGFnZSBzcGVjaWZpZWQgaW4gcGFnZVVybCBpbiB0aGUgcmlnaHQgc2VjdGlvblsvZW5dXG4gICAqICAgW2phXeaMh+WumuOBl+OBn1VSTOOCkuODoeOCpOODs+ODmuODvOOCuOOCkuiqreOBv+i+vOOBv+OBvuOBmeOAglsvamFdXG4gICAqIEByZXR1cm4ge1Byb21pc2V9XG4gICAqICAgW2VuXVJlc29sdmVzIHRvIHRoZSBuZXcgcGFnZSBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIGxvYWQocGFnZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5fcGFnZSA9IHBhZ2U7XG4gICAgY29uc3QgY2FsbGJhY2sgPSBvcHRpb25zLmNhbGxiYWNrIHx8ICgoKSA9PiB7fSk7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBsZXQgb2xkQ29udGVudCA9IHRoaXMuX2NvbnRlbnQgfHwgbnVsbDtcblxuICAgICAgdGhpcy5fcGFnZUxvYWRlci5sb2FkKHtwYWdlLCBwYXJlbnQ6IHRoaXN9LCBwYWdlRWxlbWVudCA9PiB7XG4gICAgICAgIGlmIChvbGRDb250ZW50KSB7XG4gICAgICAgICAgdGhpcy5fcGFnZUxvYWRlci51bmxvYWQob2xkQ29udGVudCk7XG4gICAgICAgICAgb2xkQ29udGVudCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGhpcy5fc2hvdygpKTtcblxuICAgICAgICBjYWxsYmFjayhwYWdlRWxlbWVudCk7XG4gICAgICAgIHJlc29sdmUocGFnZUVsZW1lbnQpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBfc2hvdygpIHtcbiAgICBpZiAodGhpcy5fY29udGVudCkge1xuICAgICAgdGhpcy5fY29udGVudC5fc2hvdygpO1xuICAgIH1cbiAgfVxuXG4gIF9oaWRlKCkge1xuICAgIGlmICh0aGlzLl9jb250ZW50KSB7XG4gICAgICB0aGlzLl9jb250ZW50Ll9oaWRlKCk7XG4gICAgfVxuICB9XG5cbiAgX2Rlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMuX2NvbnRlbnQpIHtcbiAgICAgIHRoaXMuX3BhZ2VMb2FkZXIudW5sb2FkKHRoaXMuX2NvbnRlbnQpO1xuICAgIH1cbiAgICB0aGlzLnJlbW92ZSgpO1xuICB9XG5cbiAgc3RhdGljIGdldCBldmVudHMoKSB7XG4gICAgcmV0dXJuIFsncHJlb3BlbicsICdwb3N0b3BlbicsICdwcmVjbG9zZScsICdwb3N0Y2xvc2UnLCAnbW9kZWNoYW5nZSddO1xuICB9XG5cbiAgc3RhdGljIGdldCByZXdyaXRhYmxlcygpIHtcbiAgICByZXR1cm4gcmV3cml0YWJsZXM7XG4gIH1cbn1cblxub25zRWxlbWVudHMuU3BsaXR0ZXJTaWRlID0gU3BsaXR0ZXJTaWRlRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXNwbGl0dGVyLXNpZGUnLCBTcGxpdHRlclNpZGVFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VDaGVja2JveEVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtY2hlY2tib3gnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi9vbnMvY29udGVudC1yZWFkeSc7XG5pbXBvcnQgR2VzdHVyZURldGVjdG9yIGZyb20gJy4uL29ucy9nZXN0dXJlLWRldGVjdG9yJztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnJzogJ3N3aXRjaC0tKicsXG4gICcuc3dpdGNoX19pbnB1dCc6ICdzd2l0Y2gtLSpfX2lucHV0JyxcbiAgJy5zd2l0Y2hfX2hhbmRsZSc6ICdzd2l0Y2gtLSpfX2hhbmRsZScsXG4gICcuc3dpdGNoX190b2dnbGUnOiAnc3dpdGNoLS0qX190b2dnbGUnXG59O1xuXG5jb25zdCBsb2NhdGlvbnMgPSB7XG4gIGlvczogWzEsIDIxXSxcbiAgbWF0ZXJpYWw6IFswLCAxNl1cbn07XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXN3aXRjaFxuICogQGNhdGVnb3J5IGZvcm1cbiAqIEBkZXNjcmlwdGlvblxuICogICBbZW5dXG4gKiAgICAgU3dpdGNoIGNvbXBvbmVudC4gVGhlIHN3aXRjaCBjYW4gYmUgdG9nZ2xlZCBib3RoIGJ5IGRyYWdnaW5nIGFuZCB0YXBwaW5nLlxuICpcbiAqICAgICBXaWxsIGF1dG9tYXRpY2FsbHkgZGlzcGxheXMgYSBNYXRlcmlhbCBEZXNpZ24gc3dpdGNoIG9uIEFuZHJvaWQgZGV2aWNlcy5cbiAqICAgWy9lbl1cbiAqICAgW2phXeOCueOCpOODg+ODgeOCkuihqOekuuOBmeOCi+OCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAglsvamFdXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiBzd2l0Y2hbL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBjb2RlcGVuIExwWFpRUVxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3N3aXRjaFxuICogQGd1aWRlIHRoZW1pbmcuaHRtbCNtb2RpZmllcnMgW2VuXU1vcmUgZGV0YWlscyBhYm91dCB0aGUgYG1vZGlmaWVyYCBhdHRyaWJ1dGVbL2VuXVtqYV1tb2RpZmllcuWxnuaAp+OBruS9v+OBhOaWuVsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy1zd2l0Y2ggY2hlY2tlZD48L29ucy1zd2l0Y2g+XG4gKiA8b25zLXN3aXRjaCBkaXNhYmxlZD48L29ucy1zd2l0Y2g+XG4gKiA8b25zLXN3aXRjaCBtb2RpZmllcj1cIm1hdGVyaWFsXCI+PC9vbnMtc3dpdGNoPlxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN3aXRjaEVsZW1lbnQgZXh0ZW5kcyBCYXNlQ2hlY2tib3hFbGVtZW50IHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKCdtb2RpZmllcicsIG51bGwsIHRoaXMuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX29uQ2hhbmdlID0gdGhpcy5fb25DaGFuZ2UuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9vblJlbGVhc2UgPSB0aGlzLl9vblJlbGVhc2UuYmluZCh0aGlzKTtcbiAgICB0aGlzLl9sYXN0VGltZVN0YW1wID0gMDtcbiAgfVxuXG4gIGdldCBfc2NoZW1lKCkge1xuICAgIHJldHVybiBzY2hlbWU7XG4gIH1cblxuICBnZXQgX2RlZmF1bHRDbGFzc05hbWUoKSB7XG4gICAgcmV0dXJuICdzd2l0Y2gnO1xuICB9XG5cbiAgZ2V0IF90ZW1wbGF0ZSgpIHtcbiAgICByZXR1cm4gYFxuICAgICAgPGlucHV0IHR5cGU9XCIke3RoaXMudHlwZX1cIiBjbGFzcz1cIiR7dGhpcy5fZGVmYXVsdENsYXNzTmFtZX1fX2lucHV0XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiJHt0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lfV9fdG9nZ2xlXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCIke3RoaXMuX2RlZmF1bHRDbGFzc05hbWV9X19oYW5kbGVcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiJHt0aGlzLl9kZWZhdWx0Q2xhc3NOYW1lfV9fdG91Y2hcIj48L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICBgO1xuICB9XG5cbiAgZ2V0IHR5cGUoKSB7XG4gICAgcmV0dXJuICdjaGVja2JveCc7XG4gIH1cblxuICAvKiBPd24gcHJvcHMgKi9cblxuICBfZ2V0UG9zaXRpb24oZSkge1xuICAgIGNvbnN0IGwgPSB0aGlzLl9sb2NhdGlvbnM7XG4gICAgcmV0dXJuIE1hdGgubWluKGxbMV0sIE1hdGgubWF4KGxbMF0sIHRoaXMuX3N0YXJ0WCArIGUuZ2VzdHVyZS5kZWx0YVgpKTtcbiAgfVxuXG4gIF9lbWl0Q2hhbmdlRXZlbnQoKSB7XG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdjaGFuZ2UnLCB7XG4gICAgICB2YWx1ZTogdGhpcy5jaGVja2VkLFxuICAgICAgc3dpdGNoOiB0aGlzLFxuICAgICAgaXNJbnRlcmFjdGl2ZTogdHJ1ZVxuICAgIH0pO1xuICB9XG5cbiAgX29uQ2hhbmdlKGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50ICYmIGV2ZW50LnN0b3BQcm9wYWdhdGlvbikge1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuXG4gICAgdGhpcy5fZW1pdENoYW5nZUV2ZW50KCk7XG4gIH1cblxuICBfb25DbGljayhldikge1xuICAgIGlmIChldi50YXJnZXQuY2xhc3NMaXN0LmNvbnRhaW5zKGAke3RoaXMuZGVmYXVsdEVsZW1lbnRDbGFzc31fX3RvdWNoYClcbiAgICAgIHx8IChldi50aW1lU3RhbXAgLSB0aGlzLl9sYXN0VGltZVN0YW1wIDwgNTApIC8vIFByZXZlbnQgc2Vjb25kIGNsaWNrIHRyaWdnZXJlZCBieSA8bGFiZWw+XG4gICAgKSB7XG4gICAgICBldi5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgICB0aGlzLl9sYXN0VGltZVN0YW1wID0gZXYudGltZVN0YW1wO1xuICB9XG5cbiAgX29uSG9sZChlKSB7XG4gICAgaWYgKCF0aGlzLmRpc2FibGVkKSB7XG4gICAgICBNb2RpZmllclV0aWwuYWRkTW9kaWZpZXIodGhpcywgJ2FjdGl2ZScpO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncmVsZWFzZScsIHRoaXMuX29uUmVsZWFzZSk7XG4gICAgfVxuICB9XG5cbiAgX29uRHJhZ1N0YXJ0KGUpIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCB8fCBbJ2xlZnQnLCAncmlnaHQnXS5pbmRleE9mKGUuZ2VzdHVyZS5kaXJlY3Rpb24pID09PSAtMSkge1xuICAgICAgTW9kaWZpZXJVdGlsLnJlbW92ZU1vZGlmaWVyKHRoaXMsICdhY3RpdmUnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBlLmNvbnN1bWVkID0gdHJ1ZTtcblxuICAgIE1vZGlmaWVyVXRpbC5hZGRNb2RpZmllcih0aGlzLCAnYWN0aXZlJyk7XG4gICAgdGhpcy5fc3RhcnRYID0gdGhpcy5fbG9jYXRpb25zW3RoaXMuY2hlY2tlZCA/IDEgOiAwXTsvLyAtIGUuZ2VzdHVyZS5kZWx0YVg7XG5cbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWcnLCB0aGlzLl9vbkRyYWcpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3JlbGVhc2UnLCB0aGlzLl9vblJlbGVhc2UpO1xuICB9XG5cbiAgX29uRHJhZyhlKSB7XG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLl9oYW5kbGUuc3R5bGUubGVmdCA9IHRoaXMuX2dldFBvc2l0aW9uKGUpICsgJ3B4JztcbiAgfVxuXG4gIF9vblJlbGVhc2UoZSkge1xuICAgIGNvbnN0IGwgPSB0aGlzLl9sb2NhdGlvbnM7XG4gICAgY29uc3QgcG9zaXRpb24gPSB0aGlzLl9nZXRQb3NpdGlvbihlKTtcbiAgICBjb25zdCBwcmV2aW91c1ZhbHVlID0gdGhpcy5jaGVja2VkO1xuXG4gICAgdGhpcy5jaGVja2VkID0gcG9zaXRpb24gPj0gKGxbMF0gKyBsWzFdKSAvIDI7XG5cbiAgICBpZiAodGhpcy5jaGVja2VkICE9PSBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICB0aGlzLl9lbWl0Q2hhbmdlRXZlbnQoKTtcbiAgICB9XG5cbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2RyYWcnLCB0aGlzLl9vbkRyYWcpO1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3JlbGVhc2UnLCB0aGlzLl9vblJlbGVhc2UpO1xuXG4gICAgdGhpcy5faGFuZGxlLnN0eWxlLmxlZnQgPSAnJztcbiAgICBNb2RpZmllclV0aWwucmVtb3ZlTW9kaWZpZXIodGhpcywgJ2FjdGl2ZScpO1xuICB9XG5cbiAgY2xpY2soZXYgPSB7fSkge1xuICAgIGlmICghdGhpcy5kaXNhYmxlZCkge1xuICAgICAgdGhpcy5jaGVja2VkID0gIXRoaXMuY2hlY2tlZDtcbiAgICAgIHRoaXMuX2VtaXRDaGFuZ2VFdmVudCgpO1xuICAgICAgdGhpcy5fbGFzdFRpbWVTdGFtcCA9IGV2LnRpbWVTdGFtcCB8fCAwO1xuICAgIH1cbiAgfVxuXG4gIGdldCBfaGFuZGxlKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoYC4ke3RoaXMuX2RlZmF1bHRDbGFzc05hbWV9X19oYW5kbGVgKTtcbiAgfVxuXG4gIGdldCBjaGVja2JveCgpIHtcbiAgICByZXR1cm4gdGhpcy5faW5wdXQ7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5faW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgdGhpcy5fb25DaGFuZ2UpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdkcmFnc3RhcnQnLCB0aGlzLl9vbkRyYWdTdGFydCk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdob2xkJywgdGhpcy5fb25Ib2xkKTtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoJ3RhcCcsIHRoaXMuY2xpY2spO1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLl9vbkNsaWNrKTtcbiAgICB0aGlzLl9nZXN0dXJlRGV0ZWN0b3IgPSBuZXcgR2VzdHVyZURldGVjdG9yKHRoaXMsIHsgZHJhZ01pbkRpc3RhbmNlOiAxLCBob2xkVGltZW91dDogMjUxLCBwYXNzaXZlOiB0cnVlIH0pO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX2lucHV0LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIHRoaXMuX29uQ2hhbmdlKTtcbiAgICB9KTtcblxuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJhZ3N0YXJ0JywgdGhpcy5fb25EcmFnU3RhcnQpO1xuICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcignaG9sZCcsIHRoaXMuX29uSG9sZCk7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCd0YXAnLCB0aGlzLmNsaWNrKTtcbiAgICB0aGlzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5fb25DbGljayk7XG4gICAgaWYgKHRoaXMuX2dlc3R1cmVEZXRlY3Rvcikge1xuICAgICAgdGhpcy5fZ2VzdHVyZURldGVjdG9yLmRpc3Bvc2UoKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgZ2V0IG9ic2VydmVkQXR0cmlidXRlcygpIHtcbiAgICByZXR1cm4gWy4uLnN1cGVyLm9ic2VydmVkQXR0cmlidXRlcywgJ21vZGlmaWVyJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChuYW1lID09PSAnbW9kaWZpZXInKSB7XG4gICAgICBjb25zdCBtZCA9IChjdXJyZW50IHx8ICcnKS5pbmRleE9mKCdtYXRlcmlhbCcpICE9PSAtMTtcbiAgICAgIHRoaXMuX2xvY2F0aW9ucyA9IGxvY2F0aW9uc1ttZCA/ICdtYXRlcmlhbCcgOiAnaW9zJ107XG4gICAgfVxuXG4gICAgc3VwZXIuYXR0cmlidXRlQ2hhbmdlZENhbGxiYWNrKG5hbWUsIGxhc3QsIGN1cnJlbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBldmVudCBjaGFuZ2VcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUZpcmVkIHdoZW4gdGhlIHN3aXRjaCBpcyB0b2dnbGVkLlsvZW5dXG4gICAqICAgW2phXU9OL09GRuOBjOWkieOCj+OBo+OBn+aZguOBq+eZuueBq+OBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBldmVudFxuICAgKiAgIFtlbl1FdmVudCBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kk44OZ44Oz44OI44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnN3aXRjaFxuICAgKiAgIFtlbl1Td2l0Y2ggb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCpOODmeODs+ODiOOBjOeZuueBq+OBl+OBn1N3aXRjaOOCquODluOCuOOCp+OCr+ODiOOCkui/lOOBl+OBvuOBmeOAglsvamFdXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gZXZlbnQudmFsdWVcbiAgICogICBbZW5dQ3VycmVudCB2YWx1ZS5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjga7lgKTjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IGV2ZW50LmlzSW50ZXJhY3RpdmVcbiAgICogICBbZW5dVHJ1ZSBpZiB0aGUgY2hhbmdlIHdhcyB0cmlnZ2VyZWQgYnkgdGhlIHVzZXIgY2xpY2tpbmcgb24gdGhlIHN3aXRjaC5bL2VuXVxuICAgKiAgIFtqYV3jgr/jg4Pjg5fjgoTjgq/jg6rjg4Pjgq/jgarjganjga7jg6bjg7zjgrbjga7mk43kvZzjgavjgojjgaPjgablpInjgo/jgaPjgZ/loLTlkIjjgavjga90cnVl44KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICBbZW5dVGhlIGFwcGVhcmFuY2Ugb2YgdGhlIHN3aXRjaC5bL2VuXVxuICAgKiAgW2phXeOCueOCpOODg+ODgeOBruihqOePvuOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGRpc2FibGVkXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBzd2l0Y2ggaXMgYmUgZGlzYWJsZWQuWy9lbl1cbiAgICogICBbamFd44K544Kk44OD44OB44KS54Sh5Yq544Gu54q25oWL44Gr44GZ44KL5aC05ZCI44Gr5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgY2hlY2tlZFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgc3dpdGNoIGlzIGNoZWNrZWQuWy9lbl1cbiAgICogICBbamFd44K544Kk44OD44OB44GMT07jga7nirbmhYvjgavjgZnjgovjgajjgY3jgavmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBpbnB1dC1pZFxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYGlkYCBhdHRyaWJ1dGUgb2YgdGhlIGlubmVyIGA8aW5wdXQ+YCBlbGVtZW50LiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHVzaW5nIGA8bGFiZWwgZm9yPVwiLi4uXCI+YCBlbGVtZW50cy5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGNoZWNrZWRcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGlzIHZhbHVlIGlzIGB0cnVlYCBpZiB0aGUgc3dpdGNoIGlzIGNoZWNrZWQuWy9lbl1cbiAgICogICBbamFd44K544Kk44OD44OB44GMT07jga7loLTlkIjjgatgdHJ1ZWDjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IHZhbHVlXG4gICAqIEB0eXBlIHtTdHJpbmd9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgaW5wdXQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBkaXNhYmxlZFxuICAgKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVdoZXRoZXIgdGhlIGVsZW1lbnQgaXMgZGlzYWJsZWQgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeeEoeWKueWMluOBleOCjOOBpuOBhOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgY2hlY2tib3hcbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtIVE1MRWxlbWVudH1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSB1bmRlcmx5aW5nIGNoZWNrYm94IGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFd44Kz44Oz44Od44O844ON44Oz44OI5YaF6YOo44GuY2hlY2tib3jopoHntKDjgavjgarjgorjgb7jgZnjgIJbL2phXVxuICAgKi9cblxufVxuXG5vbnNFbGVtZW50cy5Td2l0Y2ggPSBTd2l0Y2hFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtc3dpdGNoJywgU3dpdGNoRWxlbWVudCk7XG4iLCIvKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgb25zRWxlbWVudHMgZnJvbSAnLi4vLi4vb25zL2VsZW1lbnRzJztcbmltcG9ydCB1dGlsIGZyb20gJy4uLy4uL29ucy91dGlsJztcbmltcG9ydCBpbnRlcm5hbCBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi8uLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBTd2lwZXIgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL3N3aXBlcic7XG5pbXBvcnQgTW9kaWZpZXJVdGlsIGZyb20gJy4uLy4uL29ucy9pbnRlcm5hbC9tb2RpZmllci11dGlsJztcbmltcG9ydCBCYXNlRWxlbWVudCBmcm9tICcuLi9iYXNlL2Jhc2UtZWxlbWVudCc7XG5pbXBvcnQgY29udGVudFJlYWR5IGZyb20gJy4uLy4uL29ucy9jb250ZW50LXJlYWR5JztcblxuY29uc3Qgc2NoZW1lID0ge1xuICAnLnRhYmJhcl9fY29udGVudCc6ICd0YWJiYXItLSpfX2NvbnRlbnQnLFxuICAnLnRhYmJhcl9fYm9yZGVyJzogJ3RhYmJhci0tKl9fYm9yZGVyJyxcbiAgJy50YWJiYXInOiAndGFiYmFyLS0qJ1xufTtcblxuY29uc3QgcmV3cml0YWJsZXMgPSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge0VsZW1lbnR9IHRhYmJhckVsZW1lbnRcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHJlYWR5KHRhYmJhckVsZW1lbnQsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxufTtcblxuY29uc3QgbnVsbFBhZ2UgPSBpbnRlcm5hbC5udWxsRWxlbWVudDtcbmNvbnN0IGxlcnAgPSAoeDAsIHgxLCB0KSA9PiAoMSAtIHQpICogeDAgKyB0ICogeDE7XG5cbi8qKlxuICogQGVsZW1lbnQgb25zLXRhYmJhclxuICogQGNhdGVnb3J5IHRhYmJhclxuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1BIGNvbXBvbmVudCB0byBkaXNwbGF5IGEgdGFiIGJhciBvbiB0aGUgYm90dG9tIG9mIGEgcGFnZS4gVXNlZCB3aXRoIGA8b25zLXRhYj5gIHRvIG1hbmFnZSBwYWdlcyB1c2luZyB0YWJzLlsvZW5dXG4gKiAgIFtqYV3jgr/jg5bjg5Djg7zjgpLjg5rjg7zjgrjkuIvpg6jjgavooajnpLrjgZnjgovjgZ/jgoHjga7jgrPjg7Pjg53jg7zjg43jg7Pjg4jjgafjgZnjgIJvbnMtdGFi44Go57WE44G/5ZCI44KP44Gb44Gm5L2/44GG44GT44Go44Gn44CB44Oa44O844K444KS566h55CG44Gn44GN44G+44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIHBHdURMXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvdGFiYmFyXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXUEgdGFiYmFyIGluIE1hdGVyaWFsIERlc2lnbi5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciBhdXRvZ3Jvd1xuICogICBbZW5dVGFicyBhdXRvbWF0aWNhbGx5IGdyb3cgZGVwZW5kaW5nIG9uIHRoZWlyIGNvbnRlbnQgaW5zdGVhZCBvZiBoYXZpbmcgYSBmaXhlZCB3aWR0aC5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciB0b3AtYm9yZGVyXG4gKiAgIFtlbl1TaG93cyBhIHN0YXRpYyBib3JkZXItYm90dG9tIGluIHRhYnMgZm9yIGlPUyB0b3AgdGFiYmFycy5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBndWlkZSBmdW5kYW1lbnRhbHMuaHRtbCNtYW5hZ2luZy1wYWdlc1xuICogIFtlbl1NYW5hZ2luZyBtdWx0aXBsZSBwYWdlcy5bL2VuXVxuICogIFtqYV3opIfmlbDjga7jg5rjg7zjgrjjgpLnrqHnkIbjgZnjgotbL2phXVxuICogQHNlZWFsc28gb25zLXRhYlxuICogICBbZW5dVGhlIGA8b25zLXRhYj5gIGNvbXBvbmVudC5bL2VuXVxuICogICBbamFdb25zLXRhYuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtcGFnZVxuICogICBbZW5dVGhlIGA8b25zLXBhZ2U+YCBjb21wb25lbnQuWy9lbl1cbiAqICAgW2phXW9ucy1wYWdl44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXRhYmJhcj5cbiAqICAgPG9ucy10YWJcbiAqICAgICBwYWdlPVwiaG9tZS5odG1sXCJcbiAqICAgICBsYWJlbD1cIkhvbWVcIlxuICogICAgIGFjdGl2ZT5cbiAqICAgPC9vbnMtdGFiPlxuICogICA8b25zLXRhYlxuICogICAgIHBhZ2U9XCJzZXR0aW5ncy5odG1sXCJcbiAqICAgICBsYWJlbD1cIlNldHRpbmdzXCJcbiAqICAgICBhY3RpdmU+XG4gKiAgIDwvb25zLXRhYj5cbiAqIDwvb25zLXRhYmJhcj5cbiAqXG4gKiA8dGVtcGxhdGUgaWQ9XCJob21lLmh0bWxcIj5cbiAqICAgLi4uXG4gKiA8L3RlbXBsYXRlPlxuICpcbiAqIDx0ZW1wbGF0ZSBpZD1cInNldHRpbmdzLmh0bWxcIj5cbiAqICAgLi4uXG4gKiA8L3RlbXBsYXRlPlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBUYWJiYXJFbGVtZW50IGV4dGVuZHMgQmFzZUVsZW1lbnQge1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcHJlY2hhbmdlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlcyBqdXN0IGJlZm9yZSB0aGUgdGFiIGlzIGNoYW5nZWQuWy9lbl1cbiAgICogICBbamFd44Ki44Kv44OG44Kj44OW44Gq44K/44OW44GM5aSJ44KP44KL5YmN44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gZXZlbnQuaW5kZXhcbiAgICogICBbZW5dQ3VycmVudCBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjgqLjgq/jg4bjgqPjg5bjgavjgarjgaPjgabjgYTjgotvbnMtdGFi44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnRhYkl0ZW1cbiAgICogICBbZW5dVGFiIGl0ZW0gb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXXRhYkl0ZW3jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBldmVudC5jYW5jZWxcbiAgICogICBbZW5dQ2FsbCB0aGlzIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgY2hhbmdlIGV2ZW50LlsvZW5dXG4gICAqICAgW2phXeOBk+OBrumWouaVsOOCkuWRvOOBs+WHuuOBmeOBqOOAgeOCouOCr+ODhuOCo+ODluOBquOCv+ODluOBruWkieabtOOBjOOCreODo+ODs+OCu+ODq+OBleOCjOOBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAZXZlbnQgcG9zdGNoYW5nZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRmlyZXMganVzdCBhZnRlciB0aGUgdGFiIGlzIGNoYW5nZWQuWy9lbl1cbiAgICogICBbamFd44Ki44Kv44OG44Kj44OW44Gq44K/44OW44GM5aSJ44KP44Gj44Gf5b6M44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gZXZlbnQuaW5kZXhcbiAgICogICBbZW5dQ3VycmVudCBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjgqLjgq/jg4bjgqPjg5bjgavjgarjgaPjgabjgYTjgotvbnMtdGFi44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnRhYkl0ZW1cbiAgICogICBbZW5dVGFiIGl0ZW0gb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXXRhYkl0ZW3jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGV2ZW50IHJlYWN0aXZlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1GaXJlcyBpZiB0aGUgYWxyZWFkeSBvcGVuIHRhYiBpcyB0YXBwZWQgYWdhaW4uWy9lbl1cbiAgICogICBbamFd44GZ44Gn44Gr44Ki44Kv44OG44Kj44OW44Gr44Gq44Gj44Gm44GE44KL44K/44OW44GM44KC44GG5LiA5bqm44K/44OD44OX44KE44Kv44Oq44OD44Kv44GV44KM44Gf5aC05ZCI44Gr55m654Gr44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50XG4gICAqICAgW2VuXUV2ZW50IG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqTjg5njg7Pjg4jjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge051bWJlcn0gZXZlbnQuaW5kZXhcbiAgICogICBbZW5dQ3VycmVudCBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3nj77lnKjjgqLjgq/jg4bjgqPjg5bjgavjgarjgaPjgabjgYTjgotvbnMtdGFi44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQHBhcmFtIHtPYmplY3R9IGV2ZW50LnRhYkl0ZW1cbiAgICogICBbZW5dVGFiIGl0ZW0gb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXXRhYkl0ZW3jgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgbm9uZVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dSWYgdGhpcyBhdHRyaWJ1dGUgaXMgc2V0IHRvIGBcIm5vbmVcImAgdGhlIHRyYW5zaXRpb25zIHdpbGwgbm90IGJlIGFuaW1hdGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvbi1vcHRpb25zXG4gICAqIEB0eXBlIHtFeHByZXNzaW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgdGltaW5nLCBkZWxheeOCkuOCquODluOCuOOCp+OCr+ODiOODquODhuODqeODq+OBp+aMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAxLCB0aW1pbmc6ICdlYXNlLWluJ31bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBwb3NpdGlvblxuICAgKiBAaW5pdG9ubHlcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgYm90dG9tXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UYWJiYXIncyBwb3NpdGlvbi4gQXZhaWxhYmxlIHZhbHVlcyBhcmUgYFwiYm90dG9tXCJgIGFuZCBgXCJ0b3BcImAuIFVzZSBgXCJhdXRvXCJgIHRvIGNob29zZSBwb3NpdGlvbiBkZXBlbmRpbmcgb24gcGxhdGZvcm0gKGJvdHRvbSBmb3IgaU9TIGZsYXQgZGVzaWduLCB0b3AgZm9yIE1hdGVyaWFsIERlc2lnbikuWy9lbl1cbiAgICogICBbamFd44K/44OW44OQ44O844Gu5L2N572u44KS5oyH5a6a44GX44G+44GZ44CCXCJib3R0b21cIuOCguOBl+OBj+OBr1widG9wXCLjgpLpgbjmip7jgafjgY3jgb7jgZnjgILjg4fjg5Xjgqnjg6vjg4jjga9cImJvdHRvbVwi44Gn44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgc3dpcGVhYmxlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1JZiB0aGlzIGF0dHJpYnV0ZSBpcyBzZXQgdGhlIHRhYiBiYXIgY2FuIGJlIHNjcm9sbGVkIGJ5IGRyYWcgb3Igc3dpcGUuWy9lbl1cbiAgICogICBbamFd44GT44Gu5bGe5oCn44GM44GC44KL5pmC44CB44K/44OW44OQ44O844KS44K544Ov44Kk44OX44KE44OJ44Op44OD44Kw44Gn56e75YuV44Gn44GN44KL44KI44GG44Gr44Gq44KK44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaWdub3JlLWVkZ2Utd2lkdGhcbiAgICogQHR5cGUge051bWJlcn1cbiAgICogQGRlZmF1bHQgMjBcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXURpc3RhbmNlIGluIHBpeGVscyBmcm9tIGJvdGggZWRnZXMuIFN3aXBpbmcgb24gdGhlc2UgYXJlYXMgd2lsbCBwcmlvcml0aXplIHBhcmVudCBjb21wb25lbnRzIHN1Y2ggYXMgYG9ucy1zcGxpdHRlcmAgb3IgYG9ucy1uYXZpZ2F0b3JgLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGhpZGUtdGFic1xuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0byBoaWRlIHRoZSB0YWJzLlsvZW5dXG4gICAqICAgW2phXeOCv+ODluOCkumdnuihqOekuuOBq+OBmeOCi+WgtOWQiOOBq+aMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIHRhYi1ib3JkZXJcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUlmIHRoaXMgYXR0cmlidXRlIGlzIHNldCB0aGUgdGFicyBzaG93IGEgZHluYW1pYyBib3R0b20gYm9yZGVyLiBPbmx5IHdvcmtzIGZvciBpT1MgZmxhdCBkZXNpZ24gc2luY2UgdGhlIGJvcmRlciBpcyBhbHdheXMgdmlzaWJsZSBpbiBNYXRlcmlhbCBEZXNpZ24uWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSB0YWJiYXIuWy9lbl1cbiAgICogICBbamFd44K/44OW44OQ44O844Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLl9sb2FkSW5hY3RpdmUgPSB1dGlsLmRlZmVyKCk7IC8vIEltcHJvdmVzICMyMzI0XG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2NvbXBpbGUoKSk7XG4gIH1cblxuICBjb25uZWN0ZWRDYWxsYmFjaygpIHtcbiAgICBpZiAoIXRoaXMuX3N3aXBlcikge1xuICAgICAgdGhpcy5fc3dpcGVyID0gbmV3IFN3aXBlcih7XG4gICAgICAgIGdldEVsZW1lbnQ6ICgpID0+IHRoaXMuX2NvbnRlbnRFbGVtZW50LFxuICAgICAgICBnZXRJbml0aWFsSW5kZXg6ICgpID0+IHRoaXMuZ2V0QXR0cmlidXRlKCdhY3RpdmVJbmRleCcpIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdhY3RpdmUtaW5kZXgnKSxcbiAgICAgICAgZ2V0QXV0b1Njcm9sbFJhdGlvOiB0aGlzLl9nZXRBdXRvU2Nyb2xsUmF0aW8uYmluZCh0aGlzKSxcbiAgICAgICAgZ2V0QnViYmxlV2lkdGg6ICgpID0+IHBhcnNlSW50KHRoaXMuZ2V0QXR0cmlidXRlKCdpZ25vcmUtZWRnZS13aWR0aCcpIHx8IDI1LCAxMCksXG4gICAgICAgIGlzQXV0b1Njcm9sbGFibGU6ICgpID0+IHRydWUsXG4gICAgICAgIHByZUNoYW5nZUhvb2s6IHRoaXMuX29uUHJlQ2hhbmdlLmJpbmQodGhpcyksXG4gICAgICAgIHBvc3RDaGFuZ2VIb29rOiB0aGlzLl9vblBvc3RDaGFuZ2UuYmluZCh0aGlzKSxcbiAgICAgICAgcmVmcmVzaEhvb2s6IHRoaXMuX29uUmVmcmVzaC5iaW5kKHRoaXMpLFxuICAgICAgICBzY3JvbGxIb29rOiB0aGlzLl9vblNjcm9sbC5iaW5kKHRoaXMpXG4gICAgICB9KTtcblxuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgICAgdGhpcy5fdGFiYmFyQm9yZGVyID0gdXRpbC5maW5kQ2hpbGQodGhpcy5fdGFiYmFyRWxlbWVudCwgJy50YWJiYXJfX2JvcmRlcicpO1xuICAgICAgICB0aGlzLl9zd2lwZXIuaW5pdCh7IHN3aXBlYWJsZTogdGhpcy5oYXNBdHRyaWJ1dGUoJ3N3aXBlYWJsZScpIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHtcbiAgICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKCk7XG5cbiAgICAgIGlmICghdXRpbC5maW5kUGFyZW50KHRoaXMsICdvbnMtcGFnZScsIHAgPT4gcCA9PT0gZG9jdW1lbnQuYm9keSkpIHtcbiAgICAgICAgdGhpcy5fc2hvdygpOyAvLyBUaGlzIHRhYmJhciBpcyB0aGUgdG9wIGNvbXBvbmVudFxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgaWYgKHRoaXMuX3N3aXBlciAmJiB0aGlzLl9zd2lwZXIuaW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRoaXMuX3N3aXBlci5kaXNwb3NlKCk7XG4gICAgICB0aGlzLl9zd2lwZXIgPSBudWxsO1xuICAgICAgdGhpcy5fdGFiYmFyQm9yZGVyID0gbnVsbDtcbiAgICAgIHRoaXMuX3RhYnNSZWN0ID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBfbm9ybWFsaXplRXZlbnQoZXZlbnQpIHtcbiAgICByZXR1cm4geyAuLi5ldmVudCwgaW5kZXg6IGV2ZW50LmFjdGl2ZUluZGV4LCB0YWJJdGVtOiB0aGlzLnRhYnNbZXZlbnQuYWN0aXZlSW5kZXhdIH07XG4gIH1cblxuICBfb25Qb3N0Q2hhbmdlKGV2ZW50KSB7XG4gICAgZXZlbnQgPSB0aGlzLl9ub3JtYWxpemVFdmVudChldmVudCk7XG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwb3N0Y2hhbmdlJywgZXZlbnQpO1xuICAgIGNvbnN0IHBhZ2UgPSBldmVudC50YWJJdGVtLnBhZ2VFbGVtZW50O1xuICAgIHBhZ2UgJiYgcGFnZS5fc2hvdygpO1xuICB9XG5cbiAgX29uUHJlQ2hhbmdlKGV2ZW50KSB7XG4gICAgZXZlbnQgPSB0aGlzLl9ub3JtYWxpemVFdmVudChldmVudCk7XG4gICAgZXZlbnQuY2FuY2VsID0gKCkgPT4gZXZlbnQuY2FuY2VsZWQgPSB0cnVlO1xuXG4gICAgdXRpbC50cmlnZ2VyRWxlbWVudEV2ZW50KHRoaXMsICdwcmVjaGFuZ2UnLCBldmVudCk7XG5cbiAgICBpZiAoIWV2ZW50LmNhbmNlbGVkKSB7XG4gICAgICBjb25zdCB7IGFjdGl2ZUluZGV4LCBsYXN0QWN0aXZlSW5kZXggfSA9IGV2ZW50O1xuICAgICAgY29uc3QgdGFicyA9IHRoaXMudGFicztcblxuICAgICAgdGFic1thY3RpdmVJbmRleF0uc2V0QWN0aXZlKHRydWUpO1xuICAgICAgaWYgKGxhc3RBY3RpdmVJbmRleCA+PSAwKSB7XG4gICAgICAgIGNvbnN0IHByZXZUYWIgPSB0YWJzW2xhc3RBY3RpdmVJbmRleF07XG4gICAgICAgIHByZXZUYWIuc2V0QWN0aXZlKGZhbHNlKTtcbiAgICAgICAgcHJldlRhYi5wYWdlRWxlbWVudCAmJiBwcmV2VGFiLnBhZ2VFbGVtZW50Ll9oaWRlKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGV2ZW50LmNhbmNlbGVkXG4gIH1cblxuICBfb25TY3JvbGwoaW5kZXgsIG9wdGlvbnMgPSB7fSkge1xuICAgIGlmICh0aGlzLl90YWJiYXJCb3JkZXIpIHtcbiAgICAgIHRoaXMuX3RhYmJhckJvcmRlci5zdHlsZS50cmFuc2l0aW9uID0gYGFsbCAke29wdGlvbnMuZHVyYXRpb24gfHwgMH1zICR7b3B0aW9ucy50aW1pbmcgfHwgJyd9YDtcblxuICAgICAgaWYgKHRoaXMuX2F1dG9ncm93ICYmIHRoaXMuX3RhYnNSZWN0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgYSA9IE1hdGguZmxvb3IoaW5kZXgpLCBiID0gTWF0aC5jZWlsKGluZGV4KSwgciA9IGluZGV4ICUgMTtcbiAgICAgICAgdGhpcy5fdGFiYmFyQm9yZGVyLnN0eWxlLndpZHRoID0gbGVycCh0aGlzLl90YWJzUmVjdFthXS53aWR0aCwgdGhpcy5fdGFic1JlY3RbYl0ud2lkdGgsIHIpICsgJ3B4JztcbiAgICAgICAgdGhpcy5fdGFiYmFyQm9yZGVyLnN0eWxlLnRyYW5zZm9ybSA9IGB0cmFuc2xhdGUzZCgke2xlcnAodGhpcy5fdGFic1JlY3RbYV0ubGVmdCwgdGhpcy5fdGFic1JlY3RbYl0ubGVmdCwgcil9cHgsIDAsIDApYDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3RhYmJhckJvcmRlci5zdHlsZS50cmFuc2Zvcm0gPSBgdHJhbnNsYXRlM2QoJHtpbmRleCAqIDEwMH0lLCAwLCAwKWA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5fb25Td2lwZSAmJiB0aGlzLl9vblN3aXBlKGluZGV4LCBvcHRpb25zKTtcbiAgfVxuXG4gIF9vblJlZnJlc2goKSB7XG4gICAgdGhpcy5fYXV0b2dyb3cgPSB1dGlsLmhhc01vZGlmaWVyKHRoaXMsICdhdXRvZ3JvdycpO1xuICAgIHRoaXMuX3RhYnNSZWN0ID0gdGhpcy50YWJzLm1hcCh0YWIgPT4gdGFiLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpKTtcbiAgICBpZiAodGhpcy5fdGFiYmFyQm9yZGVyKSB7XG4gICAgICB0aGlzLl90YWJiYXJCb3JkZXIuc3R5bGUuZGlzcGxheSA9IHRoaXMuaGFzQXR0cmlidXRlKCd0YWItYm9yZGVyJykgfHwgdXRpbC5oYXNNb2RpZmllcih0aGlzLCAnbWF0ZXJpYWwnKSA/ICdibG9jaycgOiAnbm9uZSc7XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMuZ2V0QWN0aXZlVGFiSW5kZXgoKTtcbiAgICAgIGlmICh0aGlzLl90YWJzUmVjdC5sZW5ndGggPiAwICYmIGluZGV4ID49IDApIHtcbiAgICAgICAgdGhpcy5fdGFiYmFyQm9yZGVyLnN0eWxlLndpZHRoID0gdGhpcy5fdGFic1JlY3RbaW5kZXhdLndpZHRoICsgJ3B4JztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBfZ2V0QXV0b1Njcm9sbFJhdGlvKG1hdGNoZXMsIHZlbG9jaXR5LCBzaXplKSB7XG4gICAgY29uc3QgcmF0aW8gPSAuNjsgLy8gQmFzZSByYXRpb1xuICAgIGNvbnN0IG1vZGlmaWVyID0gc2l6ZSAvIDMwMCAqIChtYXRjaGVzID8gLTEgOiAxKTsgLy8gQmFzZWQgb24gc2NyZWVuIHNpemVcbiAgICByZXR1cm4gTWF0aC5taW4oMSwgTWF0aC5tYXgoMCwgcmF0aW8gKyB2ZWxvY2l0eSAqIG1vZGlmaWVyKSk7XG4gIH1cblxuICBnZXQgX3RhYmJhckVsZW1lbnQoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsICcudGFiYmFyJyk7XG4gIH1cblxuICBnZXQgX2NvbnRlbnRFbGVtZW50KCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRDaGlsZCh0aGlzLCAnLnRhYmJhcl9fY29udGVudCcpO1xuICB9XG5cbiAgZ2V0IF90YXJnZXRFbGVtZW50KCkge1xuICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLl9jb250ZW50RWxlbWVudDtcbiAgICByZXR1cm4gY29udGVudCAmJiBjb250ZW50LmNoaWxkcmVuWzBdIHx8IG51bGw7XG4gIH1cblxuICBfY29tcGlsZSgpIHtcbiAgICBhdXRvU3R5bGUucHJlcGFyZSh0aGlzKTtcblxuICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLl9jb250ZW50RWxlbWVudCB8fCB1dGlsLmNyZWF0ZSgnLnRhYmJhcl9fY29udGVudCcpO1xuICAgIGNvbnRlbnQuY2xhc3NMaXN0LmFkZCgnb25zLXRhYmJhcl9fY29udGVudCcpO1xuICAgIGNvbnN0IHRhYmJhciA9IHRoaXMuX3RhYmJhckVsZW1lbnQgfHwgdXRpbC5jcmVhdGUoJy50YWJiYXInKTtcbiAgICB0YWJiYXIuY2xhc3NMaXN0LmFkZCgnb25zLXRhYmJhcl9fZm9vdGVyJyk7XG5cbiAgICBpZiAoIXRhYmJhci5wYXJlbnROb2RlKSB7XG4gICAgICB3aGlsZSAodGhpcy5maXJzdENoaWxkKSB7XG4gICAgICAgIHRhYmJhci5hcHBlbmRDaGlsZCh0aGlzLmZpcnN0Q2hpbGQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGFjdGl2ZUluZGV4ID0gTnVtYmVyKHRoaXMuZ2V0QXR0cmlidXRlKCdhY3RpdmVJbmRleCcpKTsgLy8gMCBieSBkZWZhdWx0XG4gICAgaWYgKHRhYmJhci5jaGlsZHJlbi5sZW5ndGggPiBhY3RpdmVJbmRleCAmJiAhdXRpbC5maW5kQ2hpbGQodGFiYmFyLCAnW2FjdGl2ZV0nKSkge1xuICAgICAgdGFiYmFyLmNoaWxkcmVuW2FjdGl2ZUluZGV4XS5zZXRBdHRyaWJ1dGUoJ2FjdGl2ZScsICcnKTtcbiAgICB9XG5cbiAgICB0aGlzLl90YWJiYXJCb3JkZXIgPSB1dGlsLmZpbmRDaGlsZCh0YWJiYXIsICcudGFiYmFyX19ib3JkZXInKSB8fCB1dGlsLmNyZWF0ZSgnLnRhYmJhcl9fYm9yZGVyJyk7XG4gICAgdGFiYmFyLmFwcGVuZENoaWxkKHRoaXMuX3RhYmJhckJvcmRlcik7XG4gICAgdGFiYmFyLmNsYXNzTGlzdC5hZGQoJ29ucy1zd2lwZXItdGFiYmFyJyk7IC8vIEhpZGVzIG1hdGVyaWFsIGJvcmRlclxuXG4gICAgIWNvbnRlbnQuY2hpbGRyZW5bMF0gJiYgY29udGVudC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSk7XG4gICAgIWNvbnRlbnQuY2hpbGRyZW5bMV0gJiYgY29udGVudC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSk7XG4gICAgY29udGVudC5hcHBlbmRDaGlsZCA9IGNvbnRlbnQuYXBwZW5kQ2hpbGQuYmluZChjb250ZW50LmNoaWxkcmVuWzBdKTtcbiAgICBjb250ZW50Lmluc2VydEJlZm9yZSA9IGNvbnRlbnQuaW5zZXJ0QmVmb3JlLmJpbmQoY29udGVudC5jaGlsZHJlblswXSk7XG5cbiAgICB0aGlzLmFwcGVuZENoaWxkKGNvbnRlbnQpO1xuICAgIHRoaXMuYXBwZW5kQ2hpbGQodGFiYmFyKTsgLy8gVHJpZ2dlcnMgb25zLXRhYiBjb25uZWN0ZWRDYWxsYmFja1xuXG4gICAgTW9kaWZpZXJVdGlsLmluaXRNb2RpZmllcih0aGlzLCBzY2hlbWUpO1xuICB9XG5cbiAgX3VwZGF0ZVBvc2l0aW9uKHBvc2l0aW9uID0gdGhpcy5nZXRBdHRyaWJ1dGUoJ3Bvc2l0aW9uJykpIHtcbiAgICBjb25zdCB0b3AgPSB0aGlzLl90b3AgPSBwb3NpdGlvbiA9PT0gJ3RvcCcgfHwgKHBvc2l0aW9uID09PSAnYXV0bycgJiYgdXRpbC5oYXNNb2RpZmllcih0aGlzLCAnbWF0ZXJpYWwnKSk7XG4gICAgY29uc3QgYWN0aW9uID0gdG9wID8gdXRpbC5hZGRNb2RpZmllciA6IHV0aWwucmVtb3ZlTW9kaWZpZXI7XG5cbiAgICBhY3Rpb24odGhpcywgJ3RvcCcpO1xuXG4gICAgY29uc3QgcGFnZSA9IHV0aWwuZmluZFBhcmVudCh0aGlzLCAnb25zLXBhZ2UnKTtcbiAgICBpZiAocGFnZSkge1xuICAgICAgY29udGVudFJlYWR5KHBhZ2UsICgpID0+IHtcbiAgICAgICAgbGV0IHAgPSAwO1xuICAgICAgICBpZiAocGFnZS5jaGlsZHJlblswXSAmJiB1dGlsLm1hdGNoKHBhZ2UuY2hpbGRyZW5bMF0sICdvbnMtdG9vbGJhcicpKSB7XG4gICAgICAgICAgYWN0aW9uKHBhZ2UuY2hpbGRyZW5bMF0sICdub3NoYWRvdycpO1xuICAgICAgICAgIHAgPSAxOyAvLyBWaXN1YWwgZml4IGZvciBzb21lIGRldmljZXNcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNvbnRlbnQgPSBwYWdlLl9nZXRDb250ZW50RWxlbWVudCgpO1xuICAgICAgICBjb25zdCBjcyA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHBhZ2UuX2dldENvbnRlbnRFbGVtZW50KCksIG51bGwpXG5cbiAgICAgICAgdGhpcy5zdHlsZS50b3AgPSB0b3AgPyBwYXJzZUludChjcy5nZXRQcm9wZXJ0eVZhbHVlKCdwYWRkaW5nLXRvcCcpLCAxMCkgLSBwICsgJ3B4JyA6ICcnO1xuXG4gICAgICAgIC8vIFJlZnJlc2ggY29udGVudCB0b3AgLSBGaXggZm9yIGlPUyA4XG4gICAgICAgIGNvbnRlbnQuc3R5bGUudG9wID0gY3MudG9wO1xuICAgICAgICBjb250ZW50LnN0eWxlLnRvcCA9ICcnO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgaW50ZXJuYWwuYXV0b1N0YXR1c0JhckZpbGwoKCkgPT4ge1xuICAgICAgY29uc3QgZmlsbGVkID0gdXRpbC5maW5kUGFyZW50KHRoaXMsIGUgPT4gZS5oYXNBdHRyaWJ1dGUoJ3N0YXR1cy1iYXItZmlsbCcpKTtcbiAgICAgIHV0aWwudG9nZ2xlQXR0cmlidXRlKHRoaXMsICdzdGF0dXMtYmFyLWZpbGwnLCB0b3AgJiYgIWZpbGxlZCk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgdG9wUGFnZSgpIHtcbiAgICBjb25zdCB0YWJzID0gdGhpcy50YWJzLFxuICAgICAgaW5kZXggPSB0aGlzLmdldEFjdGl2ZVRhYkluZGV4KCk7XG4gICAgcmV0dXJuIHRhYnNbaW5kZXhdXG4gICAgICA/IHRhYnNbaW5kZXhdLnBhZ2VFbGVtZW50IHx8IHRoaXMucGFnZXNbMF0gfHwgbnVsbFxuICAgICAgOiBudWxsO1xuICB9XG5cbiAgZ2V0IHBhZ2VzKCkge1xuICAgIHJldHVybiB1dGlsLmFycmF5RnJvbSh0aGlzLl90YXJnZXRFbGVtZW50LmNoaWxkcmVuKTtcbiAgfVxuXG4gIGdldCB0YWJzKCkge1xuICAgIHJldHVybiBBcnJheS5wcm90b3R5cGUuZmlsdGVyLmNhbGwodGhpcy5fdGFiYmFyRWxlbWVudC5jaGlsZHJlbiwgZSA9PiBlLnRhZ05hbWUgPT09ICdPTlMtVEFCJyk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzZXRBY3RpdmVUYWJcbiAgICogQHNpZ25hdHVyZSBzZXRBY3RpdmVUYWIoaW5kZXgsIFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGluZGV4XG4gICAqICAgW2VuXVRhYiBpbmRleC5bL2VuXVxuICAgKiAgIFtqYV3jgr/jg5bjga7jgqTjg7Pjg4fjg4Pjgq/jgrnjgpLmjIflrprjgZfjgb7jgZnjgIJbL2phXVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gW29wdGlvbnMuY2FsbGJhY2tdXG4gICAqICAgW2VuXUZ1bmN0aW9uIHRoYXQgcnVucyB3aGVuIHRoZSBuZXcgcGFnZSBoYXMgbG9hZGVkLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUlmIHRoaXMgb3B0aW9uIGlzIFwibm9uZVwiLCB0aGUgdHJhbnNpdGlvbiB3b24ndCBzbGlkZS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNob3cgc3BlY2lmaWVkIHRhYiBwYWdlLiBBbmltYXRpb25zIGFuZCB0aGVpciBvcHRpb25zIGNhbiBiZSBzcGVjaWZpZWQgYnkgdGhlIHNlY29uZCBwYXJhbWV0ZXIuWy9lbl1cbiAgICogICBbamFd5oyH5a6a44GX44Gf44Kk44Oz44OH44OD44Kv44K544Gu44K/44OW44KS6KGo56S644GX44G+44GZ44CC44Ki44OL44Oh44O844K344On44Oz44Gq44Gp44Gu44Kq44OX44K344On44Oz44KS5oyH5a6a44Gn44GN44G+44GZ44CCWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIG5ldyBwYWdlIGVsZW1lbnQuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG4gIHNldEFjdGl2ZVRhYihuZXh0SW5kZXgsIG9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IHByZXZJbmRleCA9IHRoaXMuZ2V0QWN0aXZlVGFiSW5kZXgoKTtcbiAgICBjb25zdCBwcmV2VGFiID0gdGhpcy50YWJzW3ByZXZJbmRleF0sXG4gICAgICBuZXh0VGFiID0gdGhpcy50YWJzW25leHRJbmRleF07XG5cbiAgICBpZiAoIW5leHRUYWIpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnU3BlY2lmaWVkIGluZGV4IGRvZXMgbm90IG1hdGNoIGFueSB0YWIuJyk7XG4gICAgfVxuXG4gICAgaWYgKG5leHRJbmRleCA9PT0gcHJldkluZGV4KSB7XG4gICAgICB1dGlsLnRyaWdnZXJFbGVtZW50RXZlbnQodGhpcywgJ3JlYWN0aXZlJywgeyBpbmRleDogbmV4dEluZGV4LCBhY3RpdmVJbmRleDogbmV4dEluZGV4LCB0YWJJdGVtOiBuZXh0VGFiIH0pO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXh0VGFiLnBhZ2VFbGVtZW50KTtcbiAgICB9XG5cbiAgICAvLyBGSVhNRTogbmV4dFRhYi5sb2FkZWQgaXMgYnJva2VuIGluIFpvbmUuanMgcHJvbWlzZXMgKEFuZ3VsYXIyKVxuICAgIGNvbnN0IG5leHRQYWdlID0gbmV4dFRhYi5wYWdlRWxlbWVudDtcbiAgICByZXR1cm4gKG5leHRQYWdlID8gUHJvbWlzZS5yZXNvbHZlKG5leHRQYWdlKSA6IG5leHRUYWIubG9hZGVkKVxuICAgICAgLnRoZW4obmV4dFBhZ2UgPT4gdGhpcy5fc3dpcGVyLnNldEFjdGl2ZUluZGV4KG5leHRJbmRleCwge1xuICAgICAgICByZWplY3Q6IHRydWUsXG4gICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgIGFuaW1hdGlvbjogcHJldlRhYiAmJiBuZXh0UGFnZSA/IG9wdGlvbnMuYW5pbWF0aW9uIHx8IHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24nKSA6ICdub25lJyxcbiAgICAgICAgYW5pbWF0aW9uT3B0aW9uczogdXRpbC5leHRlbmQoXG4gICAgICAgICAgeyBkdXJhdGlvbjogLjMsIHRpbWluZzogJ2N1YmljLWJlemllciguNCwgLjcsIC41LCAxKScgfSxcbiAgICAgICAgICB0aGlzLmhhc0F0dHJpYnV0ZSgnYW5pbWF0aW9uLW9wdGlvbnMnKSA/IHV0aWwuYW5pbWF0aW9uT3B0aW9uc1BhcnNlKHRoaXMuZ2V0QXR0cmlidXRlKCdhbmltYXRpb24tb3B0aW9ucycpKSA6IHt9LFxuICAgICAgICAgIG9wdGlvbnMuYW5pbWF0aW9uT3B0aW9ucyB8fCB7fVxuICAgICAgICApXG4gICAgICB9KS50aGVuKCgpID0+IHtcbiAgICAgICAgb3B0aW9ucy5jYWxsYmFjayBpbnN0YW5jZW9mIEZ1bmN0aW9uICYmIG9wdGlvbnMuY2FsbGJhY2sobmV4dFBhZ2UpO1xuICAgICAgICByZXR1cm4gbmV4dFBhZ2U7XG4gICAgICB9KSk7XG4gIH1cblxuICAvKipcbiAgICogQG1ldGhvZCBzZXRUYWJiYXJWaXNpYmlsaXR5XG4gICAqIEBzaWduYXR1cmUgc2V0VGFiYmFyVmlzaWJpbGl0eSh2aXNpYmxlKVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IHZpc2libGVcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVVzZWQgdG8gaGlkZSBvciBzaG93IHRoZSB0YWIgYmFyLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBzZXRUYWJiYXJWaXNpYmlsaXR5KHZpc2libGUpIHtcbiAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4ge1xuICAgICAgdGhpcy5fY29udGVudEVsZW1lbnQuc3R5bGVbdGhpcy5fdG9wID8gJ3RvcCcgOiAnYm90dG9tJ10gPSB2aXNpYmxlID8gJycgOiAnMHB4JztcbiAgICAgIHRoaXMuX3RhYmJhckVsZW1lbnQuc3R5bGUuZGlzcGxheSA9IHZpc2libGUgPyAnJyA6ICdub25lJztcbiAgICAgIHZpc2libGUgJiYgdGhpcy5fb25SZWZyZXNoKCk7XG4gICAgfSk7XG4gIH1cblxuICBzaG93KCkge1xuICAgIHRoaXMuc2V0VGFiYmFyVmlzaWJpbGl0eSh0cnVlKTtcbiAgfVxuXG4gIGhpZGUoKSB7XG4gICAgdGhpcy5zZXRUYWJiYXJWaXNpYmlsaXR5KGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSB0YWJiYXIgaXMgdmlzaWJsZSBvciBub3QuWy9lbl1cbiAgICogICBbamFd44K/44OW44OQ44O844GM6KaL44GI44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG4gIGdldCB2aXNpYmxlKCkge1xuICAgIHJldHVybiB0aGlzLl90YWJiYXJFbGVtZW50LnN0eWxlLmRpc3BsYXkgIT09ICdub25lJztcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgc3dpcGVhYmxlXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dRW5hYmxlIHN3aXBlIGludGVyYWN0aW9uLlsvZW5dXG4gICAqICAgW2phXXN3aXBlYWJsZeOBp+OBguOCjOOBsHRydWXjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0IHN3aXBlYWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5oYXNBdHRyaWJ1dGUoJ3N3aXBlYWJsZScpO1xuICB9XG5cbiAgc2V0IHN3aXBlYWJsZSh2YWx1ZSkge1xuICAgIHJldHVybiB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnc3dpcGVhYmxlJywgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSBvblN3aXBlXG4gICAqIEB0eXBlIHtGdW5jdGlvbn1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUhvb2sgY2FsbGVkIHdoZW5ldmVyIHRoZSB1c2VyIHNsaWRlcyB0aGUgdGFiYmFyLiBJdCBnZXRzIGEgZGVjaW1hbCBpbmRleCBhbmQgYW4gYW5pbWF0aW9uT3B0aW9ucyBvYmplY3QgYXMgYXJndW1lbnRzLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqL1xuICBnZXQgb25Td2lwZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fb25Td2lwZTtcbiAgfVxuXG4gIHNldCBvblN3aXBlKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmICEodmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHV0aWwudGhyb3coYFwib25Td2lwZVwiIG11c3QgYmUgYSBmdW5jdGlvbmApXG4gICAgfVxuICAgIHRoaXMuX29uU3dpcGUgPSB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAbWV0aG9kIGdldEFjdGl2ZVRhYkluZGV4XG4gICAqIEBzaWduYXR1cmUgZ2V0QWN0aXZlVGFiSW5kZXgoKVxuICAgKiBAcmV0dXJuIHtOdW1iZXJ9XG4gICAqICAgW2VuXVRoZSBpbmRleCBvZiB0aGUgY3VycmVudGx5IGFjdGl2ZSB0YWIuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Ki44Kv44OG44Kj44OW44Gr44Gq44Gj44Gm44GE44KL44K/44OW44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CCWy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVJldHVybnMgdGFiIGluZGV4IG9uIGN1cnJlbnQgYWN0aXZlIHRhYi4gSWYgYWN0aXZlIHRhYiBpcyBub3QgZm91bmQsIHJldHVybnMgLTEuWy9lbl1cbiAgICogICBbamFd54++5Zyo44Ki44Kv44OG44Kj44OW44Gr44Gq44Gj44Gm44GE44KL44K/44OW44Gu44Kk44Oz44OH44OD44Kv44K544KS6L+U44GX44G+44GZ44CC54++5Zyo44Ki44Kv44OG44Kj44OW44Gq44K/44OW44GM44Gq44GE5aC05ZCI44Gr44GvLTHjgpLov5TjgZfjgb7jgZnjgIJbL2phXVxuICAgKi9cbiAgZ2V0QWN0aXZlVGFiSW5kZXgodGFicyA9IHRoaXMudGFicykge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGFicy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHRhYnNbaV0gJiYgdGFic1tpXS50YWdOYW1lID09PSAnT05TLVRBQicgJiYgdGFic1tpXS5pc0FjdGl2ZSgpKSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH1cblxuICBfc2hvdygpIHtcbiAgICB0aGlzLl9zd2lwZXIuc2hvdygpO1xuXG4gICAgc2V0SW1tZWRpYXRlKCgpID0+IHtcbiAgICAgIGNvbnN0IHRhYnMgPSB0aGlzLnRhYnM7XG4gICAgICBjb25zdCBhY3RpdmVJbmRleCA9IHRoaXMuZ2V0QWN0aXZlVGFiSW5kZXgodGFicyk7XG4gICAgICB0aGlzLl9sb2FkSW5hY3RpdmUucmVzb2x2ZSgpO1xuICAgICAgaWYgKHRhYnMubGVuZ3RoID4gMCAmJiBhY3RpdmVJbmRleCA+PSAwKSB7XG4gICAgICAgIHRhYnNbYWN0aXZlSW5kZXhdLmxvYWRlZC50aGVuKGVsID0+IGVsICYmIHNldEltbWVkaWF0ZSgoKSA9PiBlbC5fc2hvdygpKSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBfaGlkZSgpIHtcbiAgICB0aGlzLl9zd2lwZXIuaGlkZSgpO1xuICAgIGNvbnN0IHRvcFBhZ2UgPSB0aGlzLnRvcFBhZ2U7XG4gICAgdG9wUGFnZSAmJiB0b3BQYWdlLl9oaWRlKCk7XG4gIH1cblxuICBfZGVzdHJveSgpIHtcbiAgICB0aGlzLnRhYnMuZm9yRWFjaCh0YWIgPT4gdGFiLnJlbW92ZSgpKTtcbiAgICB0aGlzLnJlbW92ZSgpO1xuICB9XG5cbiAgc3RhdGljIGdldCBvYnNlcnZlZEF0dHJpYnV0ZXMoKSB7XG4gICAgcmV0dXJuIFsnbW9kaWZpZXInLCAncG9zaXRpb24nLCAnc3dpcGVhYmxlJywgJ3RhYi1ib3JkZXInLCAnaGlkZS10YWJzJ107XG4gIH1cblxuICBhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sobmFtZSwgbGFzdCwgY3VycmVudCkge1xuICAgIGlmIChuYW1lID09PSAnbW9kaWZpZXInKSB7XG4gICAgICBNb2RpZmllclV0aWwub25Nb2RpZmllckNoYW5nZWQobGFzdCwgY3VycmVudCwgdGhpcywgc2NoZW1lKTtcbiAgICAgIGNvbnN0IGlzVG9wID0gbSA9PiAvKF58XFxzKyl0b3AoJHxcXHMrKS9pLnRlc3QobSk7XG4gICAgICBpc1RvcChsYXN0KSAhPT0gaXNUb3AoY3VycmVudCkgJiYgdGhpcy5fdXBkYXRlUG9zaXRpb24oKTtcbiAgICB9IGVsc2UgaWYgKG5hbWUgPT09ICdwb3NpdGlvbicpIHtcbiAgICAgIHV0aWwuaXNBdHRhY2hlZCh0aGlzKSAmJiB0aGlzLl91cGRhdGVQb3NpdGlvbigpO1xuICAgIH0gZWxzZSBpZiAobmFtZSA9PT0gJ3N3aXBlYWJsZScpIHtcbiAgICAgIHRoaXMuX3N3aXBlciAmJiB0aGlzLl9zd2lwZXIudXBkYXRlU3dpcGVhYmxlKHRoaXMuaGFzQXR0cmlidXRlKCdzd2lwZWFibGUnKSk7XG4gICAgfSBlbHNlIGlmIChuYW1lID09PSAnaGlkZS10YWJzJykge1xuICAgICAgdGhpcy5zZXRUYWJiYXJWaXNpYmlsaXR5KCF0aGlzLmhhc0F0dHJpYnV0ZSgnaGlkZS10YWJzJykgfHwgY3VycmVudCA9PT0gJ2ZhbHNlJyk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGdldCByZXdyaXRhYmxlcygpIHtcbiAgICByZXR1cm4gcmV3cml0YWJsZXM7XG4gIH1cblxuICBzdGF0aWMgZ2V0IGV2ZW50cygpIHtcbiAgICByZXR1cm4gWydwcmVjaGFuZ2UnLCAncG9zdGNoYW5nZScsICdyZWFjdGl2ZSddO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlRhYmJhciA9IFRhYmJhckVsZW1lbnQ7XG5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ29ucy10YWJiYXInLCBUYWJiYXJFbGVtZW50KTtcbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEJhc2VFbGVtZW50IGZyb20gJy4vYmFzZS9iYXNlLWVsZW1lbnQnO1xuaW1wb3J0IFRhYmJhckVsZW1lbnQgZnJvbSAnLi9vbnMtdGFiYmFyJztcbmltcG9ydCBjb250ZW50UmVhZHkgZnJvbSAnLi4vb25zL2NvbnRlbnQtcmVhZHknO1xuaW1wb3J0IHsgUGFnZUxvYWRlciwgZGVmYXVsdFBhZ2VMb2FkZXIgfSBmcm9tICcuLi9vbnMvcGFnZS1sb2FkZXInO1xuXG5jb25zdCBkZWZhdWx0Q2xhc3NOYW1lID0gJ3RhYmJhcl9faXRlbSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJyc6ICd0YWJiYXItLSpfX2l0ZW0nLFxuICAnLnRhYmJhcl9fYnV0dG9uJzogJ3RhYmJhci0tKl9fYnV0dG9uJ1xufTtcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtdGFiXG4gKiBAY2F0ZWdvcnkgdGFiYmFyXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXVJlcHJlc2VudHMgYSB0YWIgaW5zaWRlIHRhYiBiYXIuIEVhY2ggYDxvbnMtdGFiPmAgcmVwcmVzZW50cyBhIHBhZ2UuWy9lbl1cbiAqICAgW2phXVxuICogICAgIOOCv+ODluODkOODvOOBq+mFjee9ruOBleOCjOOCi+WQhOOCouOCpOODhuODoOOBruOCs+ODs+ODneODvOODjeODs+ODiOOBp+OBmeOAguOBneOCjOOBnuOCjOOBrm9ucy10YWLjga/jg5rjg7zjgrjjgpLooajjgZfjgb7jgZnjgIJcbiAqICAgICBvbnMtdGFi6KaB57Sg44Gu5Lit44Gr44Gv44CB44K/44OW44Gr6KGo56S644GV44KM44KL44Kz44Oz44OG44Oz44OE44KS55u05o6l6KiY6L+w44GZ44KL44GT44Go44GM5Ye65p2l44G+44GZ44CCXG4gKiAgIFsvamFdXG4gKiBAY29kZXBlbiBwR3VETFxuICogQHR1dG9yaWFsIHZhbmlsbGEvUmVmZXJlbmNlL3RhYmJhclxuICogQGd1aWRlIGZ1bmRhbWVudGFscy5odG1sI21hbmFnaW5nLXBhZ2VzXG4gKiAgIFtlbl1NYW5hZ2luZyBtdWx0aXBsZSBwYWdlcy5bL2VuXVxuICogICBbamFd6KSH5pWw44Gu44Oa44O844K444KS566h55CG44GZ44KLWy9qYV1dXG4gKiBAZ3VpZGUgYXBwc2l6ZS5odG1sI3JlbW92aW5nLWljb24tcGFja3MgW2VuXVJlbW92aW5nIGljb24gcGFja3MuWy9lbl1bamFdWy9qYV1cbiAqIEBndWlkZSBmYXEuaHRtbCNob3ctY2FuLWktdXNlLWN1c3RvbS1pY29uLXBhY2tzIFtlbl1BZGRpbmcgY3VzdG9tIGljb24gcGFja3MuWy9lbl1bamFdWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy10YWJiYXJcbiAqICAgW2VuXW9ucy10YWJiYXIgY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy10YWJiYXLjgrPjg7Pjg53jg7zjg43jg7Pjg4hbL2phXVxuICogQHNlZWFsc28gb25zLXBhZ2VcbiAqICAgW2VuXW9ucy1wYWdlIGNvbXBvbmVudFsvZW5dXG4gKiAgIFtqYV1vbnMtcGFnZeOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAc2VlYWxzbyBvbnMtaWNvblxuICogICBbZW5db25zLWljb24gY29tcG9uZW50Wy9lbl1cbiAqICAgW2phXW9ucy1pY29u44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBleGFtcGxlXG4gKiA8b25zLXRhYmJhcj5cbiAqICAgPG9ucy10YWJcbiAqICAgICBwYWdlPVwiaG9tZS5odG1sXCJcbiAqICAgICBsYWJlbD1cIkhvbWVcIlxuICogICAgIGFjdGl2ZT5cbiAqICAgPC9vbnMtdGFiPlxuICogICA8b25zLXRhYlxuICogICAgIHBhZ2U9XCJzZXR0aW5ncy5odG1sXCJcbiAqICAgICBsYWJlbD1cIlNldHRpbmdzXCJcbiAqICAgICBhY3RpdmU+XG4gKiAgIDwvb25zLXRhYj5cbiAqIDwvb25zLXRhYmJhcj5cbiAqXG4gKiA8dGVtcGxhdGUgaWQ9XCJob21lLmh0bWxcIj5cbiAqICAgLi4uXG4gKiA8L3RlbXBsYXRlPlxuICpcbiAqIDx0ZW1wbGF0ZSBpZD1cInNldHRpbmdzLmh0bWxcIj5cbiAqICAgLi4uXG4gKiA8L3RlbXBsYXRlPlxuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRhYkVsZW1lbnQgZXh0ZW5kcyBCYXNlRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgcGFnZVxuICAgKiBAaW5pdG9ubHlcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBwYWdlIHRoYXQgaXMgZGlzcGxheWVkIHdoZW4gdGhlIHRhYiBpcyB0YXBwZWQuWy9lbl1cbiAgICogICBbamFdb25zLXRhYuOBjOWPgueFp+OBmeOCi+ODmuODvOOCuOOBuOOBrlVSTOOCkuaMh+WumuOBl+OBvuOBmeOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGljb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVxuICAgKiAgICAgVGhlIGljb24gbmFtZSBmb3IgdGhlIHRhYi4gQ2FuIHNwZWNpZnkgdGhlIHNhbWUgaWNvbiBuYW1lIGFzIGA8b25zLWljb24+YC4gQ2hlY2sgW1NlZSBhbHNvXSgjc2VlYWxzbykgc2VjdGlvbiBmb3IgbW9yZSBpbmZvcm1hdGlvbi5cbiAgICogICBbL2VuXVxuICAgKiAgIFtqYV1cbiAgICogICAgIOOCouOCpOOCs+ODs+WQjeOCkuaMh+WumuOBl+OBvuOBmeOAgm9ucy1pY29u44Go5ZCM44GY44Ki44Kk44Kz44Oz5ZCN44KS5oyH5a6a44Gn44GN44G+44GZ44CCXG4gICAqICAgICDlgIvliKXjgavjgqLjgqTjgrPjg7PjgpLjgqvjgrnjgr/jg57jgqTjgrrjgZnjgovloLTlkIjjga/jgIFiYWNrZ3JvdW5kLWltYWdl44Gq44Gp44GuQ1NT44K544K/44Kk44Or44KS55So44GE44Gm5oyH5a6a44Gn44GN44G+44GZ44CCXG4gICAqICAgWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYWN0aXZlLWljb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBuYW1lIG9mIHRoZSBpY29uIHdoZW4gdGhlIHRhYiBpcyBhY3RpdmUuWy9lbl1cbiAgICogICBbamFd44Ki44Kv44OG44Kj44OW44Gu6Zqb44Gu44Ki44Kk44Kz44Oz5ZCN44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbGFiZWxcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBsYWJlbCBvZiB0aGUgdGFiIGl0ZW0uWy9lbl1cbiAgICogICBbamFd44Ki44Kk44Kz44Oz5LiL44Gr6KGo56S644GV44KM44KL44Op44OZ44Or44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYmFkZ2VcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXURpc3BsYXkgYSBub3RpZmljYXRpb24gYmFkZ2Ugb24gdG9wIG9mIHRoZSB0YWIuWy9lbl1cbiAgICogICBbamFd44OQ44OD44K444Gr6KGo56S644GZ44KL5YaF5a6544KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgYWN0aXZlXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1UaGlzIGF0dHJpYnV0ZSBzaG91bGQgYmUgc2V0IHRvIHRoZSB0YWIgdGhhdCBpcyBhY3RpdmUgYnkgZGVmYXVsdC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKFsnbGFiZWwnLCAnaWNvbicsICdiYWRnZSddLnNvbWUodGhpcy5oYXNBdHRyaWJ1dGUuYmluZCh0aGlzKSkpIHtcbiAgICAgIHRoaXMuX2NvbXBpbGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGVudFJlYWR5KHRoaXMsICgpID0+IHRoaXMuX2NvbXBpbGUoKSk7XG4gICAgfVxuXG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IGRlZmF1bHRQYWdlTG9hZGVyO1xuICAgIHRoaXMuX29uQ2xpY2sgPSB0aGlzLl9vbkNsaWNrLmJpbmQodGhpcyk7XG4gIH1cblxuICBzZXQgcGFnZUxvYWRlcihsb2FkZXIpIHtcbiAgICBpZiAoIShsb2FkZXIgaW5zdGFuY2VvZiBQYWdlTG9hZGVyKSkge1xuICAgICAgdXRpbC50aHJvd1BhZ2VMb2FkZXIoKTtcbiAgICB9XG4gICAgdGhpcy5fcGFnZUxvYWRlciA9IGxvYWRlcjtcbiAgfVxuXG4gIGdldCBwYWdlTG9hZGVyKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWdlTG9hZGVyO1xuICB9XG5cbiAgX2NvbXBpbGUoKSB7XG4gICAgYXV0b1N0eWxlLnByZXBhcmUodGhpcyk7XG4gICAgdGhpcy5jbGFzc0xpc3QuYWRkKGRlZmF1bHRDbGFzc05hbWUpO1xuXG4gICAgaWYgKHRoaXMuX2J1dHRvbikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGJ1dHRvbiA9IHV0aWwuY3JlYXRlKCdidXR0b24udGFiYmFyX19idXR0b24nKTtcbiAgICB3aGlsZSAodGhpcy5jaGlsZE5vZGVzWzBdKSB7XG4gICAgICBidXR0b24uYXBwZW5kQ2hpbGQodGhpcy5jaGlsZE5vZGVzWzBdKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbnB1dCA9IHV0aWwuY3JlYXRlKCdpbnB1dCcsIHsgZGlzcGxheTogJ25vbmUnIH0pO1xuICAgIGlucHV0LnR5cGUgPSAncmFkaW8nO1xuXG4gICAgdGhpcy5hcHBlbmRDaGlsZChpbnB1dCk7XG4gICAgdGhpcy5hcHBlbmRDaGlsZChidXR0b24pO1xuXG4gICAgdGhpcy5fdXBkYXRlQnV0dG9uQ29udGVudCgpO1xuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgc2NoZW1lKTtcbiAgICB0aGlzLl91cGRhdGVSaXBwbGUoKTtcbiAgfVxuXG4gIF91cGRhdGVSaXBwbGUoKSB7XG4gICAgdGhpcy5fYnV0dG9uICYmIHV0aWwudXBkYXRlUmlwcGxlKHRoaXMuX2J1dHRvbiwgdGhpcy5oYXNBdHRyaWJ1dGUoJ3JpcHBsZScpKTtcbiAgfVxuXG4gIF91cGRhdGVCdXR0b25Db250ZW50KCkge1xuICAgIGNvbnN0IGJ1dHRvbiA9IHRoaXMuX2J1dHRvbjtcblxuICAgIGxldCBpY29uV3JhcHBlciA9IHRoaXMuX2ljb247XG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdpY29uJykpIHtcbiAgICAgIGljb25XcmFwcGVyID0gaWNvbldyYXBwZXIgfHwgdXRpbC5jcmVhdGVFbGVtZW50KCc8ZGl2IGNsYXNzPVwidGFiYmFyX19pY29uXCI+PG9ucy1pY29uPjwvb25zLWljb24+PC9kaXY+Jyk7XG4gICAgICBjb25zdCBpY29uID0gaWNvbldyYXBwZXIuY2hpbGRyZW5bMF07XG4gICAgICBjb25zdCBmaXggPSAobGFzdCA9PiAoKSA9PiBpY29uLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjaygnaWNvbicsIGxhc3QsIHRoaXMuZ2V0QXR0cmlidXRlKCdpY29uJykpKShpY29uLmdldEF0dHJpYnV0ZSgnaWNvbicpKTtcbiAgICAgIGljb24uc2V0QXR0cmlidXRlKCdpY29uJywgdGhpcy5nZXRBdHRyaWJ1dGUodGhpcy5pc0FjdGl2ZSgpID8gJ2FjdGl2ZS1pY29uJyA6ICdpY29uJykpO1xuICAgICAgaWNvbldyYXBwZXIucGFyZW50RWxlbWVudCAhPT0gYnV0dG9uICYmIGJ1dHRvbi5pbnNlcnRCZWZvcmUoaWNvbldyYXBwZXIsIGJ1dHRvbi5maXJzdENoaWxkKTtcblxuICAgICAgLy8gZGlydHkgZml4IGZvciBodHRwczovL2dpdGh1Yi5jb20vT25zZW5VSS9PbnNlblVJL2lzc3Vlcy8xNjU0XG4gICAgICBpY29uLmF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayBpbnN0YW5jZW9mIEZ1bmN0aW9uXG4gICAgICAgID8gZml4KClcbiAgICAgICAgOiBzZXRJbW1lZGlhdGUoKCkgPT4gaWNvbi5hdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2sgaW5zdGFuY2VvZiBGdW5jdGlvbiAmJiBmaXgoKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGljb25XcmFwcGVyICYmIGljb25XcmFwcGVyLnJlbW92ZSgpO1xuICAgIH1cblxuICAgIFsnbGFiZWwnLCAnYmFkZ2UnXS5mb3JFYWNoKChhdHRyLCBpbmRleCkgPT4ge1xuICAgICAgbGV0IHByb3AgPSB0aGlzLnF1ZXJ5U2VsZWN0b3IoYC50YWJiYXJfXyR7YXR0cn1gKTtcbiAgICAgIGlmICh0aGlzLmhhc0F0dHJpYnV0ZShhdHRyKSkge1xuICAgICAgICBwcm9wID0gcHJvcCB8fCB1dGlsLmNyZWF0ZShgLnRhYmJhcl9fJHthdHRyfWAgKyAoYXR0ciA9PT0gJ2JhZGdlJyA/ICcgbm90aWZpY2F0aW9uJyA6ICcnKSk7XG4gICAgICAgIHByb3AudGV4dENvbnRlbnQgPSB0aGlzLmdldEF0dHJpYnV0ZShhdHRyKTtcbiAgICAgICAgcHJvcC5wYXJlbnRFbGVtZW50ICE9PSBidXR0b24gJiYgYnV0dG9uLmFwcGVuZENoaWxkKHByb3ApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHJvcCAmJiBwcm9wLnJlbW92ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgZ2V0IF9pbnB1dCgpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJ2lucHV0Jyk7XG4gIH1cblxuICBnZXQgX2J1dHRvbigpIHtcbiAgICByZXR1cm4gdXRpbC5maW5kQ2hpbGQodGhpcywgJy50YWJiYXJfX2J1dHRvbicpO1xuICB9XG5cbiAgZ2V0IF9pY29uKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3IoJy50YWJiYXJfX2ljb24nKTtcbiAgfVxuXG4gIGdldCBfdGFiYmFyKCkge1xuICAgIHJldHVybiB1dGlsLmZpbmRQYXJlbnQodGhpcywgJ29ucy10YWJiYXInKTtcbiAgfVxuXG4gIGdldCBpbmRleCgpIHtcbiAgICByZXR1cm4gQXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbCh0aGlzLnBhcmVudEVsZW1lbnQuY2hpbGRyZW4sIHRoaXMpO1xuICB9XG5cbiAgX29uQ2xpY2soKSB7XG4gICAgaWYgKHRoaXMub25DbGljayBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICB0aGlzLm9uQ2xpY2soKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fdGFiYmFyLnNldEFjdGl2ZVRhYih0aGlzLmluZGV4LCB7IHJlamVjdDogZmFsc2UgfSk7XG4gICAgfVxuICB9XG5cbiAgc2V0QWN0aXZlKGFjdGl2ZSA9IHRydWUpIHtcbiAgICB0aGlzLl9pbnB1dC5jaGVja2VkID0gYWN0aXZlO1xuICAgIHRoaXMuY2xhc3NMaXN0LnRvZ2dsZSgnYWN0aXZlJywgYWN0aXZlKTtcbiAgICB1dGlsLnRvZ2dsZUF0dHJpYnV0ZSh0aGlzLCAnYWN0aXZlJywgYWN0aXZlKVxuXG4gICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdpY29uJykgJiYgdGhpcy5oYXNBdHRyaWJ1dGUoJ2FjdGl2ZS1pY29uJykpIHtcbiAgICAgIHRoaXMuX2ljb24uY2hpbGRyZW5bMF0uc2V0QXR0cmlidXRlKCdpY29uJywgdGhpcy5nZXRBdHRyaWJ1dGUoYWN0aXZlID8gJ2FjdGl2ZS1pY29uJyA6ICdpY29uJykpO1xuICAgIH1cbiAgfVxuXG4gIF9sb2FkUGFnZUVsZW1lbnQocGFyZW50LCBwYWdlKSB7XG4gICAgdGhpcy5faGFzTG9hZGVkID0gdHJ1ZTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHRoaXMuX3BhZ2VMb2FkZXIubG9hZCh7IHBhcmVudCwgcGFnZSB9LCBwYWdlRWxlbWVudCA9PiB7XG4gICAgICAgIHBhcmVudC5yZXBsYWNlQ2hpbGQocGFnZUVsZW1lbnQsIHBhcmVudC5jaGlsZHJlblt0aGlzLmluZGV4XSk7IC8vIEVuc3VyZSBwb3NpdGlvblxuICAgICAgICB0aGlzLl9sb2FkZWRQYWdlID0gcGFnZUVsZW1lbnQ7XG4gICAgICAgIHJlc29sdmUocGFnZUVsZW1lbnQpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBnZXQgcGFnZUVsZW1lbnQoKSB7XG4gICAgLy8gSXQgaGFzIGJlZW4gbG9hZGVkIGJ5IG9ucy10YWJcbiAgICBpZiAodGhpcy5fbG9hZGVkUGFnZSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2xvYWRlZFBhZ2U7XG4gICAgfVxuICAgIC8vIE1hbnVhbGx5IGF0dGFjaGVkIHRvIERPTSwgMSBwZXIgdGFiXG4gICAgY29uc3QgdGFiYmFyID0gdGhpcy5fdGFiYmFyO1xuICAgIGlmICh0YWJiYXIucGFnZXMubGVuZ3RoID09PSB0YWJiYXIudGFicy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB0YWJiYXIucGFnZXNbdGhpcy5pbmRleF07XG4gICAgfVxuICAgIC8vIExvYWRlZCBpbiBhbm90aGVyIHdheVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59XG4gICAqL1xuICBpc0FjdGl2ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5jbGFzc0xpc3QuY29udGFpbnMoJ2FjdGl2ZScpO1xuICB9XG5cbiAgZGlzY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uQ2xpY2ssIGZhbHNlKTtcbiAgICBpZiAodGhpcy5fbG9hZGVkUGFnZSkge1xuICAgICAgdGhpcy5faGFzTG9hZGVkID0gZmFsc2U7XG4gICAgICB0aGlzLmxvYWRlZCA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgY29ubmVjdGVkQ2FsbGJhY2soKSB7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuX29uQ2xpY2ssIGZhbHNlKTtcblxuICAgIGlmICghdXRpbC5pc0F0dGFjaGVkKHRoaXMpIHx8IHRoaXMubG9hZGVkKSB7XG4gICAgICByZXR1cm47IC8vIG9ucy10YWJiYXIgY29tcGlsYXRpb24gbWF5IHRyaWdnZXIgdGhpc1xuICAgIH1cblxuICAgIGNvbnN0IGRlZmVycmVkID0gdXRpbC5kZWZlcigpO1xuICAgIHRoaXMubG9hZGVkID0gZGVmZXJyZWQucHJvbWlzZTtcblxuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB7XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMuaW5kZXg7XG4gICAgICBjb25zdCB0YWJiYXIgPSB0aGlzLl90YWJiYXI7XG4gICAgICBpZiAoIXRhYmJhcikge1xuICAgICAgICB1dGlsLnRocm93KCdUYWIgZWxlbWVudHMgbXVzdCBiZSBjaGlsZHJlbiBvZiBUYWJiYXInKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRhYmJhci5oYXNBdHRyaWJ1dGUoJ21vZGlmaWVyJykpIHtcbiAgICAgICAgdXRpbC5hZGRNb2RpZmllcih0aGlzLCB0YWJiYXIuZ2V0QXR0cmlidXRlKCdtb2RpZmllcicpKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCF0aGlzLl9oYXNMb2FkZWQpIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzQXR0cmlidXRlKCdhY3RpdmUnKSkge1xuICAgICAgICAgIHRoaXMuc2V0QWN0aXZlKHRydWUpO1xuICAgICAgICAgIHRhYmJhci5zZXRBdHRyaWJ1dGUoJ2FjdGl2ZUluZGV4JywgaW5kZXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGluZGV4ID09PSB0YWJiYXIudGFicy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgdGFiYmFyLl9vblJlZnJlc2goKTtcbiAgICAgICAgICBzZXRJbW1lZGlhdGUoKCkgPT4gdGFiYmFyLl9vblJlZnJlc2goKSk7XG4gICAgICAgIH1cblxuICAgICAgICBUYWJiYXJFbGVtZW50LnJld3JpdGFibGVzLnJlYWR5KHRhYmJhciwgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHBhZ2VUYXJnZXQgPSB0aGlzLnBhZ2UgfHwgdGhpcy5nZXRBdHRyaWJ1dGUoJ3BhZ2UnKTtcbiAgICAgICAgICBpZiAoIXRoaXMucGFnZUVsZW1lbnQgJiYgcGFnZVRhcmdldCkge1xuICAgICAgICAgICAgY29uc3QgcGFyZW50VGFyZ2V0ID0gdGFiYmFyLl90YXJnZXRFbGVtZW50O1xuICAgICAgICAgICAgY29uc3QgZHVtbXlQYWdlID0gdXRpbC5jcmVhdGUoJ2RpdicsIHsgaGVpZ2h0OiAnMTAwJScsIHdpZHRoOiAnMTAwJScsIHZpc2liaWxpdHk6ICdoaWRkZW4nIH0pO1xuICAgICAgICAgICAgcGFyZW50VGFyZ2V0Lmluc2VydEJlZm9yZShkdW1teVBhZ2UsIHBhcmVudFRhcmdldC5jaGlsZHJlbltpbmRleF0pOyAvLyBFbnN1cmUgcG9zaXRpb25cblxuICAgICAgICAgICAgY29uc3QgbG9hZCA9ICgpID0+IHRoaXMuX2xvYWRQYWdlRWxlbWVudChwYXJlbnRUYXJnZXQsIHBhZ2VUYXJnZXQpLnRoZW4oZGVmZXJyZWQucmVzb2x2ZSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5pc0FjdGl2ZSgpID8gbG9hZCgpIDogdGFiYmFyLl9sb2FkSW5hY3RpdmUucHJvbWlzZS50aGVuKGxvYWQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBkZWZlcnJlZC5yZXNvbHZlKHRoaXMucGFnZUVsZW1lbnQpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgb2JzZXJ2ZWRBdHRyaWJ1dGVzKCkge1xuICAgIHJldHVybiBbJ21vZGlmaWVyJywgJ3JpcHBsZScsICdpY29uJywgJ2xhYmVsJywgJ3BhZ2UnLCAnYmFkZ2UnLCAnY2xhc3MnXTtcbiAgfVxuXG4gIGF0dHJpYnV0ZUNoYW5nZWRDYWxsYmFjayhuYW1lLCBsYXN0LCBjdXJyZW50KSB7XG4gICAgc3dpdGNoIChuYW1lKSB7XG4gICAgICBjYXNlICdjbGFzcyc6XG4gICAgICAgIHV0aWwucmVzdG9yZUNsYXNzKHRoaXMsIGRlZmF1bHRDbGFzc05hbWUsIHNjaGVtZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kaWZpZXInOlxuICAgICAgICBjb250ZW50UmVhZHkodGhpcywgKCkgPT4gTW9kaWZpZXJVdGlsLm9uTW9kaWZpZXJDaGFuZ2VkKGxhc3QsIGN1cnJlbnQsIHRoaXMsIHNjaGVtZSkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3JpcHBsZSc6XG4gICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVSaXBwbGUoKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaWNvbic6XG4gICAgICBjYXNlICdsYWJlbCc6XG4gICAgICBjYXNlICdiYWRnZSc6XG4gICAgICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl91cGRhdGVCdXR0b25Db250ZW50KCkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3BhZ2UnOlxuICAgICAgICB0aGlzLnBhZ2UgPSBjdXJyZW50IHx8ICcnO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cbn1cblxub25zRWxlbWVudHMuVGFiID0gVGFiRWxlbWVudDtcbmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnb25zLXRhYicsIFRhYkVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IEJhc2VBbmltYXRvciBmcm9tICcuLi8uLi9vbnMvYmFzZS1hbmltYXRvcic7XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRvYXN0QW5pbWF0b3IgZXh0ZW5kcyBCYXNlQW5pbWF0b3Ige1xuXG4gIC8qKlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy50aW1pbmdcbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuZHVyYXRpb25cbiAgICogQHBhcmFtIHtOdW1iZXJ9IG9wdGlvbnMuZGVsYXlcbiAgICovXG4gIGNvbnN0cnVjdG9yKHt0aW1pbmcgPSAnbGluZWFyJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMn0gPSB7fSkge1xuICAgIHN1cGVyKHsgdGltaW5nLCBkZWxheSwgZHVyYXRpb24gfSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gbW9kYWxcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHNob3cobW9kYWwsIGNhbGxiYWNrKSB7XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBtb2RhbFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgaGlkZShtb2RhbCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjaygpO1xuICB9XG59XG4iLCJcbi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBhbmltaXQgZnJvbSAnLi4vLi4vb25zL2FuaW1pdCc7XG5pbXBvcnQgVG9hc3RBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcblxuLyoqXG4gKiBpT1Mgc3R5bGUgYW5pbWF0b3IgZm9yIGRpYWxvZy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmFkZVRvYXN0QW5pbWF0b3IgZXh0ZW5kcyBUb2FzdEFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7dGltaW5nID0gJ2xpbmVhcicsIGRlbGF5ID0gMCwgZHVyYXRpb24gPSAwLjN9ID0ge30pIHtcbiAgICBzdXBlcih7IHRpbWluZywgZGVsYXksIGR1cmF0aW9uIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRvYXN0XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KHRvYXN0LCBjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gY2FsbGJhY2sgPyBjYWxsYmFjayA6IGZ1bmN0aW9uKCkge307XG5cbiAgICBhbmltaXQodG9hc3QsIHRoaXMuZGVmKVxuICAgICAgLmRlZmF1bHQoeyBvcGFjaXR5OiAwIH0sIHsgb3BhY2l0eTogMSB9KVxuICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICBkb25lKCk7XG4gICAgICB9KVxuICAgICAgLnBsYXkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSB0b2FzdFxuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFja1xuICAgKi9cbiAgaGlkZSh0b2FzdCwgY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IGNhbGxiYWNrID8gY2FsbGJhY2sgOiBmdW5jdGlvbigpIHt9O1xuXG4gICAgYW5pbWl0KHRvYXN0LCB0aGlzLmRlZilcbiAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMSB9LCB7IG9wYWNpdHk6IDAgfSlcbiAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgZG9uZSgpO1xuICAgICAgfSlcbiAgICAgIC5wbGF5KCk7XG4gIH1cbn1cbiIsIlxuLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGFuaW1pdCBmcm9tICcuLi8uLi9vbnMvYW5pbWl0JztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuLi8uLi9vbnMvcGxhdGZvcm0nO1xuaW1wb3J0IGlQaG9uZVhQYXRjaCBmcm9tICcuLi8uLi9vbnMvaXBob25leC1wYXRjaCc7XG5pbXBvcnQgVG9hc3RBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcblxuLyoqXG4gKiBBc2NlbmQgVG9hc3QgQW5pbWF0b3IuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEFzY2VuZFRvYXN0QW5pbWF0b3IgZXh0ZW5kcyBUb2FzdEFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7IHRpbWluZyA9ICdlYXNlJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMjUgfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcblxuICAgIHRoaXMubWVzc2FnZURlbGF5ID0gdGhpcy5kdXJhdGlvbiAqIDAuNCArIHRoaXMuZGVsYXk7IC8vIERlbGF5IG1lc3NhZ2Ugb3BhY2l0eSBjaGFuZ2VcbiAgICBpZiAocGxhdGZvcm0uaXNBbmRyb2lkKCkpIHtcbiAgICAgIHRoaXMuYXNjZW5zaW9uID0gNDg7IC8vIFRvYXN0cyBhcmUgYWx3YXlzIDEgbGluZVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWFBvcnRyYWl0UGF0Y2hBY3RpdmUoKSkge1xuICAgICAgICB0aGlzLmFzY2Vuc2lvbiA9IDk4OyAvLyA2NCArIDM0XG4gICAgICB9IGVsc2UgaWYgKGlQaG9uZVhQYXRjaC5pc0lQaG9uZVhMYW5kc2NhcGVQYXRjaEFjdGl2ZSgpKSB7XG4gICAgICAgIHRoaXMuYXNjZW5zaW9uID0gODU7IC8vIDY0ICsgMjFcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYXNjZW5zaW9uID0gNjQ7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRvYXN0XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KHRvYXN0LCBjYWxsYmFjaykge1xuICAgIHRvYXN0ID0gdG9hc3QuX3RvYXN0O1xuICAgIHV0aWwuZ2xvYmFscy5mYWJPZmZzZXQgPSB0aGlzLmFzY2Vuc2lvbjtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG4gICAgICBhbmltaXQodG9hc3QsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDAsICR7dGhpcy5hc2NlbnNpb259cHgsIDApYCB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pLFxuXG4gICAgICBhbmltaXQodGhpcy5fZ2V0RmFicygpKVxuICAgICAgICAud2FpdCh0aGlzLmRlbGF5KVxuICAgICAgICAucXVldWUoeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAtJHt0aGlzLmFzY2Vuc2lvbn1weCwgMCkgc2NhbGUoMSlgIH0sIHRoaXMuZGVmKSxcblxuICAgICAgYW5pbWl0KHV0aWwuYXJyYXlGcm9tKHRvYXN0LmNoaWxkcmVuKSwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KHsgb3BhY2l0eTogMCB9LCB7IG9wYWNpdHk6IDEgfSlcbiAgICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gdG9hc3RcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUodG9hc3QsIGNhbGxiYWNrKSB7XG4gICAgdG9hc3QgPSB0b2FzdC5fdG9hc3Q7XG4gICAgdXRpbC5nbG9iYWxzLmZhYk9mZnNldCA9IDA7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KHRvYXN0LCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScgfSxcbiAgICAgICAgICB7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDAsICR7dGhpcy5hc2NlbnNpb259cHgsIDApYCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KSxcblxuICAgICAgYW5pbWl0KHRoaXMuX2dldEZhYnMoKSwgdGhpcy5kZWYpXG4gICAgICAgIC53YWl0KHRoaXMuZGVsYXkpXG4gICAgICAgIC5xdWV1ZSh7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDAsIDAsIDApIHNjYWxlKDEpYCB9LCB0aGlzLmRlZiksXG5cbiAgICAgIGFuaW1pdCh1dGlsLmFycmF5RnJvbSh0b2FzdC5jaGlsZHJlbiksIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdCh7IG9wYWNpdHk6IDEgfSwgeyBvcGFjaXR5OiAwIH0pXG4gICAgKTtcbiAgfVxuXG4gIF9nZXRGYWJzKCkge1xuICAgIHJldHVybiB1dGlsLmFycmF5RnJvbShkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdvbnMtZmFiW3Bvc2l0aW9ufj1ib3R0b21dLCBvbnMtc3BlZWQtZGlhbFtwb3NpdGlvbn49Ym90dG9tXScpKS5maWx0ZXIoZmFiID0+IGZhYi52aXNpYmxlKTtcbiAgfVxufVxuIiwiXG4vKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IGlQaG9uZVhQYXRjaCBmcm9tICcuLi8uLi9vbnMvaXBob25leC1wYXRjaCc7XG5pbXBvcnQgVG9hc3RBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcblxuLyoqXG4gKiBMaWZ0LWZhZGUgVG9hc3QgQW5pbWF0b3JcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTGlmdFRvYXN0QW5pbWF0b3IgZXh0ZW5kcyBUb2FzdEFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7IHRpbWluZyA9ICdlYXNlJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMzUgfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcbiAgICB0aGlzLmJvZHlIZWlnaHQgPSBkb2N1bWVudC5ib2R5LmNsaWVudEhlaWdodDsgLy8gYXZvaWQgRm9yY2VkIFN5bmNocm9ub3VzIExheW91dFxuICAgIGlmIChpUGhvbmVYUGF0Y2guaXNJUGhvbmVYUG9ydHJhaXRQYXRjaEFjdGl2ZSgpKSB7XG4gICAgICB0aGlzLmxpZnRBbW91bnQgPSAnY2FsYygxMDAlICsgMzRweCknO1xuICAgIH0gZWxzZSBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWExhbmRzY2FwZVBhdGNoQWN0aXZlKCkpIHtcbiAgICAgIHRoaXMubGlmdEFtb3VudCA9ICdjYWxjKDEwMCUgKyAyMXB4KSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubGlmdEFtb3VudCA9ICcxMDAlJztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gdG9hc3RcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIHNob3codG9hc3QsIGNhbGxiYWNrKSB7XG4gICAgdG9hc3QgPSB0b2FzdC5fdG9hc3Q7XG5cbiAgICBhbmltaXQucnVuQWxsKFxuICAgICAgYW5pbWl0KHRvYXN0LCB0aGlzLmRlZilcbiAgICAgICAgLmRlZmF1bHQoXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAke3RoaXMubGlmdEFtb3VudH0sIDApYCwgb3BhY2l0eTogMCB9LFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiAxIH1cbiAgICAgICAgKVxuICAgICAgICAucXVldWUoZG9uZSA9PiB7XG4gICAgICAgICAgY2FsbGJhY2sgJiYgY2FsbGJhY2soKTtcbiAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH0pXG4gICAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRvYXN0XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBoaWRlKHRvYXN0LCBjYWxsYmFjaykge1xuICAgIHRvYXN0ID0gdG9hc3QuX3RvYXN0O1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0b2FzdCwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiAxIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAke3RoaXMubGlmdEFtb3VudH0sIDApYCwgb3BhY2l0eTogMCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIGNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgICAgICAgZG9uZSgpO1xuICAgICAgICB9KVxuICAgICk7XG4gIH1cblxuICBfdXBkYXRlUG9zaXRpb24odG9hc3QpIHtcbiAgICBpZiAocGFyc2VJbnQodG9hc3Quc3R5bGUudG9wLCAxMCkgPT09IDApIHtcbiAgICAgIHRvYXN0LnN0eWxlLnRvcCA9IHRvYXN0LnN0eWxlLmJvdHRvbSA9ICcnO1xuICAgIH1cbiAgfVxufVxuIiwiXG4vKlxuQ29weXJpZ2h0IDIwMTMtMjAxNSBBU0lBTCBDT1JQT1JBVElPTlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuXG5Vbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG5kaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG5XSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cblNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbmxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuXG4qL1xuXG5pbXBvcnQgdXRpbCBmcm9tICcuLi8uLi9vbnMvdXRpbCc7XG5pbXBvcnQgYW5pbWl0IGZyb20gJy4uLy4uL29ucy9hbmltaXQnO1xuaW1wb3J0IGlQaG9uZVhQYXRjaCBmcm9tICcuLi8uLi9vbnMvaXBob25leC1wYXRjaCc7XG5pbXBvcnQgVG9hc3RBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcblxuLyoqXG4gKiBGYWxsLWZhZGUgVG9hc3QgQW5pbWF0b3JcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRmFsbFRvYXN0QW5pbWF0b3IgZXh0ZW5kcyBUb2FzdEFuaW1hdG9yIHtcblxuICBjb25zdHJ1Y3Rvcih7IHRpbWluZyA9ICdlYXNlJywgZGVsYXkgPSAwLCBkdXJhdGlvbiA9IDAuMzUgfSA9IHt9KSB7XG4gICAgc3VwZXIoeyB0aW1pbmcsIGRlbGF5LCBkdXJhdGlvbiB9KTtcbiAgICBpZiAoaVBob25lWFBhdGNoLmlzSVBob25lWFBvcnRyYWl0UGF0Y2hBY3RpdmUoKSkge1xuICAgICAgdGhpcy5mYWxsQW1vdW50ID0gJ2NhbGMoLTEwMCUgLSA0NHB4KSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZmFsbEFtb3VudCA9ICctMTAwJSc7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHRvYXN0XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAqL1xuICBzaG93KHRvYXN0LCBjYWxsYmFjaykge1xuICAgIHRvYXN0ID0gdG9hc3QuX3RvYXN0O1xuICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKHRvYXN0KTtcblxuICAgIGFuaW1pdC5ydW5BbGwoXG4gICAgICBhbmltaXQodG9hc3QsIHRoaXMuZGVmKVxuICAgICAgICAuZGVmYXVsdChcbiAgICAgICAgICB7IHRyYW5zZm9ybTogYHRyYW5zbGF0ZTNkKDAsICR7dGhpcy5mYWxsQW1vdW50fSwgMClgLCBvcGFjaXR5OiAwIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06ICd0cmFuc2xhdGUzZCgwLCAwLCAwKScsIG9wYWNpdHk6IDEgfVxuICAgICAgICApXG4gICAgICAgIC5xdWV1ZShkb25lID0+IHtcbiAgICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gdG9hc3RcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2tcbiAgICovXG4gIGhpZGUodG9hc3QsIGNhbGxiYWNrKSB7XG4gICAgdG9hc3QgPSB0b2FzdC5fdG9hc3Q7XG4gICAgdGhpcy5fdXBkYXRlUG9zaXRpb24odG9hc3QpO1xuXG4gICAgYW5pbWl0LnJ1bkFsbChcbiAgICAgIGFuaW1pdCh0b2FzdCwgdGhpcy5kZWYpXG4gICAgICAgIC5kZWZhdWx0KFxuICAgICAgICAgIHsgdHJhbnNmb3JtOiAndHJhbnNsYXRlM2QoMCwgMCwgMCknLCBvcGFjaXR5OiAxIH0sXG4gICAgICAgICAgeyB0cmFuc2Zvcm06IGB0cmFuc2xhdGUzZCgwLCAke3RoaXMuZmFsbEFtb3VudH0sIDApYCwgb3BhY2l0eTogMCB9XG4gICAgICAgIClcbiAgICAgICAgLnF1ZXVlKGRvbmUgPT4ge1xuICAgICAgICAgIHRoaXMuX3VwZGF0ZVBvc2l0aW9uKHRvYXN0LCB0cnVlKTtcbiAgICAgICAgICBjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgX3VwZGF0ZVBvc2l0aW9uKHRvYXN0LCBjbGVhblVwKSB7XG4gICAgbGV0IGNvcnJlY3RUb3A7XG4gICAgaWYgKGlQaG9uZVhQYXRjaC5pc0lQaG9uZVhQb3J0cmFpdFBhdGNoQWN0aXZlKCkpIHtcbiAgICAgIGNvcnJlY3RUb3AgPSAnNDRweCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvcnJlY3RUb3AgPSAnMCc7XG4gICAgfVxuXG4gICAgaWYgKHRvYXN0LnN0eWxlLnRvcCAhPT0gY29ycmVjdFRvcCkge1xuICAgICAgdG9hc3Quc3R5bGUudG9wID0gY29ycmVjdFRvcDtcbiAgICAgIHRvYXN0LnN0eWxlLmJvdHRvbSA9ICdpbml0aWFsJztcbiAgICB9XG4gIH1cbn1cbiIsIi8qXG5Db3B5cmlnaHQgMjAxMy0yMDE1IEFTSUFMIENPUlBPUkFUSU9OXG5cbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG55b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG5Zb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcblxuICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG5cblVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbmRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbldJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxubGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG5cbiovXG5cbmltcG9ydCBvbnNFbGVtZW50cyBmcm9tICcuLi8uLi9vbnMvZWxlbWVudHMnO1xuaW1wb3J0IHV0aWwgZnJvbSAnLi4vLi4vb25zL3V0aWwnO1xuaW1wb3J0IGF1dG9TdHlsZSBmcm9tICcuLi8uLi9vbnMvYXV0b3N0eWxlJztcbmltcG9ydCBNb2RpZmllclV0aWwgZnJvbSAnLi4vLi4vb25zL2ludGVybmFsL21vZGlmaWVyLXV0aWwnO1xuaW1wb3J0IEFuaW1hdG9yRmFjdG9yeSBmcm9tICcuLi8uLi9vbnMvaW50ZXJuYWwvYW5pbWF0b3ItZmFjdG9yeSc7XG5pbXBvcnQgVG9hc3RBbmltYXRvciBmcm9tICcuL2FuaW1hdG9yJztcbmltcG9ydCBGYWRlVG9hc3RBbmltYXRvciBmcm9tICcuL2ZhZGUtYW5pbWF0b3InO1xuaW1wb3J0IEFzY2VuZFRvYXN0QW5pbWF0b3IgZnJvbSAnLi9hc2NlbmQtYW5pbWF0b3InO1xuaW1wb3J0IExpZnRUb2FzdEFuaW1hdG9yIGZyb20gJy4vbGlmdC1hbmltYXRvcic7XG5pbXBvcnQgRmFsbFRvYXN0QW5pbWF0b3IgZnJvbSAnLi9mYWxsLWFuaW1hdG9yJztcbmltcG9ydCBwbGF0Zm9ybSBmcm9tICcuLi8uLi9vbnMvcGxhdGZvcm0nO1xuaW1wb3J0IEJhc2VEaWFsb2dFbGVtZW50IGZyb20gJy4uL2Jhc2UvYmFzZS1kaWFsb2cnO1xuaW1wb3J0IGNvbnRlbnRSZWFkeSBmcm9tICcuLi8uLi9vbnMvY29udGVudC1yZWFkeSc7XG5cbmNvbnN0IHNjaGVtZSA9IHtcbiAgJy50b2FzdCc6ICd0b2FzdC0tKicsXG4gICcudG9hc3RfX21lc3NhZ2UnOiAndG9hc3QtLSpfX21lc3NhZ2UnLFxuICAnLnRvYXN0X19idXR0b24nOiAndG9hc3QtLSpfX2J1dHRvbidcbn07XG5cbmNvbnN0IGRlZmF1bHRDbGFzc05hbWUgPSAndG9hc3QnO1xuXG5jb25zdCBfYW5pbWF0b3JEaWN0ID0ge1xuICAnZGVmYXVsdCc6IHBsYXRmb3JtLmlzQW5kcm9pZCgpID8gQXNjZW5kVG9hc3RBbmltYXRvciA6IExpZnRUb2FzdEFuaW1hdG9yLFxuICAnZmFkZSc6IEZhZGVUb2FzdEFuaW1hdG9yLFxuICAnYXNjZW5kJzogQXNjZW5kVG9hc3RBbmltYXRvcixcbiAgJ2xpZnQnOiBMaWZ0VG9hc3RBbmltYXRvcixcbiAgJ2ZhbGwnOiBGYWxsVG9hc3RBbmltYXRvcixcbiAgJ25vbmUnOiBUb2FzdEFuaW1hdG9yXG59O1xuXG4vKipcbiAqIEBlbGVtZW50IG9ucy10b2FzdFxuICogQGNhdGVnb3J5IGRpYWxvZ1xuICogQGRlc2NyaXB0aW9uXG4gKiAgIFtlbl1cbiAqICAgICBUaGUgVG9hc3Qgb3IgU25hY2tiYXIgY29tcG9uZW50IGlzIHVzZWZ1bCBmb3IgZGlzcGxheWluZyBkaXNtaXNzYWJsZSBpbmZvcm1hdGlvbiBvciBzaW1wbGUgYWN0aW9ucyBhdCAobm9ybWFsbHkpIHRoZSBib3R0b20gb2YgdGhlIHBhZ2UuXG4gKlxuICogICAgIFRoaXMgY29tcG9uZW50IGRvZXMgbm90IGJsb2NrIHVzZXIgaW5wdXQsIGFsbG93aW5nIHRoZSBhcHAgdG8gY29udGludWUgaXRzIGZsb3cuIEZvciBzaW1wbGUgdG9hc3RzLCBjb25zaWRlciBgb25zLm5vdGlmaWNhdGlvbi50b2FzdGAgaW5zdGVhZC5cbiAqICAgWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvdG9hc3RcbiAqIEBzZWVhbHNvIG9ucy1hbGVydC1kaWFsb2dcbiAqICAgW2VuXVRoZSBgPG9ucy1hbGVydC1kaWFsb2c+YCBjb21wb25lbnQgaXMgcHJlZmVycmVkIGZvciBkaXNwbGF5aW5nIHVuZGlzbWlzc2FibGUgaW5mb3JtYXRpb24uWy9lbl1cbiAqICAgW2phXVsvamFdXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFRvYXN0RWxlbWVudCBleHRlbmRzIEJhc2VEaWFsb2dFbGVtZW50IHtcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZSBhbmltYXRpb25cbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlZmF1bHQgZGVmYXVsdFxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1UaGUgYW5pbWF0aW9uIHVzZWQgd2hlbiBzaG93aW5nIGFuZCBoaWRpbmcgdGhlIHRvYXN0LiBDYW4gYmUgZWl0aGVyIGBcImRlZmF1bHRcImAsIGBcImFzY2VuZFwiYCAoQW5kcm9pZCksIGBcImxpZnRcImAgKGlPUyksIGBcImZhbGxcImAsIGBcImZhZGVcImAgb3IgYFwibm9uZVwiYC5bL2VuXVxuICAgKiAgW2phXVsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlIGFuaW1hdGlvbi1vcHRpb25zXG4gICAqIEB0eXBlIHtFeHByZXNzaW9ufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgdGltaW5nIGFuZCBkZWxheSB3aXRoIGFuIG9iamVjdCBsaXRlcmFsLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDEsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgdGltaW5nLCBkZWxheeOCkuOCquODluOCuOOCp+OCr+ODiOODquODhuODqeODq+OBp+aMh+WumuOBl+OBvuOBmeOAgmUuZy4gPGNvZGU+e2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAxLCB0aW1pbmc6ICdlYXNlLWluJ308L2NvZGU+Wy9qYV1cbiAgICovXG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuX2RlZmF1bHREQkIgPSBudWxsO1xuICAgIGNvbnRlbnRSZWFkeSh0aGlzLCAoKSA9PiB0aGlzLl9jb21waWxlKCkpO1xuICB9XG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHNjaGVtZTtcbiAgfVxuXG4gIGdldCBfdG9hc3QoKSB7XG4gICAgcmV0dXJuIHV0aWwuZmluZENoaWxkKHRoaXMsIGAuJHtkZWZhdWx0Q2xhc3NOYW1lfWApO1xuICB9XG5cbiAgX3VwZGF0ZUFuaW1hdG9yRmFjdG9yeSgpIHtcbiAgICAvLyBSZXNldCBwb3NpdGlvbiBzdHlsZVxuICAgIHRoaXMuX3RvYXN0ICYmICh0aGlzLl90b2FzdC5zdHlsZS50b3AgPSB0aGlzLl90b2FzdC5zdHlsZS5ib3R0b20gPSAnJyk7XG5cbiAgICByZXR1cm4gbmV3IEFuaW1hdG9yRmFjdG9yeSh7XG4gICAgICBhbmltYXRvcnM6IF9hbmltYXRvckRpY3QsXG4gICAgICBiYXNlQ2xhc3M6IFRvYXN0QW5pbWF0b3IsXG4gICAgICBiYXNlQ2xhc3NOYW1lOiAnVG9hc3RBbmltYXRvcicsXG4gICAgICBkZWZhdWx0QW5pbWF0aW9uOiB0aGlzLmdldEF0dHJpYnV0ZSgnYW5pbWF0aW9uJylcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgb25EZXZpY2VCYWNrQnV0dG9uXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1CYWNrLWJ1dHRvbiBoYW5kbGVyLlsvZW5dXG4gICAqICAgW2phXeODkOODg+OCr+ODnOOCv+ODs+ODj+ODs+ODieODqeOAglsvamFdXG4gICAqL1xuXG4gIF9jb21waWxlKCkge1xuICAgIGF1dG9TdHlsZS5wcmVwYXJlKHRoaXMpO1xuXG4gICAgdGhpcy5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIHRoaXMuc3R5bGUuekluZGV4ID0gMTAwMDA7IC8vIExvd2VyIHRoYW4gZGlhbG9nc1xuXG4gICAgY29uc3QgbWVzc2FnZUNsYXNzTmFtZSA9ICd0b2FzdF9fbWVzc2FnZSc7XG4gICAgY29uc3QgYnV0dG9uQ2xhc3NOYW1lID0gJ3RvYXN0X19idXR0b24nO1xuXG4gICAgbGV0IHRvYXN0ID0gdXRpbC5maW5kQ2hpbGQodGhpcywgYC4ke2RlZmF1bHRDbGFzc05hbWV9YCk7XG4gICAgaWYgKCF0b2FzdCkge1xuICAgICAgdG9hc3QgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIHRvYXN0LmNsYXNzTGlzdC5hZGQoZGVmYXVsdENsYXNzTmFtZSk7XG4gICAgICB3aGlsZSAodGhpcy5jaGlsZE5vZGVzWzBdKSB7XG4gICAgICAgIHRvYXN0LmFwcGVuZENoaWxkKHRoaXMuY2hpbGROb2Rlc1swXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IGJ1dHRvbiA9IHV0aWwuZmluZENoaWxkKHRvYXN0LCBgLiR7YnV0dG9uQ2xhc3NOYW1lfWApO1xuICAgIGlmICghYnV0dG9uKSB7XG4gICAgICBidXR0b24gPSB1dGlsLmZpbmRDaGlsZCh0b2FzdCwgZSA9PiB1dGlsLm1hdGNoKGUsICcuYnV0dG9uJykgfHwgdXRpbC5tYXRjaChlLCAnYnV0dG9uJykpO1xuICAgICAgaWYgKGJ1dHRvbikge1xuICAgICAgICBidXR0b24uY2xhc3NMaXN0LnJlbW92ZSgnYnV0dG9uJyk7XG4gICAgICAgIGJ1dHRvbi5jbGFzc0xpc3QuYWRkKGJ1dHRvbkNsYXNzTmFtZSk7XG4gICAgICAgIHRvYXN0LmFwcGVuZENoaWxkKGJ1dHRvbik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCF1dGlsLmZpbmRDaGlsZCh0b2FzdCwgYC4ke21lc3NhZ2VDbGFzc05hbWV9YCkpIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXRpbC5maW5kQ2hpbGQodG9hc3QsICcubWVzc2FnZScpO1xuICAgICAgaWYgKCFtZXNzYWdlKSB7XG4gICAgICAgIG1lc3NhZ2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IHRvYXN0LmNoaWxkTm9kZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICBpZiAodG9hc3QuY2hpbGROb2Rlc1tpXSAhPT0gYnV0dG9uKSB7XG4gICAgICAgICAgICBtZXNzYWdlLmluc2VydEJlZm9yZSh0b2FzdC5jaGlsZE5vZGVzW2ldLCBtZXNzYWdlLmZpcnN0Q2hpbGQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbWVzc2FnZS5jbGFzc0xpc3QuYWRkKG1lc3NhZ2VDbGFzc05hbWUpO1xuXG4gICAgICB0b2FzdC5pbnNlcnRCZWZvcmUobWVzc2FnZSwgdG9hc3QuZmlyc3RDaGlsZCk7XG4gICAgfVxuXG4gICAgaWYgKHRvYXN0LnBhcmVudE5vZGUgIT09IHRoaXMpIHtcbiAgICAgIHRoaXMuYXBwZW5kQ2hpbGQodG9hc3QpO1xuICAgIH1cblxuICAgIE1vZGlmaWVyVXRpbC5pbml0TW9kaWZpZXIodGhpcywgdGhpcy5fc2NoZW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJvcGVydHkgdmlzaWJsZVxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0Jvb2xlYW59XG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1XaGV0aGVyIHRoZSBlbGVtZW50IGlzIHZpc2libGUgb3Igbm90LlsvZW5dXG4gICAqICAgW2phXeimgee0oOOBjOimi+OBiOOCi+WgtOWQiOOBq2B0cnVlYOOAglsvamFdXG4gICAqL1xuXG4gIC8qKlxuICAgKiBAbWV0aG9kIHNob3dcbiAgICogQHNpZ25hdHVyZSBzaG93KFtvcHRpb25zXSlcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiAgIFtlbl1QYXJhbWV0ZXIgb2JqZWN0LlsvZW5dXG4gICAqICAgW2phXeOCquODl+OCt+ODp+ODs+OCkuaMh+WumuOBmeOCi+OCquODluOCuOOCp+OCr+ODiOOAglsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25dXG4gICAqICAgW2VuXUFuaW1hdGlvbiBuYW1lLiBBdmFpbGFibGUgYW5pbWF0aW9ucyBhcmUgYFwiZGVmYXVsdFwiYCwgYFwiYXNjZW5kXCJgIChBbmRyb2lkKSwgYFwibGlmdFwiYCAoaU9TKSwgYFwiZmFsbFwiYCwgYFwiZmFkZVwiYCBvciBgXCJub25lXCJgLlsvZW5dXG4gICAqICAgW2phXVsvamFdXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbmltYXRpb25PcHRpb25zXVxuICAgKiAgIFtlbl1TcGVjaWZ5IHRoZSBhbmltYXRpb24ncyBkdXJhdGlvbiwgZGVsYXkgYW5kIHRpbWluZy4gRS5nLiBge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfWAuWy9lbl1cbiAgICogICBbamFd44Ki44OL44Oh44O844K344On44Oz5pmC44GuZHVyYXRpb24sIGRlbGF5LCB0aW1pbmfjgpLmjIflrprjgZfjgb7jgZnjgIJlLmcuIHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31bL2phXVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dU2hvdyB0aGUgZWxlbWVudC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcmV0dXJuIHtQcm9taXNlfVxuICAgKiAgIFtlbl1SZXNvbHZlcyB0byB0aGUgZGlzcGxheWVkIGVsZW1lbnRbL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCB0b2dnbGVcbiAgICogQHNpZ25hdHVyZSB0b2dnbGUoW29wdGlvbnNdKVxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdXG4gICAqICAgW2VuXVBhcmFtZXRlciBvYmplY3QuWy9lbl1cbiAgICogICBbamFd44Kq44OX44K344On44Oz44KS5oyH5a6a44GZ44KL44Kq44OW44K444Kn44Kv44OI44CCWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbl1cbiAgICogICBbZW5dQW5pbWF0aW9uIG5hbWUuIEF2YWlsYWJsZSBhbmltYXRpb25zIGFyZSBgXCJkZWZhdWx0XCJgLCBgXCJhc2NlbmRcImAgKEFuZHJvaWQpLCBgXCJsaWZ0XCJgIChpT1MpLCBgXCJmYWxsXCJgLCBgXCJmYWRlXCJgIG9yIGBcIm5vbmVcImAuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmFuaW1hdGlvbk9wdGlvbnNdXG4gICAqICAgW2VuXVNwZWNpZnkgdGhlIGFuaW1hdGlvbidzIGR1cmF0aW9uLCBkZWxheSBhbmQgdGltaW5nLiBFLmcuIGB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9YC5bL2VuXVxuICAgKiAgIFtqYV3jgqLjg4vjg6Hjg7zjgrfjg6fjg7PmmYLjga5kdXJhdGlvbiwgZGVsYXksIHRpbWluZ+OCkuaMh+WumuOBl+OBvuOBmeOAgmUuZy4ge2R1cmF0aW9uOiAwLjIsIGRlbGF5OiAwLjQsIHRpbWluZzogJ2Vhc2UtaW4nfVsvamFdXG4gICAqIEBkZXNjcmlwdGlvblxuICAgKiAgIFtlbl1Ub2dnbGUgdG9hc3QgdmlzaWJpbGl0eS5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQG1ldGhvZCBoaWRlXG4gICAqIEBzaWduYXR1cmUgaGlkZShbb3B0aW9uc10pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc11cbiAgICogICBbZW5dUGFyYW1ldGVyIG9iamVjdC5bL2VuXVxuICAgKiAgIFtqYV3jgqrjg5fjgrfjg6fjg7PjgpLmjIflrprjgZnjgovjgqrjg5bjgrjjgqfjgq/jg4jjgIJbL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uXVxuICAgKiAgIFtlbl1BbmltYXRpb24gbmFtZS4gQXZhaWxhYmxlIGFuaW1hdGlvbnMgYXJlIGBcImRlZmF1bHRcImAsIGBcImFzY2VuZFwiYCAoQW5kcm9pZCksIGBcImxpZnRcImAgKGlPUyksIGBcImZhbGxcImAsIGBcImZhZGVcImAgb3IgYFwibm9uZVwiYC5bL2VuXVxuICAgKiAgIFtqYV1bL2phXVxuICAgKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuYW5pbWF0aW9uT3B0aW9uc11cbiAgICogICBbZW5dU3BlY2lmeSB0aGUgYW5pbWF0aW9uJ3MgZHVyYXRpb24sIGRlbGF5IGFuZCB0aW1pbmcuIEUuZy4gYHtkdXJhdGlvbjogMC4yLCBkZWxheTogMC40LCB0aW1pbmc6ICdlYXNlLWluJ31gLlsvZW5dXG4gICAqICAgW2phXeOCouODi+ODoeODvOOCt+ODp+ODs+aZguOBrmR1cmF0aW9uLCBkZWxheSwgdGltaW5n44KS5oyH5a6a44GX44G+44GZ44CCZS5nLiB7ZHVyYXRpb246IDAuMiwgZGVsYXk6IDAuNCwgdGltaW5nOiAnZWFzZS1pbid9Wy9qYV1cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXUhpZGUgdG9hc3QuWy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICogQHJldHVybiB7UHJvbWlzZX1cbiAgICogICBbZW5dUmVzb2x2ZXMgdG8gdGhlIGhpZGRlbiBlbGVtZW50Wy9lbl1cbiAgICogICBbamFdWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IEFuaW1hdG9yXG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXJBbmltYXRvcihuYW1lLCBBbmltYXRvcikge1xuICAgIGlmICghKEFuaW1hdG9yLnByb3RvdHlwZSBpbnN0YW5jZW9mIFRvYXN0QW5pbWF0b3IpKSB7XG4gICAgICB1dGlsLnRocm93KCdcIkFuaW1hdG9yXCIgcGFyYW0gbXVzdCBpbmhlcml0IE9uc1RvYXN0RWxlbWVudC5Ub2FzdEFuaW1hdG9yJyk7XG4gICAgfVxuICAgIF9hbmltYXRvckRpY3RbbmFtZV0gPSBBbmltYXRvcjtcbiAgfVxuXG4gIHN0YXRpYyBnZXQgYW5pbWF0b3JzKCkge1xuICAgIHJldHVybiBfYW5pbWF0b3JEaWN0O1xuICB9XG5cbiAgc3RhdGljIGdldCBUb2FzdEFuaW1hdG9yKCkge1xuICAgIHJldHVybiBUb2FzdEFuaW1hdG9yO1xuICB9XG59XG5cbm9uc0VsZW1lbnRzLlRvYXN0ID0gVG9hc3RFbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtdG9hc3QnLCBUb2FzdEVsZW1lbnQpO1xuIiwiLypcbkNvcHlyaWdodCAyMDEzLTIwMTUgQVNJQUwgQ09SUE9SQVRJT05cblxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbnlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbllvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuXG4gICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cblxuKi9cblxuaW1wb3J0IG9uc0VsZW1lbnRzIGZyb20gJy4uL29ucy9lbGVtZW50cyc7XG5pbXBvcnQgQmFzZUJ1dHRvbkVsZW1lbnQgZnJvbSAnLi9iYXNlL2Jhc2UtYnV0dG9uJztcblxuLyoqXG4gKiBAZWxlbWVudCBvbnMtdG9vbGJhci1idXR0b25cbiAqIEBjYXRlZ29yeSBwYWdlXG4gKiBAbW9kaWZpZXIgbWF0ZXJpYWxcbiAqICAgW2VuXU1hdGVyaWFsIERlc2lnbiB0b29sYmFyIGJ1dHRvbi5bL2VuXVxuICogICBbamFdWy9qYV1cbiAqIEBtb2RpZmllciBvdXRsaW5lXG4gKiAgIFtlbl1BIGJ1dHRvbiB3aXRoIGFuIG91dGxpbmUuWy9lbl1cbiAqICAgW2phXeOCouOCpuODiOODqeOCpOODs+OCkuOCguOBo+OBn+ODnOOCv+ODs+OCkuihqOekuuOBl+OBvuOBmeOAglsvamFdXG4gKiBAZGVzY3JpcHRpb25cbiAqICAgW2VuXUJ1dHRvbiBjb21wb25lbnQgZm9yIG9ucy10b29sYmFyIGFuZCBvbnMtYm90dG9tLXRvb2xiYXIuWy9lbl1cbiAqICAgW2phXW9ucy10b29sYmFy44GC44KL44GE44Gvb25zLWJvdHRvbS10b29sYmFy44Gr6Kit572u44Gn44GN44KL44Oc44K/44Oz55So44Kz44Oz44Od44O844ON44Oz44OI44Gn44GZ44CCWy9qYV1cbiAqIEBjb2RlcGVuIGFIbUdMXG4gKiBAdHV0b3JpYWwgdmFuaWxsYS9SZWZlcmVuY2UvcGFnZVxuICogQGd1aWRlIGNvbXBpbGF0aW9uLmh0bWwjdG9vbGJhci1jb21waWxhdGlvblxuICogICBbZW5dQWRkaW5nIGEgdG9vbGJhclsvZW5dXG4gKiAgIFtqYV3jg4Tjg7zjg6vjg5Djg7zjga7ov73liqBbL2phXVxuICogQHNlZWFsc28gb25zLXRvb2xiYXJcbiAqICAgW2VuXVRoZSBgPG9ucy10b29sYmFyPmAgY29tcG9uZW50IGRpc3BsYXlzIGEgbmF2aWdhdGlvbiBiYXIgYXQgdGhlIHRvcCBvZiBhIHBhZ2UuWy9lbl1cbiAqICAgW2phXW9ucy10b29sYmFy44Kz44Oz44Od44O844ON44Oz44OIWy9qYV1cbiAqIEBzZWVhbHNvIG9ucy1iYWNrLWJ1dHRvblxuICogICBbZW5dVGhlIGA8b25zLWJhY2stYnV0dG9uPmAgZGlzcGxheXMgYSBiYWNrIGJ1dHRvbiBpbiB0aGUgbmF2aWdhdGlvbiBiYXIuWy9lbl1cbiAqICAgW2phXW9ucy1iYWNrLWJ1dHRvbuOCs+ODs+ODneODvOODjeODs+ODiFsvamFdXG4gKiBAZXhhbXBsZVxuICogPG9ucy10b29sYmFyPlxuICogICA8ZGl2IGNsYXNzPVwibGVmdFwiPlxuICogICAgIDxvbnMtdG9vbGJhci1idXR0b24+XG4gKiAgICAgICBCdXR0b25cbiAqICAgICA8L29ucy10b29sYmFyLWJ1dHRvbj5cbiAqICAgPC9kaXY+XG4gKiAgIDxkaXYgY2xhc3M9XCJjZW50ZXJcIj5cbiAqICAgICBUaXRsZVxuICogICA8L2Rpdj5cbiAqICAgPGRpdiBjbGFzcz1cInJpZ2h0XCI+XG4gKiAgICAgPG9ucy10b29sYmFyLWJ1dHRvbj5cbiAqICAgICAgIDxvbnMtaWNvbiBpY29uPVwiaW9uLW5hdmljb25cIiBzaXplPVwiMjhweFwiPjwvb25zLWljb24+XG4gKiAgICAgPC9vbnMtdG9vbGJhci1idXR0b24+XG4gKiAgIDwvZGl2PlxuICogPC9vbnMtdG9vbGJhcj5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVG9vbGJhckJ1dHRvbkVsZW1lbnQgZXh0ZW5kcyBCYXNlQnV0dG9uRWxlbWVudCB7XG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgbW9kaWZpZXJcbiAgICogQHR5cGUge1N0cmluZ31cbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVRoZSBhcHBlYXJhbmNlIG9mIHRoZSBidXR0b24uWy9lbl1cbiAgICogICBbamFd44Oc44K/44Oz44Gu6KGo54++44KS5oyH5a6a44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgaWNvblxuICAgKiBAdHlwZSB7U3RyaW5nfVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogIFtlbl1DcmVhdGVzIGFuIGBvbnMtaWNvbmAgY29tcG9uZW50IHdpdGggdGhpcyBzdHJpbmcuWy9lbl1cbiAgICogIFtqYV1gb25zLWljb25g44Kz44Oz44Od44O844ON44Oz44OI44KS5oKq5oCn44GX44G+44GZ44CCWy9qYV1cbiAgICovXG5cbiAgLyoqXG4gICAqIEBhdHRyaWJ1dGUgZGlzYWJsZWRcbiAgICogQGRlc2NyaXB0aW9uXG4gICAqICAgW2VuXVNwZWNpZnkgaWYgYnV0dG9uIHNob3VsZCBiZSBkaXNhYmxlZC5bL2VuXVxuICAgKiAgIFtqYV3jg5zjgr/jg7PjgpLnhKHlirnljJbjgZnjgovloLTlkIjjga/mjIflrprjgZfjgabjgY/jgaDjgZXjgYTjgIJbL2phXVxuICAgKi9cblxuICAvKipcbiAgICogQHByb3BlcnR5IGRpc2FibGVkXG4gICAqIEB0eXBlIHtCb29sZWFufVxuICAgKiBAZGVzY3JpcHRpb25cbiAgICogICBbZW5dV2hldGhlciB0aGUgZWxlbWVudCBpcyBkaXNhYmxlZCBvciBub3QuWy9lbl1cbiAgICogICBbamFd54Sh5Yq55YyW44GV44KM44Gm44GE44KL5aC05ZCI44GrYHRydWVg44CCWy9qYV1cbiAgICovXG5cbiAgZ2V0IF9zY2hlbWUoKSB7XG4gICAgcmV0dXJuIHsgJyc6ICd0b29sYmFyLWJ1dHRvbi0tKicgfTtcbiAgfVxuXG4gIGdldCBfZGVmYXVsdENsYXNzTmFtZSgpIHtcbiAgICByZXR1cm4gJ3Rvb2xiYXItYnV0dG9uJztcbiAgfVxuXG4gIGdldCBfcmlwcGxlT3B0KCkge1xuICAgIHJldHVybiBbdGhpcywgdW5kZWZpbmVkLCB7IGNlbnRlcjogJycsICdzaXplJzogJ2NvbnRhaW4nLCAnYmFja2dyb3VuZCc6ICd0cmFuc3BhcmVudCcgfV07XG4gIH1cbn1cblxub25zRWxlbWVudHMuVG9vbGJhckJ1dHRvbiA9IFRvb2xiYXJCdXR0b25FbGVtZW50O1xuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdvbnMtdG9vbGJhci1idXR0b24nLCBUb29sYmFyQnV0dG9uRWxlbWVudCk7XG4iLCJpbXBvcnQgb25zIGZyb20gJy4vb25zJzsgLy8gQWRkIG9ucyBpbnRlcm5hbHNcbmltcG9ydCBzZXR1cCBmcm9tICcuL3NldHVwJzsgLy8gQWRkIHBvbHlmaWxsc1xuXG4vLyBBZGQgYW5kIHJlZ2lzdGVyIEN1c3RvbSBFbGVtZW50c1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy10ZW1wbGF0ZSc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWlmJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtYWN0aW9uLXNoZWV0JztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtYWN0aW9uLXNoZWV0LWJ1dHRvbic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWFsZXJ0LWRpYWxvZyc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWFsZXJ0LWRpYWxvZy1idXR0b24nO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1iYWNrLWJ1dHRvbic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWJvdHRvbS10b29sYmFyJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtYnV0dG9uJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtY2FyZCc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWNhcm91c2VsLWl0ZW0nO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1jYXJvdXNlbCc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWNvbCc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWRpYWxvZyc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWZhYic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWdlc3R1cmUtZGV0ZWN0b3InO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1pY29uJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtbGF6eS1yZXBlYXQnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1saXN0LWhlYWRlcic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLWxpc3QtdGl0bGUnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1saXN0LWl0ZW0nO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1saXN0JztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtaW5wdXQnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1jaGVja2JveCc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXJhZGlvJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc2VhcmNoLWlucHV0JztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtbW9kYWwnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1uYXZpZ2F0b3InO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1wYWdlJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtcG9wb3Zlcic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXByb2dyZXNzLWJhcic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXByb2dyZXNzLWNpcmN1bGFyJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtcHVsbC1ob29rJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtcmFuZ2UnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1yaXBwbGUnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1yb3cnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1zZWdtZW50JztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc2VsZWN0JztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc3BlZWQtZGlhbC1pdGVtJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc3BlZWQtZGlhbCc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXNwbGl0dGVyLWNvbnRlbnQnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy1zcGxpdHRlci1tYXNrJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc3BsaXR0ZXItc2lkZSc7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXNwbGl0dGVyJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtc3dpdGNoJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtdGFiJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtdGFiYmFyJztcbmltcG9ydCAnLi9lbGVtZW50cy9vbnMtdG9hc3QnO1xuaW1wb3J0ICcuL2VsZW1lbnRzL29ucy10b29sYmFyLWJ1dHRvbic7XG5pbXBvcnQgJy4vZWxlbWVudHMvb25zLXRvb2xiYXInO1xuXG5zZXR1cChvbnMpOyAvLyBTZXR1cCBpbml0aWFsIGxpc3RlbmVyc1xud2luZG93Ll9zdXBlclNlY3JldE9ucyA9IG9ucztcblxuZXhwb3J0IGRlZmF1bHQgb25zO1xuIl0sIm5hbWVzIjpbInByZWZpeCIsInN0eWxlcyIsIndpbmRvdyIsImdldENvbXB1dGVkU3R5bGUiLCJkb2N1bWVudCIsImRvY3VtZW50RWxlbWVudCIsIkFycmF5IiwicHJvdG90eXBlIiwic2xpY2UiLCJjYWxsIiwiam9pbiIsIm1hdGNoIiwiT0xpbmsiLCJuYW1lIiwidXRpbCIsImh5cGhlbmF0ZSIsInN0eWxlciIsImVsZW1lbnQiLCJzdHlsZSIsImtleXMiLCJmb3JFYWNoIiwia2V5Iiwid2FybiIsImNsZWFyIiwiY2xlYXJsaXN0Iiwic3BsaXQiLCJyZWR1Y2UiLCJyIiwicyIsImNvbmNhdCIsImkiLCJsZW5ndGgiLCJzb21lIiwiaW5kZXhPZiIsInB1c2giLCJnZXRBdHRyaWJ1dGUiLCJyZW1vdmVBdHRyaWJ1dGUiLCJOYXRpdmVIVE1MRWxlbWVudCIsIkhUTUxFbGVtZW50IiwiUGxhdGZvcm0iLCJfc2VsZWN0ZWRQbGF0Zm9ybSIsIl9pZ25vcmVQbGF0Zm9ybVNlbGVjdCIsInBsYXRmb3JtIiwidHJpbSIsInRvTG93ZXJDYXNlIiwiZm4iLCJyZXN1bHQiLCJyZWFkeVN0YXRlIiwiRXJyb3IiLCJjb3Jkb3ZhIiwicGhvbmVnYXAiLCJQaG9uZUdhcCIsInRlc3QiLCJuYXZpZ2F0b3IiLCJ1c2VyQWdlbnQiLCJpc0lQaG9uZSIsInNjcmVlbiIsIndpZHRoIiwiaGVpZ2h0IiwiZm9yY2VBY3R1YWxQbGF0Zm9ybSIsIl9nZXRTZWxlY3RlZFBsYXRmb3JtIiwiZGV2aWNlIiwicGFyc2VJbnQiLCJ2ZXJzaW9uIiwidmVyIiwicmVwbGFjZSIsInVhIiwiaXNJT1MiLCJzdGFuZGFsb25lIiwibHRlOSIsIndlYmtpdCIsIm1lc3NhZ2VIYW5kbGVycyIsImluZGV4ZWREQiIsImlzSU9TU2FmYXJpIiwiaXNXS1dlYlZpZXciLCJvcGVyYSIsIkluc3RhbGxUcmlnZ2VyIiwiT2JqZWN0IiwidG9TdHJpbmciLCJwIiwic2FmYXJpIiwicHVzaE5vdGlmaWNhdGlvbiIsImNocm9tZSIsImRvY3VtZW50TW9kZSIsImlzQW5kcm9pZCIsImlzV1AiLCJpc0lQYWQiLCJpc0lQb2QiLCJlcnJvciIsInRocm93IiwibWVzc2FnZSIsInBhZ2VBdHRyaWJ1dGVFeHByZXNzaW9uIiwidmFsdWUiLCJvdmVyd3JpdGUiLCJfdmFyaWFibGVzIiwiaGFzT3duUHJvcGVydHkiLCJwYXJ0IiwiYyIsImluSW50ZXJwb2xhdGlvbiIsImN1cnJlbnRJbmRleCIsInRva2VucyIsImNoYXJBdCIsInRva2VuIiwic3Vic3RyaW5nIiwicmUiLCJ2YXJpYWJsZSIsImdldFZhcmlhYmxlIiwicnYiLCJtYXAiLCJfcmVwbGFjZVRva2VuIiwiYmluZCIsImV4cHJlc3Npb24iLCJfcGFyc2VQYXJ0IiwiX3JlcGxhY2VUb2tlbnMiLCJfcGFyc2VFeHByZXNzaW9uIiwiZGVmaW5lVmFyaWFibGUiLCJnZXRNb2JpbGVPUyIsImdldElPU0RldmljZSIsImlzV2ViVmlldyIsImludGVybmFsIiwiY29uZmlnIiwibnVsbEVsZW1lbnQiLCJjcmVhdGVFbGVtZW50IiwiaXNFbmFibGVkQXV0b1N0YXR1c0JhckZpbGwiLCJhdXRvU3RhdHVzQmFyRmlsbCIsIm5vcm1hbGl6ZVBhZ2VIVE1MIiwiaHRtbCIsIndhaXRET01Db250ZW50TG9hZGVkIiwid3JhcHBlZENhbGxiYWNrIiwicmVtb3ZlRXZlbnRMaXN0ZW5lciIsImFkZEV2ZW50TGlzdGVuZXIiLCJjYWxsYmFjayIsIm9uUmVhZHkiLCJzaG91bGRGaWxsU3RhdHVzQmFyIiwiaXNJT1M3YWJvdmUiLCJpc0lQaG9uZVgiLCJib2R5IiwicXVlcnlTZWxlY3RvciIsInRlbXBsYXRlU3RvcmUiLCJfc3RvcmFnZSIsInRlbXBsYXRlIiwiZSIsInRhcmdldCIsIm5vZGVOYW1lIiwic2V0IiwidGVtcGxhdGVJZCIsInJlZ2lzdGVyIiwicXVlcnkiLCJ0ZW1wbGF0ZXMiLCJxdWVyeVNlbGVjdG9yQWxsIiwidGV4dENvbnRlbnQiLCJjb250ZW50IiwiZ2V0VGVtcGxhdGVIVE1MQXN5bmMiLCJwYWdlIiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJjYWNoZSIsImdldCIsIkRvY3VtZW50RnJhZ21lbnQiLCJsb2NhbCIsImdldEVsZW1lbnRCeUlkIiwieGhyIiwiWE1MSHR0cFJlcXVlc3QiLCJvcGVuIiwib25sb2FkIiwicmVzcG9uc2VUZXh0Iiwic3RhdHVzIiwiZnJhZ21lbnQiLCJjcmVhdGVGcmFnbWVudCIsImFycmF5RnJvbSIsInNjcmlwdCIsInR5cGUiLCJlbCIsImFwcGVuZENoaWxkIiwiY3JlYXRlVGV4dE5vZGUiLCJ0ZXh0IiwiaW5uZXJIVE1MIiwicGFyZW50Tm9kZSIsInJlcGxhY2VDaGlsZCIsIm9uZXJyb3IiLCJzZW5kIiwiZ2V0UGFnZUhUTUxBc3luYyIsInBhZ2VzIiwiZXZhbHVhdGUiLCJnZXRQYWdlIiwiY2F0Y2giLCJzaGlmdCIsIkFuaW1hdG9yRmFjdG9yeSIsIm9wdHMiLCJfYW5pbWF0b3JzIiwiYW5pbWF0b3JzIiwiX2Jhc2VDbGFzcyIsImJhc2VDbGFzcyIsIl9iYXNlQ2xhc3NOYW1lIiwiYmFzZUNsYXNzTmFtZSIsIl9hbmltYXRpb24iLCJkZWZhdWx0QW5pbWF0aW9uIiwiX2FuaW1hdGlvbk9wdGlvbnMiLCJkZWZhdWx0QW5pbWF0aW9uT3B0aW9ucyIsIm9wdGlvbnMiLCJkZWZhdWx0QW5pbWF0b3IiLCJhbmltYXRvciIsImFuaW1hdGlvbiIsIkFuaW1hdG9yIiwiYW5pbWF0aW9uT3B0cyIsImV4dGVuZCIsImFuaW1hdGlvbk9wdGlvbnMiLCJhbmltYXRpb25zRGlzYWJsZWQiLCJkdXJhdGlvbiIsImRlbGF5IiwianNvblN0cmluZyIsImFuaW1hdGlvbk9wdGlvbnNQYXJzZSIsImF1dG9TdHlsZUVuYWJsZWQiLCJtb2RpZmllcnNNYXAiLCJwbGF0Zm9ybXMiLCJhbmRyb2lkIiwiZWxlbWVudE5hbWUiLCJ0YWdOYW1lIiwiaGFzTW9kaWZpZXIiLCJvbGRNb2RpZmllciIsIm5ld01vZGlmaWVyIiwidW5zaGlmdCIsInNldEF0dHJpYnV0ZSIsImVsZW1lbnRzIiwiaGFzQXR0cmlidXRlIiwiaW9zIiwicmVtb3ZlTW9kaWZpZXIiLCJhZGRNb2RpZmllciIsInVubG9ja2VkIiwiZ2V0UGxhdGZvcm0iLCJmb3JjZSIsIm1vYmlsZU9TIiwib25zUGxhdGZvcm0iLCJwcmVwYXJlIiwibWFwTW9kaWZpZXIiLCJtb2RpZmllciIsIm0iLCJyZXN0b3JlTW9kaWZpZXIiLCJNb2RpZmllclV0aWwiLCJsYXN0IiwiY3VycmVudCIsIm1ha2VEaWN0IiwicmVtb3ZlZCIsImFkZGVkIiwiZGljdCIsImRpZmYiLCJjbGFzc0xpc3QiLCJrbGFzcyIsImFkZCIsImsiLCJyZW1vdmUiLCJzY2hlbWUiLCJ0YXJnZXRFbGVtZW50cyIsInNlbGVjdG9yIiwiZmlsdGVyIiwiZmluZFBhcmVudCIsInRhcmdldEVsZW1lbnQiLCJwYXJlbnQiLCJhcHBseURpZmZUb0NsYXNzTGlzdCIsImFwcGx5RGlmZlRvRWxlbWVudCIsIm1vZGlmaWVyVG9rZW4iLCJpbmRleCIsInNwbGljZSIsIl9kb21Db250ZW50TG9hZGVkIiwiX3JlYWR5IiwiX29uRE9NQ29udGVudExvYWRlZCIsIkhhbmRsZXJSZXBvc2l0b3J5IiwiaGFuZGxlciIsImRhdGFzZXQiLCJkZXZpY2VCYWNrQnV0dG9uSGFuZGxlcklkIiwiaWQiLCJfZ2VuSWQiLCJfc3RvcmUiLCJ1bmRlZmluZWQiLCJEZXZpY2VCYWNrQnV0dG9uRGlzcGF0Y2hlciIsIl9pc0VuYWJsZWQiLCJfYm91bmRDYWxsYmFjayIsIl9jYWxsYmFjayIsImFkZEJhY2tCdXR0b25MaXN0ZW5lciIsInJlbW92ZUJhY2tCdXR0b25MaXN0ZW5lciIsImV2ZW50IiwiY3JlYXRlRXZlbnQiLCJpbml0RXZlbnQiLCJkaXNwYXRjaEV2ZW50IiwiX2Rpc3BhdGNoRGV2aWNlQmFja0J1dHRvbkV2ZW50IiwiRnVuY3Rpb24iLCJfZWxlbWVudCIsImVuYWJsZSIsInRyZWUiLCJfY2FwdHVyZVRyZWUiLCJfZmluZEhhbmRsZXJMZWFmRWxlbWVudCIsImNyZWF0ZVRyZWUiLCJhcHBseSIsImFycmF5T2YiLCJjaGlsZHJlbiIsImNoaWxkRWxlbWVudCIsImRpc3BsYXkiLCJfaXNTaG93biIsImhhcyIsInN1YlRyZWUiLCJmaW5kIiwibm9kZSIsImNoaWxkTm9kZSIsImxlZnQiLCJyaWdodCIsImxlZnRaIiwiekluZGV4IiwicmlnaHRaIiwiaXNOYU4iLCJkYmJEaXNwYXRjaGVyIiwiZGV2aWNlQmFja0J1dHRvbkRpc3BhdGNoZXIiLCJzdGFydHNXaXRoIiwic3Vic3RyIiwiZW5kc1dpdGgiLCJ1bndyYXAiLCJpc09iamVjdFN0cmluZyIsImlzQXJyYXlTdHJpbmciLCJpc1F1b3RlZFN0cmluZyIsInN0cmluZyIsIm9yaWdpbmFsU3RyaW5nIiwicHJvY2Vzc1Rva2VuIiwicGFyc2VPYmplY3QiLCJwYXJzZUFycmF5IiwibmV4dFRva2VuIiwibGltaXQiLCJjaGFyQ29kZUF0IiwibmVzdGVkT2JqZWN0IiwiaXNWYWxpZEtleSIsIm9iamVjdCIsInJlYWRpbmdLZXkiLCJwcmV2aW91c1Rva2VuIiwiYXJyYXkiLCJwYXJzZSIsImVycm9yUHJlZml4IiwiZ2xvYmFscyIsIl9ydW5PbkFjdHVhbFBsYXRmb3JtIiwiYWN0dWFsTW9iaWxlT1MiLCJpc1VJV2ViVmlldyIsImRlZmluZVByb3BlcnR5Iiwic3VwcG9ydHNQYXNzaXZlIiwib3B0IiwiaXNHRCIsImNhcHR1cmUiLCJwcmVwYXJlUXVlcnkiLCJtYXRjaGVzIiwid2Via2l0TWF0Y2hlc1NlbGVjdG9yIiwibW96TWF0Y2hlc1NlbGVjdG9yIiwibXNNYXRjaGVzU2VsZWN0b3IiLCJmaW5kQ2hpbGQiLCJjaGlsZE5vZGVzIiwibm9kZVR5cGUiLCJOb2RlIiwiRUxFTUVOVF9OT0RFIiwidW50aWwiLCJpc0F0dGFjaGVkIiwiY29udGFpbnMiLCJoYXNBbnlDb21wb25lbnRBc1BhcmVudCIsImdldEFsbENoaWxkTm9kZXMiLCJmcm9tIiwiY2hpbGRFbCIsImlzUGFnZUNvbnRyb2wiLCJwcm9wYWdhdGVBY3Rpb24iLCJhY3Rpb24iLCJjaGlsZCIsImNhbWVsaXplIiwibCIsInRvVXBwZXJDYXNlIiwiY3JlYXRlIiwiY2xhc3NOYW1lIiwid3JhcHBlciIsImltcG9ydE5vZGUiLCJkc3QiLCJhcmdzIiwiaiIsImFycmF5TGlrZSIsInBhcnNlSlNPTk9iamVjdFNhZmVseSIsImZhaWxTYWZlIiwiSlNPTiIsImZpbmRGcm9tUGF0aCIsInBhdGgiLCJnZXRUb3BQYWdlIiwiY29udGFpbmVyIiwidG9wUGFnZSIsImZpbmRUb29sYmFyUGFnZSIsIl9jYW5BbmltYXRlVG9vbGJhciIsIl9jb250ZW50RWxlbWVudCIsIm5leHRQYWdlIiwidHJpZ2dlckVsZW1lbnRFdmVudCIsImV2ZW50TmFtZSIsImRldGFpbCIsIkN1c3RvbUV2ZW50IiwibW9kaWZpZXJOYW1lIiwiUmVnRXhwIiwiYXV0b1N0eWxlIiwiZm9yY2VBdXRvU3R5bGUiLCJuZXdNb2RpZmllcnMiLCJ0b2dnbGVNb2RpZmllciIsInRvZ2dsZSIsInJlc3RvcmVDbGFzcyIsImRlZmF1bHRDbGFzcyIsInJlZnJlc2giLCJ1cGRhdGVQYXJlbnRQb3NpdGlvbiIsIl9wYXJlbnRVcGRhdGVkIiwicGFyZW50RWxlbWVudCIsImdldFByb3BlcnR5VmFsdWUiLCJwb3NpdGlvbiIsInRvZ2dsZUF0dHJpYnV0ZSIsImJpbmRMaXN0ZW5lcnMiLCJsaXN0ZW5lck5hbWVzIiwiYm91bmROYW1lIiwiZWFjaCIsIm9iaiIsImYiLCJ1cGRhdGVSaXBwbGUiLCJoYXNSaXBwbGUiLCJhdHRycyIsInJpcHBsZUVsZW1lbnQiLCJpbnNlcnRCZWZvcmUiLCJmaXJzdENoaWxkIiwiaXNJbnRlZ2VyIiwiaXNGaW5pdGUiLCJNYXRoIiwiZmxvb3IiLCJkZWZlciIsImRlZmVycmVkIiwicHJvbWlzZSIsIndhcm5pbmdzRGlzYWJsZWQiLCJ0aHJvd0Fic3RyYWN0IiwidGhyb3dNZW1iZXIiLCJ0aHJvd1BhZ2VMb2FkZXIiLCJ0aHJvd0FuaW1hdG9yIiwicHJldmVudCIsImNhbmNlbGFibGUiLCJwcmV2ZW50RGVmYXVsdCIsImlvc1ByZXZlbnRTY3JvbGwiLCJjbGVhbiIsIm9mZiIsIm9uIiwiaW9zUGFnZVNjcm9sbEZpeCIsImZvcmNlVUlXZWJWaWV3U2Nyb2xsRml4IiwiaW9zTWFza1Njcm9sbEZpeCIsImlzVmFsaWRHZXN0dXJlIiwiZ2VzdHVyZSIsImRpc3RhbmNlIiwiZGVsdGFUaW1lIiwiY2hlY2tNaXNzaW5nSW1wb3J0IiwiZWxlbWVudE5hbWVzIiwib25zRWxlbWVudHMiLCJUSU1FT1VUX1JBVElPIiwiY2FwaXRhbGl6ZSIsInN0ciIsImJ1aWxkVHJhbnNpdGlvblZhbHVlIiwicGFyYW1zIiwicHJvcGVydHkiLCJ0aW1pbmciLCJwcm9wcyIsInByb3AiLCJvbmNlT25UcmFuc2l0aW9uRW5kIiwic3RvcFByb3BhZ2F0aW9uIiwicmVtb3ZlTGlzdGVuZXJzIiwiX3RyYW5zaXRpb25FbmRFdmVudHMiLCJ2ZW5kb3JQcmVmaXgiLCJfY3NzUHJvcGVydHlEaWN0IiwiYSIsInoiLCJ1cHBlciIsImhhc0Nzc1Byb3BlcnR5IiwicHJlIiwiZm9yY2VMYXlvdXRBdE9uY2UiLCJiYXRjaEltbWVkaWF0ZSIsIm9mZnNldEhlaWdodCIsImNhbGxiYWNrcyIsImNvbmNyZWF0ZUNhbGxiYWNrcyIsImJhdGNoQW5pbWF0aW9uRnJhbWUiLCJyYWYiLCJyZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJ3ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJtb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJvUmVxdWVzdEFuaW1hdGlvbkZyYW1lIiwibXNSZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJ0cmFuc2l0aW9uUHJvcGVydHlOYW1lIiwiQW5pbWl0IiwiZGVmYXVsdHMiLCJ0cmFuc2l0aW9uUXVldWUiLCJsYXN0U3R5bGVBdHRyaWJ1dGVEaWN0IiwiZG9uZSIsInN0YXJ0QW5pbWF0aW9uIiwidG8iLCJzdGVwIiwiY3NzIiwic2F2ZVN0eWxlIiwicXVldWUiLCJ3YWl0IiwicmVzdG9yZVN0eWxlIiwidHJhbnNpdGlvbiIsIlRyYW5zaXRpb24iLCJidWlsZCIsInNlY29uZHMiLCJzZWxmIiwidHJhbnNpdGlvbk5hbWUiLCJ0cmFuc2l0aW9uVmFsdWUiLCJ0aW1lb3V0SWQiLCJjbGVhclRyYW5zaXRpb24iLCJzZXRUaW1lb3V0IiwibGVuIiwicmVzZXQiLCJfZGVxdWV1ZVRyYW5zaXRpb24iLCJfY3VycmVudFRyYW5zaXRpb24iLCJjYWxsZWQiLCJydW5BbGwiLCJhcmd1bWVudHMiLCJwbGF5IiwiY3JlYXRlQWN0dWFsQ3NzUHJvcHMiLCJ0aW1lb3V0IiwicHJlZml4ZWQiLCJFdmVudCIsIlV0aWxzIiwiRGV0ZWN0aW9uIiwiUG9pbnRlckV2ZW50IiwiR2VzdHVyZURldGVjdG9yIiwiSW5zdGFuY2UiLCJET0NVTUVOVCIsIkhBU19QT0lOVEVSRVZFTlRTIiwicG9pbnRlckVuYWJsZWQiLCJtc1BvaW50ZXJFbmFibGVkIiwiSEFTX1RPVUNIRVZFTlRTIiwiSVNfTU9CSUxFIiwiTk9fTU9VU0VFVkVOVFMiLCJDQUxDVUxBVEVfSU5URVJWQUwiLCJFVkVOVF9UWVBFUyIsIkRJUkVDVElPTl9ET1dOIiwiRElSRUNUSU9OX0xFRlQiLCJESVJFQ1RJT05fVVAiLCJESVJFQ1RJT05fUklHSFQiLCJQT0lOVEVSX01PVVNFIiwiUE9JTlRFUl9UT1VDSCIsIlBPSU5URVJfUEVOIiwiRVZFTlRfU1RBUlQiLCJFVkVOVF9NT1ZFIiwiRVZFTlRfRU5EIiwiRVZFTlRfUkVMRUFTRSIsIkVWRU5UX1RPVUNIIiwiUkVBRFkiLCJwbHVnaW5zIiwiZ2VzdHVyZXMiLCJzZXR1cCIsImRldGVybWluZUV2ZW50VHlwZXMiLCJvblRvdWNoIiwiZGV0ZWN0IiwidXRpbHMiLCJkZXN0Iiwic3JjIiwibWVyZ2UiLCJpdGVyYXRvciIsImNvbnRleHQiLCJpblN0ciIsImluQXJyYXkiLCJkZWVwIiwiZXZlcnkiLCJ0b0FycmF5IiwiaGFzUGFyZW50IiwiZ2V0Q2VudGVyIiwidG91Y2hlcyIsInBhZ2VYIiwicGFnZVkiLCJjbGllbnRYIiwiY2xpZW50WSIsIm1pbiIsIm1heCIsInRvdWNoIiwiZ2V0VmVsb2NpdHkiLCJkZWx0YVgiLCJkZWx0YVkiLCJhYnMiLCJnZXRBbmdsZSIsInRvdWNoMSIsInRvdWNoMiIsIngiLCJ5IiwiYXRhbjIiLCJQSSIsImdldERpcmVjdGlvbiIsImdldERpc3RhbmNlIiwic3FydCIsImdldFNjYWxlIiwic3RhcnQiLCJlbmQiLCJnZXRSb3RhdGlvbiIsImlzVmVydGljYWwiLCJkaXJlY3Rpb24iLCJzZXRQcmVmaXhlZENzcyIsInByZWZpeGVzIiwidG9DYW1lbENhc2UiLCJ0b2dnbGVCZWhhdmlvciIsImZhbHNlRm4iLCJ1c2VyU2VsZWN0Iiwib25zZWxlY3RzdGFydCIsInVzZXJEcmFnIiwib25kcmFnc3RhcnQiLCJob29rIiwidHlwZXMiLCJldmVudFR5cGUiLCJvblRvdWNoSGFuZGxlciIsImV2Iiwic3JjVHlwZSIsImlzUG9pbnRlciIsImlzTW91c2UiLCJ0cmlnZ2VyVHlwZSIsInByZXZlbnRNb3VzZUV2ZW50cyIsImJ1dHRvbiIsInNob3VsZERldGVjdCIsImJ1dHRvbnMiLCJtYXRjaFR5cGUiLCJ1cGRhdGVQb2ludGVyIiwiZG9EZXRlY3QiLCJ0b3VjaExpc3QiLCJnZXRUb3VjaExpc3QiLCJ0b3VjaExpc3RMZW5ndGgiLCJ0cmlnZ2VyQ2hhbmdlIiwidHJpZ2dlciIsImNoYW5nZWRMZW5ndGgiLCJjaGFuZ2VkVG91Y2hlcyIsInN0YXJ0ZWQiLCJldkRhdGEiLCJjb2xsZWN0RXZlbnREYXRhIiwiaWRlbnRpZmllcnMiLCJpZGVudGlmaWVyIiwicG9pbnRlclR5cGUiLCJEYXRlIiwibm93Iiwic3JjRXZlbnQiLCJwcmV2ZW50TWFuaXB1bGF0aW9uIiwic3RvcERldGVjdCIsInRvdWNobGlzdCIsInBvaW50ZXJzIiwicG9pbnRlciIsInBvaW50ZXJFdmVudCIsInBvaW50ZXJJZCIsInB0IiwiTVNQT0lOVEVSX1RZUEVfTU9VU0UiLCJNU1BPSU5URVJfVFlQRV9UT1VDSCIsIk1TUE9JTlRFUl9UWVBFX1BFTiIsInJlc2V0TGlzdCIsImRldGVjdGlvbiIsInN0YXJ0RGV0ZWN0IiwiaW5zdCIsImV2ZW50RGF0YSIsInN0b3BwZWQiLCJleHRlbmRFdmVudERhdGEiLCJpbnN0T3B0aW9ucyIsInRyaWdnZXJHZXN0dXJlIiwiZW5hYmxlZCIsImxhc3RFdmVudCIsInByZXZpb3VzIiwiZ2V0Q2FsY3VsYXRlZERhdGEiLCJjZW50ZXIiLCJjdXIiLCJyZWNhbGMiLCJjYWxjRXYiLCJsYXN0Q2FsY0V2ZW50IiwiY2FsY0RhdGEiLCJsYXN0Q2FsY0RhdGEiLCJ0aW1lU3RhbXAiLCJmdXR1cmVDYWxjRXZlbnQiLCJ2ZWxvY2l0eSIsImFuZ2xlIiwidmVsb2NpdHlYIiwidmVsb2NpdHlZIiwiaW50ZXJpbUFuZ2xlIiwiaW50ZXJpbURpcmVjdGlvbiIsInN0YXJ0RXYiLCJzdGFydEV2ZW50IiwibGFzdEV2Iiwic29ydCIsImIiLCJsaXN0ZW5lck9wdGlvbnMiLCJwYXNzaXZlIiwiYmVoYXZpb3IiLCJldmVudFN0YXJ0SGFuZGxlciIsImV2ZW50SGFuZGxlcnMiLCJvbkV2ZW50Iiwib2ZmRXZlbnQiLCJ0cmlnZ2VyRXZlbnQiLCJzdGF0ZSIsImRpc3Bvc2UiLCJlaCIsInRyaWdnZXJlZCIsImRyYWdHZXN0dXJlIiwiZHJhZ01heFRvdWNoZXMiLCJkcmFnTWluRGlzdGFuY2UiLCJzdGFydENlbnRlciIsImRyYWdEaXN0YW5jZUNvcnJlY3Rpb24iLCJmYWN0b3IiLCJkcmFnTG9ja1RvQXhpcyIsImRyYWdMb2NrTWluRGlzdGFuY2UiLCJsYXN0RGlyZWN0aW9uIiwiZHJhZ0Jsb2NrVmVydGljYWwiLCJkcmFnQmxvY2tIb3Jpem9udGFsIiwiRHJhZyIsIkdlc3R1cmUiLCJyZWxlYXNlR2VzdHVyZSIsInRpbWVyIiwiaG9sZEdlc3R1cmUiLCJob2xkVGltZW91dCIsImhvbGRUaHJlc2hvbGQiLCJIb2xkIiwiUmVsZWFzZSIsIkluZmluaXR5IiwiU3dpcGUiLCJzd2lwZUdlc3R1cmUiLCJzd2lwZU1pblRvdWNoZXMiLCJzd2lwZU1heFRvdWNoZXMiLCJzd2lwZVZlbG9jaXR5WCIsInN3aXBlVmVsb2NpdHlZIiwiaGFzTW92ZWQiLCJ0YXBHZXN0dXJlIiwicHJldiIsInNpbmNlUHJldiIsImRpZERvdWJsZVRhcCIsInRhcE1heERpc3RhbmNlIiwidGFwTWF4VGltZSIsImRvdWJsZVRhcEludGVydmFsIiwiZG91YmxlVGFwRGlzdGFuY2UiLCJ0YXBBbHdheXMiLCJUYXAiLCJUb3VjaCIsInRvdWNoR2VzdHVyZSIsInByZXZlbnRNb3VzZSIsInRyYW5zZm9ybUdlc3R1cmUiLCJzY2FsZVRocmVzaG9sZCIsInNjYWxlIiwicm90YXRpb25UaHJlc2hvbGQiLCJyb3RhdGlvbiIsInRyYW5zZm9ybU1pblNjYWxlIiwidHJhbnNmb3JtTWluUm90YXRpb24iLCJUcmFuc2Zvcm0iLCJyZWFkeU1hcCIsInF1ZXVlTWFwIiwiaXNDb250ZW50UmVhZHkiLCJzZXRDb250ZW50UmVhZHkiLCJhZGRDYWxsYmFjayIsImNvbnN1bWVRdWV1ZSIsImRlbGV0ZSIsImNvbnRlbnRSZWFkeSIsIldlYWtNYXAiLCJvYnNlcnZlciIsIk11dGF0aW9uT2JzZXJ2ZXIiLCJvYnNlcnZlIiwiY2hpbGRMaXN0IiwiY2hhcmFjdGVyRGF0YSIsIlRvYXN0UXVldWUiLCJ0aGVuIiwiX3NldEF0dHJpYnV0ZXMiLCJfbm9ybWFsaXplQXJndW1lbnRzIiwibWVzc2FnZUhUTUwiLCJidXR0b25MYWJlbHMiLCJidXR0b25MYWJlbCIsImlzQXJyYXkiLCJwYXJhbSIsIm5vdGlmaWNhdGlvbiIsIl9jcmVhdGVBbGVydERpYWxvZyIsImlucHV0U3RyaW5nIiwiaXNQcm9tcHQiLCJpbnB1dFR5cGUiLCJwbGFjZWhvbGRlciIsImRlZmF1bHRWYWx1ZSIsImxhYmVsIiwicHJpbWFyeUJ1dHRvbkluZGV4IiwiX2Rlc3Ryb3lEaWFsb2ciLCJkaWFsb2ciLCJvbkRpYWxvZ0NhbmNlbCIsImRlc3Ryb3kiLCJtYXNrQ29sb3IiLCJ0aXRsZSIsInN1Ym1pdE9uRW50ZXIiLCJpbnB1dCIsIm9ua2V5cHJlc3MiLCJrZXlDb2RlIiwiaGlkZSIsInJlc29sdmVWYWx1ZSIsImZvb3RlciIsImJ1dHRvbkVsZW1lbnQiLCJvbmNsaWNrIiwiY29tcGlsZSIsInNob3ciLCJhdXRvZm9jdXMiLCJzdHJMZW5ndGgiLCJmb2N1cyIsInNldFNlbGVjdGlvblJhbmdlIiwiYWxlcnQiLCJjb25maXJtIiwicHJvbXB0IiwidG9hc3QiLCJmaW5pc2giLCJfdG9hc3QiLCJjaGVja09wdGlvbnMiLCJlcnIiLCJpbnN0YW5jZU9mIiwiY2IiLCJkIiwiYWN0aW9uU2hlZXQiLCJjbGFzcyIsImNyZWF0ZURvY3VtZW50RnJhZ21lbnQiLCJpdGVtIiwiYnV0dG9uT3B0aW9ucyIsImRlc3RydWN0aXZlIiwiaWNvbiIsIk1pY3JvRXZlbnQiLCJmY3QiLCJfZXZlbnRzIiwiX2ZjdCIsIm1peGluIiwiZGVzdE9iamVjdCIsIl9pc1BvcnRyYWl0IiwiaXNQb3J0cmFpdCIsIl9vbk9yaWVudGF0aW9uQ2hhbmdlIiwiX29uUmVzaXplIiwiaW5uZXJIZWlnaHQiLCJpbm5lcldpZHRoIiwiX2luc3RhbGxJc1BvcnRyYWl0SW1wbGVtZW50YXRpb24iLCJlbWl0Iiwib3JpZW50YXRpb24iLCJuSXRlciIsImludGVydmFsIiwic2V0SW50ZXJ2YWwiLCJ3IiwiaCIsIl9pbml0IiwibW9kaWZpZXJzIiwic29mdHdhcmVLZXlib2FyZCIsIl92aXNpYmxlIiwib25TaG93Iiwib25IaWRlIiwiYmluZEV2ZW50cyIsIktleWJvYXJkIiwib25zaG93Iiwib25oaWRlIiwidmlzaWJsZSIsImlzVmlzaWJsZSIsIm5vUGx1Z2luRXJyb3IiLCJnZW5lcmF0ZUlkIiwiRG9vckxvY2siLCJfbG9ja0xpc3QiLCJfd2FpdExpc3QiLCJfbG9nIiwibG9nIiwidW5sb2NrIiwiX3VubG9jayIsIl90cnlUb0ZyZWVXYWl0TGlzdCIsImlzTG9ja2VkIiwibG9hZFBhZ2UiLCJwYWdlRWxlbWVudCIsInVubG9hZFBhZ2UiLCJfZGVzdHJveSIsIlBhZ2VMb2FkZXIiLCJsb2FkZXIiLCJ1bmxvYWRlciIsIl9sb2FkZXIiLCJfdW5sb2FkZXIiLCJFbGVtZW50IiwiZGVmYXVsdFBhZ2VMb2FkZXIiLCJpbnN0YW50UGFnZUxvYWRlciIsIm9ucyIsInNlbGVjdCIsImxvY2F0aW9uIiwic2VhcmNoIiwid2FpdERldmljZVJlYWR5IiwicmVhZHlFcnJvciIsImFmdGVyIiwiaXNSZWFkeSIsIl9yZWFkeUxvY2siLCJyZWFkeSIsIndhaXRVbmxvY2siLCJzZXREZWZhdWx0RGV2aWNlQmFja0J1dHRvbkxpc3RlbmVyIiwibGlzdGVuZXIiLCJfZGVmYXVsdERldmljZUJhY2tCdXR0b25IYW5kbGVyIiwic2V0TGlzdGVuZXIiLCJkaXNhYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXIiLCJkaXNhYmxlIiwiZW5hYmxlRGV2aWNlQmFja0J1dHRvbkhhbmRsZXIiLCJmaXJlRGV2aWNlQmFja0J1dHRvbkV2ZW50IiwiZW5hYmxlQXV0b1N0YXR1c0JhckZpbGwiLCJkaXNhYmxlQXV0b1N0YXR1c0JhckZpbGwiLCJtb2NrU3RhdHVzQmFyIiwibW9jayIsImRpc2FibGVBbmltYXRpb25zIiwiZW5hYmxlQW5pbWF0aW9ucyIsIl9kaXNhYmxlV2FybmluZ3MiLCJfZW5hYmxlV2FybmluZ3MiLCJkaXNhYmxlQXV0b1N0eWxpbmciLCJlbmFibGVBdXRvU3R5bGluZyIsImRpc2FibGVJY29uQXV0b1ByZWZpeCIsIkljb24iLCJzZXRBdXRvUHJlZml4IiwiZm9yY2VQbGF0Zm9ybVN0eWxpbmciLCJuZXdQbGF0Zm9ybSIsIl91dGlsIiwiX3BsYXRmb3JtVXBkYXRlIiwiX3VwZGF0ZVBvc2l0aW9uIiwicHJlbG9hZCIsImFsbCIsImFwcGVuZCIsImxpbmsiLCJjcmVhdGVQb3BvdmVyIiwiY3JlYXRlRGlhbG9nIiwiY3JlYXRlQWxlcnREaWFsb2ciLCJvcGVuQWN0aW9uU2hlZXQiLCJyZXNvbHZlTG9hZGluZ1BsYWNlaG9sZGVyIiwiX3Jlc29sdmVMb2FkaW5nUGxhY2Vob2xkZXIiLCJfc2V0dXBMb2FkaW5nUGxhY2VIb2xkZXJzIiwicmVtb3ZlQ2hpbGQiLCJ1bmxvY2tEZXZpY2VSZWFkeSIsImxvY2siLCJnZXRDUyIsImN1cnJlbnRTY3JpcHQiLCJzY3JpcHRzIiwiZ2V0U2NyaXB0UGFnZSIsIkZhc3RDbGljayIsImxheWVyIiwib2xkT25DbGljayIsInRyYWNraW5nQ2xpY2siLCJ0cmFja2luZ0NsaWNrU3RhcnQiLCJ0b3VjaFN0YXJ0WCIsInRvdWNoU3RhcnRZIiwibGFzdFRvdWNoSWRlbnRpZmllciIsInRvdWNoQm91bmRhcnkiLCJ0YXBEZWxheSIsInRhcFRpbWVvdXQiLCJub3ROZWVkZWQiLCJtZXRob2QiLCJtZXRob2RzIiwiZGV2aWNlSXNBbmRyb2lkIiwib25Nb3VzZSIsIm9uQ2xpY2siLCJvblRvdWNoU3RhcnQiLCJvblRvdWNoTW92ZSIsIm9uVG91Y2hFbmQiLCJvblRvdWNoQ2FuY2VsIiwic3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uIiwicm12IiwiaGlqYWNrZWQiLCJhZHYiLCJwcm9wYWdhdGlvblN0b3BwZWQiLCJkZXZpY2VJc1dpbmRvd3NQaG9uZSIsImRldmljZUlzSU9TIiwiZGV2aWNlSXNJT1M0IiwiZGV2aWNlSXNJT1NXaXRoQmFkVGFyZ2V0IiwiZGV2aWNlSXNCbGFja0JlcnJ5MTAiLCJ0ZXh0RmllbGRzIiwibmVlZHNDbGljayIsImRpc2FibGVkIiwibmVlZHNGb2N1cyIsInJlYWRPbmx5Iiwic2VuZENsaWNrIiwiY2xpY2tFdmVudCIsImFjdGl2ZUVsZW1lbnQiLCJibHVyIiwiaW5pdE1vdXNlRXZlbnQiLCJkZXRlcm1pbmVFdmVudFR5cGUiLCJzY3JlZW5YIiwic2NyZWVuWSIsImZvcndhcmRlZFRvdWNoRXZlbnQiLCJ1cGRhdGVTY3JvbGxQYXJlbnQiLCJzY3JvbGxQYXJlbnQiLCJmYXN0Q2xpY2tTY3JvbGxQYXJlbnQiLCJzY3JvbGxIZWlnaHQiLCJmYXN0Q2xpY2tMYXN0U2Nyb2xsVG9wIiwic2Nyb2xsVG9wIiwiZ2V0VGFyZ2V0RWxlbWVudEZyb21FdmVudFRhcmdldCIsImV2ZW50VGFyZ2V0IiwiVEVYVF9OT0RFIiwiaXNUZXh0RmllbGQiLCJ0YXJnZXRUb3VjaGVzIiwiaXNDb250ZW50RWRpdGFibGUiLCJsYXN0Q2xpY2tUaW1lIiwidG91Y2hIYXNNb3ZlZCIsImJvdW5kYXJ5IiwiZmluZENvbnRyb2wiLCJsYWJlbEVsZW1lbnQiLCJjb250cm9sIiwiaHRtbEZvciIsImZvckVsZW1lbnQiLCJ0YXJnZXRUYWdOYW1lIiwiY2FuY2VsTmV4dENsaWNrIiwiZWxlbWVudEZyb21Qb2ludCIsInBhZ2VYT2Zmc2V0IiwicGFnZVlPZmZzZXQiLCJ0b3AiLCJwZXJtaXR0ZWQiLCJtZXRhVmlld3BvcnQiLCJjaHJvbWVWZXJzaW9uIiwiYmxhY2tiZXJyeVZlcnNpb24iLCJmaXJlZm94VmVyc2lvbiIsIm9udG91Y2hzdGFydCIsImV4ZWMiLCJzY3JvbGxXaWR0aCIsIm91dGVyV2lkdGgiLCJtc1RvdWNoQWN0aW9uIiwidG91Y2hBY3Rpb24iLCJhdHRhY2giLCJkZWZpbmUiLCJiYWJlbEhlbHBlcnMudHlwZW9mIiwiYW1kIiwibW9kdWxlIiwiZXhwb3J0cyIsImN1c3RvbUVsZW1lbnRzIiwiZm9yY2VQb2x5ZmlsbCIsImdsb2JhbCIsIl9fZyIsImNvcmUiLCJfX2UiLCJpdCIsImlzT2JqZWN0IiwiVHlwZUVycm9yIiwicmVxdWlyZSQkMCIsImlzIiwicmVxdWlyZSQkMSIsInJlcXVpcmUkJDIiLCJTIiwidmFsIiwidmFsdWVPZiIsImRQIiwiTyIsIlAiLCJBdHRyaWJ1dGVzIiwidG9QcmltaXRpdmUiLCJJRThfRE9NX0RFRklORSIsImJpdG1hcCIsImNyZWF0ZURlc2MiLCJweCIsInJhbmRvbSIsIlNSQyIsIlRPX1NUUklORyIsIiR0b1N0cmluZyIsIlRQTCIsImluc3BlY3RTb3VyY2UiLCJzYWZlIiwiaXNGdW5jdGlvbiIsIlN0cmluZyIsInRoYXQiLCJQUk9UT1RZUEUiLCIkZXhwb3J0Iiwic291cmNlIiwiSVNfRk9SQ0VEIiwiRiIsIklTX0dMT0JBTCIsIkciLCJJU19TVEFUSUMiLCJJU19QUk9UTyIsIklTX0JJTkQiLCJCIiwiZXhwUHJvdG8iLCJvd24iLCJvdXQiLCJleHAiLCJjdHgiLCJyZWRlZmluZSIsIlUiLCJXIiwiUiIsInByb3BlcnR5SXNFbnVtZXJhYmxlIiwiY29mIiwiSU9iamVjdCIsImRlZmluZWQiLCJnT1BEIiwiZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIiwidG9JT2JqZWN0IiwicElFIiwiY2hlY2siLCJwcm90byIsInNldFByb3RvdHlwZU9mIiwiYnVnZ3kiLCJfX3Byb3RvX18iLCJTSEFSRUQiLCJzdG9yZSIsIlN5bWJvbCIsIlVTRV9TWU1CT0wiLCIkZXhwb3J0cyIsInVpZCIsIlRBRyIsIkFSRyIsInRyeUdldCIsIlQiLCJjYWxsZWUiLCJjbGFzc29mIiwiY2VpbCIsInBvcyIsInRvSW50ZWdlciIsIklTX0lOQ0xVREVTIiwiJHRoaXMiLCJmcm9tSW5kZXgiLCJ0b0xlbmd0aCIsInRvQWJzb2x1dGVJbmRleCIsInNoYXJlZCIsImFycmF5SW5kZXhPZiIsIklFX1BST1RPIiwibmFtZXMiLCIka2V5cyIsImVudW1CdWdLZXlzIiwiZGVmaW5lUHJvcGVydGllcyIsIlByb3BlcnRpZXMiLCJnZXRLZXlzIiwiRW1wdHkiLCJjcmVhdGVEaWN0IiwiaWZyYW1lIiwibHQiLCJndCIsImlmcmFtZURvY3VtZW50IiwiY29udGVudFdpbmRvdyIsIndyaXRlIiwiY2xvc2UiLCJhbk9iamVjdCIsImRQcyIsImRlZiIsInRhZyIsInN0YXQiLCJjb25maWd1cmFibGUiLCJJdGVyYXRvclByb3RvdHlwZSIsIkNvbnN0cnVjdG9yIiwiTkFNRSIsIm5leHQiLCJkZXNjcmlwdG9yIiwiT2JqZWN0UHJvdG8iLCJnZXRQcm90b3R5cGVPZiIsInRvT2JqZWN0IiwiY29uc3RydWN0b3IiLCJJVEVSQVRPUiIsIkJVR0dZIiwiRkZfSVRFUkFUT1IiLCJLRVlTIiwiVkFMVUVTIiwicmV0dXJuVGhpcyIsIkJhc2UiLCJERUZBVUxUIiwiSVNfU0VUIiwiRk9SQ0VEIiwiZ2V0TWV0aG9kIiwia2luZCIsInZhbHVlcyIsImVudHJpZXMiLCJERUZfVkFMVUVTIiwiVkFMVUVTX0JVRyIsIiRuYXRpdmUiLCIkZGVmYXVsdCIsIiRlbnRyaWVzIiwiJGFueU5hdGl2ZSIsIkxJQlJBUlkiLCIkYXQiLCJpdGVyYXRlZCIsIl90IiwiX2kiLCJwb2ludCIsIlVOU0NPUEFCTEVTIiwiQXJyYXlQcm90byIsIl9rIiwiSXRlcmF0b3JzIiwiQXJndW1lbnRzIiwiYWRkVG9VbnNjb3BhYmxlcyIsIndrcyIsIlRPX1NUUklOR19UQUciLCJBcnJheVZhbHVlcyIsIkRPTUl0ZXJhYmxlcyIsImNvbGxlY3Rpb25zIiwiZXhwbGljaXQiLCJDb2xsZWN0aW9uIiwiJGl0ZXJhdG9ycyIsImZvcmJpZGRlbkZpZWxkIiwicmV0IiwiZ2V0SXRlcmF0b3JNZXRob2QiLCJCUkVBSyIsIlJFVFVSTiIsIml0ZXJhYmxlIiwiaXRlckZuIiwiZ2V0SXRlckZuIiwiaXNBcnJheUl0ZXIiLCJTUEVDSUVTIiwiS0VZIiwiQyIsIkRFU0NSSVBUT1JTIiwiTUVUQSIsInNldERlc2MiLCJpc0V4dGVuc2libGUiLCJGUkVFWkUiLCJwcmV2ZW50RXh0ZW5zaW9ucyIsInNldE1ldGEiLCJmYXN0S2V5IiwiZ2V0V2VhayIsIm9uRnJlZXplIiwibWV0YSIsIk5FRUQiLCJUWVBFIiwiU0laRSIsImdldEVudHJ5IiwiZW50cnkiLCJfZiIsIm4iLCJJU19NQVAiLCJBRERFUiIsIl9sIiwiZm9yT2YiLCJ2YWxpZGF0ZSIsImRhdGEiLCJjYWxsYmFja2ZuIiwidiIsIlNBRkVfQ0xPU0lORyIsInJpdGVyIiwic2tpcENsb3NpbmciLCJhcnIiLCJpdGVyIiwiY29tbW9uIiwiSVNfV0VBSyIsImZpeE1ldGhvZCIsImZhaWxzIiwiZ2V0Q29uc3RydWN0b3IiLCJpbnN0YW5jZSIsIkhBU05UX0NIQUlOSU5HIiwiVEhST1dTX09OX1BSSU1JVElWRVMiLCJBQ0NFUFRfSVRFUkFCTEVTIiwiJGl0ZXJEZXRlY3QiLCJCVUdHWV9aRVJPIiwiJGluc3RhbmNlIiwiaW5oZXJpdElmUmVxdWlyZWQiLCJzZXRTdHJvbmciLCJTRVQiLCJTZXQiLCJzdHJvbmciLCJ0b0pTT04iLCJDT0xMRUNUSU9OIiwib2YiLCJBIiwibWFwRm4iLCJtYXBwaW5nIiwiYUZ1bmN0aW9uIiwibmV4dEl0ZW0iLCJyZXF1aXJlJCQ3IiwiTUFQIiwiTWFwIiwiYXJnIiwib3JpZ2luYWwiLCJzcGVjaWVzQ29uc3RydWN0b3IiLCIkY3JlYXRlIiwiSVNfRklMVEVSIiwiSVNfU09NRSIsIklTX0VWRVJZIiwiSVNfRklORF9JTkRFWCIsIk5PX0hPTEVTIiwiYXNjIiwicmVzIiwiZ2V0T3duUHJvcGVydHlTeW1ib2xzIiwiJGFzc2lnbiIsImFzc2lnbiIsIksiLCJhTGVuIiwiZ2V0U3ltYm9scyIsImdPUFMiLCJpc0VudW0iLCJhcnJheUZpbmQiLCJjcmVhdGVBcnJheU1ldGhvZCIsImFycmF5RmluZEluZGV4IiwidW5jYXVnaHRGcm96ZW5TdG9yZSIsIlVuY2F1Z2h0RnJvemVuU3RvcmUiLCJmaW5kVW5jYXVnaHRGcm96ZW4iLCIkaGFzIiwiV0VBS19NQVAiLCJ3ZWFrIiwidWZzdG9yZSIsInRtcCIsIkludGVybmFsTWFwIiwiJFdlYWtNYXAiLCJmcmVlemUiLCJyZXF1aXJlJCQ1IiwiJGRlZmluZVByb3BlcnR5IiwibWFwZm4iLCJyZXNlcnZlZFRhZ0xpc3QiLCJpc1ZhbGlkQ3VzdG9tRWxlbWVudE5hbWUiLCJsb2NhbE5hbWUiLCJyZXNlcnZlZCIsInZhbGlkRm9ybSIsImlzQ29ubmVjdGVkIiwibmF0aXZlVmFsdWUiLCJfX0NFX2lzSW1wb3J0RG9jdW1lbnQiLCJEb2N1bWVudCIsIlNoYWRvd1Jvb3QiLCJob3N0IiwibmV4dFNpYmxpbmdPckFuY2VzdG9yU2libGluZyIsInJvb3QiLCJuZXh0U2libGluZyIsIm5leHROb2RlIiwid2Fsa0RlZXBEZXNjZW5kYW50RWxlbWVudHMiLCJ2aXNpdGVkSW1wb3J0cyIsImltcG9ydCIsInNoYWRvd1Jvb3QiLCJfX0NFX3NoYWRvd1Jvb3QiLCJzZXRQcm9wZXJ0eVVuY2hlY2tlZCIsImRlc3RpbmF0aW9uIiwiQ3VzdG9tRWxlbWVudFN0YXRlIiwiQ3VzdG9tRWxlbWVudEludGVybmFscyIsIl9sb2NhbE5hbWVUb0RlZmluaXRpb24iLCJfY29uc3RydWN0b3JUb0RlZmluaXRpb24iLCJfcGF0Y2hlcyIsIl9oYXNQYXRjaGVzIiwiZGVmaW5pdGlvbiIsInBhdGNoIiwiX19DRV9wYXRjaGVkIiwiX19DRV9zdGF0ZSIsIkNFU3RhdGUiLCJjdXN0b20iLCJVdGlsaXRpZXMiLCJjb25uZWN0ZWRDYWxsYmFjayIsInVwZ3JhZGVFbGVtZW50IiwiZGlzY29ubmVjdGVkQ2FsbGJhY2siLCJnYXRoZXJFbGVtZW50cyIsIl9fQ0VfaGFzUmVnaXN0cnkiLCJfX0NFX2RvY3VtZW50TG9hZEhhbmRsZWQiLCJwYXRjaEFuZFVwZ3JhZGVUcmVlIiwiY3VycmVudFN0YXRlIiwibG9jYWxOYW1lVG9EZWZpbml0aW9uIiwiY29uc3RydWN0aW9uU3RhY2siLCJwb3AiLCJmYWlsZWQiLCJfX0NFX2RlZmluaXRpb24iLCJhdHRyaWJ1dGVDaGFuZ2VkQ2FsbGJhY2siLCJvYnNlcnZlZEF0dHJpYnV0ZXMiLCJfX0NFX2lzQ29ubmVjdGVkQ2FsbGJhY2tDYWxsZWQiLCJvbGRWYWx1ZSIsIm5ld1ZhbHVlIiwibmFtZXNwYWNlIiwiRG9jdW1lbnRDb25zdHJ1Y3Rpb25PYnNlcnZlciIsImludGVybmFscyIsImRvYyIsIl9pbnRlcm5hbHMiLCJfZG9jdW1lbnQiLCJfb2JzZXJ2ZXIiLCJfaGFuZGxlTXV0YXRpb25zIiwiZGlzY29ubmVjdCIsIm11dGF0aW9ucyIsImFkZGVkTm9kZXMiLCJEZWZlcnJlZCIsIl92YWx1ZSIsIl9yZXNvbHZlIiwiX3Byb21pc2UiLCJDdXN0b21FbGVtZW50UmVnaXN0cnkiLCJfZWxlbWVudERlZmluaXRpb25Jc1J1bm5pbmciLCJfd2hlbkRlZmluZWREZWZlcnJlZCIsIl9mbHVzaENhbGxiYWNrIiwiX2ZsdXNoUGVuZGluZyIsIl91bmZsdXNoZWRMb2NhbE5hbWVzIiwiX2RvY3VtZW50Q29uc3RydWN0aW9uT2JzZXJ2ZXIiLCJTeW50YXhFcnJvciIsImFkb3B0ZWRDYWxsYmFjayIsImdldENhbGxiYWNrIiwiY2FsbGJhY2tWYWx1ZSIsInNldERlZmluaXRpb24iLCJfZmx1c2giLCJwcmlvciIsInRvUHJvbWlzZSIsIm91dGVyIiwiaW5uZXIiLCJmbHVzaCIsIndoZW5EZWZpbmVkIiwicG9seWZpbGxXcmFwRmx1c2hDYWxsYmFjayIsImNyZWF0ZUVsZW1lbnROUyIsImNsb25lTm9kZSIsImdldEF0dHJpYnV0ZU5TIiwic2V0QXR0cmlidXRlTlMiLCJyZW1vdmVBdHRyaWJ1dGVOUyIsIkFscmVhZHlDb25zdHJ1Y3RlZE1hcmtlciIsImNvbnN0cnVjdG9yVG9EZWZpbml0aW9uIiwiTmF0aXZlIiwiRG9jdW1lbnRfY3JlYXRlRWxlbWVudCIsImxhc3RJbmRleCIsImJ1aWx0SW4iLCJub2RlcyIsImNvbm5lY3RlZEJlZm9yZSIsInByZXBlbmQiLCJkaXNjb25uZWN0VHJlZSIsImNvbm5lY3RUcmVlIiwiY2xvbmUiLCJEb2N1bWVudF9pbXBvcnROb2RlIiwicGF0Y2hUcmVlIiwiTlNfSFRNTCIsIkRvY3VtZW50X2NyZWF0ZUVsZW1lbnROUyIsIkRvY3VtZW50X3ByZXBlbmQiLCJEb2N1bWVudF9hcHBlbmQiLCJyZWZOb2RlIiwiaW5zZXJ0ZWROb2RlcyIsIm5hdGl2ZVJlc3VsdCIsIk5vZGVfaW5zZXJ0QmVmb3JlIiwibm9kZVdhc0Nvbm5lY3RlZCIsIk5vZGVfYXBwZW5kQ2hpbGQiLCJOb2RlX2Nsb25lTm9kZSIsIm93bmVyRG9jdW1lbnQiLCJOb2RlX3JlbW92ZUNoaWxkIiwibm9kZVRvSW5zZXJ0Iiwibm9kZVRvUmVtb3ZlIiwiTm9kZV9yZXBsYWNlQ2hpbGQiLCJub2RlVG9JbnNlcnRXYXNDb25uZWN0ZWQiLCJ0aGlzSXNDb25uZWN0ZWQiLCJwYXRjaF90ZXh0Q29udGVudCIsImJhc2VEZXNjcmlwdG9yIiwiZW51bWVyYWJsZSIsImFzc2lnbmVkVmFsdWUiLCJyZW1vdmVkTm9kZXMiLCJjaGlsZE5vZGVzTGVuZ3RoIiwiTm9kZV90ZXh0Q29udGVudCIsImFkZFBhdGNoIiwicGFydHMiLCJiZWZvcmUiLCJ3YXNDb25uZWN0ZWQiLCJyZXBsYWNlV2l0aCIsIkVsZW1lbnRfYXR0YWNoU2hhZG93IiwiaW5pdCIsInBhdGNoX2lubmVySFRNTCIsImh0bWxTdHJpbmciLCJyZW1vdmVkRWxlbWVudHMiLCJFbGVtZW50X2lubmVySFRNTCIsIkhUTUxFbGVtZW50X2lubmVySFRNTCIsInJhd0RpdiIsIkVsZW1lbnRfc2V0QXR0cmlidXRlIiwiRWxlbWVudF9nZXRBdHRyaWJ1dGUiLCJFbGVtZW50X3NldEF0dHJpYnV0ZU5TIiwiRWxlbWVudF9nZXRBdHRyaWJ1dGVOUyIsIkVsZW1lbnRfcmVtb3ZlQXR0cmlidXRlIiwiRWxlbWVudF9yZW1vdmVBdHRyaWJ1dGVOUyIsInBhdGNoX2luc2VydEFkamFjZW50RWxlbWVudCIsImJhc2VNZXRob2QiLCJ3aGVyZSIsImluc2VydGVkRWxlbWVudCIsIkhUTUxFbGVtZW50X2luc2VydEFkamFjZW50RWxlbWVudCIsIkVsZW1lbnRfaW5zZXJ0QWRqYWNlbnRFbGVtZW50IiwiRWxlbWVudF9wcmVwZW5kIiwiRWxlbWVudF9hcHBlbmQiLCJFbGVtZW50X2JlZm9yZSIsIkVsZW1lbnRfYWZ0ZXIiLCJFbGVtZW50X3JlcGxhY2VXaXRoIiwiRWxlbWVudF9yZW1vdmUiLCJwcmlvckN1c3RvbUVsZW1lbnRzIiwiSnNNdXRhdGlvbk9ic2VydmVyIiwicmVnaXN0cmF0aW9uc1RhYmxlIiwic2V0SW1tZWRpYXRlIiwic2V0SW1tZWRpYXRlUXVldWUiLCJzZW50aW5lbCIsImZ1bmMiLCJwb3N0TWVzc2FnZSIsImlzU2NoZWR1bGVkIiwic2NoZWR1bGVkT2JzZXJ2ZXJzIiwic2NoZWR1bGVDYWxsYmFjayIsImRpc3BhdGNoQ2FsbGJhY2tzIiwid3JhcElmTmVlZGVkIiwiU2hhZG93RE9NUG9seWZpbGwiLCJvYnNlcnZlcnMiLCJvMSIsIm8yIiwidWlkXyIsImFueU5vbkVtcHR5IiwidGFrZVJlY29yZHMiLCJjYWxsYmFja18iLCJyZW1vdmVUcmFuc2llbnRPYnNlcnZlcnNGb3IiLCJub2Rlc18iLCJyZWdpc3RyYXRpb25zIiwicmVnaXN0cmF0aW9uIiwicmVtb3ZlVHJhbnNpZW50T2JzZXJ2ZXJzIiwiZm9yRWFjaEFuY2VzdG9yQW5kT2JzZXJ2ZXJFbnF1ZXVlUmVjb3JkIiwic3VidHJlZSIsInJlY29yZCIsImVucXVldWUiLCJ1aWRDb3VudGVyIiwicmVjb3Jkc18iLCJhdHRyaWJ1dGVzIiwiYXR0cmlidXRlT2xkVmFsdWUiLCJhdHRyaWJ1dGVGaWx0ZXIiLCJjaGFyYWN0ZXJEYXRhT2xkVmFsdWUiLCJSZWdpc3RyYXRpb24iLCJhZGRMaXN0ZW5lcnMiLCJjb3B5T2ZSZWNvcmRzIiwiTXV0YXRpb25SZWNvcmQiLCJwcmV2aW91c1NpYmxpbmciLCJhdHRyaWJ1dGVOYW1lIiwiYXR0cmlidXRlTmFtZXNwYWNlIiwiY29weU11dGF0aW9uUmVjb3JkIiwiY3VycmVudFJlY29yZCIsInJlY29yZFdpdGhPbGRWYWx1ZSIsImdldFJlY29yZCIsImdldFJlY29yZFdpdGhPbGRWYWx1ZSIsImNsZWFyUmVjb3JkcyIsInJlY29yZFJlcHJlc2VudHNDdXJyZW50TXV0YXRpb24iLCJzZWxlY3RSZWNvcmQiLCJsYXN0UmVjb3JkIiwibmV3UmVjb3JkIiwidHJhbnNpZW50T2JzZXJ2ZWROb2RlcyIsInJlY29yZHMiLCJyZWNvcmRUb1JlcGxhY2VMYXN0IiwiYWRkTGlzdGVuZXJzXyIsInJlbW92ZUxpc3RlbmVyc18iLCJhdHRyTmFtZSIsInJlbGF0ZWROb2RlIiwibmFtZXNwYWNlVVJJIiwiYXR0ckNoYW5nZSIsIk11dGF0aW9uRXZlbnQiLCJBRERJVElPTiIsInByZXZWYWx1ZSIsImFkZFRyYW5zaWVudE9ic2VydmVyIiwiY2hhbmdlZE5vZGUiLCJfaXNQb2x5ZmlsbGVkIiwibmV4dEhhbmRsZSIsInRhc2tzQnlIYW5kbGUiLCJjdXJyZW50bHlSdW5uaW5nQVRhc2siLCJhZGRGcm9tU2V0SW1tZWRpYXRlQXJndW1lbnRzIiwicGFydGlhbGx5QXBwbGllZCIsInJ1bklmUHJlc2VudCIsImhhbmRsZSIsInRhc2siLCJjbGVhckltbWVkaWF0ZSIsImluc3RhbGxOZXh0VGlja0ltcGxlbWVudGF0aW9uIiwibmV4dFRpY2siLCJjYW5Vc2VQb3N0TWVzc2FnZSIsImltcG9ydFNjcmlwdHMiLCJwb3N0TWVzc2FnZUlzQXN5bmNocm9ub3VzIiwib2xkT25NZXNzYWdlIiwib25tZXNzYWdlIiwiaW5zdGFsbFBvc3RNZXNzYWdlSW1wbGVtZW50YXRpb24iLCJtZXNzYWdlUHJlZml4Iiwib25HbG9iYWxNZXNzYWdlIiwiYXR0YWNoRXZlbnQiLCJpbnN0YWxsTWVzc2FnZUNoYW5uZWxJbXBsZW1lbnRhdGlvbiIsImNoYW5uZWwiLCJNZXNzYWdlQ2hhbm5lbCIsInBvcnQxIiwicG9ydDIiLCJpbnN0YWxsUmVhZHlTdGF0ZUNoYW5nZUltcGxlbWVudGF0aW9uIiwib25yZWFkeXN0YXRlY2hhbmdlIiwiaW5zdGFsbFNldFRpbWVvdXRJbXBsZW1lbnRhdGlvbiIsImF0dGFjaFRvIiwicHJvY2VzcyIsIkRFRkFVTFRfVklFV1BPUlQiLCJWaWV3cG9ydCIsInZpZXdwb3J0RWxlbWVudCIsImhlYWQiLCJlbnN1cmVWaWV3cG9ydEVsZW1lbnQiLCJfb25zTG9hZGVkIiwiZmFzdENsaWNrIiwic3VwcG9ydFRvdWNoQWN0aW9uIiwiX2ludGVybmFsIiwiY3JlYXRlSGFuZGxlciIsImFwcCIsImV4aXRBcHAiLCJfZ2VzdHVyZURldGVjdG9yIiwiZ2V0RWxlbWVudENsYXNzIiwiQmFzZUVsZW1lbnQiLCJUZW1wbGF0ZUVsZW1lbnQiLCJvdXRlckhUTUwiLCJidWJibGVzIiwiVGVtcGxhdGUiLCJJZkVsZW1lbnQiLCJfaXNBbGxvd2VkUGxhdGZvcm0iLCJjb25kaXRpb25hbE9yaWVudGF0aW9uIiwiY3VycmVudE9yaWVudGF0aW9uIiwiSWYiLCJCYXNlQW5pbWF0b3IiLCJwcm9wZXJ0aWVzIiwiZXh0ZW5kZWRBbmltYXRvciIsIm5ld0FuaW1hdG9yIiwiaVBob25lWFBhdGNoIiwiaXNJUGhvbmVYUG9ydHJhaXRQYXRjaEFjdGl2ZSIsImlzSVBob25lWExhbmRzY2FwZVBhdGNoQWN0aXZlIiwiZ2V0U2FmZUFyZWFMZW5ndGhzIiwic2FmZUFyZWFMZW5ndGhzIiwiZ2V0U2FmZUFyZWFET01SZWN0Iiwic2FmZUFyZWFSZWN0IiwiQWN0aW9uU2hlZXRBbmltYXRvciIsIk1EQWN0aW9uU2hlZXRBbmltYXRvciIsIm1hc2tUaW1pbmciLCJtYXNrRHVyYXRpb24iLCJhbmltaXQiLCJfbWFzayIsIm9wYWNpdHkiLCJfc2hlZXQiLCJkZWZhdWx0IiwidHJhbnNmb3JtIiwiSU9TQWN0aW9uU2hlZXRBbmltYXRvciIsImxpZnRBbW91bnQiLCJjbGllbnRIZWlnaHQiLCJCYXNlRGlhbG9nRWxlbWVudCIsInNob3VsZFNob3ciLCJfZG9vckxvY2siLCJfY2FuY2VsIiwiX3NlbGZDYW1lbE5hbWUiLCJfZGVmYXVsdERCQiIsImNhbGxQYXJlbnRIYW5kbGVyIiwiX2FuaW1hdG9yRmFjdG9yeSIsIl91cGRhdGVBbmltYXRvckZhY3RvcnkiLCJfcnVubmluZyIsIl9zZXRWaXNpYmxlIiwicGFyc2VBbmltYXRpb25PcHRpb25zU3RyaW5nIiwiY2FuY2VsZWQiLCJfdG9nZ2xlU3R5bGUiLCJiYWNrZ3JvdW5kQ29sb3IiLCJvbkRldmljZUJhY2tCdXR0b24iLCJfYmFja0J1dHRvbkhhbmRsZXIiLCJvbk1vZGlmaWVyQ2hhbmdlZCIsIl9zY2hlbWUiLCJfdXBkYXRlTWFzayIsIl9hbmltYXRvckRpY3QiLCJBY3Rpb25TaGVldEVsZW1lbnQiLCJfY29tcGlsZSIsInNoZWV0IiwiX3RpdGxlIiwibWFzayIsImluaXRNb2RpZmllciIsIl91cGRhdGVUaXRsZSIsIkFjdGlvblNoZWV0IiwiQmFzZUJ1dHRvbkVsZW1lbnQiLCJfZGVmYXVsdENsYXNzTmFtZSIsIl9pY29uIiwiX3VwZGF0ZVJpcHBsZSIsIl9yaXBwbGVPcHQiLCJfdXBkYXRlSWNvbiIsIkFjdGlvblNoZWV0QnV0dG9uRWxlbWVudCIsIkFjdGlvblNoZWV0QnV0dG9uIiwiQWxlcnREaWFsb2dBbmltYXRvciIsIkFuZHJvaWRBbGVydERpYWxvZ0FuaW1hdG9yIiwiX2RpYWxvZyIsIklPU0FsZXJ0RGlhbG9nQW5pbWF0b3IiLCJBbGVydERpYWxvZ0VsZW1lbnQiLCJBbGVydERpYWxvZyIsIkFsZXJ0RGlhbG9nQnV0dG9uRWxlbWVudCIsIkFsZXJ0RGlhbG9nQnV0dG9uIiwiZGVmYXVsdENsYXNzTmFtZSIsIkJhY2tCdXR0b25FbGVtZW50IiwiX29wdGlvbnMiLCJfYm91bmRPbkNsaWNrIiwiX29uQ2xpY2siLCJtZEJhY2tCdXR0b25JY29uIiwiaW9zQmFja0J1dHRvbkljb24iLCJwb3BQYWdlIiwiQmFja0J1dHRvbiIsIkJvdHRvbVRvb2xiYXJFbGVtZW50IiwiQm90dG9tVG9vbGJhciIsIkJ1dHRvbkVsZW1lbnQiLCJCdXR0b24iLCJDYXJkRWxlbWVudCIsIkNhcmQiLCJDYXJvdXNlbEl0ZW1FbGVtZW50IiwiQ2Fyb3VzZWxJdGVtIiwiZGlyZWN0aW9uTWFwIiwiU3dpcGVyIiwiRkFMU0UiLCJnZXRFbGVtZW50Iiwic2Nyb2xsSG9vayIsIml0ZW1TaXplIiwiZ2V0QXV0b1Njcm9sbFJhdGlvIiwicmF0aW8iLCJzaG91bGRCbG9jayIsIm9uRHJhZ1N0YXJ0Iiwib25EcmFnIiwib25EcmFnRW5kIiwib25SZXNpemUiLCJfc2hvdWxkRml4U2Nyb2xsIiwic3dpcGVhYmxlIiwiYXV0b1JlZnJlc2giLCJpbml0aWFsaXplZCIsImJsb2NrZXIiLCJfbXV0YXRpb25PYnNlcnZlciIsInVwZGF0ZVN3aXBlYWJsZSIsInVwZGF0ZUF1dG9SZWZyZXNoIiwiX3Njcm9sbCIsIl9vZmZzZXQiLCJfbGFzdEFjdGl2ZUluZGV4IiwiX3VwZGF0ZUxheW91dCIsIl9zZXR1cEluaXRpYWxJbmRleCIsInNldHVwUmVzaXplIiwidGFyZ2V0U2l6ZSIsIl9yZXNldCIsInNldEFjdGl2ZUluZGV4Iiwicm91bmQiLCJOdW1iZXIiLCJnZXRJbml0aWFsSW5kZXgiLCJpdGVtQ291bnQiLCJpdGVtTnVtU2l6ZSIsIl9zY3JvbGxUbyIsIl9zZXRTd2lwaW5nIiwic2Nyb2xsIiwibWF4U2Nyb2xsIiwiYXJyYXlPZkFycmF5IiwiY29udGVudHMiLCJfY2hhbmdlVG8iLCJjb3VudCIsInNpemUiLCJzaG91bGRVcGRhdGUiLCJzaG91bGRXYXRjaCIsIm5ld1NpemUiLCJibG9jayIsInBvaW50ZXJFdmVudHMiLCJpc0ZpcnN0IiwiaXNPdmVyU2Nyb2xsYWJsZSIsImlzTGFzdCIsIl9pZ25vcmVEcmFnIiwiY29uc3VtZWQiLCJjb25zdW1lIiwiX2NhbkNvbnN1bWVHZXN0dXJlIiwic3RhcnRYIiwiZGlzdEZyb21FZGdlIiwiZ2V0QnViYmxlV2lkdGgiLCJfc3RhcnRlZCIsInRvZ2dsZUJsb2NrZXIiLCJfY29udGludWVkIiwiX2dldERlbHRhIiwidGhyb3R0bGUiLCJub3JtYWxpemVkU2Nyb2xsIiwiX25vcm1hbGl6ZVNjcm9sbCIsIl9zdGFydE1vbWVudHVtU2Nyb2xsIiwiX2tpbGxPdmVyU2Nyb2xsIiwiX2dldFZlbG9jaXR5IiwibWF0Y2hlc0RpcmVjdGlvbiIsImRNIiwiZGlyIiwibmV4dFNjcm9sbCIsIl9nZXRBdXRvU2Nyb2xsIiwic3dpcGUiLCJraWxsT3ZlclNjcm9sbCIsIm92ZXJTY3JvbGxIb29rIiwiYWN0aXZlSW5kZXgiLCJnZXRBY3RpdmVJbmRleCIsImxhc3RBY3RpdmVJbmRleCIsImNoYW5nZSIsInByZUNoYW5nZUhvb2siLCJwb3N0Q2hhbmdlSG9vayIsInRvRml4ZWQiLCJfZ2V0VHJhbnNmb3JtIiwib2Zmc2V0IiwiaXNBdXRvU2Nyb2xsYWJsZSIsImxhc3RTY3JvbGwiLCJzY3JvbGxSYXRpbyIsIl90YXJnZXRTaXplIiwiX2l0ZW1OdW1TaXplIiwicmVmcmVzaEhvb2siLCJheGlzIiwidDNkIiwibmV4dEVsZW1lbnRTaWJsaW5nIiwiaXNDZW50ZXJlZCIsIl9jYWxjdWxhdGVJdGVtU2l6ZSIsIkNhcm91c2VsRWxlbWVudCIsIl9zd2lwZXIiLCJhdXRvU2Nyb2xsUmF0aW8iLCJ2ZXJ0aWNhbCIsIm92ZXJzY3JvbGxhYmxlIiwiY2VudGVyZWQiLCJhdXRvU2Nyb2xsIiwiX29uT3ZlclNjcm9sbCIsIl9vbkNoYW5nZSIsIl9vblJlZnJlc2giLCJfb25Td2lwZSIsInVwZGF0ZUl0ZW1TaXplIiwid2FpdEZvckFjdGlvbiIsImNhcm91c2VsIiwiaXRlbVNpemVBdHRyIiwicGFyc2VGbG9hdCIsIkNhcm91c2VsIiwiQ29sRWxlbWVudCIsIl91cGRhdGVXaWR0aCIsIkNvbCIsIkRpYWxvZ0FuaW1hdG9yIiwiQW5kcm9pZERpYWxvZ0FuaW1hdG9yIiwiSU9TRGlhbG9nQW5pbWF0b3IiLCJib2R5SGVpZ2h0IiwiU2xpZGVEaWFsb2dBbmltYXRvciIsIkRpYWxvZ0VsZW1lbnQiLCJEaWFsb2ciLCJGYWJFbGVtZW50IiwiX2hpZGUiLCJfc2hvdyIsIl9tYW51YWxseUhpZGRlbiIsIl90b2dnbGUiLCJpc0JvdHRvbSIsInRyYW5zbGF0ZSIsImZhYk9mZnNldCIsIkZhYiIsIkdlc3R1cmVEZXRlY3RvckVsZW1lbnQiLCJhdXRvUHJlZml4IiwiSWNvbkVsZW1lbnQiLCJfY2xlYW5DbGFzc0F0dHJpYnV0ZSIsIl91cGRhdGUiLCJfYnVpbGRDbGFzc0FuZFN0eWxlIiwiX3BhcnNlQXR0ciIsImF0dHIiLCJtZCIsImxhc3RJY29uIiwibGFzdE1vZGlmaWVyIiwiX3ByZWZpeEljb24iLCJjdXN0b21QcmVmaXhSRSIsImljb25OYW1lIiwicmVtb3ZlUHJvcGVydHkiLCJmb250U2l6ZSIsIkxhenlSZXBlYXREZWxlZ2F0ZSIsInVzZXJEZWxlZ2F0ZSIsInRlbXBsYXRlRWxlbWVudCIsIl91c2VyRGVsZWdhdGUiLCJfdGVtcGxhdGVFbGVtZW50IiwiX3JlbmRlciIsImxvYWRJdGVtRWxlbWVudCIsImNyZWF0ZUl0ZW1Db250ZW50IiwiY291bnRJdGVtcyIsInVwZGF0ZUl0ZW1Db250ZW50IiwiY2FsY3VsYXRlSXRlbUhlaWdodCIsImRlc3Ryb3lJdGVtIiwiaXRlbUhlaWdodCIsIkxhenlSZXBlYXRQcm92aWRlciIsIndyYXBwZXJFbGVtZW50IiwiZGVsZWdhdGUiLCJfd3JhcHBlckVsZW1lbnQiLCJfZGVsZWdhdGUiLCJfaW5zZXJ0SW5kZXgiLCJfcGFnZUNvbnRlbnQiLCJfZmluZFBhZ2VDb250ZW50RWxlbWVudCIsImxhc3RTY3JvbGxUb3AiLCJwYWRkaW5nIiwiX3RvcFBvc2l0aW9ucyIsIl9yZW5kZXJlZEl0ZW1zIiwiX3Vua25vd25JdGVtSGVpZ2h0IiwiX2FkZEV2ZW50TGlzdGVuZXJzIiwicGFnZUNvbnRlbnQiLCJfaXRlbUhlaWdodCIsInZpc2liaWxpdHkiLCJzdGF0aWNJdGVtSGVpZ2h0IiwiX2dldEl0ZW1IZWlnaHQiLCJmb3JjZVJlbmRlciIsImZvcmNlU2Nyb2xsRG93biIsImZpcnN0SXRlbUluZGV4IiwiX2ZpcnN0SXRlbVJlbmRlcmVkIiwiX2NhbGN1bGF0ZVJlbmRlcmVkSGVpZ2h0IiwiZm9yY2VGaXJzdEluZGV4IiwiX3JlbW92ZUFsbEVsZW1lbnRzIiwiZm9yY2VMYXN0SW5kZXgiLCJfY2hlY2tJdGVtSGVpZ2h0IiwiaXNTY3JvbGxVcCIsImtlZXAiLCJnZXRCb3VuZGluZ0NsaWVudFJlY3QiLCJfY291bnRJdGVtcyIsIl9jYWxjdWxhdGVTdGFydEluZGV4IiwiaGFzUmVuZGVyRnVuY3Rpb24iLCJfcmVuZGVyRWxlbWVudCIsIl9yZW1vdmVFbGVtZW50IiwidXBkYXRlSXRlbSIsImxhc3RJdGVtSW5kZXgiLCJfbGFzdEl0ZW1SZW5kZXJlZCIsIl9yZWNhbGN1bGF0ZVRvcFBvc2l0aW9ucyIsIm1pZGRsZSIsImltbWVkaWF0ZSIsImNhbGxOb3ciLCJfZGVib3VuY2UiLCJfYm91bmRPbkNoYW5nZSIsIl9ib3VuZERvdWJsZUZpcmVPblRvdWNoZW5kIiwiX3BhcmVudEVsZW1lbnQiLCJfcmVtb3ZlRXZlbnRMaXN0ZW5lcnMiLCJwYWRkaW5nVG9wIiwiTGF6eVJlcGVhdEVsZW1lbnQiLCJfbGF6eVJlcGVhdFByb3ZpZGVyIiwiTGF6eVJlcGVhdCIsIkxpc3RIZWFkZXJFbGVtZW50IiwiTGlzdEhlYWRlciIsIkxpc3RUaXRsZUVsZW1lbnQiLCJMaXN0VGl0bGUiLCJMaXN0SXRlbUFuaW1hdG9yIiwibGlzdEl0ZW0iLCJTbGlkZUxpc3RJdGVtQW5pbWF0b3IiLCJfYW5pbWF0ZUV4cGFuc2lvbiIsInNob3VsZE9wZW4iLCJvbGRIZWlnaHQiLCJleHBhbmRhYmxlQ29udGVudCIsIm9sZERpc3BsYXkiLCJjb21wdXRlZFN0eWxlIiwiZXhwYW5zaW9uT3BlblRyYW5zaXRpb24iLCJwYWRkaW5nQm90dG9tIiwiaWNvbk9wZW5UcmFuc2l0aW9uIiwicmV2ZXJzZSIsImV4cGFuZENoZXZyb24iLCJMaXN0SXRlbUVsZW1lbnQiLCJ0b2dnbGVFeHBhbnNpb24iLCJfc2hvdWxkSWdub3JlVGFwIiwic2hvd0V4cGFuc2lvbiIsImhpZGVFeHBhbnNpb24iLCJ0b3BDb250ZW50IiwiY2VudGVyQ29udGVudCIsIl90b3AiLCJjaGV2cm9uIiwiX2V4cGFuZGluZyIsImV4cGFuZGVkIiwiX3NldHVwTGlzdGVuZXJzIiwiX29yaWdpbmFsQmFja2dyb3VuZENvbG9yIiwidGFwcGVkIiwiX29uVG91Y2giLCJfb25SZWxlYXNlIiwiX29uRHJhZyIsInRvdWNoU3R5bGUiLCJib3hTaGFkb3ciLCJMaXN0SXRlbSIsIkxpc3RFbGVtZW50IiwiTGlzdCIsIklOUFVUX0FUVFJJQlVURVMiLCJCYXNlSW5wdXRFbGVtZW50IiwiX2JvdW5kRGVsZWdhdGVFdmVudCIsIl9kZWxlZ2F0ZUV2ZW50IiwiX3RlbXBsYXRlIiwiX3NldElucHV0SWQiLCJfdXBkYXRlQm91bmRBdHRyaWJ1dGVzIiwiX2lucHV0IiwidG9JU09TdHJpbmciLCJJbnB1dEVsZW1lbnQiLCJfYm91bmRPbklucHV0IiwiX2JvdW5kT25Gb2N1c2luIiwiX3VwZGF0ZUxhYmVsIiwiX3VwZGF0ZUxhYmVsQ2xhc3MiLCJfaGVscGVyIiwiaW5uZXJUZXh0IiwiSW5wdXQiLCJCYXNlQ2hlY2tib3hFbGVtZW50IiwiY2hlY2tlZCIsIkNoZWNrYm94RWxlbWVudCIsIkNoZWNrYm94IiwiUmFkaW9FbGVtZW50IiwiUmFkaW8iLCJTZWFyY2hJbnB1dEVsZW1lbnQiLCJTZWFyY2hJbnB1dCIsIk1vZGFsQW5pbWF0b3IiLCJtb2RhbCIsIkZhZGVNb2RhbEFuaW1hdG9yIiwiTGlmdE1vZGFsQW5pbWF0b3IiLCJNb2RhbEVsZW1lbnQiLCJNb2RhbCIsIndpZHRoVG9QeCIsIm9mZnNldFdpZHRoIiwiU3dpcGVSZXZlYWwiLCJlbGVtZW50SGFuZGxlciIsImdldFRocmVzaG9sZCIsImdldFNpZGUiLCJoYW5kbGVHZXN0dXJlIiwiZ2VzdHVyZURldGVjdG9yIiwiaWdub3JlU3dpcGUiLCJfd2lkdGgiLCJfc3RhcnREaXN0YW5jZSIsIl9kaXN0YW5jZSIsImlzSW5pdGlhbFN0YXRlIiwiZGVsdGEiLCJzd2lwZU1pZCIsImlzU3dpcGVNYXgiLCJzd2lwZU1heCIsInN3aXBlTWluIiwiTmF2aWdhdG9yQW5pbWF0b3IiLCJlbnRlclBhZ2UiLCJsZWF2ZVBhZ2UiLCJJT1NTd2lwZU5hdmlnYXRvckFuaW1hdG9yIiwiZHVyYXRpb25SZXN0b3JlIiwiZHVyYXRpb25Td2lwZSIsInRpbWluZ1N3aXBlIiwicmVzdCIsIm9wdFN3aXBlIiwib3B0UmVzdG9yZSIsInN3aXBlU2hhZG93IiwiaXNEcmFnU3RhcnQiLCJ1bmJsb2NrIiwiYmFja2dyb3VuZE1hc2siLCJkZWNvbXAiLCJfZGVjb21wb3NlIiwiZW50ZXIiLCJsZWF2ZSIsIl9jYWxjdWxhdGVEZWx0YSIsInNob3VsZEFuaW1hdGVUb29sYmFyIiwiX3Nob3VsZEFuaW1hdGVUb29sYmFyIiwidG9vbGJhciIsIl9zYXZlU3R5bGUiLCJvdmVyZmxvd0VsZW1lbnQiLCJtYXhXaWR0aCIsImlzU3dpcGluZyIsIl9kcmFnU3RhcnRTZXR1cCIsInN3aXBlUmF0aW8iLCJib3R0b21Ub29sYmFyIiwiYmFja2dyb3VuZCIsInRvb2xiYXJDZW50ZXIiLCJiYWNrQnV0dG9uTGFiZWwiLCJvdGhlciIsIl9zYXZlZFN0eWxlIiwic2F2ZSIsInJlc3RvcmUiLCJfcmVzdG9yZVN0eWxlIiwidHJhbnNsYXRlM2QiLCJJT1NTbGlkZU5hdmlnYXRvckFuaW1hdG9yIiwiX2dldFRvb2xiYXJFbGVtZW50IiwiX2dldFRvb2xiYXJMZWZ0SXRlbXNFbGVtZW50IiwiX2dldFRvb2xiYXJSaWdodEl0ZW1zRWxlbWVudCIsImV4Y2x1ZGVCYWNrQnV0dG9uIiwiX2dldFRvb2xiYXJDZW50ZXJJdGVtc0VsZW1lbnQiLCJfZ2V0VG9vbGJhckJhY2tCdXR0b25JY29uRWxlbWVudCIsIl9nZXRUb29sYmFyQmFja0J1dHRvbkxhYmVsRWxlbWVudCIsIl9nZXRDb250ZW50RWxlbWVudCIsIl9nZXRCYWNrZ3JvdW5kRWxlbWVudCIsIl9nZXRCb3R0b21Ub29sYmFyRWxlbWVudCIsInRvb2xiYXJzIiwiZW50ZXJUb29sYmFyIiwibGVhdmVUb29sYmFyIiwiaXNTdGF0aWMiLCJpc01hdGVyaWFsIiwiaXNUcmFuc3BhcmVudCIsImRlY29tcG9zaXRpb24iLCJwYWdlUmVjdCIsImxhYmVsUmVjdCIsImJhY2tCdXR0b25JY29uIiwiZW50ZXJQYWdlVGFyZ2V0IiwibGVhdmVQYWdlVGFyZ2V0IiwiZW50ZXJQYWdlRGVjb21wb3NpdGlvbiIsImxlYXZlUGFnZURlY29tcG9zaXRpb24iLCJwb3BTd2lwZSIsIklPU0xpZnROYXZpZ2F0b3JBbmltYXRvciIsIklPU0ZhZGVOYXZpZ2F0b3JBbmltYXRvciIsIk1EU2xpZGVOYXZpZ2F0b3JBbmltYXRvciIsImJsYWNrTWFza09wYWNpdHkiLCJNRExpZnROYXZpZ2F0b3JBbmltYXRvciIsIm1hc2tDbGVhciIsIk1ERmFkZU5hdmlnYXRvckFuaW1hdG9yIiwidGltaW5nUG9wIiwiTm9uZU5hdmlnYXRvckFuaW1hdG9yIiwicmV3cml0YWJsZXMiLCJuYXZpZ2F0b3JFbGVtZW50IiwidmVyaWZ5UGFnZUVsZW1lbnQiLCJOYXZpZ2F0b3JFbGVtZW50IiwiX2lzUnVubmluZyIsIl9pbml0aWFsaXplZCIsIl9wYWdlTG9hZGVyIiwiX3BhZ2VNYXAiLCJfcGFnZSIsIl9vbkRldmljZUJhY2tCdXR0b24iLCJzd2lwZUFuaW1hdG9yIiwiX3N3aXBlIiwicHJldmlvdXNFbGVtZW50U2libGluZyIsImFyZWEiLCJpc0JCIiwicHVzaGVkT3B0aW9ucyIsImFuaW1hdG9yRmFjdG9yeSIsImxvYWRlZCIsIl9nZXRQYWdlVGFyZ2V0IiwicHVzaFBhZ2UiLCJfdXBkYXRlTGFzdFBhZ2VCYWNrQnV0dG9uIiwidXBkYXRlIiwiX3ByZXBhcmVQYWdlQW5kT3B0aW9ucyIsInRpbWVzIiwiX3JlbW92ZVBhZ2VzIiwicG9wVXBkYXRlIiwidW5sb2FkIiwiX3BvcFBhZ2UiLCJfZW1pdFByZVBvcEV2ZW50IiwidXBkYXRlQmFja0J1dHRvbiIsInBhZ2VIVE1MIiwiX3B1c2hQYWdlIiwibG9hZCIsIl9lbWl0UHJlUHVzaEV2ZW50IiwicGFnZUxlbmd0aCIsIl9yZXBsYWNlUGFnZSIsInJlc29sdmVkVmFsdWUiLCJfbm9ybWFsaXplSW5kZXgiLCJpbnNlcnRQYWdlIiwibmV3UGFnZSIsIl9sYXN0SW5kZXhPZlBhZ2UiLCJwYWdlTmFtZSIsImlzQ2FuY2VsZWQiLCJfZW1pdFByZUV2ZW50IiwidGVtcGxhdGVIVE1MIiwicGFnZUxvYWRlciIsImxhc3RFbGVtZW50Q2hpbGQiLCJOYXZpZ2F0b3IiLCJUb29sYmFyRWxlbWVudCIsInNpYmxpbmdCYWNrZ3JvdW5kIiwic2libGluZ0NvbnRlbnQiLCJzZXRWaXNpYmlsaXR5IiwiX2Vuc3VyZVRvb2xiYXJJdGVtRWxlbWVudHMiLCJfZW5zdXJlVG9vbGJhckVsZW1lbnQiLCJUb29sYmFyIiwiUGFnZUVsZW1lbnQiLCJfZGVyaXZlSG9va3MiLCJfYmFja2dyb3VuZEVsZW1lbnQiLCJfZWxlbWVudFNob3VsZEJlTW92ZWQiLCJfdHJ5VG9GaWxsU3RhdHVzQmFyIiwiZml4ZWRFbGVtZW50cyIsIm9uSW5pdCIsImJhY2tCdXR0b24iLCJvdmVyTGltaXQiLCJfaW5maW5pdGVTY3JvbGxMaW1pdCIsIl9vbkluZmluaXRlU2Nyb2xsIiwiX2xvYWRpbmdDb250ZW50Iiwib25JbmZpbml0ZVNjcm9sbCIsIm9uRGVzdHJveSIsImV2ZW50cyIsIl9ib3VuZE9uU2Nyb2xsIiwiX29uU2Nyb2xsIiwiUGFnZSIsIlBvcG92ZXJBbmltYXRvciIsInBvcG92ZXIiLCJhbmltYXRpb25zIiwiX2FuaW1hdGUiLCJmYWRlIiwiTURGYWRlUG9wb3ZlckFuaW1hdG9yIiwiX2FuaW1hdGVBbGwiLCJpbiIsIklPU0ZhZGVQb3BvdmVyQW5pbWF0b3IiLCJwb3NpdGlvbnMiLCJQb3BvdmVyRWxlbWVudCIsIl9jdXJyZW50VGFyZ2V0IiwiX3Bvc2l0aW9uUG9wb3ZlciIsIl9jbGVhclN0eWxlcyIsInJhZGl1cyIsIl9yYWRpdXMiLCJjb250ZW50RWxlbWVudCIsIl9jb250ZW50IiwibWFyZ2luIiwiX21hcmdpbiIsInRhcmdldFJlY3QiLCJpc01EIiwiY292ZXIiLCJwYXJlbnREaW1lbnNpb25zIiwibWF4UG9zaXRpb25zIiwiYm90dG9tIiwidGFyZ2V0RGlzdGFuY2UiLCJ0YXJnZXRDZW50ZXJEaXN0YW5jZUZyb20iLCJfY2FsY3VsYXRlRGlyZWN0aW9ucyIsInByaW1hcnlEaXJlY3Rpb24iLCJwcmltYXJ5Iiwic2Vjb25kYXJ5RGlyZWN0aW9uIiwic2Vjb25kYXJ5IiwiX2N1cnJlbnREaXJlY3Rpb24iLCJzaXplTmFtZSIsImNvbnRlbnRTaXplIiwidGFyZ2V0QW5kQXJyb3dMZW5ndGgiLCJwcmltYXJ5T2Zmc2V0Iiwic2Vjb25kYXJ5T2Zmc2V0IiwiX3BvcG92ZXIiLCJfYXJyb3ciLCJoYXNEZWZhdWx0Q29udGFpbmVyIiwiYXJyb3ciLCJQb3BvdmVyIiwiSU5ERVQiLCJQcm9ncmVzc0JhckVsZW1lbnQiLCJfaXNDb21waWxlZCIsIl9wcmltYXJ5IiwiX3NlY29uZGFyeSIsIl91cGRhdGVEZXRlcm1pbmF0ZSIsIl91cGRhdGVWYWx1ZSIsImJhckVsZW1lbnQiLCJQcm9ncmVzc0JhciIsIlByb2dyZXNzQ2lyY3VsYXJFbGVtZW50IiwicGVyIiwic3ZnIiwiUHJvZ3Jlc3NDaXJjdWxhciIsIlNUQVRFX0lOSVRJQUwiLCJTVEFURV9QUkVBQ1RJT04iLCJTVEFURV9BQ1RJT04iLCJ0aHJvd1R5cGUiLCJQdWxsSG9va0VsZW1lbnQiLCJfb25EcmFnU3RhcnQiLCJfb25EcmFnRW5kIiwiX3NldFN0YXRlIiwibGluZUhlaWdodCIsIl9wYWdlRWxlbWVudCIsInRhcFkiLCJtYXhZIiwiZHJhZ2dhYmxlQXJlYVJhdGlvIiwiX3N0YXJ0U2Nyb2xsIiwiX2N1cnJlbnRUcmFuc2xhdGlvbiIsInRoIiwidGhyZXNob2xkSGVpZ2h0IiwiX2ZpbmlzaCIsIl90cmFuc2xhdGVUbyIsImFuaW1hdGUiLCJvbkFjdGlvbiIsIm5vRXZlbnQiLCJsYXN0U3RhdGUiLCJtYXJnaW5Ub3AiLCJfb25QdWxsIiwic2Nyb2xsRWxlbWVudCIsIl9kcmFnTG9ja0Rpc2FibGVkIiwic2Nyb2xsVG9nZ2xlIiwiZ2RUb2dnbGUiLCJfc2V0U3R5bGUiLCJfb25BY3Rpb24iLCJQdWxsSG9vayIsImFjdGl2ZUNsYXNzVG9rZW4iLCJSYW5nZUVsZW1lbnQiLCJfb25Nb3VzZURvd24iLCJfb25Nb3VzZVVwIiwiX29uVG91Y2hTdGFydCIsIl9vblRvdWNoRW5kIiwiX29uSW5wdXQiLCJfb25EcmFnc3RhcnQiLCJfb25EcmFnZW5kIiwiX3VwZGF0ZURpc2FibGVkIiwiZm9jdXNSaW5nIiwiX2ZvY3VzUmluZyIsImJhY2tncm91bmRTaXplIiwiX3JhdGlvIiwiUmFuZ2UiLCJBbmltYXRvckNTUyIsImZpbmFsIiwiZ2V0VGltZSIsImluaXRpYWwiLCJ1cGRhdGVTdHlsZXMiLCJjbGVhclRpbWVvdXQiLCJ0cmFuc2l0aW9uRHVyYXRpb24iLCJzdG9wTmV4dCIsIm5ld0R1cmF0aW9uIiwicGFzc2VkIiwicmVtYWluaW5nIiwic3BlZWRVcFRpbWUiLCJzdG9wIiwibWlsbGlzZWNvbmRzIiwic3BlZWQiLCJ0cmFuc2l0aW9uUHJvcGVydHkiLCJfb25TdG9wQW5pbWF0aW9ucyIsIl9xdWV1ZSIsIl9pbmRleCIsInN0b3BBbmltYXRpb25zIiwiUmlwcGxlRWxlbWVudCIsIl9vblRhcCIsIl9vbkhvbGQiLCJfYW5pbWF0b3IiLCJfd2F2ZSIsImdldEVsZW1lbnRzQnlDbGFzc05hbWUiLCJfYmFja2dyb3VuZCIsInNpemVzIiwiX2dldEVmZmVjdFNpemUiLCJfY2VudGVyIiwiX21pblIiLCJfY2FsY3VsYXRlQ29vcmRzIiwic3RvcEFsbCIsInJpcHBsZSIsIl91cGRhdGVQYXJlbnQiLCJfcmlwcGxlQW5pbWF0aW9uIiwiX2hvbGRpbmciLCJfcGFyZW50Tm9kZSIsInBuIiwiUmlwcGxlIiwiUm93RWxlbWVudCIsIlJvdyIsIlNlZ21lbnRFbGVtZW50IiwiX3NlZ21lbnRJZCIsIl90YWJiYXIiLCJfb25UYWJiYXJQcmVDaGFuZ2UiLCJnZXRBY3RpdmVUYWJJbmRleCIsImdldEFjdGl2ZUJ1dHRvbkluZGV4IiwiX3NldENoZWNrZWQiLCJmaXJzdEVsZW1lbnRDaGlsZCIsInNldEFjdGl2ZVRhYiIsIl9wb3N0Q2hhbmdlIiwiU2VnbWVudCIsIlNlbGVjdEVsZW1lbnQiLCJfZGVyaXZlR2V0dGVycyIsIl9zZWxlY3QiLCJzZWwiLCJvcHRpb24iLCJTZWxlY3QiLCJTcGVlZERpYWxJdGVtRWxlbWVudCIsIlNwZWVkRGlhbEl0ZW0iLCJTcGVlZERpYWxFbGVtZW50IiwiX2l0ZW1TaG93biIsIl91cGRhdGVEaXJlY3Rpb24iLCJ0b2dnbGVJdGVtcyIsImlubGluZSIsIl9mYWIiLCJpdGVtcyIsIl9nZXRUcmFuc2xhdGUiLCJoaWRlSXRlbXMiLCJ0b3RhbERlbGF5IiwiaXNPcGVuIiwic2hvd0l0ZW1zIiwiU3BlZWREaWFsIiwiU3BsaXR0ZXJDb250ZW50RWxlbWVudCIsIm9sZENvbnRlbnQiLCJTcGxpdHRlckNvbnRlbnQiLCJTcGxpdHRlck1hc2tFbGVtZW50IiwiX3NpZGVzIiwic2lkZSIsIm1vZGUiLCJTcGxpdHRlck1hc2siLCJTcGxpdHRlckFuaW1hdG9yIiwic2lkZUVsZW1lbnQiLCJzcGxpdHRlciIsIl9zaWRlIiwiX29wcG9zaXRlU2lkZSIsImNsZWFyTWFzayIsIk92ZXJsYXlTcGxpdHRlckFuaW1hdG9yIiwibWludXMiLCJQdXNoU3BsaXR0ZXJBbmltYXRvciIsInNsaWRpbmdFbGVtZW50cyIsIl9zbGlkaW5nRWxlbWVudHMiLCJfZ2V0U2xpZGluZ0VsZW1lbnRzIiwiUmV2ZWFsU3BsaXR0ZXJBbmltYXRvciIsIl9zZXRTdHlsZXMiLCJfdW5zZXRTdHlsZXMiLCJfZ2VuZXJhdGVCZWhpbmRQYWdlU3R5bGUiLCJiZWhpbmREaXN0YW5jZSIsImJlaGluZFRyYW5zZm9ybSIsIl9nZXRNYXhXaWR0aCIsIm1lbnVTdHlsZSIsIlNwbGl0dGVyRWxlbWVudCIsIl9sYXlvdXQiLCJfZ2V0U2lkZSIsIl9vbk1vZGVDaGFuZ2UiLCJTcGxpdHRlciIsIlNQTElUX01PREUiLCJDT0xMQVBTRV9NT0RFIiwiQ0xPU0VEX1NUQVRFIiwiT1BFTl9TVEFURSIsIkNIQU5HSU5HX1NUQVRFIiwic3BsaXR0ZXJTaWRlRWxlbWVudCIsIkNvbGxhcHNlRGV0ZWN0aW9uIiwiY2hhbmdlVGFyZ2V0IiwiX3RhcmdldCIsIl9vcmllbnRhdGlvbiIsImFjdGl2YXRlIiwiX3VwZGF0ZU1vZGUiLCJfbWF0Y2giLCJfcXVlcnlSZXN1bHQiLCJtYXRjaE1lZGlhIiwiYWRkTGlzdGVuZXIiLCJyZW1vdmVMaXN0ZW5lciIsIlNwbGl0dGVyU2lkZUVsZW1lbnQiLCJfc3RhdGUiLCJfbG9jayIsIl9jb2xsYXBzZURldGVjdGlvbiIsIl9hbmltYXRpb25PcHQiLCJjbG9zZWQiLCJ2YWxpZERyYWciLCJfbW9kZSIsIl9pc090aGVyU2lkZU9wZW4iLCJkZWFjdGl2YXRlIiwidXBkYXRlT3B0aW9ucyIsIkZJTkFMX1NUQVRFIiwiX2VtaXRFdmVudCIsIl91cGRhdGVBbmltYXRpb24iLCJTcGxpdHRlclNpZGUiLCJsb2NhdGlvbnMiLCJTd2l0Y2hFbGVtZW50IiwiX2xhc3RUaW1lU3RhbXAiLCJfbG9jYXRpb25zIiwiX3N0YXJ0WCIsIl9lbWl0Q2hhbmdlRXZlbnQiLCJkZWZhdWx0RWxlbWVudENsYXNzIiwiX2hhbmRsZSIsIl9nZXRQb3NpdGlvbiIsInByZXZpb3VzVmFsdWUiLCJjbGljayIsIlN3aXRjaCIsInRhYmJhckVsZW1lbnQiLCJsZXJwIiwieDAiLCJ4MSIsInQiLCJUYWJiYXJFbGVtZW50IiwiX2xvYWRJbmFjdGl2ZSIsIl9nZXRBdXRvU2Nyb2xsUmF0aW8iLCJfb25QcmVDaGFuZ2UiLCJfb25Qb3N0Q2hhbmdlIiwiX3RhYmJhckJvcmRlciIsIl90YWJiYXJFbGVtZW50IiwiX3RhYnNSZWN0IiwidGFiSXRlbSIsInRhYnMiLCJfbm9ybWFsaXplRXZlbnQiLCJjYW5jZWwiLCJzZXRBY3RpdmUiLCJwcmV2VGFiIiwiX2F1dG9ncm93IiwidGFiIiwidGFiYmFyIiwiY3MiLCJmaWxsZWQiLCJuZXh0SW5kZXgiLCJwcmV2SW5kZXgiLCJuZXh0VGFiIiwic2V0VGFiYmFyVmlzaWJpbGl0eSIsImlzQWN0aXZlIiwiaXNUb3AiLCJfdGFyZ2V0RWxlbWVudCIsIlRhYmJhciIsIlRhYkVsZW1lbnQiLCJfYnV0dG9uIiwiX3VwZGF0ZUJ1dHRvbkNvbnRlbnQiLCJpY29uV3JhcHBlciIsImZpeCIsImFjdGl2ZSIsIl9oYXNMb2FkZWQiLCJfbG9hZGVkUGFnZSIsInBhZ2VUYXJnZXQiLCJwYXJlbnRUYXJnZXQiLCJkdW1teVBhZ2UiLCJfbG9hZFBhZ2VFbGVtZW50IiwiVGFiIiwiVG9hc3RBbmltYXRvciIsIkZhZGVUb2FzdEFuaW1hdG9yIiwiQXNjZW5kVG9hc3RBbmltYXRvciIsIm1lc3NhZ2VEZWxheSIsImFzY2Vuc2lvbiIsIl9nZXRGYWJzIiwiZmFiIiwiTGlmdFRvYXN0QW5pbWF0b3IiLCJGYWxsVG9hc3RBbmltYXRvciIsImZhbGxBbW91bnQiLCJjbGVhblVwIiwiY29ycmVjdFRvcCIsIlRvYXN0RWxlbWVudCIsIm1lc3NhZ2VDbGFzc05hbWUiLCJidXR0b25DbGFzc05hbWUiLCJUb2FzdCIsIlRvb2xiYXJCdXR0b25FbGVtZW50IiwiVG9vbGJhckJ1dHRvbiIsIl9zdXBlclNlY3JldE9ucyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFBQSxrQkFBZSxFQUFmOztBQ0FBOzs7Ozs7Ozs7Ozs7Ozs7OztBQWlCQSxBQUVBOzs7Ozs7QUFNQSxJQUFNQSxTQUFVLFlBQVc7TUFDbkJDLFNBQVNDLE9BQU9DLGdCQUFQLENBQXdCQyxTQUFTQyxlQUFqQyxFQUFrRCxFQUFsRCxDQUFmO01BQ01MLFNBQVMsQ0FBQ00sTUFBTUMsU0FBTixDQUFnQkMsS0FBaEIsQ0FDYkMsSUFEYSxDQUNSUixNQURRLEVBRWJTLElBRmEsQ0FFUixFQUZRLEVBR2JDLEtBSGEsQ0FHUCxtQkFITyxLQUdrQlYsT0FBT1csS0FBUCxLQUFpQixFQUFqQixJQUF1QixDQUFDLEVBQUQsRUFBSyxHQUFMLENBSDFDLEVBSWIsQ0FKYSxDQUFmOztTQU1PLFVBQVNDLElBQVQsRUFBZTtXQUNiLE1BQU1iLE1BQU4sR0FBZSxHQUFmLEdBQXFCYyxPQUFLQyxTQUFMLENBQWVGLElBQWYsQ0FBNUI7R0FERjtDQVJhLEVBQWY7Ozs7Ozs7Ozs7QUFzQkEsSUFBTUcsU0FBUyxTQUFUQSxNQUFTLENBQVNDLE9BQVQsRUFBa0JDLEtBQWxCLEVBQXlCO1NBQy9CQyxJQUFQLENBQVlELEtBQVosRUFBbUJFLE9BQW5CLENBQTJCLFVBQVNDLEdBQVQsRUFBYztRQUNuQ0EsT0FBT0os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